Spaces:
Paused
Paused
File size: 4,721 Bytes
6d01d5b ed6b1d2 6d01d5b 2a4b4c6 6d01d5b 2a4b4c6 6d01d5b 3f8cf16 6d01d5b 2a4b4c6 6d01d5b 3f8cf16 6d01d5b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from passlib.context import CryptContext
from jose import jwt
from pydantic import BaseModel, EmailStr
from app.database import get_db # Updated: use the correct async session dependency
from app.models import User
import os
import logging
from dotenv import load_dotenv
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import JWTError
router = APIRouter()
logger = logging.getLogger(__name__)
load_dotenv()
# Load secret key and JWT algorithm
SECRET_KEY = os.getenv("SECRET_KEY", "secret")
ALGORITHM = "HS256"
# Password hashing config
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
security = HTTPBearer()
async def get_current_user(token: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db)):
credentials_exception = HTTPException(
status_code=401,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token.credentials, SECRET_KEY, algorithms=[ALGORITHM])
user_id: int = payload.get("user_id")
if user_id is None:
raise credentials_exception
except JWTError:
raise credentials_exception
result = await db.execute(select(User).where(User.id == user_id))
user = result.scalar_one_or_none()
if user is None:
raise credentials_exception
return user
# Request Schemas
class SignUp(BaseModel):
email: EmailStr
password: str
mobile: str | None = None
name: str | None = None
dob: str | None = None
preparing_for: str | None = None
class Login(BaseModel):
email: EmailStr
password: str
class UpdateProfile(BaseModel):
mobile: str | None = None
name: str | None = None
dob: str | None = None
preparing_for: str | None = None
@router.put("/auth/profile")
async def update_profile(data: UpdateProfile,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)):
# Update user fields if provided
if data.mobile is not None:
current_user.mobile = data.mobile
if data.name is not None:
current_user.name = data.name
if data.dob is not None:
current_user.dob = data.dob
if data.preparing_for is not None:
current_user.preparing_for = data.preparing_for
try:
await db.commit()
await db.refresh(current_user)
return {"message": "Profile updated successfully",
"user": {"id": current_user.id,
"email": current_user.email,
"mobile": current_user.mobile,
"name": current_user.name,
"dob": current_user.dob,
"preparing_for": current_user.preparing_for}}
except Exception as e:
await db.rollback()
logger.error(f"Profile update error: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
@router.post("/auth/signup")
async def signup(data: SignUp, db: AsyncSession = Depends(get_db)):
# Check if user already exists
result = await db.execute(select(User).where(User.email == data.email))
existing_user = result.scalar_one_or_none()
if existing_user:
raise HTTPException(status_code=400, detail="Email already exists")
hashed_password = pwd_context.hash(data.password)
new_user = User(email=data.email, hashed_password=hashed_password,
mobile=data.mobile, name=data.name, dob=data.dob,
preparing_for=data.preparing_for)
try:
db.add(new_user)
await db.commit()
await db.refresh(new_user)
return {"message": "User created", "user_id": new_user.id}
except Exception as e:
await db.rollback()
logger.error(f"Signup error: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
@router.post("/auth/login")
async def login(data: Login, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(User).where(User.email == data.email))
user = result.scalar_one_or_none()
if not user or not pwd_context.verify(data.password, user.hashed_password):
raise HTTPException(status_code=401, detail="Invalid credentials")
token = jwt.encode({"user_id": user.id}, SECRET_KEY, algorithm=ALGORITHM)
return {
"access_token": token,
"token_type": "bearer",
"user": {"id": user.id, "email": user.email},
}
|