from __future__ import annotations from types import SimpleNamespace import unittest from sqlalchemy import create_engine from sqlalchemy.orm import Session from govoplan_access.backend.db.models import Account, Group, User from govoplan_campaign.backend.db.models import Campaign, CampaignShare from govoplan_campaign.backend.search_source import ( CampaignSearchSource, PROVIDER_ID, RESOURCE_TYPE, ) from govoplan_core.auth import ApiPrincipal from govoplan_core.core.access import PrincipalRef from govoplan_core.core.search import ( SearchAuthorizationRequest, SearchBackfillRequest, SearchResourceReference, ) from govoplan_core.core.change_sequence import ChangeSequenceEntry from govoplan_core.db.base import Base class CampaignSearchSourceTests(unittest.TestCase): def setUp(self) -> None: self.engine = create_engine("sqlite://") Base.metadata.create_all( self.engine, tables=( Account.__table__, User.__table__, Group.__table__, Campaign.__table__, CampaignShare.__table__, ChangeSequenceEntry.__table__, ), ) self.session = Session(self.engine) self.session.add_all( ( Account( id="account-1", email="one@example.test", normalized_email="one@example.test", ), User( id="user-1", tenant_id="tenant-1", account_id="account-1", email="one@example.test", ), Campaign( id="campaign-1", tenant_id="tenant-1", owner_user_id="user-1", external_id="monthly-letters", name="Monthly letters", ), Campaign( id="campaign-other", tenant_id="tenant-2", external_id="other", name="Other tenant", ), ) ) self.session.commit() self.source = CampaignSearchSource() def tearDown(self) -> None: self.session.close() self.engine.dispose() def test_backfill_and_live_acl_recheck_do_not_cross_tenants(self) -> None: page = self.source.backfill( self.session, request=SearchBackfillRequest( tenant_id="tenant-1", provider_id=PROVIDER_ID, resource_type=RESOURCE_TYPE, rebuild_id="rebuild-1", ), ) self.assertEqual(("campaign-1",), tuple(doc.resource_id for doc in page.documents)) reference = SearchResourceReference( tenant_id="tenant-1", module_id="campaigns", resource_type=RESOURCE_TYPE, resource_id="campaign-1", ) request = SearchAuthorizationRequest(reference=reference, source_revision="1") self.assertTrue( self.source.authorize( self.session, _principal({"campaigns:campaign:read"}), requests=(request,), )[reference.key] ) self.assertFalse( self.source.authorize( self.session, _principal(set()), requests=(request,), )[reference.key] ) def _principal(scopes: set[str]) -> ApiPrincipal: return ApiPrincipal( principal=PrincipalRef( account_id="account-1", membership_id="user-1", tenant_id="tenant-1", scopes=frozenset(scopes), ), account=SimpleNamespace(id="account-1"), user=SimpleNamespace(id="user-1"), ) if __name__ == "__main__": unittest.main()