mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-23 20:50:00 +00:00
feat(core): Use WebCrypto to generate all random numbers and strings (#9786)
This commit is contained in:
committed by
GitHub
parent
cfc4db00e3
commit
65c5609ab5
@@ -7,6 +7,7 @@ module.exports = {
|
||||
globalSetup: '<rootDir>/test/setup.ts',
|
||||
globalTeardown: '<rootDir>/test/teardown.ts',
|
||||
setupFilesAfterEnv: [
|
||||
'n8n-workflow/test/setup.ts',
|
||||
'<rootDir>/test/setup-test-folder.ts',
|
||||
'<rootDir>/test/setup-mocks.ts',
|
||||
'<rootDir>/test/extend-expect.ts',
|
||||
|
||||
@@ -3,6 +3,8 @@ import type { Entry as LdapUser } from 'ldapts';
|
||||
import { Filter } from 'ldapts/filters/Filter';
|
||||
import { Container } from 'typedi';
|
||||
import { validate } from 'jsonschema';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import * as Db from '@/Db';
|
||||
import config from '@/config';
|
||||
import { User } from '@db/entities/User';
|
||||
@@ -38,13 +40,6 @@ export const getLdapLoginLabel = (): string => config.getEnv(LDAP_LOGIN_LABEL);
|
||||
*/
|
||||
export const isLdapLoginEnabled = (): boolean => config.getEnv(LDAP_LOGIN_ENABLED);
|
||||
|
||||
/**
|
||||
* Return a random password to be assigned to the LDAP users
|
||||
*/
|
||||
export const randomPassword = (): string => {
|
||||
return Math.random().toString(36).slice(-8);
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the structure of the LDAP configuration schema
|
||||
*/
|
||||
@@ -161,7 +156,7 @@ export const mapLdapUserToDbUser = (
|
||||
Object.assign(user, data);
|
||||
if (toCreate) {
|
||||
user.role = 'global:member';
|
||||
user.password = randomPassword();
|
||||
user.password = randomString(8);
|
||||
user.disabled = false;
|
||||
} else {
|
||||
user.disabled = true;
|
||||
@@ -278,7 +273,7 @@ export const createLdapAuthIdentity = async (user: User, ldapId: string) => {
|
||||
|
||||
export const createLdapUserOnLocalDb = async (data: Partial<User>, ldapId: string) => {
|
||||
const { user } = await Container.get(UserRepository).createUserWithProject({
|
||||
password: randomPassword(),
|
||||
password: randomString(8),
|
||||
role: 'global:member',
|
||||
...data,
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import { createReadStream, createWriteStream, existsSync } from 'fs';
|
||||
import { pipeline } from 'stream/promises';
|
||||
import replaceStream from 'replacestream';
|
||||
import glob from 'fast-glob';
|
||||
import { jsonParse } from 'n8n-workflow';
|
||||
import { jsonParse, randomString } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import { ActiveExecutions } from '@/ActiveExecutions';
|
||||
@@ -265,12 +265,7 @@ export class Start extends BaseCommand {
|
||||
|
||||
if (tunnelSubdomain === '') {
|
||||
// When no tunnel subdomain did exist yet create a new random one
|
||||
const availableCharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
tunnelSubdomain = Array.from({ length: 24 })
|
||||
.map(() =>
|
||||
availableCharacters.charAt(Math.floor(Math.random() * availableCharacters.length)),
|
||||
)
|
||||
.join('');
|
||||
tunnelSubdomain = randomString(24).toLowerCase();
|
||||
|
||||
this.instanceSettings.update({ tunnelSubdomain });
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import { ALPHABET } from 'n8n-workflow';
|
||||
import type { N8nInstanceType } from '@/Interfaces';
|
||||
|
||||
const nanoid = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 16);
|
||||
const nanoid = customAlphabet(ALPHABET, 16);
|
||||
|
||||
export function generateNanoId() {
|
||||
return nanoid();
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import Container from 'typedi';
|
||||
import { stringify } from 'flatted';
|
||||
import { NodeConnectionType, randomInt } from 'n8n-workflow';
|
||||
|
||||
import { mockInstance } from '@test/mocking';
|
||||
import { randomInteger } from '@test-integration/random';
|
||||
import { createWorkflow } from '@test-integration/db/workflows';
|
||||
import { createExecution } from '@test-integration/db/executions';
|
||||
import * as testDb from '@test-integration/testDb';
|
||||
|
||||
import { NodeConnectionType } from 'n8n-workflow';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { OrchestrationService } from '@/services/orchestration.service';
|
||||
import config from '@/config';
|
||||
import { ExecutionRecoveryService } from '@/executions/execution-recovery.service';
|
||||
import { ExecutionRepository } from '@/databases/repositories/execution.repository';
|
||||
import type { WorkflowEntity } from '@/databases/entities/WorkflowEntity';
|
||||
import { InternalHooks } from '@/InternalHooks';
|
||||
import { Push } from '@/push';
|
||||
import { ARTIFICIAL_TASK_DATA } from '@/constants';
|
||||
@@ -20,9 +20,7 @@ import { NodeCrashedError } from '@/errors/node-crashed.error';
|
||||
import { WorkflowCrashedError } from '@/errors/workflow-crashed.error';
|
||||
import { EventMessageNode } from '@/eventbus/EventMessageClasses/EventMessageNode';
|
||||
import { EventMessageWorkflow } from '@/eventbus/EventMessageClasses/EventMessageWorkflow';
|
||||
|
||||
import type { EventMessageTypes as EventMessage } from '@/eventbus/EventMessageClasses';
|
||||
import type { WorkflowEntity } from '@/databases/entities/WorkflowEntity';
|
||||
import type { Logger } from '@/Logger';
|
||||
|
||||
/**
|
||||
@@ -301,7 +299,7 @@ describe('ExecutionRecoveryService', () => {
|
||||
/**
|
||||
* Arrange
|
||||
*/
|
||||
const inexistentExecutionId = randomInteger(100).toString();
|
||||
const inexistentExecutionId = randomInt(100).toString();
|
||||
const noMessages: EventMessage[] = [];
|
||||
|
||||
/**
|
||||
@@ -373,7 +371,7 @@ describe('ExecutionRecoveryService', () => {
|
||||
/**
|
||||
* Arrange
|
||||
*/
|
||||
const inexistentExecutionId = randomInteger(100).toString();
|
||||
const inexistentExecutionId = randomInt(100).toString();
|
||||
const messages = setupMessages(inexistentExecutionId, 'Some workflow');
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import { Container } from 'typedi';
|
||||
import type { FlowResult } from 'samlify/types/src/flow';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import { AuthIdentity } from '@db/entities/AuthIdentity';
|
||||
import type { User } from '@db/entities/User';
|
||||
import { UserRepository } from '@db/repositories/user.repository';
|
||||
import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository';
|
||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||
import { AuthError } from '@/errors/response-errors/auth.error';
|
||||
import { License } from '@/License';
|
||||
import { PasswordUtility } from '@/services/password.utility';
|
||||
|
||||
import type { SamlPreferences } from './types/samlPreferences';
|
||||
import type { SamlUserAttributes } from './types/samlUserAttributes';
|
||||
import type { FlowResult } from 'samlify/types/src/flow';
|
||||
import type { SamlAttributeMapping } from './types/samlAttributeMapping';
|
||||
import { SAML_LOGIN_ENABLED, SAML_LOGIN_LABEL } from './constants';
|
||||
import {
|
||||
@@ -17,10 +24,6 @@ import {
|
||||
} from '../ssoHelpers';
|
||||
import { getServiceProviderConfigTestReturnUrl } from './serviceProvider.ee';
|
||||
import type { SamlConfiguration } from './types/requests';
|
||||
import { UserRepository } from '@db/repositories/user.repository';
|
||||
import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository';
|
||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||
import { AuthError } from '@/errors/response-errors/auth.error';
|
||||
|
||||
/**
|
||||
* Check whether the SAML feature is licensed and enabled in the instance
|
||||
@@ -73,39 +76,18 @@ export const isSamlPreferences = (candidate: unknown): candidate is SamlPreferen
|
||||
);
|
||||
};
|
||||
|
||||
export function generatePassword(): string {
|
||||
const length = 18;
|
||||
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
const charsetNoNumbers = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const randomNumber = Math.floor(Math.random() * 10);
|
||||
const randomUpper = charset.charAt(Math.floor(Math.random() * charsetNoNumbers.length));
|
||||
const randomNumberPosition = Math.floor(Math.random() * length);
|
||||
const randomUpperPosition = Math.floor(Math.random() * length);
|
||||
let password = '';
|
||||
for (let i = 0, n = charset.length; i < length; ++i) {
|
||||
password += charset.charAt(Math.floor(Math.random() * n));
|
||||
}
|
||||
password =
|
||||
password.substring(0, randomNumberPosition) +
|
||||
randomNumber.toString() +
|
||||
password.substring(randomNumberPosition);
|
||||
password =
|
||||
password.substring(0, randomUpperPosition) +
|
||||
randomUpper +
|
||||
password.substring(randomUpperPosition);
|
||||
return password;
|
||||
}
|
||||
|
||||
export async function createUserFromSamlAttributes(attributes: SamlUserAttributes): Promise<User> {
|
||||
return await Container.get(UserRepository).manager.transaction(async (trx) => {
|
||||
const { user } = await Container.get(UserRepository).createUserWithProject(
|
||||
const randomPassword = randomString(18);
|
||||
const userRepository = Container.get(UserRepository);
|
||||
return await userRepository.manager.transaction(async (trx) => {
|
||||
const { user } = await userRepository.createUserWithProject(
|
||||
{
|
||||
email: attributes.email.toLowerCase(),
|
||||
firstName: attributes.firstName,
|
||||
lastName: attributes.lastName,
|
||||
role: 'global:member',
|
||||
// generates a password that is not used or known to the user
|
||||
password: await Container.get(PasswordUtility).hash(generatePassword()),
|
||||
password: await Container.get(PasswordUtility).hash(randomPassword),
|
||||
},
|
||||
trx,
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { CliWorkflowOperationError, SubworkflowOperationError } from 'n8n-workflow';
|
||||
import type { INode } from 'n8n-workflow';
|
||||
import { STARTING_NODES } from './constants';
|
||||
import { STARTING_NODES } from '@/constants';
|
||||
|
||||
/**
|
||||
* Returns if the given id is a valid workflow id
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Container } from 'typedi';
|
||||
import type { INode, WorkflowSettings } from 'n8n-workflow';
|
||||
import { SubworkflowOperationError, Workflow } from 'n8n-workflow';
|
||||
import { SubworkflowOperationError, Workflow, randomInt } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import type { User } from '@db/entities/User';
|
||||
@@ -15,11 +15,7 @@ import { OwnershipService } from '@/services/ownership.service';
|
||||
import { PermissionChecker } from '@/UserManagement/PermissionChecker';
|
||||
|
||||
import { mockInstance } from '../shared/mocking';
|
||||
import {
|
||||
randomCredentialPayload as randomCred,
|
||||
randomName,
|
||||
randomPositiveDigit,
|
||||
} from '../integration/shared/random';
|
||||
import { randomCredentialPayload as randomCred, randomName } from '../integration/shared/random';
|
||||
import { LicenseMocker } from '../integration/shared/license';
|
||||
import * as testDb from '../integration/shared/testDb';
|
||||
import type { SaveCredentialFunction } from '../integration/shared/types';
|
||||
@@ -77,7 +73,7 @@ const ownershipService = mockInstance(OwnershipService);
|
||||
|
||||
const createWorkflow = async (nodes: INode[], workflowOwner?: User): Promise<WorkflowEntity> => {
|
||||
const workflowDetails = {
|
||||
id: randomPositiveDigit().toString(),
|
||||
id: randomInt(1, 10).toString(),
|
||||
name: 'test',
|
||||
active: false,
|
||||
connections: {},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Container } from 'typedi';
|
||||
import type { Scope } from '@sentry/node';
|
||||
import { Credentials } from 'n8n-core';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import type { ListQuery } from '@/requests';
|
||||
import type { User } from '@db/entities/User';
|
||||
@@ -16,7 +17,6 @@ import {
|
||||
randomCredentialPayload as payload,
|
||||
randomCredentialPayload,
|
||||
randomName,
|
||||
randomString,
|
||||
} from '../shared/random';
|
||||
import {
|
||||
saveCredential,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Container } from 'typedi';
|
||||
import { IsNull } from '@n8n/typeorm';
|
||||
import validator from 'validator';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import type { User } from '@db/entities/User';
|
||||
@@ -8,13 +9,7 @@ import { UserRepository } from '@db/repositories/user.repository';
|
||||
import { ProjectRepository } from '@db/repositories/project.repository';
|
||||
|
||||
import { SUCCESS_RESPONSE_BODY } from './shared/constants';
|
||||
import {
|
||||
randomApiKey,
|
||||
randomEmail,
|
||||
randomName,
|
||||
randomString,
|
||||
randomValidPassword,
|
||||
} from './shared/random';
|
||||
import { randomApiKey, randomEmail, randomName, randomValidPassword } from './shared/random';
|
||||
import * as testDb from './shared/testDb';
|
||||
import * as utils from './shared/utils/';
|
||||
import { addApiKey, createOwner, createUser, createUserShell } from './shared/db/users';
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import Container from 'typedi';
|
||||
import { randomInt, randomString } from 'n8n-workflow';
|
||||
|
||||
import { AuthService } from '@/auth/auth.service';
|
||||
import config from '@/config';
|
||||
import type { User } from '@db/entities/User';
|
||||
import { AuthUserRepository } from '@db/repositories/authUser.repository';
|
||||
import { randomPassword } from '@/Ldap/helpers';
|
||||
import { TOTPService } from '@/Mfa/totp.service';
|
||||
|
||||
import * as testDb from '../shared/testDb';
|
||||
import * as utils from '../shared/utils';
|
||||
import { randomDigit, randomString, randomValidPassword, uniqueId } from '../shared/random';
|
||||
import { randomValidPassword, uniqueId } from '../shared/random';
|
||||
import { createUser, createUserWithMfaEnabled } from '../shared/db/users';
|
||||
|
||||
jest.mock('@/telemetry');
|
||||
@@ -150,18 +150,6 @@ describe('Disable MFA setup', () => {
|
||||
});
|
||||
|
||||
describe('Change password with MFA enabled', () => {
|
||||
test('PATCH /me/password should fail due to missing MFA token', async () => {
|
||||
const { user, rawPassword } = await createUserWithMfaEnabled();
|
||||
|
||||
const newPassword = randomPassword();
|
||||
|
||||
await testServer
|
||||
.authAgentFor(user)
|
||||
.patch('/me/password')
|
||||
.send({ currentPassword: rawPassword, newPassword })
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
test('POST /change-password should fail due to missing MFA token', async () => {
|
||||
await createUserWithMfaEnabled();
|
||||
|
||||
@@ -185,7 +173,7 @@ describe('Change password with MFA enabled', () => {
|
||||
.send({
|
||||
password: newPassword,
|
||||
token: resetPasswordToken,
|
||||
mfaToken: randomDigit(),
|
||||
mfaToken: randomInt(10),
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
@@ -226,7 +214,7 @@ describe('Change password with MFA enabled', () => {
|
||||
|
||||
describe('Login', () => {
|
||||
test('POST /login with email/password should succeed when mfa is disabled', async () => {
|
||||
const password = randomPassword();
|
||||
const password = randomString(8);
|
||||
|
||||
const user = await createUser({ password });
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Container } from 'typedi';
|
||||
import validator from 'validator';
|
||||
|
||||
import config from '@/config';
|
||||
import type { User } from '@db/entities/User';
|
||||
import { UserRepository } from '@db/repositories/user.repository';
|
||||
|
||||
import {
|
||||
randomEmail,
|
||||
randomInvalidPassword,
|
||||
@@ -11,8 +14,6 @@ import {
|
||||
import * as testDb from './shared/testDb';
|
||||
import * as utils from './shared/utils/';
|
||||
import { createUserShell } from './shared/db/users';
|
||||
import { UserRepository } from '@db/repositories/user.repository';
|
||||
import Container from 'typedi';
|
||||
|
||||
const testServer = utils.setupTestServer({ endpointGroups: ['owner'] });
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { v4 as uuid } from 'uuid';
|
||||
import { compare } from 'bcryptjs';
|
||||
import { Container } from 'typedi';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import { AuthService } from '@/auth/auth.service';
|
||||
import { License } from '@/License';
|
||||
@@ -12,6 +13,7 @@ import { ExternalHooks } from '@/ExternalHooks';
|
||||
import { JwtService } from '@/services/jwt.service';
|
||||
import { UserManagementMailer } from '@/UserManagement/email';
|
||||
import { UserRepository } from '@db/repositories/user.repository';
|
||||
import { PasswordUtility } from '@/services/password.utility';
|
||||
|
||||
import { mockInstance } from '../shared/mocking';
|
||||
import { getAuthToken, setupTestServer } from './shared/utils/';
|
||||
@@ -19,12 +21,10 @@ import {
|
||||
randomEmail,
|
||||
randomInvalidPassword,
|
||||
randomName,
|
||||
randomString,
|
||||
randomValidPassword,
|
||||
} from './shared/random';
|
||||
import * as testDb from './shared/testDb';
|
||||
import { createUser } from './shared/db/users';
|
||||
import { PasswordUtility } from '@/services/password.utility';
|
||||
|
||||
config.set('userManagement.jwtSecret', randomString(5, 10));
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Container } from 'typedi';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import type { User } from '@db/entities/User';
|
||||
import { CredentialsRepository } from '@db/repositories/credentials.repository';
|
||||
import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository';
|
||||
|
||||
import { randomApiKey, randomName, randomString } from '../shared/random';
|
||||
import { randomApiKey, randomName } from '../shared/random';
|
||||
import * as utils from '../shared/utils/';
|
||||
import type { CredentialPayload, SaveCredentialFunction } from '../shared/types';
|
||||
import * as testDb from '../shared/testDb';
|
||||
|
||||
@@ -1,39 +1,19 @@
|
||||
import { randomBytes } from 'crypto';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { randomInt, randomString, UPPERCASE_LETTERS } from 'n8n-workflow';
|
||||
|
||||
import { MIN_PASSWORD_CHAR_LENGTH, MAX_PASSWORD_CHAR_LENGTH } from '@/constants';
|
||||
import type { CredentialPayload } from './types';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
/**
|
||||
* Create a random alphanumeric string of random length between two limits, both inclusive.
|
||||
* Limits should be even numbers (round down otherwise).
|
||||
*/
|
||||
export function randomString(min: number, max: number) {
|
||||
const randomInteger = Math.floor(Math.random() * (max - min) + min) + 1;
|
||||
return randomBytes(randomInteger / 2).toString('hex');
|
||||
}
|
||||
export const randomApiKey = () => `n8n_api_${randomString(40)}`;
|
||||
|
||||
export function randomApiKey() {
|
||||
return `n8n_api_${randomBytes(20).toString('hex')}`;
|
||||
}
|
||||
export const chooseRandomly = <T>(array: T[]) => array[randomInt(array.length)];
|
||||
|
||||
export const chooseRandomly = <T>(array: T[]) => array[Math.floor(Math.random() * array.length)];
|
||||
|
||||
export const randomInteger = (max = 1000) => Math.floor(Math.random() * max);
|
||||
|
||||
export const randomDigit = () => Math.floor(Math.random() * 10);
|
||||
|
||||
export const randomPositiveDigit = (): number => {
|
||||
const digit = randomDigit();
|
||||
|
||||
return digit === 0 ? randomPositiveDigit() : digit;
|
||||
};
|
||||
|
||||
const randomUppercaseLetter = () => chooseRandomly('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''));
|
||||
const randomUppercaseLetter = () => chooseRandomly(UPPERCASE_LETTERS.split(''));
|
||||
|
||||
export const randomValidPassword = () =>
|
||||
randomString(MIN_PASSWORD_CHAR_LENGTH, MAX_PASSWORD_CHAR_LENGTH - 2) +
|
||||
randomUppercaseLetter() +
|
||||
randomDigit();
|
||||
randomInt(10);
|
||||
|
||||
export const randomInvalidPassword = () =>
|
||||
chooseRandomly([
|
||||
@@ -54,7 +34,7 @@ const POPULAR_TOP_LEVEL_DOMAINS = ['com', 'org', 'net', 'io', 'edu'];
|
||||
|
||||
const randomTopLevelDomain = () => chooseRandomly(POPULAR_TOP_LEVEL_DOMAINS);
|
||||
|
||||
export const randomName = () => randomString(4, 8);
|
||||
export const randomName = () => randomString(4, 8).toLowerCase();
|
||||
|
||||
export const randomCredentialPayload = (): CredentialPayload => ({
|
||||
name: randomName(),
|
||||
|
||||
@@ -2,13 +2,12 @@ import type { DataSourceOptions, Repository } from '@n8n/typeorm';
|
||||
import { DataSource as Connection } from '@n8n/typeorm';
|
||||
import { Container } from 'typedi';
|
||||
import type { Class } from 'n8n-core';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import * as Db from '@/Db';
|
||||
import { getOptionOverrides } from '@db/config';
|
||||
|
||||
import { randomString } from './random';
|
||||
|
||||
export const testDbPrefix = 'n8n_test_';
|
||||
|
||||
/**
|
||||
@@ -16,7 +15,7 @@ export const testDbPrefix = 'n8n_test_';
|
||||
*/
|
||||
export async function init() {
|
||||
const dbType = config.getEnv('database.type');
|
||||
const testDbName = `${testDbPrefix}${randomString(6, 10)}_${Date.now()}`;
|
||||
const testDbName = `${testDbPrefix}${randomString(6, 10).toLowerCase()}_${Date.now()}`;
|
||||
|
||||
if (dbType === 'postgresdb') {
|
||||
const bootstrapPostgres = await new Connection(
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { type Response } from 'express';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { randomString } from 'n8n-workflow';
|
||||
import type { IHttpRequestMethods } from 'n8n-workflow';
|
||||
|
||||
import type { IWebhookManager, WebhookCORSRequest, WebhookRequest } from '@/Interfaces';
|
||||
import { webhookRequestHandler } from '@/WebhookHelpers';
|
||||
|
||||
@@ -82,7 +84,7 @@ describe('WebhookHelpers', () => {
|
||||
});
|
||||
|
||||
it('should handle wildcard origin', async () => {
|
||||
const randomOrigin = (Math.random() * 10e6).toString(16);
|
||||
const randomOrigin = randomString(10);
|
||||
const req = mock<WebhookRequest | WebhookCORSRequest>({
|
||||
method: 'OPTIONS',
|
||||
headers: {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { randomInt } from 'n8n-workflow';
|
||||
import { User } from '@db/entities/User';
|
||||
import { CredentialsEntity } from '@db/entities/CredentialsEntity';
|
||||
import { Project } from '@db/entities/Project';
|
||||
|
||||
import {
|
||||
randomCredentialPayload,
|
||||
randomEmail,
|
||||
randomInteger,
|
||||
randomName,
|
||||
uniqueId,
|
||||
} from '../../integration/shared/random';
|
||||
import { Project } from '@/databases/entities/Project';
|
||||
|
||||
export const mockCredential = (): CredentialsEntity =>
|
||||
Object.assign(new CredentialsEntity(), randomCredentialPayload());
|
||||
|
||||
export const mockUser = (): User =>
|
||||
Object.assign(new User(), {
|
||||
id: randomInteger(),
|
||||
id: randomInt(1000),
|
||||
email: randomEmail(),
|
||||
firstName: randomName(),
|
||||
lastName: randomName(),
|
||||
|
||||
Reference in New Issue
Block a user