# /opt/docker/dev/service_finder/backend/app/schemas/admin.py from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func, text, delete from typing import List, Any, Dict, Optional from datetime import datetime, timedelta from app.api import deps from app.models.identity import User, UserRole from app.models.system import SystemParameter from app.models import SecurityAuditLog, OperationalLog from app.models import PendingAction, ActionStatus from app.services.security_service import security_service from app.services.translation_service import TranslationService from app.schemas.admin import PointRuleResponse, LevelConfigResponse, ConfigUpdate from app.schemas.admin_security import PendingActionResponse, SecurityStatusResponse router = APIRouter() # --- 🛡️ ADMIN JOGOSULTSÁG ELLENŐRZŐ --- async def check_admin_access(current_user: User = Depends(deps.get_current_active_user)): """ Csak Admin vagy Superadmin léphet be a Sentinel központba. """ if current_user.role not in [UserRole.admin, UserRole.superadmin]: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Sentinel jogosultság szükséges a művelethez!" ) return current_user # --- 🛰️ 1. SENTINEL: RENDSZERÁLLAPOT ÉS MONITORING --- @router.get("/health-monitor", response_model=Dict[str, Any], tags=["Sentinel Monitoring"]) async def get_system_health( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): """ Részletes rendszerstatisztikák (Felhasználók, Eszközök, Biztonság). """ stats = {} # Felhasználói eloszlás (Nyers SQL a sebességért) user_res = await db.execute(text("SELECT subscription_plan, count(*) FROM identity.users GROUP BY subscription_plan")) stats["user_distribution"] = {row[0]: row[1] for row in user_res} # Eszköz és Szervezet számlálók stats["total_assets"] = (await db.execute(text("SELECT count(*) FROM vehicle.assets"))).scalar() stats["total_organizations"] = (await db.execute(text("SELECT count(*) FROM fleet.organizations"))).scalar() # Biztonsági riasztások (Kritikus logok az elmúlt 24 órában) day_ago = datetime.now() - timedelta(days=1) crit_logs = await db.execute( select(func.count(SecurityAuditLog.id)) .where(SecurityAuditLog.is_critical == True, SecurityAuditLog.created_at >= day_ago) ) stats["critical_alerts_24h"] = crit_logs.scalar() or 0 return stats # --- ⚖️ 2. SENTINEL: NÉGY SZEM ELV (Approval System) --- @router.get("/pending-actions", response_model=List[PendingActionResponse], tags=["Sentinel Security"]) async def list_pending_actions( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): """ Jóváhagyásra váró kritikus műveletek 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}", tags=["Sentinel Security"]) 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 egy 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=status.HTTP_400_BAD_REQUEST, detail=str(e)) # --- ⚙️ 3. DINAMIKUS KONFIGURÁCIÓ (System Parameters) --- @router.get("/parameters", tags=["Dynamic Configuration"]) async def list_all_parameters( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): """ Globális és lokális paraméterek (Limitek, XP szorzók) lekérése. """ result = await db.execute(select(SystemParameter)) return result.scalars().all() @router.post("/parameters", tags=["Dynamic Configuration"]) async def set_parameter( config: ConfigUpdate, db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): """ Paraméter beállítása vagy frissítése hierarchikus scope-al. """ query = text(""" INSERT INTO system.system_parameters (key, value, scope_level, scope_id, category, last_modified_by) VALUES (:key, :val, :sl, :sid, :cat, :user) ON CONFLICT (key, scope_level, scope_id) DO UPDATE SET value = EXCLUDED.value, category = EXCLUDED.category, last_modified_by = EXCLUDED.last_modified_by, updated_at = now() """) await db.execute(query, { "key": config.key, "val": config.value, "sl": config.scope_level, "sid": config.scope_id, "cat": config.category, "user": admin.email }) await db.commit() return {"status": "success", "message": f"'{config.key}' frissítve."} @router.post("/translations/sync", tags=["System Utilities"]) async def sync_translations(db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access)): """ DB fordítások exportálása JSON fájlokba a frontendnek. """ await TranslationService.export_to_json(db) return {"message": "Nyelvi fájlok frissítve."}