feat(sdk): API-Referenz Frontend + Backend-Konsolidierung (Shared Utilities, CRUD Factory)
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 18s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 18s
- API-Referenz Seite (/sdk/api-docs) mit ~690 Endpoints, Suche, Filter, Modul-Index - Shared db_utils.py (row_to_dict) + tenant_utils Integration in 6 Route-Dateien - CRUD Factory (crud_factory.py) fuer zukuenftige Module - Version-Route Auto-Registration in versioning_utils.py - 1338 Tests bestanden, -232 Zeilen Duplikat-Code Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,9 +11,10 @@ from compliance.api.escalation_routes import (
|
||||
EscalationCreate,
|
||||
EscalationUpdate,
|
||||
EscalationStatusUpdate,
|
||||
_row_to_dict,
|
||||
DEFAULT_TENANT_ID,
|
||||
)
|
||||
from compliance.api.db_utils import row_to_dict as _row_to_dict
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
|
||||
from classroom_engine.database import get_db
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ from fastapi import FastAPI
|
||||
from compliance.api.legal_template_routes import (
|
||||
LegalTemplateCreate,
|
||||
LegalTemplateUpdate,
|
||||
_row_to_dict,
|
||||
_get_tenant_id,
|
||||
DEFAULT_TENANT_ID,
|
||||
VALID_DOCUMENT_TYPES,
|
||||
VALID_STATUSES,
|
||||
router,
|
||||
)
|
||||
from compliance.api.db_utils import row_to_dict as _row_to_dict
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
from classroom_engine.database import get_db
|
||||
|
||||
app = FastAPI()
|
||||
@@ -205,22 +205,6 @@ class TestLegalTemplateDB:
|
||||
assert isinstance(result["placeholders"], list)
|
||||
assert "{{COMPANY_NAME}}" in result["placeholders"]
|
||||
|
||||
def test_get_tenant_id_default(self):
|
||||
"""_get_tenant_id returns default when no header provided."""
|
||||
result = _get_tenant_id(None)
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_get_tenant_id_valid_uuid(self):
|
||||
"""_get_tenant_id returns provided UUID when valid."""
|
||||
custom_uuid = "12345678-1234-1234-1234-123456789abc"
|
||||
result = _get_tenant_id(custom_uuid)
|
||||
assert result == custom_uuid
|
||||
|
||||
def test_get_tenant_id_invalid_uuid(self):
|
||||
"""_get_tenant_id falls back to default for invalid UUID."""
|
||||
result = _get_tenant_id("not-a-uuid")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# TestLegalTemplateSearch
|
||||
|
||||
@@ -10,12 +10,12 @@ from compliance.api.loeschfristen_routes import (
|
||||
LoeschfristCreate,
|
||||
LoeschfristUpdate,
|
||||
StatusUpdate,
|
||||
_row_to_dict,
|
||||
_get_tenant_id,
|
||||
DEFAULT_TENANT_ID,
|
||||
JSONB_FIELDS,
|
||||
router,
|
||||
)
|
||||
from compliance.api.db_utils import row_to_dict as _row_to_dict
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
@@ -128,16 +128,6 @@ class TestRowToDict:
|
||||
assert result["retention_duration"] == 7
|
||||
|
||||
|
||||
class TestGetTenantId:
|
||||
def test_valid_uuid_is_returned(self):
|
||||
assert _get_tenant_id("9282a473-5c95-4b3a-bf78-0ecc0ec71d3e") == "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
|
||||
def test_invalid_uuid_returns_default(self):
|
||||
assert _get_tenant_id("not-a-uuid") == DEFAULT_TENANT_ID
|
||||
|
||||
def test_none_returns_default(self):
|
||||
assert _get_tenant_id(None) == DEFAULT_TENANT_ID
|
||||
|
||||
|
||||
class TestJsonbFields:
|
||||
def test_jsonb_fields_set(self):
|
||||
|
||||
@@ -12,10 +12,10 @@ from compliance.api.obligation_routes import (
|
||||
ObligationCreate,
|
||||
ObligationUpdate,
|
||||
ObligationStatusUpdate,
|
||||
_row_to_dict,
|
||||
_get_tenant_id,
|
||||
DEFAULT_TENANT_ID,
|
||||
)
|
||||
from compliance.api.db_utils import row_to_dict as _row_to_dict
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
from classroom_engine.database import get_db
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -308,37 +308,6 @@ class TestRowToDict:
|
||||
assert result["flag"] is False
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Helper Tests — _get_tenant_id
|
||||
# =============================================================================
|
||||
|
||||
class TestGetTenantId:
|
||||
def test_valid_uuid_returned(self):
|
||||
tenant_id = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
result = _get_tenant_id(x_tenant_id=tenant_id)
|
||||
assert result == tenant_id
|
||||
|
||||
def test_different_valid_uuid(self):
|
||||
tenant_id = "12345678-1234-1234-1234-123456789abc"
|
||||
result = _get_tenant_id(x_tenant_id=tenant_id)
|
||||
assert result == tenant_id
|
||||
|
||||
def test_none_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id=None)
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_invalid_uuid_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="not-a-valid-uuid")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_empty_string_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_partial_uuid_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="9282a473-5c95-4b3a")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Business Logic Tests
|
||||
|
||||
@@ -18,10 +18,10 @@ from compliance.api.quality_routes import (
|
||||
MetricUpdate,
|
||||
TestCreate,
|
||||
TestUpdate,
|
||||
_row_to_dict,
|
||||
_get_tenant_id,
|
||||
DEFAULT_TENANT_ID,
|
||||
)
|
||||
from compliance.api.db_utils import row_to_dict as _row_to_dict
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
from classroom_engine.database import get_db
|
||||
|
||||
# =============================================================================
|
||||
@@ -283,31 +283,6 @@ class TestRowToDict:
|
||||
assert result["count"] == 10
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Helper Tests — _get_tenant_id
|
||||
# =============================================================================
|
||||
|
||||
class TestGetTenantId:
|
||||
def test_valid_uuid_returned(self):
|
||||
result = _get_tenant_id(x_tenant_id=DEFAULT_TENANT)
|
||||
assert result == DEFAULT_TENANT
|
||||
|
||||
def test_none_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id=None)
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_invalid_uuid_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="invalid-uuid")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_empty_string_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_other_valid_tenant(self):
|
||||
result = _get_tenant_id(x_tenant_id=OTHER_TENANT)
|
||||
assert result == OTHER_TENANT
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# HTTP Tests — GET /quality/stats
|
||||
@@ -910,19 +885,12 @@ class TestTenantIsolation:
|
||||
resp_b = client.get("/quality/tests", headers={"X-Tenant-Id": OTHER_TENANT})
|
||||
assert resp_b.json()["total"] == 0
|
||||
|
||||
def test_invalid_tenant_header_falls_back_to_default(self, mock_db):
|
||||
count_row = MagicMock()
|
||||
count_row.__getitem__ = lambda self, i: 0
|
||||
execute_result = MagicMock()
|
||||
execute_result.fetchone.return_value = count_row
|
||||
execute_result.fetchall.return_value = []
|
||||
mock_db.execute.return_value = execute_result
|
||||
|
||||
def test_invalid_tenant_header_returns_400(self, mock_db):
|
||||
response = client.get(
|
||||
"/quality/metrics",
|
||||
headers={"X-Tenant-Id": "bad-uuid"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_delete_wrong_tenant_returns_404(self, mock_db):
|
||||
"""Deleting a metric that belongs to a different tenant returns 404."""
|
||||
|
||||
@@ -16,10 +16,10 @@ from compliance.api.security_backlog_routes import (
|
||||
router,
|
||||
SecurityItemCreate,
|
||||
SecurityItemUpdate,
|
||||
_row_to_dict,
|
||||
_get_tenant_id,
|
||||
DEFAULT_TENANT_ID,
|
||||
)
|
||||
from compliance.api.db_utils import row_to_dict as _row_to_dict
|
||||
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
from classroom_engine.database import get_db
|
||||
|
||||
# =============================================================================
|
||||
@@ -241,35 +241,6 @@ class TestRowToDict:
|
||||
assert result["active"] is True
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Helper Tests — _get_tenant_id
|
||||
# =============================================================================
|
||||
|
||||
class TestGetTenantId:
|
||||
def test_valid_uuid_returned(self):
|
||||
result = _get_tenant_id(x_tenant_id=DEFAULT_TENANT)
|
||||
assert result == DEFAULT_TENANT
|
||||
|
||||
def test_none_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id=None)
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_invalid_uuid_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="not-a-uuid")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_empty_string_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
def test_different_valid_tenant(self):
|
||||
result = _get_tenant_id(x_tenant_id=OTHER_TENANT)
|
||||
assert result == OTHER_TENANT
|
||||
|
||||
def test_partial_uuid_returns_default(self):
|
||||
result = _get_tenant_id(x_tenant_id="9282a473-5c95-4b3a")
|
||||
assert result == DEFAULT_TENANT_ID
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# HTTP Tests — GET /security-backlog
|
||||
@@ -657,21 +628,12 @@ class TestTenantIsolation:
|
||||
assert resp_b.status_code == 200
|
||||
assert resp_b.json()["total"] == 0
|
||||
|
||||
def test_invalid_tenant_header_falls_back_to_default(self, mock_db):
|
||||
count_row = MagicMock()
|
||||
count_row.__getitem__ = lambda self, i: 0
|
||||
execute_result = MagicMock()
|
||||
execute_result.fetchone.return_value = count_row
|
||||
execute_result.fetchall.return_value = []
|
||||
mock_db.execute.return_value = execute_result
|
||||
|
||||
def test_invalid_tenant_header_returns_400(self, mock_db):
|
||||
response = client.get(
|
||||
"/security-backlog",
|
||||
headers={"X-Tenant-Id": "not-a-real-uuid"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
# Should succeed (falls back to DEFAULT_TENANT_ID)
|
||||
assert "items" in response.json()
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_create_uses_tenant_from_header(self, mock_db):
|
||||
created_row = make_item_row({"tenant_id": OTHER_TENANT})
|
||||
|
||||
Reference in New Issue
Block a user