Files
2026-03-22 11:02:05 +00:00

123 lines
5.3 KiB
Python
Executable File

# /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."}