"""Auth-endpoints: login, refresh, change password.""" from datetime import datetime from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.dependencies import get_current_user from app.models import User from app.schemas import Token, LoginRequest, RefreshRequest, ChangePasswordRequest from app.security import create_access_token, create_refresh_token, decode_token from app.services.user_service import UserService router = APIRouter(prefix="/auth", tags=["Authentication"]) @router.post("/login", response_model=Token) async def login(data: LoginRequest, db: AsyncSession = Depends(get_db)): service = UserService(db) user = await service.authenticate(data.email, data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect email or password", headers={"WWW-Authenticate": "Bearer"}, ) user.last_login_at = datetime.utcnow() await db.commit() access_token = create_access_token(user.id) refresh_token = create_refresh_token(user.id) return Token( access_token=access_token, refresh_token=refresh_token, expires_in=30 * 60, ) @router.post("/refresh", response_model=Token) async def refresh(data: RefreshRequest, db: AsyncSession = Depends(get_db)): payload = decode_token(data.refresh_token) if payload is None or payload.get("type") != "refresh": raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid refresh token", ) from uuid import UUID user_id = payload.get("sub") service = UserService(db) user = await service.get_by_id(UUID(user_id)) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found", ) access_token = create_access_token(user.id) refresh_token = create_refresh_token(user.id) return Token( access_token=access_token, refresh_token=refresh_token, expires_in=30 * 60, ) @router.post("/change-password") async def change_password( data: ChangePasswordRequest, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): service = UserService(db) await service.change_password(current_user, data.current_password, data.new_password) return {"message": "Password changed successfully"} @router.get("/me") async def me(current_user: User = Depends(get_current_user)): from app.schemas import UserDetailOut return UserDetailOut.model_validate(current_user)