Epic 3: Economy & Billing Engine (Pénzügyi Motor)
This commit is contained in:
173
backend/app/api/v1/endpoints/security.py
Normal file
173
backend/app/api/v1/endpoints/security.py
Normal file
@@ -0,0 +1,173 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/api/v1/endpoints/security.py
|
||||
"""
|
||||
Dual Control (Négy szem elv) API végpontok.
|
||||
Kiemelt műveletek jóváhagyási folyamata.
|
||||
"""
|
||||
import logging
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_db, get_current_user
|
||||
from app.models.identity import User, UserRole
|
||||
from app.services.security_service import security_service
|
||||
from app.schemas.security import (
|
||||
PendingActionCreate, PendingActionResponse, PendingActionApprove, PendingActionReject
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/request", response_model=PendingActionResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def request_action(
|
||||
request: PendingActionCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Dual Control: Jóváhagyási kérelem indítása kiemelt művelethez.
|
||||
|
||||
Engedélyezett művelettípusok:
|
||||
- CHANGE_ROLE: Felhasználó szerepkörének módosítása
|
||||
- SET_VIP: VIP státusz beállítása
|
||||
- WALLET_ADJUST: Pénztár egyenleg módosítása (nagy összeg)
|
||||
- SOFT_DELETE_USER: Felhasználó soft delete
|
||||
- ORGANIZATION_TRANSFER: Szervezet tulajdonjog átadása
|
||||
"""
|
||||
# Csak admin és superadmin kezdeményezhet kiemelt műveleteket
|
||||
if current_user.role not in [UserRole.admin, UserRole.superadmin]:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Csak adminisztrátorok kezdeményezhetnek Dual Control műveleteket."
|
||||
)
|
||||
|
||||
try:
|
||||
action = await security_service.request_action(
|
||||
db, requester_id=current_user.id,
|
||||
action_type=request.action_type,
|
||||
payload=request.payload,
|
||||
reason=request.reason
|
||||
)
|
||||
return PendingActionResponse.from_orm(action)
|
||||
except Exception as e:
|
||||
logger.error(f"Dual Control request error: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Hiba a kérelem létrehozásakor: {str(e)}"
|
||||
)
|
||||
|
||||
@router.get("/pending", response_model=List[PendingActionResponse])
|
||||
async def list_pending_actions(
|
||||
action_type: Optional[str] = None,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Függőben lévő Dual Control műveletek listázása.
|
||||
|
||||
Admin és superadmin látja az összes függőben lévő műveletet.
|
||||
Egyéb felhasználók csak a sajátjaikat láthatják.
|
||||
"""
|
||||
if current_user.role in [UserRole.admin, UserRole.superadmin]:
|
||||
user_id = None
|
||||
else:
|
||||
user_id = current_user.id
|
||||
|
||||
actions = await security_service.get_pending_actions(db, user_id=user_id, action_type=action_type)
|
||||
return [PendingActionResponse.from_orm(action) for action in actions]
|
||||
|
||||
@router.post("/approve/{action_id}", response_model=PendingActionResponse)
|
||||
async def approve_action(
|
||||
action_id: int,
|
||||
approve_data: PendingActionApprove,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Dual Control: Művelet jóváhagyása.
|
||||
|
||||
Csak admin/superadmin hagyhat jóvá, és nem lehet a saját kérése.
|
||||
"""
|
||||
if current_user.role not in [UserRole.admin, UserRole.superadmin]:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Csak adminisztrátorok hagyhatnak jóvá műveleteket."
|
||||
)
|
||||
|
||||
try:
|
||||
await security_service.approve_action(db, approver_id=current_user.id, action_id=action_id)
|
||||
# Frissített művelet lekérdezése
|
||||
from sqlalchemy import select
|
||||
from app.models.security import PendingAction
|
||||
stmt = select(PendingAction).where(PendingAction.id == action_id)
|
||||
action = (await db.execute(stmt)).scalar_one()
|
||||
return PendingActionResponse.from_orm(action)
|
||||
except Exception as e:
|
||||
logger.error(f"Dual Control approve error: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e)
|
||||
)
|
||||
|
||||
@router.post("/reject/{action_id}", response_model=PendingActionResponse)
|
||||
async def reject_action(
|
||||
action_id: int,
|
||||
reject_data: PendingActionReject,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Dual Control: Művelet elutasítása.
|
||||
|
||||
Csak admin/superadmin utasíthat el, és nem lehet a saját kérése.
|
||||
"""
|
||||
if current_user.role not in [UserRole.admin, UserRole.superadmin]:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Csak adminisztrátorok utasíthatnak el műveleteket."
|
||||
)
|
||||
|
||||
try:
|
||||
await security_service.reject_action(
|
||||
db, approver_id=current_user.id,
|
||||
action_id=action_id, reason=reject_data.reason
|
||||
)
|
||||
# Frissített művelet lekérdezése
|
||||
from sqlalchemy import select
|
||||
from app.models.security import PendingAction
|
||||
stmt = select(PendingAction).where(PendingAction.id == action_id)
|
||||
action = (await db.execute(stmt)).scalar_one()
|
||||
return PendingActionResponse.from_orm(action)
|
||||
except Exception as e:
|
||||
logger.error(f"Dual Control reject error: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e)
|
||||
)
|
||||
|
||||
@router.get("/{action_id}", response_model=PendingActionResponse)
|
||||
async def get_action(
|
||||
action_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Egy konkrét Dual Control művelet lekérdezése.
|
||||
|
||||
Csak a művelet létrehozója vagy admin/superadmin érheti el.
|
||||
"""
|
||||
from sqlalchemy import select
|
||||
from app.models.security import PendingAction
|
||||
stmt = select(PendingAction).where(PendingAction.id == action_id)
|
||||
action = (await db.execute(stmt)).scalar_one_or_none()
|
||||
if not action:
|
||||
raise HTTPException(status_code=404, detail="Művelet nem található.")
|
||||
|
||||
if current_user.role not in [UserRole.admin, UserRole.superadmin] and action.requester_id != current_user.id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Nincs jogosultságod ehhez a művelethez."
|
||||
)
|
||||
|
||||
return PendingActionResponse.from_orm(action)
|
||||
Reference in New Issue
Block a user