Spaces:
Running
Running
Ahmed Mostafa commited on
Commit ·
c29587d
1
Parent(s): 4577288
fix log v1.5.3
Browse files- src/auth/dependencies.py +31 -20
- src/db/firebase.py +25 -14
- test_gen.py +25 -0
- test_verify.py +29 -0
src/auth/dependencies.py
CHANGED
|
@@ -21,43 +21,54 @@ from firebase_admin import auth as firebase_auth
|
|
| 21 |
from src.db.firebase import verify_token
|
| 22 |
|
| 23 |
|
|
|
|
|
|
|
|
|
|
| 24 |
async def get_current_user(
|
| 25 |
token: str = Depends(oauth2_scheme)
|
| 26 |
) -> User:
|
| 27 |
"""
|
| 28 |
-
Get the currently authenticated user with
|
| 29 |
"""
|
| 30 |
db = get_firebase_db()
|
| 31 |
firebase_error = None
|
|
|
|
| 32 |
|
| 33 |
# Log token prefix for debugging
|
| 34 |
token_prefix = token[:10] if token else "None"
|
| 35 |
-
logger.info(f"Received token
|
| 36 |
|
| 37 |
# 1. Try Firebase Verification
|
| 38 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
firebase_result = verify_token(token)
|
| 40 |
-
|
| 41 |
-
logger.info(f"[v4] Firebase result type: {type(firebase_result)}")
|
| 42 |
|
| 43 |
if not isinstance(firebase_result, dict):
|
| 44 |
-
firebase_error = f"[
|
| 45 |
firebase_payload = None
|
| 46 |
else:
|
| 47 |
firebase_payload = firebase_result.get("payload")
|
| 48 |
firebase_error = firebase_result.get("error")
|
| 49 |
|
| 50 |
-
# CHANGED: Use explicit None check to handle empty dicts {} which are falsy
|
| 51 |
if firebase_payload is not None:
|
| 52 |
uid = firebase_payload.get("uid")
|
| 53 |
email = firebase_payload.get("email")
|
| 54 |
if not uid:
|
| 55 |
-
logger.error("[
|
| 56 |
-
|
| 57 |
-
raise HTTPException(status_code=401, detail=f"Invalid Firebase token payload [CP1-v4]. Payload: {str(firebase_payload)}")
|
| 58 |
|
| 59 |
if db is None:
|
| 60 |
-
logger.warning(f"[
|
| 61 |
return User(id=uid, email=email or "unknown@example.com", username=firebase_payload.get("name", uid), role="user")
|
| 62 |
|
| 63 |
# Retrieve from Firestore
|
|
@@ -71,7 +82,7 @@ async def get_current_user(
|
|
| 71 |
user_data.setdefault("role", user_data.get("role", "user"))
|
| 72 |
return User(**user_data)
|
| 73 |
else:
|
| 74 |
-
logger.info(f"[
|
| 75 |
return User(
|
| 76 |
id=uid,
|
| 77 |
email=email or "unknown@example.com",
|
|
@@ -82,8 +93,8 @@ async def get_current_user(
|
|
| 82 |
except HTTPException:
|
| 83 |
raise
|
| 84 |
except Exception as e:
|
| 85 |
-
logger.error(f"[
|
| 86 |
-
firebase_error = f"Exception [CP4-
|
| 87 |
|
| 88 |
# 2. Fallback to Custom JWT Decoding
|
| 89 |
try:
|
|
@@ -91,7 +102,7 @@ async def get_current_user(
|
|
| 91 |
if payload:
|
| 92 |
username: Optional[str] = payload.get("sub")
|
| 93 |
if not username:
|
| 94 |
-
raise HTTPException(status_code=401, detail="Token missing subject claim [CP5-
|
| 95 |
|
| 96 |
if db is None:
|
| 97 |
return User(id="mock_id", email="mock@example.com", username=username, password_hash="mock", role="user")
|
|
@@ -105,18 +116,18 @@ async def get_current_user(
|
|
| 105 |
user_data["id"] = user_doc.id
|
| 106 |
return User(**user_data)
|
| 107 |
else:
|
| 108 |
-
logger.error(f"[
|
| 109 |
-
raise HTTPException(status_code=401, detail="User account not found [CP6-
|
| 110 |
except HTTPException:
|
| 111 |
raise
|
| 112 |
except Exception as e:
|
| 113 |
-
logger.error(f"[
|
| 114 |
|
| 115 |
# If both failed, then it's a 401
|
| 116 |
-
fb_diag = f"Firebase(
|
| 117 |
-
error_detail = f"Auth Failure [CP8-
|
| 118 |
|
| 119 |
-
logger.error(f"Authentication failed (
|
| 120 |
raise HTTPException(
|
| 121 |
status_code=status.HTTP_401_UNAUTHORIZED,
|
| 122 |
detail=error_detail,
|
|
|
|
| 21 |
from src.db.firebase import verify_token
|
| 22 |
|
| 23 |
|
| 24 |
+
import inspect
|
| 25 |
+
import time
|
| 26 |
+
|
| 27 |
async def get_current_user(
|
| 28 |
token: str = Depends(oauth2_scheme)
|
| 29 |
) -> User:
|
| 30 |
"""
|
| 31 |
+
Get the currently authenticated user with extreme diagnostic introspection (v5).
|
| 32 |
"""
|
| 33 |
db = get_firebase_db()
|
| 34 |
firebase_error = None
|
| 35 |
+
session_id = str(int(time.time()))[-4:] # Last 4 digits of timestamp
|
| 36 |
|
| 37 |
# Log token prefix for debugging
|
| 38 |
token_prefix = token[:10] if token else "None"
|
| 39 |
+
logger.info(f"[v5-{session_id}] Received token {token_prefix}...")
|
| 40 |
|
| 41 |
# 1. Try Firebase Verification
|
| 42 |
try:
|
| 43 |
+
# INTROSPECTION: Where does verify_token come from?
|
| 44 |
+
vt_file = "Unknown"
|
| 45 |
+
try:
|
| 46 |
+
vt_file = inspect.getfile(verify_token)
|
| 47 |
+
except:
|
| 48 |
+
pass
|
| 49 |
+
vt_module = getattr(verify_token, "__module__", "Unknown")
|
| 50 |
+
|
| 51 |
+
logger.info(f"[v5-{session_id}] Calling verify_token from {vt_module} ({vt_file})")
|
| 52 |
+
|
| 53 |
firebase_result = verify_token(token)
|
| 54 |
+
logger.info(f"[v5-{session_id}] Firebase result type: {type(firebase_result)}")
|
|
|
|
| 55 |
|
| 56 |
if not isinstance(firebase_result, dict):
|
| 57 |
+
firebase_error = f"[v5] Internal Error [CP0]: verify_token returned {type(firebase_result)} (Expected dict)"
|
| 58 |
firebase_payload = None
|
| 59 |
else:
|
| 60 |
firebase_payload = firebase_result.get("payload")
|
| 61 |
firebase_error = firebase_result.get("error")
|
| 62 |
|
|
|
|
| 63 |
if firebase_payload is not None:
|
| 64 |
uid = firebase_payload.get("uid")
|
| 65 |
email = firebase_payload.get("email")
|
| 66 |
if not uid:
|
| 67 |
+
logger.error(f"[v5-{session_id}] Firebase payload missing 'uid' [CP1]")
|
| 68 |
+
raise HTTPException(status_code=401, detail=f"Invalid Firebase token payload [CP1-v5]. Payload keys: {list(firebase_payload.keys())}")
|
|
|
|
| 69 |
|
| 70 |
if db is None:
|
| 71 |
+
logger.warning(f"[v5-{session_id}] Firestore not available, returning transient user for {email} [CP2]")
|
| 72 |
return User(id=uid, email=email or "unknown@example.com", username=firebase_payload.get("name", uid), role="user")
|
| 73 |
|
| 74 |
# Retrieve from Firestore
|
|
|
|
| 82 |
user_data.setdefault("role", user_data.get("role", "user"))
|
| 83 |
return User(**user_data)
|
| 84 |
else:
|
| 85 |
+
logger.info(f"[v5-{session_id}] New Firebase user detected: {email or uid} [CP3]")
|
| 86 |
return User(
|
| 87 |
id=uid,
|
| 88 |
email=email or "unknown@example.com",
|
|
|
|
| 93 |
except HTTPException:
|
| 94 |
raise
|
| 95 |
except Exception as e:
|
| 96 |
+
logger.error(f"[v5-{session_id}] Unexpected error in Firebase auth path: {repr(e)} [CP4]")
|
| 97 |
+
firebase_error = f"Exception [CP4-v5]: {repr(e)}"
|
| 98 |
|
| 99 |
# 2. Fallback to Custom JWT Decoding
|
| 100 |
try:
|
|
|
|
| 102 |
if payload:
|
| 103 |
username: Optional[str] = payload.get("sub")
|
| 104 |
if not username:
|
| 105 |
+
raise HTTPException(status_code=401, detail="Token missing subject claim [CP5-v5]")
|
| 106 |
|
| 107 |
if db is None:
|
| 108 |
return User(id="mock_id", email="mock@example.com", username=username, password_hash="mock", role="user")
|
|
|
|
| 116 |
user_data["id"] = user_doc.id
|
| 117 |
return User(**user_data)
|
| 118 |
else:
|
| 119 |
+
logger.error(f"[v5-{session_id}] User {username} not found in database [CP6]")
|
| 120 |
+
raise HTTPException(status_code=401, detail="User account not found [CP6-v5]")
|
| 121 |
except HTTPException:
|
| 122 |
raise
|
| 123 |
except Exception as e:
|
| 124 |
+
logger.error(f"[v5-{session_id}] Unexpected error in custom JWT auth path: {repr(e)} [CP7]")
|
| 125 |
|
| 126 |
# If both failed, then it's a 401
|
| 127 |
+
fb_diag = f"Firebase(v5-{session_id}): {firebase_error if firebase_error else f'Payload is {type(firebase_payload)}({str(firebase_payload)})'}"
|
| 128 |
+
error_detail = f"Auth Failure [CP8-v5] | Token: {token_prefix}... | {fb_diag}"
|
| 129 |
|
| 130 |
+
logger.error(f"Authentication failed (v5): {error_detail}")
|
| 131 |
raise HTTPException(
|
| 132 |
status_code=status.HTTP_401_UNAUTHORIZED,
|
| 133 |
detail=error_detail,
|
src/db/firebase.py
CHANGED
|
@@ -26,11 +26,16 @@ def get_firebase_db():
|
|
| 26 |
import json
|
| 27 |
service_account_info = json.loads(settings.firebase_service_account_json)
|
| 28 |
cred = credentials.Certificate(service_account_info)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
firebase_admin.initialize_app(cred, {
|
| 30 |
-
'storageBucket': settings.firebase_storage_bucket
|
|
|
|
| 31 |
})
|
| 32 |
_db = firestore.client()
|
| 33 |
-
logger.info("Firebase initialized successfully
|
| 34 |
return _db
|
| 35 |
|
| 36 |
# Priority 2: Check for service account file
|
|
@@ -42,11 +47,12 @@ def get_firebase_db():
|
|
| 42 |
|
| 43 |
cred = credentials.Certificate(str(service_account_path))
|
| 44 |
firebase_admin.initialize_app(cred, {
|
| 45 |
-
'storageBucket': settings.firebase_storage_bucket
|
|
|
|
| 46 |
})
|
| 47 |
|
| 48 |
_db = firestore.client()
|
| 49 |
-
logger.info("Firebase initialized successfully
|
| 50 |
return _db
|
| 51 |
except Exception as e:
|
| 52 |
logger.error(f"Failed to initialize Firebase: {e}")
|
|
@@ -54,23 +60,28 @@ def get_firebase_db():
|
|
| 54 |
|
| 55 |
def verify_token(id_token: str):
|
| 56 |
"""
|
| 57 |
-
Verify a Firebase ID token with
|
|
|
|
| 58 |
"""
|
| 59 |
try:
|
| 60 |
# Check if any app is initialized, if not try to initialize
|
| 61 |
if not firebase_admin._apps:
|
| 62 |
-
logger.warning("Firebase app not initialized. Attempting default initialization...")
|
| 63 |
get_firebase_db()
|
| 64 |
|
| 65 |
if not firebase_admin._apps:
|
| 66 |
-
|
| 67 |
-
return None
|
| 68 |
|
|
|
|
| 69 |
decoded_token = auth.verify_id_token(id_token)
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
except Exception as e:
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
logger.debug(f"Token length: {len(id_token)}, starts with: {id_token[:10]}...")
|
| 76 |
-
return None
|
|
|
|
| 26 |
import json
|
| 27 |
service_account_info = json.loads(settings.firebase_service_account_json)
|
| 28 |
cred = credentials.Certificate(service_account_info)
|
| 29 |
+
|
| 30 |
+
# Explicitly extract project_id from JSON if possible
|
| 31 |
+
project_id = service_account_info.get('project_id') or settings.firebase_project_id
|
| 32 |
+
|
| 33 |
firebase_admin.initialize_app(cred, {
|
| 34 |
+
'storageBucket': settings.firebase_storage_bucket,
|
| 35 |
+
'projectId': project_id
|
| 36 |
})
|
| 37 |
_db = firestore.client()
|
| 38 |
+
logger.info(f"Firebase initialized successfully for project: {project_id} (using JSON)")
|
| 39 |
return _db
|
| 40 |
|
| 41 |
# Priority 2: Check for service account file
|
|
|
|
| 47 |
|
| 48 |
cred = credentials.Certificate(str(service_account_path))
|
| 49 |
firebase_admin.initialize_app(cred, {
|
| 50 |
+
'storageBucket': settings.firebase_storage_bucket,
|
| 51 |
+
'projectId': settings.firebase_project_id
|
| 52 |
})
|
| 53 |
|
| 54 |
_db = firestore.client()
|
| 55 |
+
logger.info(f"Firebase initialized successfully for project: {settings.firebase_project_id} (using file)")
|
| 56 |
return _db
|
| 57 |
except Exception as e:
|
| 58 |
logger.error(f"Failed to initialize Firebase: {e}")
|
|
|
|
| 60 |
|
| 61 |
def verify_token(id_token: str):
|
| 62 |
"""
|
| 63 |
+
Verify a Firebase ID token with v5 absolute diagnostic clarity.
|
| 64 |
+
Returns: {"payload": decoded_token, "error": error_message}
|
| 65 |
"""
|
| 66 |
try:
|
| 67 |
# Check if any app is initialized, if not try to initialize
|
| 68 |
if not firebase_admin._apps:
|
| 69 |
+
logger.warning("[v5] Firebase app not initialized. Attempting default initialization...")
|
| 70 |
get_firebase_db()
|
| 71 |
|
| 72 |
if not firebase_admin._apps:
|
| 73 |
+
return {"payload": None, "error": "[v5] Firebase app could not be initialized."}
|
|
|
|
| 74 |
|
| 75 |
+
# The core SDK call
|
| 76 |
decoded_token = auth.verify_id_token(id_token)
|
| 77 |
+
|
| 78 |
+
if decoded_token is None:
|
| 79 |
+
logger.error("[v5] auth.verify_id_token returned None unexpectedly.")
|
| 80 |
+
return {"payload": None, "error": "[v5] Firebase SDK returned None for token verification."}
|
| 81 |
+
|
| 82 |
+
logger.info(f"[v5] Firebase token successfully verified for UID: {decoded_token.get('uid')}")
|
| 83 |
+
return {"payload": decoded_token, "error": None}
|
| 84 |
except Exception as e:
|
| 85 |
+
error_msg = f"[v5] Exception during verify_id_token: {repr(e)}"
|
| 86 |
+
logger.error(error_msg)
|
| 87 |
+
return {"payload": None, "error": error_msg}
|
|
|
|
|
|
test_gen.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import os
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
# Add project root to path
|
| 6 |
+
sys.path.append(str(Path(__file__).parent))
|
| 7 |
+
|
| 8 |
+
from src.summarization.note_generator import NoteGenerator
|
| 9 |
+
from src.utils.config import settings
|
| 10 |
+
|
| 11 |
+
def test_note_generator():
|
| 12 |
+
print("Testing NoteGenerator initialization after fix...")
|
| 13 |
+
try:
|
| 14 |
+
# We need an API key for initialization if it's not in env
|
| 15 |
+
api_key = os.getenv("GOOGLE_API_KEY", "dummy_key")
|
| 16 |
+
gen = NoteGenerator(api_key=api_key)
|
| 17 |
+
print("✅ Initialization successful")
|
| 18 |
+
print(f"Model ID: {gen.model_id}")
|
| 19 |
+
except Exception as e:
|
| 20 |
+
print(f"❌ Initialization failed: {e}")
|
| 21 |
+
import traceback
|
| 22 |
+
traceback.print_exc()
|
| 23 |
+
|
| 24 |
+
if __name__ == "__main__":
|
| 25 |
+
test_note_generator()
|
test_verify.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
# Add src to path
|
| 5 |
+
sys.path.append(str(Path(__file__).parent))
|
| 6 |
+
|
| 7 |
+
from src.db.firebase import verify_token
|
| 8 |
+
import firebase_admin
|
| 9 |
+
|
| 10 |
+
def test_verify():
|
| 11 |
+
print("Testing verify_token with invalid token...")
|
| 12 |
+
# This should return a dict with error and no payload
|
| 13 |
+
result = verify_token("invalid_token")
|
| 14 |
+
print(f"Result type: {type(result)}")
|
| 15 |
+
print(f"Result content: {result}")
|
| 16 |
+
|
| 17 |
+
if isinstance(result, dict):
|
| 18 |
+
payload = result.get("payload")
|
| 19 |
+
error = result.get("error")
|
| 20 |
+
print(f"Payload: {payload} (Type: {type(payload)})")
|
| 21 |
+
print(f"Error: {error} (Type: {type(error)})")
|
| 22 |
+
|
| 23 |
+
if not payload:
|
| 24 |
+
print("Payload is falsy")
|
| 25 |
+
if not error:
|
| 26 |
+
print("Error is falsy")
|
| 27 |
+
|
| 28 |
+
if __name__ == "__main__":
|
| 29 |
+
test_verify()
|