import os from datetime import datetime, timedelta from jose import JWTError, jwt from dotenv import load_dotenv load_dotenv() JWT_SECRET = os.getenv("JWT_SECRET", "supersecretkey") JWT_ALGORITHM = "HS256" JWT_EXPIRE_MINUTES = 60 * 24 # 1 day def create_access_token(data: dict, expires_delta: timedelta = None): to_encode = data.copy() expire = datetime.utcnow() + (expires_delta or timedelta(minutes=JWT_EXPIRE_MINUTES)) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, JWT_SECRET, algorithm=JWT_ALGORITHM) return encoded_jwt def verify_access_token(token: str): try: payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) return payload except JWTError: return None import bcrypt from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from db import db def hash_password(password: str) -> str: salt = bcrypt.gensalt() return bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8") def verify_password(plain_password: str, hashed_password: str) -> bool: return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8")) oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login") async def get_current_user(token: str = Depends(oauth2_scheme)): print(f"DEBUG: get_current_user called with token: {token[:20]}...") try: # print("DEBUG: Decoding token with secret:", JWT_SECRET) payload = verify_access_token(token) print("DEBUG: Token decoded payload:", payload) except Exception as e: print(f"DEBUG: Token verification crashed: {e}") raise HTTPException(status_code=401, detail="Token verification failed") if not payload or "user_id" not in payload: print(f"DEBUG: Invalid token payload: {payload}") raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid authentication credentials.", headers={"WWW-Authenticate": "Bearer"}, ) from bson import ObjectId # Check if user is a caregiver based on role in token role = payload.get("role", "patient") # print(f"DEBUG: User role from token: {role}, User ID: {payload['user_id']}") try: if role == "caregiver": # Look in caregivers collection user = await db.caregivers.find_one({"_id": ObjectId(payload["user_id"])}) if not user: print(f"DEBUG: Caregiver not found in DB: {payload['user_id']}") raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Caregiver not found.", headers={"WWW-Authenticate": "Bearer"}, ) user["role"] = "caregiver" # Ensure role is present user["is_caregiver"] = True # Helper flag else: # Look in users collection (default for patients) user = await db.users.find_one({"_id": ObjectId(payload["user_id"])}) if not user: print(f"DEBUG: User not found in DB: {payload['user_id']}") raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found.", headers={"WWW-Authenticate": "Bearer"}, ) user["role"] = "patient" # Ensure role is present user["is_caregiver"] = False except Exception as e: print(f"DEBUG: Authentication exception: {str(e)}") raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=f"Authentication error: {str(e)}", headers={"WWW-Authenticate": "Bearer"}, ) print(f"DEBUG: User found: {user.get('email', 'unknown')}") return user