from __future__ import annotations from datetime import UTC, datetime from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.api.dependencies import current_user from app.db.session import get_session from app.models.user import User from app.core.security import hash_password, verify_password from app.schemas.auth import ChangePasswordRequest, LoginRequest, TokenResponse, UserRead from app.services.auth_service import AuthService from app.core.config import settings router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/login", response_model=TokenResponse) def login(payload: LoginRequest, session: Session = Depends(get_session)) -> TokenResponse: token, user = AuthService(session).login(payload.email, payload.password) return TokenResponse( access_token=token, expires_in=settings.access_token_minutes * 60, user=user, ) @router.get("/me", response_model=UserRead) def me(user: User = Depends(current_user)) -> User: return user @router.post("/change-password") def change_password( payload: ChangePasswordRequest, user: User = Depends(current_user), session: Session = Depends(get_session), ) -> dict[str, str]: if not verify_password(payload.current_password, user.password_hash): raise HTTPException(status_code=422, detail="Das aktuelle Passwort ist falsch.") if payload.new_password != payload.new_password_confirmation: raise HTTPException(status_code=422, detail="Die neuen Passwoerter stimmen nicht ueberein.") if len(payload.new_password) < 12: raise HTTPException(status_code=422, detail="Das neue Passwort muss mindestens 12 Zeichen haben.") if verify_password(payload.new_password, user.password_hash): raise HTTPException(status_code=422, detail="Das neue Passwort darf nicht identisch zum alten sein.") user.password_hash = hash_password(payload.new_password) user.must_change_password = False user.password_changed_at = datetime.now(UTC) session.commit() return {"status": "ok"}