Use capability-based module boundaries
This commit is contained in:
@@ -4,7 +4,7 @@ import uuid
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from sqlalchemy import Boolean, ForeignKey, Index, JSON, String, Text, UniqueConstraint
|
from sqlalchemy import Boolean, ForeignKey, Index, JSON, String, Text, UniqueConstraint
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from govoplan_core.db.base import Base, TimestampMixin
|
from govoplan_core.db.base import Base, TimestampMixin
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ class MailServerProfile(Base, TimestampMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
||||||
tenant_id: Mapped[str | None] = mapped_column(ForeignKey("tenancy_tenants.id", ondelete="CASCADE"), nullable=True, index=True)
|
tenant_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
||||||
scope_type: Mapped[str] = mapped_column(String(20), default="tenant", nullable=False, index=True)
|
scope_type: Mapped[str] = mapped_column(String(20), default="tenant", nullable=False, index=True)
|
||||||
scope_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
scope_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
||||||
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||||
@@ -37,8 +37,6 @@ class MailServerProfile(Base, TimestampMixin):
|
|||||||
created_by_user_id: Mapped[str | None] = mapped_column(ForeignKey("access_users.id", ondelete="SET NULL"), nullable=True, index=True)
|
created_by_user_id: Mapped[str | None] = mapped_column(ForeignKey("access_users.id", ondelete="SET NULL"), nullable=True, index=True)
|
||||||
updated_by_user_id: Mapped[str | None] = mapped_column(ForeignKey("access_users.id", ondelete="SET NULL"), nullable=True, index=True)
|
updated_by_user_id: Mapped[str | None] = mapped_column(ForeignKey("access_users.id", ondelete="SET NULL"), nullable=True, index=True)
|
||||||
|
|
||||||
tenant: Mapped["Tenant"] = relationship()
|
|
||||||
|
|
||||||
|
|
||||||
class MailProfilePolicy(Base, TimestampMixin):
|
class MailProfilePolicy(Base, TimestampMixin):
|
||||||
__tablename__ = "mail_profile_policies"
|
__tablename__ = "mail_profile_policies"
|
||||||
@@ -48,8 +46,7 @@ class MailProfilePolicy(Base, TimestampMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
||||||
tenant_id: Mapped[str | None] = mapped_column(ForeignKey("tenancy_tenants.id", ondelete="CASCADE"), nullable=True, index=True)
|
tenant_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
||||||
scope_type: Mapped[str] = mapped_column(String(20), nullable=False, index=True)
|
scope_type: Mapped[str] = mapped_column(String(20), nullable=False, index=True)
|
||||||
scope_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
scope_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
||||||
policy: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
|
policy: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from typing import Any
|
|||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
|
|
||||||
from govoplan_access.auth import ApiPrincipal, require_scope
|
from govoplan_core.auth import ApiPrincipal, require_scope
|
||||||
from govoplan_mail.backend.dev.mock_mailbox import (
|
from govoplan_mail.backend.dev.mock_mailbox import (
|
||||||
clear_records,
|
clear_records,
|
||||||
get_failures,
|
get_failures,
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ def _campaign_policy_context(session: Session, *, tenant_id: str, campaign_id: s
|
|||||||
|
|
||||||
|
|
||||||
def _legacy_tenant_settings(session: Session, tenant_id: str) -> dict[str, Any] | None:
|
def _legacy_tenant_settings(session: Session, tenant_id: str) -> dict[str, Any] | None:
|
||||||
row = session.execute(text("select settings from tenancy_tenants where id = :tenant_id"), {"tenant_id": tenant_id}).first()
|
row = session.execute(text("select settings from core_scopes where id = :tenant_id"), {"tenant_id": tenant_id}).first()
|
||||||
return _json_object(row[0]) if row else None
|
return _json_object(row[0]) if row else None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from govoplan_core.core.access import CAPABILITY_AUTH_PERMISSION_EVALUATOR, CAPABILITY_AUTH_PRINCIPAL_RESOLVER
|
||||||
from govoplan_core.core.module_guards import drop_table_retirement_provider, persistent_table_uninstall_guard
|
from govoplan_core.core.module_guards import drop_table_retirement_provider, persistent_table_uninstall_guard
|
||||||
from govoplan_core.core.modules import (
|
from govoplan_core.core.modules import (
|
||||||
DocumentationCondition,
|
DocumentationCondition,
|
||||||
@@ -87,7 +88,7 @@ manifest = ModuleManifest(
|
|||||||
id="mail",
|
id="mail",
|
||||||
name="Mail",
|
name="Mail",
|
||||||
version="0.1.6",
|
version="0.1.6",
|
||||||
dependencies=("access",),
|
required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR),
|
||||||
optional_dependencies=(),
|
optional_dependencies=(),
|
||||||
permissions=PERMISSIONS,
|
permissions=PERMISSIONS,
|
||||||
route_factory=_mail_router,
|
route_factory=_mail_router,
|
||||||
|
|||||||
@@ -16,10 +16,16 @@ branch_labels = None
|
|||||||
depends_on = None
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def _scope_fk_target(inspector) -> str:
|
||||||
|
tables = set(inspector.get_table_names())
|
||||||
|
return "core_scopes.id" if "core_scopes" in tables else "tenancy_tenants.id"
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
inspector = sa.inspect(op.get_bind())
|
inspector = sa.inspect(op.get_bind())
|
||||||
if "mail_profile_policies" in inspector.get_table_names():
|
if "mail_profile_policies" in inspector.get_table_names():
|
||||||
return
|
return
|
||||||
|
scope_fk_target = _scope_fk_target(inspector)
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"mail_profile_policies",
|
"mail_profile_policies",
|
||||||
sa.Column("id", sa.String(length=36), nullable=False),
|
sa.Column("id", sa.String(length=36), nullable=False),
|
||||||
@@ -29,7 +35,7 @@ def upgrade() -> None:
|
|||||||
sa.Column("policy", sa.JSON(), nullable=False),
|
sa.Column("policy", sa.JSON(), nullable=False),
|
||||||
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
||||||
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
||||||
sa.ForeignKeyConstraint(["tenant_id"], ["tenancy_tenants.id"], name=op.f("fk_mail_profile_policies_tenant_id_tenants"), ondelete="CASCADE"),
|
sa.ForeignKeyConstraint(["tenant_id"], [scope_fk_target], name=op.f("fk_mail_profile_policies_tenant_id_scopes"), ondelete="CASCADE"),
|
||||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_mail_profile_policies")),
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_mail_profile_policies")),
|
||||||
sa.UniqueConstraint("tenant_id", "scope_type", "scope_id", name="uq_mail_profile_policies_scope"),
|
sa.UniqueConstraint("tenant_id", "scope_type", "scope_id", name="uq_mail_profile_policies_scope"),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from govoplan_mail.backend.schemas import (
|
|||||||
MailServerProfileUpdateRequest,
|
MailServerProfileUpdateRequest,
|
||||||
MailSmtpTestRequest,
|
MailSmtpTestRequest,
|
||||||
)
|
)
|
||||||
from govoplan_access.auth import ApiPrincipal, get_api_principal, has_scope
|
from govoplan_core.auth import ApiPrincipal, get_api_principal, has_scope
|
||||||
from govoplan_core.api.v1.schemas import DeltaDeletedItem
|
from govoplan_core.api.v1.schemas import DeltaDeletedItem
|
||||||
from govoplan_core.core.change_sequence import (
|
from govoplan_core.core.change_sequence import (
|
||||||
ChangeSequenceEntry,
|
ChangeSequenceEntry,
|
||||||
|
|||||||
Reference in New Issue
Block a user