This commit is contained in:
Mikan
2026-06-20 19:13:05 +03:00
parent 32575e217e
commit 8514c63ec6
193 changed files with 22105 additions and 11660 deletions

64
app/api/deps.py Normal file
View File

@@ -0,0 +1,64 @@
"""Shared API dependencies: current user, admin guard, db session, settings."""
from __future__ import annotations
import uuid
from typing import Any
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.security import decode_token
from app.core.settings_service import get_all_settings
from app.db import get_db
from app.models import User
_bearer = HTTPBearer(auto_error=False)
async def get_current_user(
creds: HTTPAuthorizationCredentials | None = Depends(_bearer),
db: AsyncSession = Depends(get_db),
) -> User:
"""Resolve the JWT bearer token to a User row.
Raises 401 on missing/invalid/expired token.
"""
if creds is None or creds.scheme.lower() != "bearer":
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Missing bearer token")
try:
payload = decode_token(creds.credentials)
except Exception as e: # noqa: BLE001
raise HTTPException(status.HTTP_401_UNAUTHORIZED, f"Invalid token: {e}")
if payload.get("type") != "access":
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Wrong token type")
user_id_str = payload.get("sub")
if not user_id_str:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Token missing sub")
try:
user_id = uuid.UUID(user_id_str)
except ValueError:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid user id in token")
user = (
await db.execute(select(User).where(User.id == user_id))
).scalar_one_or_none()
if user is None:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "User not found")
if not user.is_active:
raise HTTPException(status.HTTP_403_FORBIDDEN, "Account disabled")
return user
async def require_admin(user: User = Depends(get_current_user)) -> User:
"""Require an admin user."""
if not user.is_admin:
raise HTTPException(status.HTTP_403_FORBIDDEN, "Admin only")
return user
async def get_settings_dict(db: AsyncSession = Depends(get_db)) -> dict[str, Any]:
"""FastAPI dependency: returns the full settings dict."""
return await get_all_settings(db)