diff --git a/colaflow-api/src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Persistence/Migrations/20251103150353_FixUserTenantRolesIgnoreNavigation.cs b/colaflow-api/src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Persistence/Migrations/20251103150353_FixUserTenantRolesIgnoreNavigation.cs
index 3bfe16a..c042a09 100644
--- a/colaflow-api/src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Persistence/Migrations/20251103150353_FixUserTenantRolesIgnoreNavigation.cs
+++ b/colaflow-api/src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/Persistence/Migrations/20251103150353_FixUserTenantRolesIgnoreNavigation.cs
@@ -10,21 +10,68 @@ namespace ColaFlow.Modules.Identity.Infrastructure.Persistence.Migrations
///
protected override void Up(MigrationBuilder migrationBuilder)
{
- // Drop and recreate foreign keys to ensure they reference the correct columns
- // This fixes BUG-002: Foreign keys were incorrectly referencing user_id1/tenant_id1
+ // IDEMPOTENT FIX: Check if table exists before modifying it
+ // If the table doesn't exist, create it first
+ migrationBuilder.Sql(@"
+ -- Create user_tenant_roles table if it doesn't exist
+ DO $$
+ BEGIN
+ IF NOT EXISTS (
+ SELECT FROM information_schema.tables
+ WHERE table_schema = 'identity'
+ AND table_name = 'user_tenant_roles'
+ ) THEN
+ -- Create the table
+ CREATE TABLE identity.user_tenant_roles (
+ id uuid NOT NULL PRIMARY KEY,
+ user_id uuid NOT NULL,
+ tenant_id uuid NOT NULL,
+ role character varying(50) NOT NULL,
+ assigned_at timestamp with time zone NOT NULL,
+ assigned_by_user_id uuid,
+ CONSTRAINT uq_user_tenant_roles_user_tenant UNIQUE (user_id, tenant_id)
+ );
- migrationBuilder.DropForeignKey(
- name: "FK_user_tenant_roles_tenants_tenant_id",
- schema: "identity",
- table: "user_tenant_roles");
+ -- Create basic indexes
+ -- Note: ix_user_tenant_roles_tenant_role will be created by a later migration
+ CREATE INDEX ix_user_tenant_roles_user_id ON identity.user_tenant_roles(user_id);
+ CREATE INDEX ix_user_tenant_roles_tenant_id ON identity.user_tenant_roles(tenant_id);
+ CREATE INDEX ix_user_tenant_roles_role ON identity.user_tenant_roles(role);
+ END IF;
+ END $$;
+ ");
- migrationBuilder.DropForeignKey(
- name: "FK_user_tenant_roles_users_user_id",
- schema: "identity",
- table: "user_tenant_roles");
+ // Drop existing foreign keys if they exist
+ migrationBuilder.Sql(@"
+ DO $$
+ BEGIN
+ -- Drop FK to tenants if it exists
+ IF EXISTS (
+ SELECT FROM information_schema.table_constraints
+ WHERE constraint_schema = 'identity'
+ AND table_name = 'user_tenant_roles'
+ AND constraint_name = 'FK_user_tenant_roles_tenants_tenant_id'
+ ) THEN
+ ALTER TABLE identity.user_tenant_roles
+ DROP CONSTRAINT ""FK_user_tenant_roles_tenants_tenant_id"";
+ END IF;
+
+ -- Drop FK to users if it exists
+ IF EXISTS (
+ SELECT FROM information_schema.table_constraints
+ WHERE constraint_schema = 'identity'
+ AND table_name = 'user_tenant_roles'
+ AND constraint_name = 'FK_user_tenant_roles_users_user_id'
+ ) THEN
+ ALTER TABLE identity.user_tenant_roles
+ DROP CONSTRAINT ""FK_user_tenant_roles_users_user_id"";
+ END IF;
+ END $$;
+ ");
// Recreate foreign keys with correct column references
- // Note: users and tenants tables are in the default schema (no explicit schema)
+ // Note: At this point in time, users and tenants are still in the default schema
+ // (They will be moved to identity schema in a later migration)
migrationBuilder.AddForeignKey(
name: "FK_user_tenant_roles_users_user_id",
schema: "identity",
@@ -47,23 +94,35 @@ namespace ColaFlow.Modules.Identity.Infrastructure.Persistence.Migrations
///
protected override void Down(MigrationBuilder migrationBuilder)
{
- migrationBuilder.AddForeignKey(
- name: "FK_user_tenant_roles_tenants_tenant_id",
- schema: "identity",
- table: "user_tenant_roles",
- column: "tenant_id",
- principalTable: "tenants",
- principalColumn: "id",
- onDelete: ReferentialAction.Cascade);
+ // Drop foreign keys if they exist
+ migrationBuilder.Sql(@"
+ DO $$
+ BEGIN
+ IF EXISTS (
+ SELECT FROM information_schema.table_constraints
+ WHERE constraint_schema = 'identity'
+ AND table_name = 'user_tenant_roles'
+ AND constraint_name = 'FK_user_tenant_roles_tenants_tenant_id'
+ ) THEN
+ ALTER TABLE identity.user_tenant_roles
+ DROP CONSTRAINT ""FK_user_tenant_roles_tenants_tenant_id"";
+ END IF;
- migrationBuilder.AddForeignKey(
- name: "FK_user_tenant_roles_users_user_id",
- schema: "identity",
- table: "user_tenant_roles",
- column: "user_id",
- principalTable: "users",
- principalColumn: "id",
- onDelete: ReferentialAction.Cascade);
+ IF EXISTS (
+ SELECT FROM information_schema.table_constraints
+ WHERE constraint_schema = 'identity'
+ AND table_name = 'user_tenant_roles'
+ AND constraint_name = 'FK_user_tenant_roles_users_user_id'
+ ) THEN
+ ALTER TABLE identity.user_tenant_roles
+ DROP CONSTRAINT ""FK_user_tenant_roles_users_user_id"";
+ END IF;
+ END $$;
+ ");
+
+ // Note: We don't drop the table in Down() because it should have been created
+ // by a previous migration. If it was created by this migration (first run),
+ // then it will be cleaned up when the database is reset.
}
}
}