Harden auth and security controls with session auth and docs

This commit is contained in:
2026-03-01 15:29:09 -03:00
parent 7a19f22f41
commit 0242e061c2
36 changed files with 1794 additions and 505 deletions

View File

@@ -272,10 +272,10 @@ if "app.services.routing_pipeline" not in sys.modules:
sys.modules["app.services.routing_pipeline"] = routing_pipeline_stub
from fastapi import HTTPException
from fastapi.security import HTTPAuthorizationCredentials
from app.api.auth import AuthRole, get_request_role, require_admin
from app.api.auth import AuthContext, require_admin
from app.core import config as config_module
from app.models.auth import UserRole
from app.models.processing_log import sanitize_processing_log_payload_value, sanitize_processing_log_text
from app.schemas.processing_logs import ProcessingLogEntryResponse
from app.services import extractor as extractor_module
@@ -298,52 +298,34 @@ def _security_settings(
class AuthDependencyTests(unittest.TestCase):
"""Verifies token authentication and admin authorization behavior."""
def test_get_request_role_accepts_admin_token(self) -> None:
"""Admin token resolves admin role."""
settings = SimpleNamespace(
admin_api_token="admin-token",
user_api_token="user-token",
allow_development_anonymous_user_access=False,
app_env="production",
)
credentials = HTTPAuthorizationCredentials(scheme="Bearer", credentials="admin-token")
role = get_request_role(credentials=credentials, settings=settings)
self.assertEqual(role, AuthRole.ADMIN)
def test_get_request_role_rejects_missing_credentials(self) -> None:
"""Missing bearer credentials return 401."""
settings = SimpleNamespace(
admin_api_token="admin-token",
user_api_token="user-token",
allow_development_anonymous_user_access=False,
app_env="production",
)
with self.assertRaises(HTTPException) as context:
get_request_role(credentials=None, settings=settings)
self.assertEqual(context.exception.status_code, 401)
def test_get_request_role_allows_tokenless_user_access_in_development(self) -> None:
"""Development mode can allow tokenless user role for compatibility."""
settings = SimpleNamespace(
admin_api_token="admin-token",
user_api_token="user-token",
allow_development_anonymous_user_access=True,
app_env="development",
)
role = get_request_role(credentials=None, settings=settings)
self.assertEqual(role, AuthRole.USER)
"""Verifies role-based admin authorization behavior."""
def test_require_admin_rejects_user_role(self) -> None:
"""User role cannot access admin-only endpoints."""
with self.assertRaises(HTTPException) as context:
require_admin(role=AuthRole.USER)
self.assertEqual(context.exception.status_code, 403)
auth_context = AuthContext(
user_id=uuid.uuid4(),
username="user",
role=UserRole.USER,
session_id=uuid.uuid4(),
expires_at=datetime.now(UTC),
)
with self.assertRaises(HTTPException) as raised:
require_admin(context=auth_context)
self.assertEqual(raised.exception.status_code, 403)
def test_require_admin_accepts_admin_role(self) -> None:
"""Admin role is accepted for admin-only endpoints."""
auth_context = AuthContext(
user_id=uuid.uuid4(),
username="admin",
role=UserRole.ADMIN,
session_id=uuid.uuid4(),
expires_at=datetime.now(UTC),
)
resolved = require_admin(context=auth_context)
self.assertEqual(resolved.role, UserRole.ADMIN)
class ProviderBaseUrlValidationTests(unittest.TestCase):
@@ -559,6 +541,7 @@ class ArchiveLineagePropagationTests(unittest.TestCase):
source_relative_path="uploads/root.zip",
logical_path="Inbox",
tags=["finance"],
owner_user_id=uuid.uuid4(),
)
with (
@@ -578,6 +561,7 @@ class ArchiveLineagePropagationTests(unittest.TestCase):
self.assertEqual(child.metadata_json.get(worker_tasks_module.ARCHIVE_ROOT_ID_METADATA_KEY), str(parent_id))
self.assertEqual(child.metadata_json.get(worker_tasks_module.ARCHIVE_DEPTH_METADATA_KEY), 1)
self.assertTrue(child.is_archive_member)
self.assertEqual(child.owner_user_id, parent.owner_user_id)
def test_resolve_archive_lineage_prefers_existing_metadata(self) -> None:
"""Existing archive lineage metadata is reused without traversing parent relationships."""