feat: integrate files and portal surfaces
This commit is contained in:
@@ -8,6 +8,7 @@ from govoplan_core.core.postbox import (
|
||||
CAPABILITY_POSTBOX_DIRECTORY,
|
||||
CAPABILITY_POSTBOX_EVIDENCE,
|
||||
CAPABILITY_POSTBOX_MESSAGES,
|
||||
CAPABILITY_POSTBOX_PORTAL,
|
||||
CAPABILITY_POSTBOX_ROUTING,
|
||||
)
|
||||
from govoplan_core.core.encryption import CAPABILITY_ENCRYPTION_CONTENT_CIPHER
|
||||
@@ -31,6 +32,7 @@ class PostboxManifestTests(unittest.TestCase):
|
||||
CAPABILITY_POSTBOX_DELIVERY,
|
||||
CAPABILITY_POSTBOX_EVIDENCE,
|
||||
CAPABILITY_POSTBOX_ROUTING,
|
||||
CAPABILITY_POSTBOX_PORTAL,
|
||||
},
|
||||
set(manifest.capability_factories),
|
||||
)
|
||||
|
||||
@@ -34,6 +34,10 @@ class PostboxMigrationTests(unittest.TestCase):
|
||||
"govoplan_postbox.backend.migrations.versions."
|
||||
"e9f4a7b2c5d8_v014_template_scope_preview"
|
||||
)
|
||||
portal_migration = importlib.import_module(
|
||||
"govoplan_postbox.backend.migrations.versions."
|
||||
"f2a5c8e1b4d7_v015_portal_visibility"
|
||||
)
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
try:
|
||||
with engine.begin() as connection:
|
||||
@@ -44,12 +48,14 @@ class PostboxMigrationTests(unittest.TestCase):
|
||||
envelope_original = envelope_migration.op
|
||||
protection_original = protection_migration.op
|
||||
scope_original = scope_migration.op
|
||||
portal_original = portal_migration.op
|
||||
migration.op = operations
|
||||
route_migration.op = operations
|
||||
occ_migration.op = operations
|
||||
envelope_migration.op = operations
|
||||
protection_migration.op = operations
|
||||
scope_migration.op = operations
|
||||
portal_migration.op = operations
|
||||
try:
|
||||
migration.upgrade()
|
||||
route_migration.upgrade()
|
||||
@@ -57,6 +63,7 @@ class PostboxMigrationTests(unittest.TestCase):
|
||||
envelope_migration.upgrade()
|
||||
protection_migration.upgrade()
|
||||
scope_migration.upgrade()
|
||||
portal_migration.upgrade()
|
||||
tables = set(inspect(connection).get_table_names())
|
||||
self.assertIn("postboxes", tables)
|
||||
self.assertIn("postbox_messages", tables)
|
||||
@@ -93,6 +100,7 @@ class PostboxMigrationTests(unittest.TestCase):
|
||||
"encryption_vault_id",
|
||||
"scope_structure_id",
|
||||
"scope_relation_type_ids",
|
||||
"portal_visible",
|
||||
}.issubset(template_revision_columns)
|
||||
)
|
||||
self.assertIn("authoring_key", message_columns)
|
||||
@@ -121,6 +129,7 @@ class PostboxMigrationTests(unittest.TestCase):
|
||||
route_columns
|
||||
)
|
||||
)
|
||||
portal_migration.downgrade()
|
||||
scope_migration.downgrade()
|
||||
protection_migration.downgrade()
|
||||
envelope_migration.downgrade()
|
||||
@@ -141,6 +150,7 @@ class PostboxMigrationTests(unittest.TestCase):
|
||||
envelope_migration.op = envelope_original
|
||||
protection_migration.op = protection_original
|
||||
scope_migration.op = scope_original
|
||||
portal_migration.op = portal_original
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ from govoplan_postbox.backend.db.models import (
|
||||
PostboxTemplateRevision,
|
||||
)
|
||||
from govoplan_postbox.backend.router import router
|
||||
from govoplan_postbox.backend.portal_projection import PortalProjection
|
||||
from govoplan_postbox.backend.service import PostboxService
|
||||
|
||||
|
||||
@@ -220,6 +221,7 @@ class PostboxRouterTests(unittest.TestCase):
|
||||
account=SimpleNamespace(id="account-1"),
|
||||
user=SimpleNamespace(id="membership-1"),
|
||||
)
|
||||
self.principal = principal
|
||||
app = FastAPI()
|
||||
app.include_router(router, prefix="/api/v1")
|
||||
|
||||
@@ -250,6 +252,35 @@ class PostboxRouterTests(unittest.TestCase):
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertIn("not active for this principal", response.text)
|
||||
|
||||
def test_portal_projection_requires_explicit_visibility_and_keeps_postbox_access(self) -> None:
|
||||
projection = PortalProjection()
|
||||
with Session(self.engine) as session, patch(
|
||||
"govoplan_postbox.backend.portal_projection.get_service",
|
||||
return_value=self.service,
|
||||
):
|
||||
self.assertEqual(
|
||||
(),
|
||||
projection.list_portal_entries(
|
||||
session,
|
||||
self.principal,
|
||||
tenant_id="tenant-1",
|
||||
),
|
||||
)
|
||||
postbox = session.get(Postbox, self.postbox_id)
|
||||
assert postbox is not None
|
||||
postbox.settings = {**postbox.settings, "portal_visible": True}
|
||||
session.flush()
|
||||
|
||||
entries = projection.list_portal_entries(
|
||||
session,
|
||||
self.principal,
|
||||
tenant_id="tenant-1",
|
||||
)
|
||||
|
||||
self.assertEqual(1, len(entries))
|
||||
self.assertEqual(self.postbox_id, entries[0].postbox.id)
|
||||
self.assertEqual(f"/postbox?postbox={self.postbox_id}", entries[0].route_path)
|
||||
|
||||
def test_template_impact_preview_is_available_without_writes(self) -> None:
|
||||
with Session(self.engine) as session:
|
||||
before = session.query(Postbox).count()
|
||||
|
||||
Reference in New Issue
Block a user