115 lines
4.6 KiB
Python
Executable File
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 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."} |