import type { MigrationContext, ReversibleMigration } from '../migration-types'; type Table = 'user' | 'shared_workflow' | 'shared_credentials'; const idColumns: Record = { user: 'id', shared_credentials: 'credentialsId', shared_workflow: 'workflowId', }; const uidColumns: Record = { user: 'id', shared_credentials: 'userId', shared_workflow: 'userId', }; const roleScopes: Record = { user: 'global', shared_credentials: 'credential', shared_workflow: 'workflow', }; const foreignKeySuffixes: Record = { user: 'f0609be844f9200ff4365b1bb3d', shared_credentials: 'c68e056637562000b68f480815a', shared_workflow: '3540da03964527aa24ae014b780', }; export class DropRoleMapping1705429061930 implements ReversibleMigration { async up(context: MigrationContext) { await this.migrateUp('user', context); await this.migrateUp('shared_workflow', context); await this.migrateUp('shared_credentials', context); } async down(context: MigrationContext) { await this.migrateDown('shared_workflow', context); await this.migrateDown('shared_credentials', context); await this.migrateDown('user', context); } private async migrateUp( table: Table, { escape, runQuery, schemaBuilder: { addNotNull, addColumns, dropColumns, dropForeignKey, column }, tablePrefix, }: MigrationContext, ) { await addColumns(table, [column('role').text]); const roleTable = escape.tableName('role'); const tableName = escape.tableName(table); const idColumn = escape.columnName(idColumns[table]); const uidColumn = escape.columnName(uidColumns[table]); const roleColumnName = table === 'user' ? 'globalRoleId' : 'roleId'; const roleColumn = escape.columnName(roleColumnName); const scope = roleScopes[table]; const roleField = `'${scope}:' || R.name`; const subQuery = ` SELECT ${roleField} as role, T.${idColumn} as id${ table !== 'user' ? `, T.${uidColumn} as uid` : '' } FROM ${tableName} T LEFT JOIN ${roleTable} R ON T.${roleColumn} = R.id and R.scope = '${scope}'`; const where = `WHERE ${tableName}.${idColumn} = mapping.id${ table !== 'user' ? ` AND ${tableName}.${uidColumn} = mapping.uid` : '' }`; const swQuery = `UPDATE ${tableName} SET role = mapping.role FROM (${subQuery}) as mapping ${where}`; await runQuery(swQuery); await addNotNull(table, 'role'); await dropForeignKey( table, roleColumnName, ['role', 'id'], `FK_${tablePrefix}${foreignKeySuffixes[table]}`, ); await dropColumns(table, [roleColumnName]); } private async migrateDown( table: Table, { escape, runQuery, schemaBuilder: { addNotNull, addColumns, dropColumns, addForeignKey, column }, tablePrefix, }: MigrationContext, ) { const roleColumnName = table === 'user' ? 'globalRoleId' : 'roleId'; await addColumns(table, [column(roleColumnName).int]); const roleTable = escape.tableName('role'); const tableName = escape.tableName(table); const idColumn = escape.columnName(idColumns[table]); const uidColumn = escape.columnName(uidColumns[table]); const roleColumn = escape.columnName(roleColumnName); const scope = roleScopes[table]; const roleField = `'${scope}:' || R.name`; const subQuery = ` SELECT R.id as role_id, T.${idColumn} as id${table !== 'user' ? `, T.${uidColumn} as uid` : ''} FROM ${tableName} T LEFT JOIN ${roleTable} R ON T.role = ${roleField} and R.scope = '${scope}'`; const where = `WHERE ${tableName}.${idColumn} = mapping.id${ table !== 'user' ? ` AND ${tableName}.${uidColumn} = mapping.uid` : '' }`; const query = `UPDATE ${tableName} SET ${roleColumn} = mapping.role_id FROM (${subQuery}) as mapping ${where}`; await runQuery(query); await addNotNull(table, roleColumnName); await addForeignKey( table, roleColumnName, ['role', 'id'], `FK_${tablePrefix}${foreignKeySuffixes[table]}`, ); await dropColumns(table, ['role']); } }