feat(security): extend rate limits on sync, tests, evidence and reports [FASE-3.4]

This commit is contained in:
2026-05-18 14:16:53 +02:00
parent 5b29c2fc56
commit 3e854b7b79
7 changed files with 94 additions and 9 deletions

View File

@@ -21,11 +21,13 @@ GET /tests/{id}/timeline — audit-log history for this test
import uuid
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from sqlalchemy.orm import Session
from app.database import get_db
from app.dependencies.auth import get_current_user, require_any_role
from app.dependencies.auth import get_current_user, require_any_role, require_role
from app.domain.enums import DataClassification
from app.limiter import limiter
from app.models.enums import TestState
from app.models.user import User
from app.schemas.test import (
@@ -37,6 +39,7 @@ from app.schemas.test import (
TestRedValidate,
TestBlueValidate,
TestRemediationUpdate,
TestClassificationUpdate,
)
from app.schemas.test_template import TestTemplateInstantiate
from app.domain.unit_of_work import UnitOfWork
@@ -112,7 +115,9 @@ def list_tests(
response_model=TestOut,
status_code=status.HTTP_201_CREATED,
)
@limiter.limit("30/minute")
def create_test(
request: Request,
payload: TestCreate,
db: Session = Depends(get_db),
current_user: User = Depends(require_any_role("red_lead", "blue_lead")),
@@ -152,7 +157,9 @@ def create_test(
response_model=TestOut,
status_code=status.HTTP_201_CREATED,
)
@limiter.limit("30/minute")
def create_test_from_template(
request: Request,
payload: TestTemplateInstantiate,
db: Session = Depends(get_db),
current_user: User = Depends(require_any_role("red_lead", "blue_lead")),
@@ -241,6 +248,36 @@ def update_test(
return test
# ---------------------------------------------------------------------------
# PATCH /tests/{id}/classification — admin data classification
# ---------------------------------------------------------------------------
@router.patch("/{test_id}/classification", response_model=TestOut)
def update_test_classification(
test_id: uuid.UUID,
payload: TestClassificationUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(require_role("admin")),
):
"""Update the data classification label for a test (admin only)."""
with UnitOfWork(db) as uow:
test = crud_get_test_or_raise(db, test_id)
test.data_classification = payload.data_classification.value
db.flush()
log_action(
db,
user_id=current_user.id,
action="update_test_classification",
entity_type="test",
entity_id=test.id,
details={"data_classification": payload.data_classification.value},
)
uow.commit()
db.refresh(test)
return test
# ---------------------------------------------------------------------------
# PATCH /tests/{id}/red — Red Team update (draft, red_executing)
# ---------------------------------------------------------------------------