"""Authentication router — register, login, refresh, me.""" from __future__ import annotations from typing import Annotated from fastapi import APIRouter, Depends from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.core.security import get_current_user, require_roles from app.models.user import User from app.schemas.auth import ( LoginRequest, RefreshRequest, RegisterRequest, TokenResponse, UserOut, ) from app.services import auth as auth_service router = APIRouter(prefix="/api/auth", tags=["auth"]) @router.get("/users", response_model=list[UserOut]) async def list_users( db: Annotated[AsyncSession, Depends(get_db)], current_user: Annotated[User, Depends(get_current_user)], ) -> list[User]: """List users (id, name, role) for assignment pickers. Previously the frontend hard-coded technician ids/names in detail.html; this endpoint makes the assign dropdown data-driven so a seed change never silently breaks technician assignment. """ result = await db.execute(select(User).order_by(User.full_name)) return list(result.scalars().all()) @router.post("/register", response_model=UserOut, status_code=201) async def register( body: RegisterRequest, db: Annotated[AsyncSession, Depends(get_db)], ) -> User: return await auth_service.register(db, body) @router.post("/login", response_model=TokenResponse) async def login( body: LoginRequest, db: Annotated[AsyncSession, Depends(get_db)], ) -> TokenResponse: access, refresh, _user = await auth_service.login(db, body.email, body.password) return TokenResponse(access_token=access, refresh_token=refresh) @router.post("/refresh", response_model=TokenResponse) async def refresh( body: RefreshRequest, db: Annotated[AsyncSession, Depends(get_db)], ) -> TokenResponse: access, refresh = await auth_service.refresh_access_token(db, body.refresh_token) return TokenResponse(access_token=access, refresh_token=refresh) @router.get("/me", response_model=UserOut) async def me(current_user: Annotated[User, Depends(get_current_user)]) -> User: return current_user @router.get("/admin-only", response_model=UserOut) async def admin_only( current_user: Annotated[User, Depends(require_roles("Admin/Jerome", "Admin/Wahab"))], ) -> User: """Example RBAC-protected endpoint — only Admins can access.""" return current_user