feat(security): extend rate limits on sync, tests, evidence and reports [FASE-3.4]
This commit is contained in:
@@ -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)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user