Spaces:
Sleeping
Sleeping
| from fastapi import APIRouter, Depends, HTTPException, status | |
| from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm | |
| from jose import jwt, JWTError | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from sqlalchemy.future import select | |
| import uuid | |
| from datetime import datetime | |
| from database.session import get_db | |
| from database.models import User | |
| from schemas import UserCreate, User as UserSchema, Token, UserLogin | |
| from auth_utils import get_password_hash, verify_password, create_access_token, SECRET_KEY, ALGORITHM | |
| router = APIRouter(prefix="/auth", tags=["Authentication"]) | |
| oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login") | |
| async def get_current_user( | |
| token: str = Depends(oauth2_scheme), | |
| db: AsyncSession = Depends(get_db) | |
| ) -> User: | |
| credentials_exception = HTTPException( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| detail="Could not validate credentials", | |
| headers={"WWW-Authenticate": "Bearer"}, | |
| ) | |
| try: | |
| payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) | |
| user_id: str = payload.get("sub") | |
| if user_id is None: | |
| raise credentials_exception | |
| except JWTError: | |
| raise credentials_exception | |
| result = await db.execute(select(User).where(User.id == uuid.UUID(user_id))) | |
| user = result.scalars().first() | |
| if user is None: | |
| raise credentials_exception | |
| if not user.is_active: | |
| raise HTTPException(status_code=400, detail="Inactive user") | |
| return user | |
| async def register(user_in: UserCreate, db: AsyncSession = Depends(get_db)): | |
| # Check if user exists | |
| result = await db.execute(select(User).where(User.email == user_in.email)) | |
| if result.scalars().first(): | |
| raise HTTPException( | |
| status_code=400, | |
| detail="User with this email already exists" | |
| ) | |
| result = await db.execute(select(User).where(User.username == user_in.username)) | |
| if result.scalars().first(): | |
| raise HTTPException( | |
| status_code=400, | |
| detail="User with this username already exists" | |
| ) | |
| # Create user | |
| db_user = User( | |
| email=user_in.email, | |
| username=user_in.username, | |
| name=user_in.name, | |
| password_hash=get_password_hash(user_in.password), | |
| role="USER", | |
| status="active", | |
| balance=0.0000, | |
| spent=0.0000 | |
| ) | |
| db.add(db_user) | |
| await db.commit() | |
| await db.refresh(db_user) | |
| return db_user | |
| async def login(user_in: UserLogin, db: AsyncSession = Depends(get_db)): | |
| result = await db.execute(select(User).where(User.email == user_in.email)) | |
| user = result.scalars().first() | |
| if not user or not verify_password(user_in.password, user.password_hash): | |
| raise HTTPException( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| detail="Incorrect email or password", | |
| headers={"WWW-Authenticate": "Bearer"}, | |
| ) | |
| if not user.is_active: | |
| raise HTTPException(status_code=400, detail="Inactive user") | |
| access_token = create_access_token(subject=user.id) | |
| return {"access_token": access_token, "token_type": "bearer"} | |
| async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(), db: AsyncSession = Depends(get_db)): | |
| # Supports standard OAuth2 form login (username/password) | |
| result = await db.execute(select(User).where(User.username == form_data.username)) | |
| user = result.scalars().first() | |
| if not user or not verify_password(form_data.password, user.password_hash): | |
| # Fallback to checking by email if username check failed | |
| result = await db.execute(select(User).where(User.email == form_data.username)) | |
| user = result.scalars().first() | |
| if not user or not verify_password(form_data.password, user.password_hash): | |
| raise HTTPException( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| detail="Incorrect username or password", | |
| headers={"WWW-Authenticate": "Bearer"}, | |
| ) | |
| access_token = create_access_token(subject=user.id) | |
| return {"access_token": access_token, "token_type": "bearer"} | |
| async def read_users_me(current_user: User = Depends(get_current_user)): | |
| return current_user | |