refactor(d3): ARCH-051 — 14 dict-body-Routes auf Pydantic-Schemas umgestellt (entity_permissions bulk ×2, guests invite, users menu-order, system_settings backup-config+dsar, knowledge ×3, self_improvement ×5); DSAR-Export F821-Bug behoben (datetime/timezone undefined → NameError beim GDPR-Export), Zeitstempel auf datetime.now(UTC); Validierung jetzt im Schema statt in Routen
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
This commit is contained in:
@@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.db import get_db
|
||||
@@ -18,6 +19,25 @@ from app.services import bulk_permission_service, entity_permission_service
|
||||
|
||||
router = APIRouter(prefix="/api/v1/permissions", tags=["entity-permissions"])
|
||||
|
||||
|
||||
class BulkShareRequest(BaseModel):
|
||||
"""Bulk-share multiple entities with a principal."""
|
||||
|
||||
entity_type: str = Field(..., min_length=1)
|
||||
entity_ids: list[str] = Field(..., min_length=1)
|
||||
principal_type: str = Field(..., pattern="^(user|group|guest)$")
|
||||
principal_id: str = Field(..., min_length=1)
|
||||
level: str = Field(..., pattern="^(read|write|admin|delete|owner)$")
|
||||
|
||||
|
||||
class BulkUnshareRequest(BaseModel):
|
||||
"""Bulk-remove permissions for a principal from multiple entities."""
|
||||
|
||||
entity_type: str = Field(..., min_length=1)
|
||||
entity_ids: list[str] = Field(..., min_length=1)
|
||||
principal_type: str = Field(..., pattern="^(user|group|guest)$")
|
||||
principal_id: str = Field(..., min_length=1)
|
||||
|
||||
# Rate limits for permission changes (prevent abuse/DoS)
|
||||
_PERM_RATE_LIMIT_MAX = 50 # max changes per minute
|
||||
_PERM_RATE_LIMIT_WINDOW = 60 # 60 seconds
|
||||
@@ -279,7 +299,7 @@ async def list_entity_registry(
|
||||
|
||||
@router.post("/bulk", status_code=status.HTTP_201_CREATED)
|
||||
async def bulk_share_permissions(
|
||||
body: dict,
|
||||
body: BulkShareRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: dict = Depends(require_permission("settings:write")),
|
||||
):
|
||||
@@ -290,11 +310,11 @@ async def bulk_share_permissions(
|
||||
result = await bulk_permission_service.bulk_share(
|
||||
db,
|
||||
tenant_id,
|
||||
body["entity_type"],
|
||||
body["entity_ids"],
|
||||
body["principal_type"],
|
||||
body["principal_id"],
|
||||
body["level"],
|
||||
body.entity_type,
|
||||
body.entity_ids,
|
||||
body.principal_type,
|
||||
body.principal_id,
|
||||
body.level,
|
||||
created_by=user_id,
|
||||
)
|
||||
return result
|
||||
@@ -304,7 +324,7 @@ async def bulk_share_permissions(
|
||||
|
||||
@router.post("/bulk/unshare", status_code=status.HTTP_200_OK)
|
||||
async def bulk_unshare_permissions(
|
||||
body: dict,
|
||||
body: BulkUnshareRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: dict = Depends(require_permission("settings:write")),
|
||||
):
|
||||
@@ -314,10 +334,10 @@ async def bulk_unshare_permissions(
|
||||
result = await bulk_permission_service.bulk_unshare(
|
||||
db,
|
||||
tenant_id,
|
||||
body["entity_type"],
|
||||
body["entity_ids"],
|
||||
body["principal_type"],
|
||||
body["principal_id"],
|
||||
body.entity_type,
|
||||
body.entity_ids,
|
||||
body.principal_type,
|
||||
body.principal_id,
|
||||
)
|
||||
return result
|
||||
except (ValueError, KeyError) as e:
|
||||
|
||||
Reference in New Issue
Block a user