amazon-transcreation/backend/app/auth/router.py
DJP 5ef7e588b6 feat: wire analytics to real data and add audit logging across all endpoints
Replace mock chart data on reports page with real backend queries (jobs over
time, locale stats, usage stats, quality metrics). Add audit logging to auth
(login/login_failed), file management (upload/delete TM and reference files),
and feedback submission so the system logs page shows complete activity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 17:17:14 -04:00

63 lines
2.3 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Request, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth.schemas import LoginRequest, RefreshRequest, TokenResponse, UserClaims
from app.auth.service import AuthService
from app.dependencies import get_current_user, get_db
from app.services.audit_service import AuditService
router = APIRouter(prefix="/auth", tags=["auth"])
auth_service = AuthService()
audit_service = AuditService()
@router.post("/login", response_model=TokenResponse)
async def login(
body: LoginRequest,
request: Request,
db: AsyncSession = Depends(get_db),
) -> TokenResponse:
"""Authenticate user and return access + refresh tokens."""
result = await auth_service.login(body.email, body.password, db)
if result is None:
await audit_service.log(
db, action="login_failed", entity_type="user", entity_id=body.email,
details={"reason": "Invalid credentials"},
ip_address=request.client.host if request.client else None,
)
await db.commit()
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid email or password",
)
# Extract user_id from the access token claims
claims = auth_service.validate_token(result["access_token"])
user_id = claims["sub"] if claims else body.email
await audit_service.log(
db, action="login", entity_type="user", entity_id=str(user_id),
user_id=user_id if claims else None,
details={"email": body.email},
ip_address=request.client.host if request.client else None,
)
await db.commit()
return TokenResponse(**result)
@router.post("/refresh", response_model=TokenResponse)
async def refresh_token(body: RefreshRequest) -> TokenResponse:
"""Exchange a valid refresh token for a new token pair."""
result = auth_service.refresh_tokens(body.refresh_token)
if result is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired refresh token",
)
return TokenResponse(**result)
@router.get("/me", response_model=UserClaims)
async def get_me(
current_user: dict = Depends(get_current_user),
) -> UserClaims:
"""Return the current authenticated user's claims."""
return UserClaims(**current_user)