Files
gartenmanager/backend/app/api/v1/auth.py

69 lines
2.4 KiB
Python
Raw Normal View History

from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, status
from jose import JWTError
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.deps import CurrentUser, get_session
from app.core.security import TOKEN_TYPE_REFRESH, create_access_token, create_refresh_token, decode_token
from app.crud.user import crud_user
from app.schemas.auth import AccessTokenResponse, LoginRequest, RefreshRequest, TokenResponse
from app.schemas.user import UserRead
router = APIRouter(prefix="/auth", tags=["Authentifizierung"])
@router.post("/login", response_model=TokenResponse)
async def login(
body: LoginRequest,
db: Annotated[AsyncSession, Depends(get_session)],
) -> TokenResponse:
user = await crud_user.authenticate(db, email=body.email, password=body.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="E-Mail oder Passwort falsch.",
)
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Benutzerkonto ist deaktiviert.",
)
tenants = await crud_user.get_tenants(db, user_id=user.id)
return TokenResponse(
access_token=create_access_token(str(user.id)),
refresh_token=create_refresh_token(str(user.id)),
user=UserRead.model_validate(user),
tenants=tenants,
)
@router.post("/refresh", response_model=AccessTokenResponse)
async def refresh_token(
body: RefreshRequest,
db: Annotated[AsyncSession, Depends(get_session)],
) -> AccessTokenResponse:
try:
payload = decode_token(body.refresh_token)
if payload.get("type") != TOKEN_TYPE_REFRESH:
raise JWTError("Falscher Token-Typ")
user_id: str = payload["sub"]
except JWTError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Ungültiger oder abgelaufener Refresh-Token.",
)
from uuid import UUID
user = await crud_user.get(db, id=UUID(user_id))
if not user or not user.is_active:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Benutzer nicht gefunden oder deaktiviert.",
)
return AccessTokenResponse(access_token=create_access_token(user_id))
@router.get("/me", response_model=UserRead)
async def get_me(current_user: CurrentUser) -> UserRead:
return UserRead.model_validate(current_user)