"""Authentication endpoints.""" from datetime import timedelta from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from ...core.config import get_settings from ...db.database import get_db from ...services.auth import AuthService from ...services.user import UserService from ...schemas.user import UserResponse, UserCreate from ...utils.schemas import Token, LoginRequest router = APIRouter() settings = get_settings() @router.post("/register", response_model=UserResponse) async def register( user_data: UserCreate, db: Session = Depends(get_db) ): """Register a new user.""" user_service = UserService(db) # Check if user already exists if user_service.get_user_by_email(user_data.email): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Email already registered" ) if user_service.get_user_by_username(user_data.username): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Username already taken" ) # Create user user = user_service.create_user(user_data) return UserResponse.from_orm(user) @router.post("/login", response_model=Token) async def login( login_data: LoginRequest, db: Session = Depends(get_db) ): """Login with email and password.""" # Authenticate user by email user = AuthService.authenticate_user_by_email(db, login_data.email, login_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect email or password", headers={"WWW-Authenticate": "Bearer"}, ) # Create access token access_token_expires = timedelta(minutes=settings.security.access_token_expire_minutes) access_token = AuthService.create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) return { "access_token": access_token, "token_type": "bearer", "expires_in": settings.security.access_token_expire_minutes * 60 } @router.post("/login-oauth", response_model=Token) async def login_oauth( form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db) ): """Login with username and password (OAuth2 compatible).""" # Authenticate user user = AuthService.authenticate_user(db, form_data.username, form_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) # Create access token access_token_expires = timedelta(minutes=settings.security.access_token_expire_minutes) access_token = AuthService.create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) return { "access_token": access_token, "token_type": "bearer", "expires_in": settings.security.access_token_expire_minutes * 60 } @router.post("/refresh", response_model=Token) async def refresh_token( current_user = Depends(AuthService.get_current_user), db: Session = Depends(get_db) ): """Refresh access token.""" # Create new access token access_token_expires = timedelta(minutes=settings.security.access_token_expire_minutes) access_token = AuthService.create_access_token( data={"sub": current_user.username}, expires_delta=access_token_expires ) return { "access_token": access_token, "token_type": "bearer", "expires_in": settings.security.access_token_expire_minutes * 60 } @router.get("/me", response_model=UserResponse) async def get_current_user_info( current_user = Depends(AuthService.get_current_user) ): """Get current user information.""" return UserResponse.from_orm(current_user)