| 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 |
|
|
| 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: |
| |
| 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 |
| |
| |
| role = payload.get("role", "patient") |
| |
| |
| try: |
| if role == "caregiver": |
| |
| 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" |
| user["is_caregiver"] = True |
| else: |
| |
| 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" |
| 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 |
|
|