Files
service-finder/backend/app/api/v1/endpoints/admin.py
Kincses 425f598fa3 feat: SuperAdmin bootstrap, i18n sync fix and AssetAssignment ORM fix
- Fixed AttributeError in User model (added region_code, preferred_language)
- Fixed InvalidRequestError in AssetAssignment (added organization relationship)
- Configured STATIC_DIR for translation sync
- Applied Alembic migrations for user schema updates
2026-02-10 21:01:58 +00:00

115 lines
4.6 KiB
Python
Executable File

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from typing import List, Any, Dict
from datetime import datetime, timedelta
from app.api import deps
from app.models.identity import User, UserRole
from app.models.system_config import SystemParameter
from app.models.security import PendingAction, ActionStatus
from app.models.history import AuditLog, LogSeverity
from app.schemas.admin_security import PendingActionResponse, SecurityStatusResponse
from app.services.security_service import security_service
# Feltételezve, hogy a JSON-alapú TranslationService-ed már készen van
from app.services.translation_service import TranslationService
router = APIRouter()
# --- 🛡️ ADMIN JOGOSULTSÁG ELLENŐRZŐ ---
async def check_admin_access(current_user: User = Depends(deps.get_current_active_user)):
if current_user.role not in [UserRole.admin, UserRole.superadmin]:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Admin jogosultság szükséges!"
)
return current_user
# --- 1. SENTINEL: NÉGY SZEM ELV (Approval System) ---
@router.get("/pending-actions", response_model=List[PendingActionResponse])
async def list_pending_actions(
db: AsyncSession = Depends(deps.get_db),
admin: User = Depends(check_admin_access)
):
"""Jóváhagyásra váró kritikus kérések listázása."""
stmt = select(PendingAction).where(PendingAction.status == ActionStatus.pending)
result = await db.execute(stmt)
return result.scalars().all()
@router.post("/approve/{action_id}")
async def approve_action(
action_id: int,
db: AsyncSession = Depends(deps.get_db),
admin: User = Depends(check_admin_access)
):
"""Művelet véglegesítése (második admin által)."""
try:
await security_service.approve_action(db, admin.id, action_id)
return {"status": "success", "message": "Művelet végrehajtva."}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
# --- 2. SENTINEL: BIZTONSÁGI ÖSSZEGZÉS ---
@router.get("/security-status", response_model=SecurityStatusResponse)
async def get_security_status(
db: AsyncSession = Depends(deps.get_db),
admin: User = Depends(check_admin_access)
):
"""Rendszerállapot: Zárolt júzerek és kritikus események."""
day_ago = datetime.now() - timedelta(days=1)
crit_count = (await db.execute(select(func.count(AuditLog.id)).where(
AuditLog.severity.in_([LogSeverity.critical, LogSeverity.emergency]),
AuditLog.timestamp >= day_ago
))).scalar() or 0
locked_count = (await db.execute(select(func.count(User.id)).where(
User.is_active == False, User.is_deleted == False
))).scalar() or 0
return {
"total_pending": (await db.execute(select(func.count(PendingAction.id)).where(PendingAction.status == ActionStatus.pending))).scalar() or 0,
"critical_logs_last_24h": crit_count,
"emergency_locks_active": locked_count
}
# --- 3. RENDSZERBEÁLLÍTÁSOK (Dynamic Config) ---
@router.get("/settings")
async def get_settings(db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access)):
"""Minden globális paraméter (Gamification, Limitek stb.) lekérése."""
result = await db.execute(select(SystemParameter))
return result.scalars().all()
@router.put("/settings/{key}")
async def update_setting(key: str, value: Any, db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access)):
"""Paraméter módosítása és Audit Log generálása."""
stmt = select(SystemParameter).where(SystemParameter.key == key)
param = (await db.execute(stmt)).scalar_one_or_none()
if not param:
raise HTTPException(status_code=404, detail="Nincs ilyen beállítás.")
old_val = param.value
param.value = value
await security_service.log_event(
db, admin.id, action="SETTING_CHANGE", severity=LogSeverity.warning,
old_data={key: old_val}, new_data={key: value}
)
await db.commit()
return {"status": "success", "key": key, "new_value": value}
# --- 🌍 JSON FORDÍTÁSOK KEZELÉSE ---
@router.post("/translations/sync")
async def sync_translations_to_json(
db: AsyncSession = Depends(deps.get_db),
admin: User = Depends(check_admin_access)
):
"""Szinkronizálja az adatbázisban tárolt fordításokat a JSON fájlokba."""
# A TranslationService-ben kell megírni a fájlbaíró logikát
await TranslationService.export_to_json(db)
return {"message": "JSON nyelvi fájlok frissítve."}