from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from typing import List from app.database import get_db, engine, Base from app.models.user import User from app.schemas.user import UserCreate, UserUpdate, UserResponse from app.core.security import get_password_hash, verify_password, create_access_token, ACCESS_TOKEN_EXPIRE_MINUTES from datetime import timedelta # Create tables Base.metadata.create_all(bind=engine) router = APIRouter() @router.post("/auth/login") def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): user = db.query(User).filter(User.username == form_data.username).first() if not user or not verify_password(form_data.password, user.hashed_password): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) if not user.is_active: raise HTTPException(status_code=400, detail="Inactive user") access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token( data={"sub": user.username, "is_admin": user.is_admin, "id": user.id}, expires_delta=access_token_expires ) return { "access_token": access_token, "token_type": "bearer", "user": { "id": user.id, "username": user.username, "email": user.email, "is_admin": user.is_admin } } @router.post("/auth/register", response_model=UserResponse) def register_user(user: UserCreate, db: Session = Depends(get_db)): db_user = db.query(User).filter(User.username == user.username).first() if db_user: raise HTTPException(status_code=400, detail="Username already registered") db_user_email = db.query(User).filter(User.email == user.email).first() if db_user_email: raise HTTPException(status_code=400, detail="Email already registered") hashed_password = get_password_hash(user.password) # If this is the first user, make them an admin is_first_user = db.query(User).count() == 0 db_user = User( username=user.username, email=user.email, hashed_password=hashed_password, is_active=True, is_admin=is_first_user or user.is_admin ) db.add(db_user) db.commit() db.refresh(db_user) return db_user @router.get("/users", response_model=List[UserResponse]) def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): users = db.query(User).offset(skip).limit(limit).all() return users @router.get("/users/{user_id}", response_model=UserResponse) def read_user(user_id: int, db: Session = Depends(get_db)): db_user = db.query(User).filter(User.id == user_id).first() if db_user is None: raise HTTPException(status_code=404, detail="User not found") return db_user @router.post("/users", response_model=UserResponse) def create_user(user: UserCreate, db: Session = Depends(get_db)): db_user = db.query(User).filter(User.username == user.username).first() if db_user: raise HTTPException(status_code=400, detail="Username already registered") db_user_email = db.query(User).filter(User.email == user.email).first() if db_user_email: raise HTTPException(status_code=400, detail="Email already registered") db_user = User( username=user.username, email=user.email, hashed_password=get_password_hash(user.password), is_active=user.is_active, is_admin=user.is_admin ) db.add(db_user) db.commit() db.refresh(db_user) return db_user @router.put("/users/{user_id}", response_model=UserResponse) def update_user(user_id: int, user: UserUpdate, db: Session = Depends(get_db)): db_user = db.query(User).filter(User.id == user_id).first() if not db_user: raise HTTPException(status_code=404, detail="User not found") update_data = user.model_dump(exclude_unset=True) for key, value in update_data.items(): if key == "password" and value: db_user.hashed_password = get_password_hash(value) elif key != "password": setattr(db_user, key, value) db.commit() db.refresh(db_user) return db_user @router.delete("/users/{user_id}") def delete_user(user_id: int, db: Session = Depends(get_db)): db_user = db.query(User).filter(User.id == user_id).first() if not db_user: raise HTTPException(status_code=404, detail="User not found") db.delete(db_user) db.commit() return {"ok": True}