from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.core.dependencies import get_current_user from app.core.security import create_access_token, hash_password, verify_password from app.database import get_db from app.models.user import User from app.schemas.schemas import TokenResponse, UserCreate, UserResponse router = APIRouter() @router.post("/register", response_model=TokenResponse, status_code=201) async def register(body: UserCreate, db: AsyncSession = Depends(get_db)): if len(body.password) < 8: raise HTTPException(status_code=400, detail="Password must be at least 8 characters") if "@" not in body.email: raise HTTPException(status_code=400, detail="Invalid email address") # Check for duplicate email existing = await db.execute(select(User).where(User.email == body.email.lower())) if existing.scalar_one_or_none(): raise HTTPException(status_code=409, detail="Email already registered") # First registered user becomes admin count_result = await db.execute(select(func.count()).select_from(User)) is_first_user = count_result.scalar() == 0 user = User( email=body.email.lower(), hashed_password=hash_password(body.password), is_admin=is_first_user, ) db.add(user) await db.commit() await db.refresh(user) return TokenResponse(access_token=create_access_token(user.id), user=user) @router.post("/login", response_model=TokenResponse) async def login(body: UserCreate, db: AsyncSession = Depends(get_db)): result = await db.execute(select(User).where(User.email == body.email.lower())) user = result.scalar_one_or_none() if not user or not verify_password(body.password, user.hashed_password): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect email or password", ) return TokenResponse(access_token=create_access_token(user.id), user=user) @router.get("/me", response_model=UserResponse) async def me(current_user: User = Depends(get_current_user)): return current_user