# /opt/docker/dev/service_finder/backend/app/api/v1/endpoints/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 # JAVÍTVA: Központi import from app.models.system import SystemParameter # JAVÍTVA: Security audit modellek from app.models.audit import SecurityAuditLog, OperationalLog # JAVÍTVA: Ezek a modellek a security.py-ból jönnek (ha ott vannak) from app.models.security import PendingAction, ActionStatus from app.services.security_service import security_service from app.services.translation_service import TranslationService from pydantic import BaseModel class ConfigUpdate(BaseModel): key: str value: Any scope_level: str = "global" scope_id: Optional[str] = None category: str = "general" router = APIRouter() async def check_admin_access(current_user: User = Depends(deps.get_current_active_user)): """ Csak Admin vagy Superadmin. """ 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!" ) return current_user @router.get("/health-monitor", tags=["Sentinel Monitoring"]) async def get_system_health( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): stats = {} # Adatbázis statisztikák (Nyers SQL marad, mert hatékony) user_stats = await db.execute(text("SELECT subscription_plan, count(*) FROM data.users GROUP BY subscription_plan")) stats["user_distribution"] = {row[0]: row[1] for row in user_stats} asset_count = await db.execute(text("SELECT count(*) FROM data.assets")) stats["total_assets"] = asset_count.scalar() org_count = await db.execute(text("SELECT count(*) FROM data.organizations")) stats["total_organizations"] = org_count.scalar() # JAVÍTVA: Biztonsági státusz az új SecurityAuditLog alapján 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 @router.get("/pending-actions", response_model=List[Any], tags=["Sentinel Security"]) async def list_pending_actions( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): 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) ): 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)) @router.get("/parameters", tags=["Dynamic Configuration"]) async def list_all_parameters( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): 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) ): query = text(""" INSERT INTO data.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_to_json( db: AsyncSession = Depends(deps.get_db), admin: User = Depends(check_admin_access) ): await TranslationService.export_to_json(db) return {"message": "JSON fájlok frissítve."}