Files
leocrm/alembic/versions/0096_workspace_tenant_integrity.py
T

94 lines
3.5 KiB
Python
Raw Normal View History

"""Workspace tenant integrity constraints.
Plan 4.3: Add tenant-bound foreign keys to workspace child tables.
- workspaces: UNIQUE (tenant_id, id)
- workspace_modules: FK (tenant_id, workspace_id) → workspaces (tenant_id, id)
- workspace_widgets: FK (tenant_id, workspace_id) → workspaces (tenant_id, id)
- workspace_users: FK (tenant_id, workspace_id) → workspaces (tenant_id, id)
- workspace_users: FK (tenant_id, user_id) → user_tenants (tenant_id, user_id)
Revision ID: 0096
Revises: 0095
"""
from __future__ import annotations
from alembic import op
revision = "0096"
down_revision = "0095"
branch_labels = None
depends_on = None
def upgrade() -> None:
# 1. Add UNIQUE (tenant_id, id) on workspaces
op.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS uq_workspaces_tenant_id "
"ON workspaces (tenant_id, id)"
)
# 2. Drop existing FKs on workspace_modules (workspace_id → workspaces.id)
# and replace with tenant-bound FK
op.execute("ALTER TABLE workspace_modules DROP CONSTRAINT IF EXISTS workspace_modules_workspace_id_fkey")
op.execute(
"ALTER TABLE workspace_modules "
"ADD CONSTRAINT fk_wm_tenant_workspace "
"FOREIGN KEY (tenant_id, workspace_id) "
"REFERENCES workspaces (tenant_id, id) ON DELETE CASCADE"
)
# 3. Drop existing FK on workspace_widgets and replace with tenant-bound FK
op.execute("ALTER TABLE workspace_widgets DROP CONSTRAINT IF EXISTS workspace_widgets_workspace_id_fkey")
op.execute(
"ALTER TABLE workspace_widgets "
"ADD CONSTRAINT fk_ww_tenant_workspace "
"FOREIGN KEY (tenant_id, workspace_id) "
"REFERENCES workspaces (tenant_id, id) ON DELETE CASCADE"
)
# 4. Drop existing FK on workspace_users and replace with tenant-bound FK
op.execute("ALTER TABLE workspace_users DROP CONSTRAINT IF EXISTS workspace_users_workspace_id_fkey")
op.execute(
"ALTER TABLE workspace_users "
"ADD CONSTRAINT fk_wu_tenant_workspace "
"FOREIGN KEY (tenant_id, workspace_id) "
"REFERENCES workspaces (tenant_id, id) ON DELETE CASCADE"
)
# 5. Add FK on workspace_users (tenant_id, user_id) → user_tenants (tenant_id, user_id)
op.execute(
"ALTER TABLE workspace_users "
"ADD CONSTRAINT fk_wu_tenant_user "
"FOREIGN KEY (tenant_id, user_id) "
"REFERENCES user_tenants (tenant_id, user_id) ON DELETE CASCADE"
)
def downgrade() -> None:
# Remove tenant-bound FKs, restore simple FKs
op.execute("ALTER TABLE workspace_users DROP CONSTRAINT IF EXISTS fk_wu_tenant_user")
op.execute("ALTER TABLE workspace_users DROP CONSTRAINT IF EXISTS fk_wu_tenant_workspace")
op.execute(
"ALTER TABLE workspace_users "
"ADD CONSTRAINT workspace_users_workspace_id_fkey "
"FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE"
)
op.execute("ALTER TABLE workspace_widgets DROP CONSTRAINT IF EXISTS fk_ww_tenant_workspace")
op.execute(
"ALTER TABLE workspace_widgets "
"ADD CONSTRAINT workspace_widgets_workspace_id_fkey "
"FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE"
)
op.execute("ALTER TABLE workspace_modules DROP CONSTRAINT IF EXISTS fk_wm_tenant_workspace")
op.execute(
"ALTER TABLE workspace_modules "
"ADD CONSTRAINT workspace_modules_workspace_id_fkey "
"FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE"
)
op.execute("DROP INDEX IF EXISTS uq_workspaces_tenant_id")