diff --git a/packages/cli/commands/execute.ts b/packages/cli/commands/execute.ts index ed8737bc2b..c2b51e78a4 100644 --- a/packages/cli/commands/execute.ts +++ b/packages/cli/commands/execute.ts @@ -108,8 +108,7 @@ export class Execute extends Command { if (flags.id) { // Id of workflow is given workflowId = flags.id; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - workflowData = await Db.collections.Workflow!.findOne(workflowId); + workflowData = await Db.collections.Workflow.findOne(workflowId); if (workflowData === undefined) { console.info(`The workflow with the id "${workflowId}" does not exist.`); process.exit(1); diff --git a/packages/cli/commands/executeBatch.ts b/packages/cli/commands/executeBatch.ts index 26f4edb594..8a0f1a9baf 100644 --- a/packages/cli/commands/executeBatch.ts +++ b/packages/cli/commands/executeBatch.ts @@ -297,7 +297,7 @@ export class ExecuteBatch extends Command { let allWorkflows; - const query = Db.collections.Workflow!.createQueryBuilder('workflows'); + const query = Db.collections.Workflow.createQueryBuilder('workflows'); if (ids.length > 0) { query.andWhere(`workflows.id in (:...ids)`, { ids }); diff --git a/packages/cli/commands/export/credentials.ts b/packages/cli/commands/export/credentials.ts index 70cff781e1..ab34c9d968 100644 --- a/packages/cli/commands/export/credentials.ts +++ b/packages/cli/commands/export/credentials.ts @@ -119,7 +119,7 @@ export class ExportCredentialsCommand extends Command { } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const credentials = await Db.collections.Credentials!.find(findQuery); + const credentials = await Db.collections.Credentials.find(findQuery); if (flags.decrypted) { const encryptionKey = await UserSettings.getEncryptionKey(); diff --git a/packages/cli/commands/export/workflow.ts b/packages/cli/commands/export/workflow.ts index 39514c0398..958efe9c2d 100644 --- a/packages/cli/commands/export/workflow.ts +++ b/packages/cli/commands/export/workflow.ts @@ -111,7 +111,7 @@ export class ExportWorkflowsCommand extends Command { } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const workflows = await Db.collections.Workflow!.find(findQuery); + const workflows = await Db.collections.Workflow.find(findQuery); if (workflows.length === 0) { throw new Error('No workflows found with specified filters.'); diff --git a/packages/cli/commands/import/credentials.ts b/packages/cli/commands/import/credentials.ts index 98f735fe5d..eb08f1a0de 100644 --- a/packages/cli/commands/import/credentials.ts +++ b/packages/cli/commands/import/credentials.ts @@ -2,7 +2,6 @@ /* eslint-disable @typescript-eslint/no-shadow */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable no-await-in-loop */ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable no-console */ @@ -150,7 +149,7 @@ export class ImportCredentialsCommand extends Command { } private async initOwnerCredentialRole() { - const ownerCredentialRole = await Db.collections.Role!.findOne({ + const ownerCredentialRole = await Db.collections.Role.findOne({ where: { name: 'owner', scope: 'credential' }, }); @@ -180,11 +179,11 @@ export class ImportCredentialsCommand extends Command { } private async getOwner() { - const ownerGlobalRole = await Db.collections.Role!.findOne({ + const ownerGlobalRole = await Db.collections.Role.findOne({ where: { name: 'owner', scope: 'global' }, }); - const owner = await Db.collections.User!.findOne({ globalRole: ownerGlobalRole }); + const owner = await Db.collections.User.findOne({ globalRole: ownerGlobalRole }); if (!owner) { throw new Error(`Failed to find owner. ${FIX_INSTRUCTION}`); @@ -194,7 +193,7 @@ export class ImportCredentialsCommand extends Command { } private async getAssignee(userId: string) { - const user = await Db.collections.User!.findOne(userId); + const user = await Db.collections.User.findOne(userId); if (!user) { throw new Error(`Failed to find user with ID ${userId}`); diff --git a/packages/cli/commands/import/workflow.ts b/packages/cli/commands/import/workflow.ts index f07a26c4f0..bb277400c1 100644 --- a/packages/cli/commands/import/workflow.ts +++ b/packages/cli/commands/import/workflow.ts @@ -157,7 +157,7 @@ export class ImportWorkflowsCommand extends Command { } private async initOwnerWorkflowRole() { - const ownerWorkflowRole = await Db.collections.Role!.findOne({ + const ownerWorkflowRole = await Db.collections.Role.findOne({ where: { name: 'owner', scope: 'workflow' }, }); @@ -187,11 +187,11 @@ export class ImportWorkflowsCommand extends Command { } private async getOwner() { - const ownerGlobalRole = await Db.collections.Role!.findOne({ + const ownerGlobalRole = await Db.collections.Role.findOne({ where: { name: 'owner', scope: 'global' }, }); - const owner = await Db.collections.User!.findOne({ globalRole: ownerGlobalRole }); + const owner = await Db.collections.User.findOne({ globalRole: ownerGlobalRole }); if (!owner) { throw new Error(`Failed to find owner. ${FIX_INSTRUCTION}`); @@ -201,7 +201,7 @@ export class ImportWorkflowsCommand extends Command { } private async getAssignee(userId: string) { - const user = await Db.collections.User!.findOne(userId); + const user = await Db.collections.User.findOne(userId); if (!user) { throw new Error(`Failed to find user with ID ${userId}`); diff --git a/packages/cli/commands/list/workflow.ts b/packages/cli/commands/list/workflow.ts index 19075bef0f..8d35ba7fab 100644 --- a/packages/cli/commands/list/workflow.ts +++ b/packages/cli/commands/list/workflow.ts @@ -42,8 +42,7 @@ export class ListWorkflowCommand extends Command { findQuery.active = flags.active === 'true'; } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const workflows = await Db.collections.Workflow!.find(findQuery); + const workflows = await Db.collections.Workflow.find(findQuery); if (flags.onlyId) { workflows.forEach((workflow) => console.log(workflow.id)); } else { diff --git a/packages/cli/commands/start.ts b/packages/cli/commands/start.ts index 5eab0995e1..dc9045d830 100644 --- a/packages/cli/commands/start.ts +++ b/packages/cli/commands/start.ts @@ -217,7 +217,7 @@ export class Start extends Command { } // Load settings from database and set them to config. - const databaseSettings = await Db.collections.Settings!.find({ loadOnStartup: true }); + const databaseSettings = await Db.collections.Settings.find({ loadOnStartup: true }); databaseSettings.forEach((setting) => { config.set(setting.key, JSON.parse(setting.value)); }); @@ -287,8 +287,8 @@ export class Start extends Command { if (dbType === 'sqlite') { const shouldRunVacuum = config.getEnv('database.sqlite.executeVacuumOnStartup'); if (shouldRunVacuum) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/no-non-null-assertion - await Db.collections.Execution!.query('VACUUM;'); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + await Db.collections.Execution.query('VACUUM;'); } } diff --git a/packages/cli/commands/update/workflow.ts b/packages/cli/commands/update/workflow.ts index 7c598b4e82..735e016da7 100644 --- a/packages/cli/commands/update/workflow.ts +++ b/packages/cli/commands/update/workflow.ts @@ -72,8 +72,7 @@ export class UpdateWorkflowCommand extends Command { findQuery.active = true; } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await Db.collections.Workflow!.update(findQuery, updateQuery); + await Db.collections.Workflow.update(findQuery, updateQuery); console.info('Done'); } catch (e) { console.error('Error updating database. See log messages for details.'); diff --git a/packages/cli/commands/user-management/reset.ts b/packages/cli/commands/user-management/reset.ts index 404e5a8df1..1dda361b0e 100644 --- a/packages/cli/commands/user-management/reset.ts +++ b/packages/cli/commands/user-management/reset.ts @@ -1,5 +1,4 @@ /* eslint-disable no-console */ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import Command from '@oclif/command'; import { Not } from 'typeorm'; @@ -27,33 +26,33 @@ export class Reset extends Command { try { const owner = await this.getInstanceOwner(); - const ownerWorkflowRole = await Db.collections.Role!.findOneOrFail({ + const ownerWorkflowRole = await Db.collections.Role.findOneOrFail({ name: 'owner', scope: 'workflow', }); - const ownerCredentialRole = await Db.collections.Role!.findOneOrFail({ + const ownerCredentialRole = await Db.collections.Role.findOneOrFail({ name: 'owner', scope: 'credential', }); - await Db.collections.SharedWorkflow!.update( + await Db.collections.SharedWorkflow.update( { user: { id: Not(owner.id) }, role: ownerWorkflowRole }, { user: owner }, ); - await Db.collections.SharedCredentials!.update( + await Db.collections.SharedCredentials.update( { user: { id: Not(owner.id) }, role: ownerCredentialRole }, { user: owner }, ); - await Db.collections.User!.delete({ id: Not(owner.id) }); - await Db.collections.User!.save(Object.assign(owner, this.defaultUserProps)); + await Db.collections.User.delete({ id: Not(owner.id) }); + await Db.collections.User.save(Object.assign(owner, this.defaultUserProps)); - await Db.collections.Settings!.update( + await Db.collections.Settings.update( { key: 'userManagement.isInstanceOwnerSetUp' }, { value: 'false' }, ); - await Db.collections.Settings!.update( + await Db.collections.Settings.update( { key: 'userManagement.skipInstanceOwnerSetup' }, { value: 'false' }, ); @@ -68,19 +67,19 @@ export class Reset extends Command { } private async getInstanceOwner(): Promise { - const globalRole = await Db.collections.Role!.findOneOrFail({ + const globalRole = await Db.collections.Role.findOneOrFail({ name: 'owner', scope: 'global', }); - const owner = await Db.collections.User!.findOne({ globalRole }); + const owner = await Db.collections.User.findOne({ globalRole }); if (owner) return owner; const user = new User(); - await Db.collections.User!.save(Object.assign(user, { ...this.defaultUserProps, globalRole })); + await Db.collections.User.save(Object.assign(user, { ...this.defaultUserProps, globalRole })); - return Db.collections.User!.findOneOrFail({ globalRole }); + return Db.collections.User.findOneOrFail({ globalRole }); } } diff --git a/packages/cli/commands/worker.ts b/packages/cli/commands/worker.ts index 5da36884e4..020e25c28f 100644 --- a/packages/cli/commands/worker.ts +++ b/packages/cli/commands/worker.ts @@ -119,7 +119,7 @@ export class Worker extends Command { async runJob(job: Bull.Job, nodeTypes: INodeTypes): Promise { const jobData = job.data as IBullJobData; - const executionDb = await Db.collections.Execution!.findOne(jobData.executionId); + const executionDb = await Db.collections.Execution.findOne(jobData.executionId); if (!executionDb) { LoggerProxy.error('Worker failed to find execution data in database. Cannot continue.', { @@ -139,7 +139,7 @@ export class Worker extends Command { const findOptions = { select: ['id', 'staticData'], } as FindOneOptions; - const workflowData = await Db.collections.Workflow!.findOne( + const workflowData = await Db.collections.Workflow.findOne( currentExecutionDb.workflowData.id, findOptions, ); diff --git a/packages/cli/src/ActiveWorkflowRunner.ts b/packages/cli/src/ActiveWorkflowRunner.ts index d24671a8b3..a62ab43e2f 100644 --- a/packages/cli/src/ActiveWorkflowRunner.ts +++ b/packages/cli/src/ActiveWorkflowRunner.ts @@ -69,7 +69,7 @@ export class ActiveWorkflowRunner { // NOTE // Here I guess we can have a flag on the workflow table like hasTrigger // so intead of pulling all the active wehhooks just pull the actives that have a trigger - const workflowsData: IWorkflowDb[] = (await Db.collections.Workflow!.find({ + const workflowsData: IWorkflowDb[] = (await Db.collections.Workflow.find({ where: { active: true }, relations: ['shared', 'shared.user', 'shared.user.globalRole'], })) as IWorkflowDb[]; @@ -256,7 +256,7 @@ export class ActiveWorkflowRunner { }); } - const workflowData = await Db.collections.Workflow!.findOne(webhook.workflowId, { + const workflowData = await Db.collections.Workflow.findOne(webhook.workflowId, { relations: ['shared', 'shared.user', 'shared.user.globalRole'], }); if (workflowData === undefined) { @@ -332,7 +332,7 @@ export class ActiveWorkflowRunner { * @memberof ActiveWorkflowRunner */ async getWebhookMethods(path: string): Promise { - const webhooks = (await Db.collections.Webhook?.find({ webhookPath: path })) as IWebhookDb[]; + const webhooks = await Db.collections.Webhook?.find({ webhookPath: path }); // Gather all request methods in string array const webhookMethods: string[] = webhooks.map((webhook) => webhook.method); @@ -349,12 +349,12 @@ export class ActiveWorkflowRunner { let activeWorkflows: WorkflowEntity[] = []; if (!user || user.globalRole.name === 'owner') { - activeWorkflows = await Db.collections.Workflow!.find({ + activeWorkflows = await Db.collections.Workflow.find({ select: ['id'], where: { active: true }, }); } else { - const shared = await Db.collections.SharedWorkflow!.find({ + const shared = await Db.collections.SharedWorkflow.find({ relations: ['workflow'], where: whereClause({ user, @@ -379,7 +379,7 @@ export class ActiveWorkflowRunner { * @memberof ActiveWorkflowRunner */ async isActive(id: string): Promise { - const workflow = await Db.collections.Workflow!.findOne(id); + const workflow = await Db.collections.Workflow.findOne(id); return !!workflow?.active; } @@ -512,7 +512,7 @@ export class ActiveWorkflowRunner { * @memberof ActiveWorkflowRunner */ async removeWorkflowWebhooks(workflowId: string): Promise { - const workflowData = await Db.collections.Workflow!.findOne(workflowId, { + const workflowData = await Db.collections.Workflow.findOne(workflowId, { relations: ['shared', 'shared.user', 'shared.user.globalRole'], }); if (workflowData === undefined) { @@ -715,7 +715,7 @@ export class ActiveWorkflowRunner { let workflowInstance: Workflow; try { if (workflowData === undefined) { - workflowData = (await Db.collections.Workflow!.findOne(workflowId, { + workflowData = (await Db.collections.Workflow.findOne(workflowId, { relations: ['shared', 'shared.user', 'shared.user.globalRole'], })) as IWorkflowDb; } diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index 27f838fffe..6477504b87 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -235,13 +235,11 @@ export class CredentialsHelper extends ICredentialsHelper { } const credential = userId - ? await Db.collections - .SharedCredentials!.findOneOrFail({ - relations: ['credentials'], - where: { credentials: { id: nodeCredential.id, type }, user: { id: userId } }, - }) - .then((shared) => shared.credentials) - : await Db.collections.Credentials!.findOneOrFail({ id: nodeCredential.id, type }); + ? await Db.collections.SharedCredentials.findOneOrFail({ + relations: ['credentials'], + where: { credentials: { id: nodeCredential.id, type }, user: { id: userId } }, + }).then((shared) => shared.credentials) + : await Db.collections.Credentials.findOneOrFail({ id: nodeCredential.id, type }); if (!credential) { throw new Error( @@ -445,7 +443,7 @@ export class CredentialsHelper extends ICredentialsHelper { type, }; - await Db.collections.Credentials!.update(findQuery, newCredentialsData); + await Db.collections.Credentials.update(findQuery, newCredentialsData); } getCredentialTestFunction( @@ -721,8 +719,7 @@ export async function getCredentialForUser( credentialId: string, user: User, ): Promise { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const sharedCredential = await Db.collections.SharedCredentials!.findOne({ + const sharedCredential = await Db.collections.SharedCredentials.findOne({ relations: ['credentials'], where: whereClause({ user, diff --git a/packages/cli/src/Db.ts b/packages/cli/src/Db.ts index 3ce8b993f9..5d9008ce75 100644 --- a/packages/cli/src/Db.ts +++ b/packages/cli/src/Db.ts @@ -1,3 +1,4 @@ +/* eslint-disable import/no-mutable-exports */ /* eslint-disable import/no-cycle */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ @@ -28,18 +29,8 @@ import { postgresMigrations } from './databases/postgresdb/migrations'; import { mysqlMigrations } from './databases/mysqldb/migrations'; import { sqliteMigrations } from './databases/sqlite/migrations'; -export const collections: IDatabaseCollections = { - Credentials: null, - Execution: null, - Workflow: null, - Webhook: null, - Tag: null, - Role: null, - User: null, - SharedCredentials: null, - SharedWorkflow: null, - Settings: null, -}; +export let isInitialized = false; +export const collections = {} as IDatabaseCollections; let connection: Connection; @@ -202,5 +193,7 @@ export async function init( collections.SharedWorkflow = linkRepository(entities.SharedWorkflow); collections.Settings = linkRepository(entities.Settings); + isInitialized = true; + return collections; } diff --git a/packages/cli/src/GenericHelpers.ts b/packages/cli/src/GenericHelpers.ts index 82b24af246..21093f52da 100644 --- a/packages/cli/src/GenericHelpers.ts +++ b/packages/cli/src/GenericHelpers.ts @@ -165,8 +165,8 @@ export async function generateUniqueName( const found: Array = entityType === 'workflow' - ? await Db.collections.Workflow!.find(findConditions) - : await Db.collections.Credentials!.find(findConditions); + ? await Db.collections.Workflow.find(findConditions) + : await Db.collections.Credentials.find(findConditions); // name is unique if (found.length === 0) { diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index cf8362838a..53d96621dd 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -72,16 +72,16 @@ export interface ICredentialsOverwrite { } export interface IDatabaseCollections { - Credentials: Repository | null; - Execution: Repository | null; - Workflow: Repository | null; - Webhook: Repository | null; - Tag: Repository | null; - Role: Repository | null; - User: Repository | null; - SharedCredentials: Repository | null; - SharedWorkflow: Repository | null; - Settings: Repository | null; + Credentials: Repository; + Execution: Repository; + Workflow: Repository; + Webhook: Repository; + Tag: Repository; + Role: Repository; + User: Repository; + SharedCredentials: Repository; + SharedWorkflow: Repository; + Settings: Repository; } export interface IWebhookDb { diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 14aff9569f..68155d0fd7 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -671,7 +671,7 @@ class App { // eslint-disable-next-line consistent-return this.app.use((req: express.Request, res: express.Response, next: express.NextFunction) => { - if (Db.collections.Workflow === null) { + if (!Db.isInitialized) { const error = new ResponseHelper.ResponseError('Database is not ready!', undefined, 503); return ResponseHelper.sendErrorResponse(res, error); } diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index 6c8defa448..59b29f69d7 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -15,7 +15,7 @@ import * as config from '../../config'; import { getWebhookBaseUrl } from '../WebhookHelpers'; export async function getWorkflowOwner(workflowId: string | number): Promise { - const sharedWorkflow = await Db.collections.SharedWorkflow!.findOneOrFail({ + const sharedWorkflow = await Db.collections.SharedWorkflow.findOneOrFail({ where: { workflow: { id: workflowId } }, relations: ['user', 'user.globalRole'], }); @@ -33,7 +33,7 @@ export function isEmailSetUp(): boolean { } async function getInstanceOwnerRole(): Promise { - const ownerRole = await Db.collections.Role!.findOneOrFail({ + const ownerRole = await Db.collections.Role.findOneOrFail({ where: { name: 'owner', scope: 'global', @@ -45,7 +45,7 @@ async function getInstanceOwnerRole(): Promise { export async function getInstanceOwner(): Promise { const ownerRole = await getInstanceOwnerRole(); - const owner = await Db.collections.User!.findOneOrFail({ + const owner = await Db.collections.User.findOneOrFail({ relations: ['globalRole'], where: { globalRole: ownerRole, @@ -121,7 +121,7 @@ export function sanitizeUser(user: User, withoutKeys?: string[]): PublicUser { } export async function getUserById(userId: string): Promise { - const user = await Db.collections.User!.findOneOrFail(userId, { + const user = await Db.collections.User.findOneOrFail(userId, { relations: ['globalRole'], }); return user; @@ -174,7 +174,7 @@ export async function checkPermissionsForExecution( } // Check for the user's permission to all used credentials - const credentialCount = await Db.collections.SharedCredentials!.count({ + const credentialCount = await Db.collections.SharedCredentials.count({ where: { user: { id: userId }, credentials: In(ids), diff --git a/packages/cli/src/UserManagement/auth/jwt.ts b/packages/cli/src/UserManagement/auth/jwt.ts index a247ad62b5..97d2e30ef0 100644 --- a/packages/cli/src/UserManagement/auth/jwt.ts +++ b/packages/cli/src/UserManagement/auth/jwt.ts @@ -37,7 +37,7 @@ export function issueJWT(user: User): JwtToken { } export async function resolveJwtContent(jwtPayload: JwtPayload): Promise { - const user = await Db.collections.User!.findOne(jwtPayload.id, { + const user = await Db.collections.User.findOne(jwtPayload.id, { relations: ['globalRole'], }); diff --git a/packages/cli/src/UserManagement/email/UserManagementMailer.ts b/packages/cli/src/UserManagement/email/UserManagementMailer.ts index 5b706aadfc..cda715a7c7 100644 --- a/packages/cli/src/UserManagement/email/UserManagementMailer.ts +++ b/packages/cli/src/UserManagement/email/UserManagementMailer.ts @@ -60,7 +60,6 @@ export class UserManagementMailer { let template = await getTemplate('invite', 'invite.html'); template = replaceStrings(template, inviteEmailData); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const result = await this.mailer?.sendMail({ emailRecipients: inviteEmailData.email, subject: 'You have been invited to n8n', diff --git a/packages/cli/src/UserManagement/routes/auth.ts b/packages/cli/src/UserManagement/routes/auth.ts index 628bade65d..a5d865eac0 100644 --- a/packages/cli/src/UserManagement/routes/auth.ts +++ b/packages/cli/src/UserManagement/routes/auth.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable import/no-cycle */ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import { Request, Response } from 'express'; import { IDataObject } from 'n8n-workflow'; @@ -32,7 +31,7 @@ export function authenticationMethods(this: N8nApp): void { let user; try { - user = await Db.collections.User!.findOne( + user = await Db.collections.User.findOne( { email: req.body.email, }, @@ -91,7 +90,7 @@ export function authenticationMethods(this: N8nApp): void { } try { - user = await Db.collections.User!.findOneOrFail({ relations: ['globalRole'] }); + user = await Db.collections.User.findOneOrFail({ relations: ['globalRole'] }); } catch (error) { throw new Error( 'No users found in database - did you wipe the users table? Create at least one user.', diff --git a/packages/cli/src/UserManagement/routes/me.ts b/packages/cli/src/UserManagement/routes/me.ts index dbe3e1e952..54f471bb81 100644 --- a/packages/cli/src/UserManagement/routes/me.ts +++ b/packages/cli/src/UserManagement/routes/me.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-cycle */ import express from 'express'; @@ -53,7 +52,7 @@ export function meNamespace(this: N8nApp): void { await validateEntity(newUser); - const user = await Db.collections.User!.save(newUser); + const user = await Db.collections.User.save(newUser); Logger.info('User updated successfully', { userId: user.id }); @@ -99,7 +98,7 @@ export function meNamespace(this: N8nApp): void { req.user.password = await hashPassword(validPassword); - const user = await Db.collections.User!.save(req.user); + const user = await Db.collections.User.save(req.user); Logger.info('Password updated successfully', { userId: user.id }); await issueCookie(res, user); @@ -135,7 +134,7 @@ export function meNamespace(this: N8nApp): void { ); } - await Db.collections.User!.save({ + await Db.collections.User.save({ id: req.user.id, personalizationAnswers, }); diff --git a/packages/cli/src/UserManagement/routes/owner.ts b/packages/cli/src/UserManagement/routes/owner.ts index 06c8605a49..f97237a9c6 100644 --- a/packages/cli/src/UserManagement/routes/owner.ts +++ b/packages/cli/src/UserManagement/routes/owner.ts @@ -55,7 +55,7 @@ export function ownerNamespace(this: N8nApp): void { ); } - let owner = await Db.collections.User!.findOne(userId, { + let owner = await Db.collections.User.findOne(userId, { relations: ['globalRole'], }); @@ -78,11 +78,11 @@ export function ownerNamespace(this: N8nApp): void { await validateEntity(owner); - owner = await Db.collections.User!.save(owner); + owner = await Db.collections.User.save(owner); Logger.info('Owner was set up successfully', { userId: req.user.id }); - await Db.collections.Settings!.update( + await Db.collections.Settings.update( { key: 'userManagement.isInstanceOwnerSetUp' }, { value: JSON.stringify(true) }, ); @@ -108,7 +108,7 @@ export function ownerNamespace(this: N8nApp): void { `/${this.restEndpoint}/owner/skip-setup`, // eslint-disable-next-line @typescript-eslint/naming-convention ResponseHelper.send(async (_req: AuthenticatedRequest, _res: express.Response) => { - await Db.collections.Settings!.update( + await Db.collections.Settings.update( { key: 'userManagement.skipInstanceOwnerSetup' }, { value: JSON.stringify(true) }, ); diff --git a/packages/cli/src/UserManagement/routes/passwordReset.ts b/packages/cli/src/UserManagement/routes/passwordReset.ts index 1217786079..1e1b19f51c 100644 --- a/packages/cli/src/UserManagement/routes/passwordReset.ts +++ b/packages/cli/src/UserManagement/routes/passwordReset.ts @@ -53,7 +53,7 @@ export function passwordResetNamespace(this: N8nApp): void { } // User should just be able to reset password if one is already present - const user = await Db.collections.User!.findOne({ email, password: Not(IsNull()) }); + const user = await Db.collections.User.findOne({ email, password: Not(IsNull()) }); if (!user || !user.password) { Logger.debug( @@ -69,7 +69,7 @@ export function passwordResetNamespace(this: N8nApp): void { const resetPasswordTokenExpiration = Math.floor(Date.now() / 1000) + 7200; - await Db.collections.User!.update(id, { resetPasswordToken, resetPasswordTokenExpiration }); + await Db.collections.User.update(id, { resetPasswordToken, resetPasswordTokenExpiration }); const baseUrl = getInstanceBaseUrl(); const url = new URL(`${baseUrl}/change-password`); @@ -134,7 +134,7 @@ export function passwordResetNamespace(this: N8nApp): void { // Timestamp is saved in seconds const currentTimestamp = Math.floor(Date.now() / 1000); - const user = await Db.collections.User!.findOne({ + const user = await Db.collections.User.findOne({ id, resetPasswordToken, resetPasswordTokenExpiration: MoreThanOrEqual(currentTimestamp), @@ -187,7 +187,7 @@ export function passwordResetNamespace(this: N8nApp): void { // Timestamp is saved in seconds const currentTimestamp = Math.floor(Date.now() / 1000); - const user = await Db.collections.User!.findOne({ + const user = await Db.collections.User.findOne({ id: userId, resetPasswordToken, resetPasswordTokenExpiration: MoreThanOrEqual(currentTimestamp), @@ -204,7 +204,7 @@ export function passwordResetNamespace(this: N8nApp): void { throw new ResponseHelper.ResponseError('', undefined, 404); } - await Db.collections.User!.update(userId, { + await Db.collections.User.update(userId, { password: await hashPassword(validPassword), resetPasswordToken: null, resetPasswordTokenExpiration: null, diff --git a/packages/cli/src/UserManagement/routes/users.ts b/packages/cli/src/UserManagement/routes/users.ts index 8f3a794d8f..3b19697036 100644 --- a/packages/cli/src/UserManagement/routes/users.ts +++ b/packages/cli/src/UserManagement/routes/users.ts @@ -1,6 +1,5 @@ /* eslint-disable no-restricted-syntax */ /* eslint-disable import/no-cycle */ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Response } from 'express'; import { In } from 'typeorm'; import validator from 'validator'; @@ -108,7 +107,7 @@ export function usersNamespace(this: N8nApp): void { createUsers[invite.email] = null; }); - const role = await Db.collections.Role!.findOne({ scope: 'global', name: 'member' }); + const role = await Db.collections.Role.findOne({ scope: 'global', name: 'member' }); if (!role) { Logger.error( @@ -122,7 +121,7 @@ export function usersNamespace(this: N8nApp): void { } // remove/exclude existing users from creation - const existingUsers = await Db.collections.User!.find({ + const existingUsers = await Db.collections.User.find({ where: { email: In(Object.keys(createUsers)) }, }); existingUsers.forEach((user) => { @@ -190,6 +189,7 @@ export function usersNamespace(this: N8nApp): void { }; if (result?.success) { void InternalHooksManager.getInstance().onUserTransactionalEmail({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion user_id: id!, message_type: 'New user invite', }); @@ -249,7 +249,7 @@ export function usersNamespace(this: N8nApp): void { } } - const users = await Db.collections.User!.find({ where: { id: In([inviterId, inviteeId]) } }); + const users = await Db.collections.User.find({ where: { id: In([inviterId, inviteeId]) } }); if (users.length !== 2) { Logger.debug( @@ -317,7 +317,7 @@ export function usersNamespace(this: N8nApp): void { const validPassword = validatePassword(password); - const users = await Db.collections.User!.find({ + const users = await Db.collections.User.find({ where: { id: In([inviterId, inviteeId]) }, relations: ['globalRole'], }); @@ -351,7 +351,7 @@ export function usersNamespace(this: N8nApp): void { invitee.lastName = lastName; invitee.password = await hashPassword(validPassword); - const updatedUser = await Db.collections.User!.save(invitee); + const updatedUser = await Db.collections.User.save(invitee); await issueCookie(res, updatedUser); @@ -366,7 +366,7 @@ export function usersNamespace(this: N8nApp): void { this.app.get( `/${this.restEndpoint}/users`, ResponseHelper.send(async () => { - const users = await Db.collections.User!.find({ relations: ['globalRole'] }); + const users = await Db.collections.User.find({ relations: ['globalRole'] }); return users.map((user): PublicUser => sanitizeUser(user, ['personalizationAnswers'])); }), @@ -398,7 +398,7 @@ export function usersNamespace(this: N8nApp): void { ); } - const users = await Db.collections.User!.find({ + const users = await Db.collections.User.find({ where: { id: In([transferId, idToDelete]) }, }); @@ -432,11 +432,11 @@ export function usersNamespace(this: N8nApp): void { } const [ownedSharedWorkflows, ownedSharedCredentials] = await Promise.all([ - Db.collections.SharedWorkflow!.find({ + Db.collections.SharedWorkflow.find({ relations: ['workflow'], where: { user: userToDelete }, }), - Db.collections.SharedCredentials!.find({ + Db.collections.SharedCredentials.find({ relations: ['credentials'], where: { user: userToDelete }, }), @@ -494,7 +494,7 @@ export function usersNamespace(this: N8nApp): void { ); } - const reinvitee = await Db.collections.User!.findOne({ id: idToReinvite }); + const reinvitee = await Db.collections.User.findOne({ id: idToReinvite }); if (!reinvitee) { Logger.debug( diff --git a/packages/cli/src/WaitTracker.ts b/packages/cli/src/WaitTracker.ts index 1534ac325b..327af008f2 100644 --- a/packages/cli/src/WaitTracker.ts +++ b/packages/cli/src/WaitTracker.ts @@ -71,7 +71,7 @@ export class WaitTrackerClass { ); } - const executions = await Db.collections.Execution!.find(findQuery); + const executions = await Db.collections.Execution.find(findQuery); if (executions.length === 0) { return; @@ -107,7 +107,7 @@ export class WaitTrackerClass { } // Also check in database - const execution = await Db.collections.Execution!.findOne(executionId); + const execution = await Db.collections.Execution.findOne(executionId); if (execution === undefined || !execution.waitTill) { throw new Error(`The execution ID "${executionId}" could not be found.`); @@ -127,7 +127,7 @@ export class WaitTrackerClass { fullExecutionData.stoppedAt = new Date(); fullExecutionData.waitTill = undefined; - await Db.collections.Execution!.update( + await Db.collections.Execution.update( executionId, ResponseHelper.flattenExecutionData(fullExecutionData), ); @@ -146,7 +146,7 @@ export class WaitTrackerClass { (async () => { // Get the data to execute - const fullExecutionDataFlatted = await Db.collections.Execution!.findOne(executionId); + const fullExecutionDataFlatted = await Db.collections.Execution.findOne(executionId); if (fullExecutionDataFlatted === undefined) { throw new Error(`The execution with the id "${executionId}" does not exist.`); diff --git a/packages/cli/src/WorkflowCredentials.ts b/packages/cli/src/WorkflowCredentials.ts index a52232866f..f266b9bbc2 100644 --- a/packages/cli/src/WorkflowCredentials.ts +++ b/packages/cli/src/WorkflowCredentials.ts @@ -33,8 +33,8 @@ export async function WorkflowCredentials(nodes: INode[]): Promise setTimeout(() => { throttling = false; @@ -371,8 +369,7 @@ export function hookFunctionsPreExecute(parentProcessMode?: string): IWorkflowEx { executionId: this.executionId, nodeName }, ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const execution = await Db.collections.Execution!.findOne(this.executionId); + const execution = await Db.collections.Execution.findOne(this.executionId); if (execution === undefined) { // Something went badly wrong if this happens. @@ -418,8 +415,7 @@ export function hookFunctionsPreExecute(parentProcessMode?: string): IWorkflowEx const flattenedExecutionData = ResponseHelper.flattenExecutionData(fullExecutionData); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await Db.collections.Execution!.update( + await Db.collections.Execution.update( this.executionId, flattenedExecutionData as IExecutionFlattedDb, ); @@ -503,7 +499,7 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { if (isManualMode && !saveManualExecutions && !fullRunData.waitTill) { // Data is always saved, so we remove from database - await Db.collections.Execution!.delete(this.executionId); + await Db.collections.Execution.delete(this.executionId); await BinaryDataManager.getInstance().markDataForDeletionByExecutionId( this.executionId, ); @@ -539,7 +535,7 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { ); } // Data is always saved, so we remove from database - await Db.collections.Execution!.delete(this.executionId); + await Db.collections.Execution.delete(this.executionId); await BinaryDataManager.getInstance().markDataForDeletionByExecutionId( this.executionId, ); @@ -580,7 +576,7 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { const executionData = ResponseHelper.flattenExecutionData(fullExecutionData); // Save the Execution in DB - await Db.collections.Execution!.update( + await Db.collections.Execution.update( this.executionId, executionData as IExecutionFlattedDb, ); @@ -588,7 +584,7 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { if (fullRunData.finished === true && this.retryOf !== undefined) { // If the retry was successful save the reference it on the original execution // await Db.collections.Execution!.save(executionData as IExecutionFlattedDb); - await Db.collections.Execution!.update(this.retryOf, { + await Db.collections.Execution.update(this.retryOf, { retrySuccessId: this.executionId, }); } @@ -693,14 +689,14 @@ function hookFunctionsSaveWorker(): IWorkflowExecuteHooks { const executionData = ResponseHelper.flattenExecutionData(fullExecutionData); // Save the Execution in DB - await Db.collections.Execution!.update( + await Db.collections.Execution.update( this.executionId, executionData as IExecutionFlattedDb, ); if (fullRunData.finished === true && this.retryOf !== undefined) { // If the retry was successful save the reference it on the original execution - await Db.collections.Execution!.update(this.retryOf, { + await Db.collections.Execution.update(this.retryOf, { retrySuccessId: this.executionId, }); } @@ -804,7 +800,7 @@ export async function getWorkflowData( relations = relations.filter((relation) => relation !== 'workflow.tags'); } - const shared = await Db.collections.SharedWorkflow!.findOne({ + const shared = await Db.collections.SharedWorkflow.findOne({ relations, where: whereClause({ user, @@ -959,7 +955,7 @@ export async function executeWorkflow( const executionData = ResponseHelper.flattenExecutionData(fullExecutionData); - await Db.collections.Execution!.update(executionId, executionData as IExecutionFlattedDb); + await Db.collections.Execution.update(executionId, executionData as IExecutionFlattedDb); throw { ...error, stack: error.stack, diff --git a/packages/cli/src/WorkflowHelpers.ts b/packages/cli/src/WorkflowHelpers.ts index 72f7cf2eb5..8ac6cc2284 100644 --- a/packages/cli/src/WorkflowHelpers.ts +++ b/packages/cli/src/WorkflowHelpers.ts @@ -107,9 +107,9 @@ export async function executeErrorWorkflow( const user = await getWorkflowOwner(workflowErrorData.workflow.id!); if (user.globalRole.name === 'owner') { - workflowData = await Db.collections.Workflow!.findOne({ id: Number(workflowId) }); + workflowData = await Db.collections.Workflow.findOne({ id: Number(workflowId) }); } else { - const sharedWorkflowData = await Db.collections.SharedWorkflow!.findOne({ + const sharedWorkflowData = await Db.collections.SharedWorkflow.findOne({ where: { workflow: { id: workflowId }, user, @@ -121,7 +121,7 @@ export async function executeErrorWorkflow( } } } else { - workflowData = await Db.collections.Workflow!.findOne({ id: Number(workflowId) }); + workflowData = await Db.collections.Workflow.findOne({ id: Number(workflowId) }); } if (workflowData === undefined) { @@ -426,7 +426,7 @@ export async function saveStaticDataById( workflowId: string | number, newStaticData: IDataObject, ): Promise { - await Db.collections.Workflow!.update(workflowId, { + await Db.collections.Workflow.update(workflowId, { staticData: newStaticData, }); } @@ -440,7 +440,7 @@ export async function saveStaticDataById( */ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function getStaticDataById(workflowId: string | number) { - const workflowData = await Db.collections.Workflow!.findOne(workflowId, { + const workflowData = await Db.collections.Workflow.findOne(workflowId, { select: ['staticData'], }); @@ -586,7 +586,7 @@ export function whereClause({ * Get the IDs of the workflows that have been shared with the user. */ export async function getSharedWorkflowIds(user: User): Promise { - const sharedWorkflows = await Db.collections.SharedWorkflow!.find({ + const sharedWorkflows = await Db.collections.SharedWorkflow.find({ relations: ['workflow'], where: whereClause({ user, diff --git a/packages/cli/src/WorkflowRunner.ts b/packages/cli/src/WorkflowRunner.ts index b88ee57a53..495a37c6f7 100644 --- a/packages/cli/src/WorkflowRunner.ts +++ b/packages/cli/src/WorkflowRunner.ts @@ -513,7 +513,7 @@ export class WorkflowRunner { reject(error); } - const executionDb = (await Db.collections.Execution!.findOne( + const executionDb = (await Db.collections.Execution.findOne( executionId, )) as IExecutionFlattedDb; const fullExecutionData = ResponseHelper.unflattenExecutionData(executionDb); @@ -548,7 +548,7 @@ export class WorkflowRunner { (workflowDidSucceed && saveDataSuccessExecution === 'none') || (!workflowDidSucceed && saveDataErrorExecution === 'none') ) { - await Db.collections.Execution!.delete(executionId); + await Db.collections.Execution.delete(executionId); await BinaryDataManager.getInstance().markDataForDeletionByExecutionId(executionId); } // eslint-disable-next-line id-denylist diff --git a/packages/cli/src/api/credentials.api.ts b/packages/cli/src/api/credentials.api.ts index f6d054782d..6880017aa8 100644 --- a/packages/cli/src/api/credentials.api.ts +++ b/packages/cli/src/api/credentials.api.ts @@ -53,12 +53,12 @@ credentialsController.get( try { if (req.user.globalRole.name === 'owner') { - credentials = await Db.collections.Credentials!.find({ + credentials = await Db.collections.Credentials.find({ select: ['id', 'name', 'type', 'nodesAccess', 'createdAt', 'updatedAt'], where: filter, }); } else { - const shared = await Db.collections.SharedCredentials!.find({ + const shared = await Db.collections.SharedCredentials.find({ where: whereClause({ user: req.user, entityType: 'credentials', @@ -67,7 +67,7 @@ credentialsController.get( if (!shared.length) return []; - credentials = await Db.collections.Credentials!.find({ + credentials = await Db.collections.Credentials.find({ select: ['id', 'name', 'type', 'nodesAccess', 'createdAt', 'updatedAt'], where: { id: In(shared.map(({ credentialId }) => credentialId)), @@ -175,7 +175,7 @@ credentialsController.post( await externalHooks.run('credentials.create', [encryptedData]); - const role = await Db.collections.Role!.findOneOrFail({ + const role = await Db.collections.Role.findOneOrFail({ name: 'owner', scope: 'credential', }); @@ -213,7 +213,7 @@ credentialsController.delete( ResponseHelper.send(async (req: CredentialRequest.Delete) => { const { id: credentialId } = req.params; - const shared = await Db.collections.SharedCredentials!.findOne({ + const shared = await Db.collections.SharedCredentials.findOne({ relations: ['credentials'], where: whereClause({ user: req.user, @@ -236,7 +236,7 @@ credentialsController.delete( await externalHooks.run('credentials.delete', [credentialId]); - await Db.collections.Credentials!.remove(shared.credentials); + await Db.collections.Credentials.remove(shared.credentials); return true; }), @@ -255,7 +255,7 @@ credentialsController.patch( await validateEntity(updateData); - const shared = await Db.collections.SharedCredentials!.findOne({ + const shared = await Db.collections.SharedCredentials.findOne({ relations: ['credentials'], where: whereClause({ user: req.user, @@ -329,11 +329,11 @@ credentialsController.patch( await externalHooks.run('credentials.update', [newCredentialData]); // Update the credentials in DB - await Db.collections.Credentials!.update(credentialId, newCredentialData); + await Db.collections.Credentials.update(credentialId, newCredentialData); // We sadly get nothing back from "update". Neither if it updated a record // nor the new value. So query now the updated entry. - const responseData = await Db.collections.Credentials!.findOne(credentialId); + const responseData = await Db.collections.Credentials.findOne(credentialId); if (responseData === undefined) { throw new ResponseHelper.ResponseError( @@ -363,7 +363,7 @@ credentialsController.get( ResponseHelper.send(async (req: CredentialRequest.Get) => { const { id: credentialId } = req.params; - const shared = await Db.collections.SharedCredentials!.findOne({ + const shared = await Db.collections.SharedCredentials.findOne({ relations: ['credentials'], where: whereClause({ user: req.user,