STABLE: Final schema sync, optimized gitignore

This commit is contained in:
Kincses
2026-02-26 08:19:25 +01:00
parent 893f39fa15
commit 505543330a
203 changed files with 11590 additions and 9542 deletions

View File

@@ -1,40 +1,123 @@
from pydantic import BaseModel, ConfigDict
from typing import Optional, Any
from datetime import datetime
# /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
# --- Pontszabályok (Point Rules) ---
class PointRuleBase(BaseModel):
rule_key: str
points: int
region_code: str = "GLOBAL"
start_date: Optional[datetime] = None
end_date: Optional[datetime] = None
is_active: bool = True
from app.api import deps
from app.models.identity import User, UserRole
from app.models.system import SystemParameter
from app.models.audit import SecurityAuditLog, OperationalLog
from app.models.security 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
class PointRuleCreate(PointRuleBase):
pass
router = APIRouter()
class PointRuleResponse(PointRuleBase):
id: int
model_config = ConfigDict(from_attributes=True)
# --- 🛡️ 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
# --- Regionális Beállítások (MOT, Tax, stb.) ---
class RegionalSettingBase(BaseModel):
region_code: str
setting_key: str
value: Any # JSON adat (pl. {"months": 24})
start_date: Optional[datetime] = None
end_date: Optional[datetime] = None
# --- 🛰️ 1. SENTINEL: RENDSZERÁLLAPOT ÉS MONITORING ---
class RegionalSettingCreate(RegionalSettingBase):
pass
@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 data.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 data.assets"))).scalar()
stats["total_organizations"] = (await db.execute(text("SELECT count(*) FROM data.organizations"))).scalar()
# --- Szintlépési Konfiguráció ---
class LevelConfigBase(BaseModel):
level_number: int
min_points: int
name_translation_key: str
region_code: str = "GLOBAL"
# 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
class LevelConfigUpdate(LevelConfigBase):
pass
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 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(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."}