""" Authentication API endpoints """ from datetime import datetime, timedelta from typing import List from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from app.database.base import get_db from app.models.user import User from app.auth.security import ( authenticate_user, create_access_token, get_password_hash, get_current_user, get_admin_user ) from app.auth.schemas import ( Token, UserCreate, UserResponse, LoginRequest ) from app.config import settings router = APIRouter() @router.post("/login", response_model=Token) async def login(login_data: LoginRequest, db: Session = Depends(get_db)): """Login endpoint""" user = authenticate_user(db, login_data.username, login_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) # Update last login user.last_login = datetime.utcnow() db.commit() access_token_expires = timedelta(minutes=settings.access_token_expire_minutes) access_token = create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) return {"access_token": access_token, "token_type": "bearer"} @router.post("/register", response_model=UserResponse) async def register( user_data: UserCreate, db: Session = Depends(get_db), current_user: User = Depends(get_admin_user) # Only admins can create users ): """Register new user (admin only)""" # Check if username or email already exists existing_user = db.query(User).filter( (User.username == user_data.username) | (User.email == user_data.email) ).first() if existing_user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Username or email already registered" ) # Create new user hashed_password = get_password_hash(user_data.password) new_user = User( username=user_data.username, email=user_data.email, full_name=user_data.full_name, hashed_password=hashed_password ) db.add(new_user) db.commit() db.refresh(new_user) return new_user @router.get("/me", response_model=UserResponse) async def read_users_me(current_user: User = Depends(get_current_user)): """Get current user info""" return current_user @router.get("/users", response_model=List[UserResponse]) async def list_users( db: Session = Depends(get_db), current_user: User = Depends(get_admin_user) ): """List all users (admin only)""" users = db.query(User).all() return users