Use core-owned scope storage
This commit is contained in:
14
README.md
14
README.md
@@ -1,9 +1,11 @@
|
||||
# GovOPlaN Tenancy
|
||||
|
||||
`govoplan-tenancy` owns the live `tenancy_tenants` table, tenant lifecycle, and
|
||||
tenant settings API route contributions during the GovOPlaN module split.
|
||||
`govoplan-tenancy` owns tenant lifecycle, tenant administration API route
|
||||
contributions, and the `tenancy.tenantResolver` capability during the GovOPlaN
|
||||
module split.
|
||||
|
||||
`govoplan-access` depends on this module, and core's registry inserts tenancy
|
||||
before access for authenticated platform composition. Core migrations rename the
|
||||
historical `tenants` table to the module-prefixed table name for existing
|
||||
development databases.
|
||||
`govoplan-access` no longer hard-depends on this module. Access can run in the
|
||||
single-scope compatibility mode used by the core/access baseline; installing
|
||||
tenancy adds explicit tenant management and resolver behavior. The shared scope
|
||||
storage table is core-owned as `core_scopes`; tenancy provides lifecycle and
|
||||
administration behavior over those rows rather than owning the table.
|
||||
|
||||
@@ -6,7 +6,7 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from govoplan_core.admin.common import AdminValidationError, slugify
|
||||
from govoplan_core.admin.settings import get_system_settings
|
||||
from govoplan_access.auth import ApiPrincipal, get_api_principal, has_scope, require_scope
|
||||
from govoplan_core.auth import ApiPrincipal, get_api_principal, has_scope, require_scope
|
||||
from govoplan_core.audit.logging import audit_event
|
||||
from govoplan_core.core.access import CAPABILITY_ACCESS_TENANT_PROVISIONER, TenantAccessProvisioner
|
||||
from govoplan_core.core.change_sequence import ChangeSequenceEntry, decode_sequence_watermark, encode_sequence_watermark, record_change, sequence_watermark_is_expired
|
||||
|
||||
@@ -1,33 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import Boolean, JSON, String, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from govoplan_core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
def new_uuid() -> str:
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class Tenant(Base, TimestampMixin):
|
||||
__tablename__ = "tenancy_tenants"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
||||
slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False, index=True)
|
||||
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
description: Mapped[str | None] = mapped_column(Text)
|
||||
default_locale: Mapped[str] = mapped_column(String(20), default="en", nullable=False)
|
||||
settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
|
||||
allow_custom_groups: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||
allow_custom_roles: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||
allow_api_keys: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
||||
|
||||
users: Mapped[list["User"]] = relationship("User", back_populates="tenant", cascade="all, delete-orphan")
|
||||
from govoplan_core.tenancy.scope import Tenant, new_uuid
|
||||
|
||||
|
||||
__all__ = ["Tenant", "new_uuid"]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from govoplan_core.core.access import CAPABILITY_TENANCY_TENANT_RESOLVER
|
||||
from govoplan_core.core.module_guards import persistent_table_uninstall_guard
|
||||
from govoplan_core.core.modules import MigrationSpec, ModuleContext, ModuleManifest
|
||||
from govoplan_core.db.base import Base
|
||||
from govoplan_tenancy.backend.db import models as tenancy_models # noqa: F401 - populate Tenancy ORM metadata
|
||||
from govoplan_core.core.access import (
|
||||
CAPABILITY_AUTH_PERMISSION_EVALUATOR,
|
||||
CAPABILITY_AUTH_PRINCIPAL_RESOLVER,
|
||||
CAPABILITY_TENANCY_TENANT_RESOLVER,
|
||||
)
|
||||
from govoplan_core.core.modules import ModuleContext, ModuleManifest
|
||||
|
||||
|
||||
def _tenant_resolver(context: ModuleContext):
|
||||
@@ -25,11 +26,8 @@ manifest = ModuleManifest(
|
||||
id="tenancy",
|
||||
name="Tenancy",
|
||||
version="0.1.6",
|
||||
required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR),
|
||||
route_factory=_route_factory,
|
||||
migration_spec=MigrationSpec(module_id="tenancy", metadata=Base.metadata),
|
||||
uninstall_guard_providers=(
|
||||
persistent_table_uninstall_guard(tenancy_models.Tenant, label="Tenancy"),
|
||||
),
|
||||
capability_factories={
|
||||
CAPABILITY_TENANCY_TENANT_RESOLVER: _tenant_resolver,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user