Spaces:
Running
Running
| from __future__ import annotations | |
| from pathlib import Path | |
| from uuid import uuid4 | |
| import pytest | |
| from app.container import build_container | |
| from app.core.config import Settings | |
| from app.security.assets import CanonicalAssetNotFoundError | |
| from app.security.schemas import APIKeyCreate | |
| from app.social.models import SocialAccount | |
| def foundation_settings(tmp_path: Path) -> Settings: | |
| return Settings( | |
| _env_file=None, | |
| database_url=f"sqlite+aiosqlite:///{tmp_path / 'security.db'}", | |
| social_database_url=f"sqlite+aiosqlite:///{tmp_path / 'social.db'}", | |
| social_auto_migrate=True, | |
| social_worker_enabled=False, | |
| auth_enabled=True, | |
| social_oauth_encryption_key="test-only-encryption-material", | |
| temp_dir=tmp_path / "temp", | |
| output_dir=tmp_path / "outputs", | |
| cleanup_interval_seconds=3600, | |
| whisper_model="tiny", | |
| ) | |
| async def _create_key(container, name: str, **kwargs: str): | |
| return await container.api_keys.create( | |
| APIKeyCreate( | |
| name=name, | |
| environment="test", | |
| role=None, | |
| scopes=["operations:execute", "operations:read"], | |
| ), | |
| created_by="tests", | |
| **kwargs, | |
| ) | |
| async def test_api_key_is_resolved_to_persisted_membership_and_rotation_preserves_it( | |
| tmp_path: Path, | |
| ) -> None: | |
| container = build_container(foundation_settings(tmp_path)) | |
| await container.security_database.initialize() | |
| try: | |
| first, first_secret = await _create_key(container, "First") | |
| first_context = await container.api_keys.authenticate(first_secret) | |
| assert first_context.workspace_id and first_context.user_id | |
| assert first_context.workspace_id != first.id | |
| assert first_context.user_id != first.id | |
| sibling, sibling_secret = await _create_key( | |
| container, | |
| "Sibling", | |
| workspace_id=first_context.workspace_id, | |
| user_id=first_context.user_id, | |
| ) | |
| sibling_context = await container.api_keys.authenticate(sibling_secret) | |
| assert sibling_context.workspace_id == first_context.workspace_id | |
| assert sibling_context.user_id == first_context.user_id | |
| isolated, isolated_secret = await _create_key(container, "Isolated") | |
| isolated_context = await container.api_keys.authenticate(isolated_secret) | |
| assert isolated_context.workspace_id != first_context.workspace_id | |
| rotated, rotated_secret = await container.api_keys.rotate( | |
| first.id, 0, created_by="tests" | |
| ) | |
| rotated_context = await container.api_keys.authenticate(rotated_secret) | |
| assert rotated_context.workspace_id == first_context.workspace_id | |
| assert rotated_context.user_id == first_context.user_id | |
| finally: | |
| await container.security_database.close() | |
| async def test_canonical_asset_cannot_be_claimed_by_another_workspace(tmp_path: Path) -> None: | |
| container = build_container(foundation_settings(tmp_path)) | |
| await container.security_database.initialize() | |
| try: | |
| _, secret_a = await _create_key(container, "A") | |
| _, secret_b = await _create_key(container, "B") | |
| context_a = await container.api_keys.authenticate(secret_a) | |
| context_b = await container.api_keys.authenticate(secret_b) | |
| request_id = str(uuid4()) | |
| output = container.settings.output_dir / request_id | |
| output.mkdir(parents=True) | |
| path = output / "asset.mp4" | |
| path.write_bytes(b"owned output") | |
| asset = await container.assets.register_output( | |
| workspace_id=str(context_a.workspace_id), | |
| user_id=context_a.user_id, | |
| request_id=request_id, | |
| path=path, | |
| mime_type="video/mp4", | |
| ) | |
| assert asset.workspace_id == context_a.workspace_id | |
| owned = await container.assets.get_owned( | |
| workspace_id=str(context_a.workspace_id), | |
| request_id=request_id, | |
| filename=path.name, | |
| ) | |
| assert owned.id == asset.id | |
| with pytest.raises(CanonicalAssetNotFoundError): | |
| await container.assets.get_owned( | |
| workspace_id=str(context_b.workspace_id), | |
| request_id=request_id, | |
| filename=path.name, | |
| ) | |
| path.write_bytes(b"tampered") | |
| with pytest.raises(CanonicalAssetNotFoundError): | |
| await container.assets.verify_file(asset, path) | |
| finally: | |
| await container.security_database.close() | |
| async def test_legacy_social_rows_are_adopted_without_reusing_api_key_tenant_id( | |
| tmp_path: Path, | |
| ) -> None: | |
| container = build_container(foundation_settings(tmp_path)) | |
| await container.security_database.initialize() | |
| await container.social.initialize() | |
| try: | |
| key, secret = await _create_key(container, "Legacy") | |
| context = await container.api_keys.authenticate(secret) | |
| legacy_account = await container.social.accounts.repository.create( | |
| SocialAccount( | |
| workspace_id=key.id, | |
| provider="youtube", | |
| account_type="channel", | |
| external_account_id="legacy-channel", | |
| status="connected", | |
| ) | |
| ) | |
| await container.social.adopt_legacy_workspaces( | |
| await container.tenants.list_principals() | |
| ) | |
| adopted = await container.social.accounts.repository.get( | |
| str(context.workspace_id), legacy_account.id | |
| ) | |
| assert adopted.workspace_id == context.workspace_id | |
| finally: | |
| await container.social.close() | |
| await container.security_database.close() | |