UNPKG

n8n

Version:

n8n Workflow Automation Tool

221 lines 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CreateProject1714133768519 = void 0; const n8n_workflow_1 = require("n8n-workflow"); const nanoid_1 = require("nanoid"); const generators_1 = require("../../../databases/utils/generators"); const projectAdminRole = 'project:personalOwner'; const table = { sharedCredentials: 'shared_credentials', sharedCredentialsTemp: 'shared_credentials_2', sharedWorkflow: 'shared_workflow', sharedWorkflowTemp: 'shared_workflow_2', project: 'project', user: 'user', projectRelation: 'project_relation', }; function escapeNames(escape) { const t = { project: escape.tableName(table.project), projectRelation: escape.tableName(table.projectRelation), sharedCredentials: escape.tableName(table.sharedCredentials), sharedCredentialsTemp: escape.tableName(table.sharedCredentialsTemp), sharedWorkflow: escape.tableName(table.sharedWorkflow), sharedWorkflowTemp: escape.tableName(table.sharedWorkflowTemp), user: escape.tableName(table.user), }; const c = { createdAt: escape.columnName('createdAt'), updatedAt: escape.columnName('updatedAt'), workflowId: escape.columnName('workflowId'), credentialsId: escape.columnName('credentialsId'), userId: escape.columnName('userId'), projectId: escape.columnName('projectId'), firstName: escape.columnName('firstName'), lastName: escape.columnName('lastName'), }; return { t, c }; } class CreateProject1714133768519 { async setupTables({ schemaBuilder: { createTable, column } }) { await createTable(table.project).withColumns(column('id').varchar(36).primary.notNull, column('name').varchar(255).notNull, column('type').varchar(36).notNull).withTimestamps; await createTable(table.projectRelation) .withColumns(column('projectId').varchar(36).primary.notNull, column('userId').uuid.primary.notNull, column('role').varchar().notNull) .withIndexOn('projectId') .withIndexOn('userId') .withForeignKey('projectId', { tableName: table.project, columnName: 'id', onDelete: 'CASCADE', }) .withForeignKey('userId', { tableName: 'user', columnName: 'id', onDelete: 'CASCADE', }).withTimestamps; } async alterSharedTable(relationTableName, { escape, isMysql, runQuery, schemaBuilder: { addForeignKey, addColumns, addNotNull, createIndex, column }, }) { const projectIdColumn = column('projectId').varchar(36).default('NULL'); await addColumns(relationTableName, [projectIdColumn]); const relationTable = escape.tableName(relationTableName); const { t, c } = escapeNames(escape); const subQuery = ` SELECT P.id as ${c.projectId}, T.${c.userId} FROM ${t.projectRelation} T LEFT JOIN ${t.project} P ON T.${c.projectId} = P.id AND P.type = 'personal' LEFT JOIN ${relationTable} S ON T.${c.userId} = S.${c.userId} WHERE P.id IS NOT NULL `; const swQuery = isMysql ? `UPDATE ${relationTable}, (${subQuery}) as mapping SET ${relationTable}.${c.projectId} = mapping.${c.projectId} WHERE ${relationTable}.${c.userId} = mapping.${c.userId}` : `UPDATE ${relationTable} SET ${c.projectId} = mapping.${c.projectId} FROM (${subQuery}) as mapping WHERE ${relationTable}.${c.userId} = mapping.${c.userId}`; await runQuery(swQuery); await addForeignKey(relationTableName, 'projectId', ['project', 'id']); await addNotNull(relationTableName, 'projectId'); await createIndex(relationTableName, ['projectId']); } async alterSharedCredentials({ escape, runQuery, schemaBuilder: { column, createTable, dropTable }, }) { await createTable(table.sharedCredentialsTemp) .withColumns(column('credentialsId').varchar(36).notNull.primary, column('projectId').varchar(36).notNull.primary, column('role').text.notNull) .withForeignKey('credentialsId', { tableName: 'credentials_entity', columnName: 'id', onDelete: 'CASCADE', }) .withForeignKey('projectId', { tableName: table.project, columnName: 'id', onDelete: 'CASCADE', }).withTimestamps; const { c, t } = escapeNames(escape); await runQuery(` INSERT INTO ${t.sharedCredentialsTemp} (${c.createdAt}, ${c.updatedAt}, ${c.credentialsId}, ${c.projectId}, role) SELECT ${c.createdAt}, ${c.updatedAt}, ${c.credentialsId}, ${c.projectId}, role FROM ${t.sharedCredentials}; `); await dropTable(table.sharedCredentials); await runQuery(`ALTER TABLE ${t.sharedCredentialsTemp} RENAME TO ${t.sharedCredentials};`); } async alterSharedWorkflow({ escape, runQuery, schemaBuilder: { column, createTable, dropTable }, }) { await createTable(table.sharedWorkflowTemp) .withColumns(column('workflowId').varchar(36).notNull.primary, column('projectId').varchar(36).notNull.primary, column('role').text.notNull) .withForeignKey('workflowId', { tableName: 'workflow_entity', columnName: 'id', onDelete: 'CASCADE', }) .withForeignKey('projectId', { tableName: table.project, columnName: 'id', onDelete: 'CASCADE', }).withTimestamps; const { c, t } = escapeNames(escape); await runQuery(` INSERT INTO ${t.sharedWorkflowTemp} (${c.createdAt}, ${c.updatedAt}, ${c.workflowId}, ${c.projectId}, role) SELECT ${c.createdAt}, ${c.updatedAt}, ${c.workflowId}, ${c.projectId}, role FROM ${t.sharedWorkflow}; `); await dropTable(table.sharedWorkflow); await runQuery(`ALTER TABLE ${t.sharedWorkflowTemp} RENAME TO ${t.sharedWorkflow};`); } async createUserPersonalProjects({ runQuery, runInBatches, escape }) { const { c, t } = escapeNames(escape); const getUserQuery = `SELECT id, ${c.firstName}, ${c.lastName}, email FROM ${t.user}`; await runInBatches(getUserQuery, async (users) => { await Promise.all(users.map(async (user) => { const projectId = (0, generators_1.generateNanoId)(); const name = this.createPersonalProjectName(user.firstName, user.lastName, user.email); await runQuery(`INSERT INTO ${t.project} (id, type, name) VALUES (:projectId, 'personal', :name)`, { projectId, name, }); await runQuery(`INSERT INTO ${t.projectRelation} (${c.projectId}, ${c.userId}, role) VALUES (:projectId, :userId, :projectRole)`, { projectId, userId: user.id, projectRole: projectAdminRole, }); })); }); } createPersonalProjectName(firstName, lastName, email) { if (firstName && lastName && email) { return `${firstName} ${lastName} <${email}>`; } else if (email) { return `<${email}>`; } else { return 'Unnamed Project'; } } async up(context) { await this.setupTables(context); await this.createUserPersonalProjects(context); await this.alterSharedTable(table.sharedCredentials, context); await this.alterSharedCredentials(context); await this.alterSharedTable(table.sharedWorkflow, context); await this.alterSharedWorkflow(context); } async down({ isMysql, logger, escape, runQuery, schemaBuilder: sb }) { const { t, c } = escapeNames(escape); const [{ count: nonPersonalProjects }] = await runQuery(`SELECT COUNT(*) FROM ${t.project} WHERE type <> 'personal';`); if (nonPersonalProjects > 0) { const message = 'Down migration only possible when there are no projects. Please delete all projects that were created via the UI first.'; logger.error(message); throw new n8n_workflow_1.UserError(message); } await sb .createTable(table.sharedWorkflowTemp) .withColumns(sb.column('workflowId').varchar(36).notNull.primary, sb.column('userId').uuid.notNull.primary, sb.column('role').text.notNull) .withForeignKey('workflowId', { tableName: 'workflow_entity', columnName: 'id', onDelete: 'CASCADE', name: isMysql ? (0, nanoid_1.nanoid)() : undefined, }) .withForeignKey('userId', { tableName: table.user, columnName: 'id', onDelete: 'CASCADE', }).withTimestamps; await runQuery(` INSERT INTO ${t.sharedWorkflowTemp} (${c.createdAt}, ${c.updatedAt}, ${c.workflowId}, role, ${c.userId}) SELECT SW.${c.createdAt}, SW.${c.updatedAt}, SW.${c.workflowId}, SW.role, PR.${c.userId} FROM ${t.sharedWorkflow} SW LEFT JOIN project_relation PR on SW.${c.projectId} = PR.${c.projectId} AND PR.role = 'project:personalOwner' `); await sb.dropTable(table.sharedWorkflow); await runQuery(`ALTER TABLE ${t.sharedWorkflowTemp} RENAME TO ${t.sharedWorkflow};`); await sb .createTable(table.sharedCredentialsTemp) .withColumns(sb.column('credentialsId').varchar(36).notNull.primary, sb.column('userId').uuid.notNull.primary, sb.column('role').text.notNull) .withForeignKey('credentialsId', { tableName: 'credentials_entity', columnName: 'id', onDelete: 'CASCADE', name: isMysql ? (0, nanoid_1.nanoid)() : undefined, }) .withForeignKey('userId', { tableName: table.user, columnName: 'id', onDelete: 'CASCADE', }).withTimestamps; await runQuery(` INSERT INTO ${t.sharedCredentialsTemp} (${c.createdAt}, ${c.updatedAt}, ${c.credentialsId}, role, ${c.userId}) SELECT SC.${c.createdAt}, SC.${c.updatedAt}, SC.${c.credentialsId}, SC.role, PR.${c.userId} FROM ${t.sharedCredentials} SC LEFT JOIN project_relation PR on SC.${c.projectId} = PR.${c.projectId} AND PR.role = 'project:personalOwner' `); await sb.dropTable(table.sharedCredentials); await runQuery(`ALTER TABLE ${t.sharedCredentialsTemp} RENAME TO ${t.sharedCredentials};`); await sb.dropTable(table.projectRelation); await sb.dropTable(table.project); } } exports.CreateProject1714133768519 = CreateProject1714133768519; //# sourceMappingURL=1714133768519-CreateProject.js.map