feat(auth): one-time login links, JWT + refresh, roles, service token, tests

This commit is contained in:
apuc committed 2026-09-26 19:52:32 +03:00
1 parent 4a610ba94a
commit 049b679654
12 files changed
+553 -1

No files matched your search

+60
View File
@@ -0,0 +1,60 @@
"""Эндпоинты аутентификации."""
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session as DBSession
from app.api.deps import get_current_session, get_current_user, require_roles
from app.db.session import get_db
from app.models.enums import RoleCode
from app.models.user import User
from app.models.user import Session as UserSession
from app.schemas.auth import (
LoginRequest,
LoginResponse,
LoginTokenCreate,
LoginTokenOut,
RefreshRequest,
TokenPair,
UserOut,
)
from app.services import auth as auth_service
router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/login-token", response_model=LoginTokenOut, status_code=201)
def create_login_token(
data: LoginTokenCreate,
user: User = Depends(require_roles(RoleCode.COORDINATOR, RoleCode.ADMIN)),
db: DBSession = Depends(get_db),
) -> LoginTokenOut:
lt, url = auth_service.create_login_token(db, data, issued_by=user.id)
return LoginTokenOut(id=lt.id, url=url, expires_at=lt.expires_at)
@router.post("/login", response_model=LoginResponse)
def login(data: LoginRequest, db: DBSession = Depends(get_db)) -> LoginResponse:
tokens, user = auth_service.login(db, data)
return LoginResponse(
**tokens.model_dump(), user=auth_service.build_user_out(db, user)
)
@router.post("/refresh", response_model=TokenPair)
def refresh(data: RefreshRequest, db: DBSession = Depends(get_db)) -> TokenPair:
return auth_service.refresh(db, data.refresh_token)
@router.post("/logout", status_code=204)
def logout(
session: UserSession = Depends(get_current_session),
db: DBSession = Depends(get_db),
) -> None:
auth_service.logout(db, session.id)
@router.get("/me", response_model=UserOut)
def me(
user: User = Depends(get_current_user),
db: DBSession = Depends(get_db),
) -> UserOut:
return auth_service.build_user_out(db, user)
+2 -1
View File
@@ -1,7 +1,8 @@
"""Корневой роутер API v1."""
from fastapi import APIRouter
from app.api.v1 import health
from app.api.v1 import auth, health
api_router = APIRouter()
api_router.include_router(health.router, tags=["system"])
api_router.include_router(auth.router)