Phase 1: Migrationsaudit + Forward-Migrationen 0093-0096
Audit (docs/migration_history_audit.md): - files.size_bytes: INTEGER (Alembic) vs BIGINT (Produktion/Plugin) - GIN-Indizes: Fehlendes USING GIN in Alembic 0002 - guest_users: ix_guest_users_email_tenant fehlt UNIQUE in Alembic 0059 - plugins.name: Doppelter Unique-Index in Produktion Forward-Migrationen: - 0093: files.size_bytes INTEGER → BIGINT - 0094: GIN-Indizes reparieren + plugins.name doppelten Index entfernen - 0095: guest_users email+tenant_id UNIQUE INDEX (mit Dubletten-Check) - 0096: Workspace tenant_integrity (tenant-bound FKs) Tests: 41/41 bestanden (17 Workspace + 24 Command) Alembic Head: 0096
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""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")
|
||||
Reference in New Issue
Block a user