diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index ee8ffea484..323fdc760f 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -268,7 +268,6 @@ export class CredentialsHelper extends ICredentialsHelper { return new Credentials( { id: credential.id, name: credential.name }, credential.type, - credential.nodesAccess, credential.data, ); } @@ -483,9 +482,9 @@ export function createCredentialsFromCredentialsEntity( credential: CredentialsEntity, encrypt = false, ): Credentials { - const { id, name, type, nodesAccess, data } = credential; + const { id, name, type, data } = credential; if (encrypt) { - return new Credentials({ id: null, name }, type, nodesAccess); + return new Credentials({ id: null, name }, type); } - return new Credentials({ id, name }, type, nodesAccess, data); + return new Credentials({ id, name }, type, data); } diff --git a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts index 81a82616a9..9fe0df30de 100644 --- a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts +++ b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts @@ -41,20 +41,6 @@ export async function createCredential( Object.assign(newCredential, properties); - if (!newCredential.nodesAccess || newCredential.nodesAccess.length === 0) { - newCredential.nodesAccess = [ - { - nodeType: `n8n-nodes-base.${properties.type?.toLowerCase() ?? 'unknown'}`, - date: new Date(), - }, - ]; - } else { - // Add the added date for node access permissions - newCredential.nodesAccess.forEach((nodeAccess) => { - nodeAccess.date = new Date(); - }); - } - return newCredential; } @@ -91,11 +77,7 @@ export async function removeCredential(credentials: CredentialsEntity): Promise< export async function encryptCredential(credential: CredentialsEntity): Promise { // Encrypt the data - const coreCredential = new Credentials( - { id: null, name: credential.name }, - credential.type, - credential.nodesAccess, - ); + const coreCredential = new Credentials({ id: null, name: credential.name }, credential.type); // @ts-ignore coreCredential.setData(credential.data); @@ -115,7 +97,7 @@ export function sanitizeCredentials( const credentialsList = argIsArray ? credentials : [credentials]; const sanitizedCredentials = credentialsList.map((credential) => { - const { data, nodesAccess, shared, ...rest } = credential; + const { data, shared, ...rest } = credential; return rest; }); diff --git a/packages/cli/src/commands/export/credentials.ts b/packages/cli/src/commands/export/credentials.ts index b0914cc4f5..e02c5e3a44 100644 --- a/packages/cli/src/commands/export/credentials.ts +++ b/packages/cli/src/commands/export/credentials.ts @@ -111,9 +111,9 @@ export class ExportCredentialsCommand extends BaseCommand { if (flags.decrypted) { for (let i = 0; i < credentials.length; i++) { - const { name, type, nodesAccess, data } = credentials[i]; + const { name, type, data } = credentials[i]; const id = credentials[i].id; - const credential = new Credentials({ id, name }, type, nodesAccess, data); + const credential = new Credentials({ id, name }, type, data); const plainData = credential.getData(); (credentials[i] as ICredentialsDecryptedDb).data = plainData; } diff --git a/packages/cli/src/commands/import/credentials.ts b/packages/cli/src/commands/import/credentials.ts index 287452d7b6..2ff971b2d2 100644 --- a/packages/cli/src/commands/import/credentials.ts +++ b/packages/cli/src/commands/import/credentials.ts @@ -141,9 +141,6 @@ export class ImportCredentialsCommand extends BaseCommand { } private async storeCredential(credential: Partial, user: User) { - if (!credential.nodesAccess) { - credential.nodesAccess = []; - } const result = await this.transactionManager.upsert(CredentialsEntity, credential, ['id']); await this.transactionManager.upsert( SharedCredentials, diff --git a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts index 518238db71..6f21069150 100644 --- a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts +++ b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts @@ -95,7 +95,7 @@ export abstract class AbstractOAuthController { credential: ICredentialsDb, decryptedData: ICredentialDataDecryptedObject, ) { - const credentials = new Credentials(credential, credential.type, credential.nodesAccess); + const credentials = new Credentials(credential, credential.type); credentials.setData(decryptedData); await this.credentialsRepository.update(credential.id, { ...credentials.getDataToSave(), diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index 9bfb505ea3..ac0598aa3f 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -109,11 +109,6 @@ export class CredentialsService { await validateEntity(newCredentials); - // Add the date for newly added node access permissions - for (const nodeAccess of newCredentials.nodesAccess) { - nodeAccess.date = new Date(); - } - return newCredentials; } @@ -132,13 +127,6 @@ export class CredentialsService { await validateEntity(updateData); - // Add the date for newly added node access permissions - for (const nodeAccess of updateData.nodesAccess) { - if (!nodeAccess.date) { - nodeAccess.date = new Date(); - } - } - // Do not overwrite the oauth data else data like the access or refresh token would get lost // everytime anybody changes anything on the credentials even if it is just the name. if (decryptedData.oauthTokenData) { @@ -149,11 +137,7 @@ export class CredentialsService { } createEncryptedData(credentialId: string | null, data: CredentialsEntity): ICredentialsDb { - const credentials = new Credentials( - { id: credentialId, name: data.name }, - data.type, - data.nodesAccess, - ); + const credentials = new Credentials({ id: credentialId, name: data.name }, data.type); credentials.setData(data.data as unknown as ICredentialDataDecryptedObject); diff --git a/packages/cli/src/databases/entities/CredentialsEntity.ts b/packages/cli/src/databases/entities/CredentialsEntity.ts index cc365c2e70..2c6206590e 100644 --- a/packages/cli/src/databases/entities/CredentialsEntity.ts +++ b/packages/cli/src/databases/entities/CredentialsEntity.ts @@ -1,8 +1,7 @@ -import type { ICredentialNodeAccess } from 'n8n-workflow'; import { Column, Entity, Index, OneToMany } from '@n8n/typeorm'; -import { IsArray, IsObject, IsString, Length } from 'class-validator'; +import { IsObject, IsString, Length } from 'class-validator'; import type { SharedCredentials } from './SharedCredentials'; -import { WithTimestampsAndStringId, jsonColumnType } from './AbstractEntity'; +import { WithTimestampsAndStringId } from './AbstractEntity'; import type { ICredentialsDb } from '@/Interfaces'; @Entity() @@ -27,8 +26,4 @@ export class CredentialsEntity extends WithTimestampsAndStringId implements ICre @OneToMany('SharedCredentials', 'credentials') shared: SharedCredentials[]; - - @Column(jsonColumnType) - @IsArray() - nodesAccess: ICredentialNodeAccess[]; } diff --git a/packages/cli/src/databases/migrations/common/1712044305787-RemoveNodesAccess.ts b/packages/cli/src/databases/migrations/common/1712044305787-RemoveNodesAccess.ts new file mode 100644 index 0000000000..8460af61c4 --- /dev/null +++ b/packages/cli/src/databases/migrations/common/1712044305787-RemoveNodesAccess.ts @@ -0,0 +1,7 @@ +import type { IrreversibleMigration, MigrationContext } from '@db/types'; + +export class RemoveNodesAccess1712044305787 implements IrreversibleMigration { + async up({ schemaBuilder: { dropColumns } }: MigrationContext) { + await dropColumns('credentials_entity', ['nodesAccess']); + } +} diff --git a/packages/cli/src/databases/migrations/mysqldb/index.ts b/packages/cli/src/databases/migrations/mysqldb/index.ts index 89a6a2b0ee..7952a923ab 100644 --- a/packages/cli/src/databases/migrations/mysqldb/index.ts +++ b/packages/cli/src/databases/migrations/mysqldb/index.ts @@ -54,6 +54,7 @@ import { AddGlobalAdminRole1700571993961 } from '../common/1700571993961-AddGlob import { DropRoleMapping1705429061930 } from '../common/1705429061930-DropRoleMapping'; import { RemoveFailedExecutionStatus1711018413374 } from '../common/1711018413374-RemoveFailedExecutionStatus'; import { MoveSshKeysToDatabase1711390882123 } from '../common/1711390882123-MoveSshKeysToDatabase'; +import { RemoveNodesAccess1712044305787 } from '../common/1712044305787-RemoveNodesAccess'; export const mysqlMigrations: Migration[] = [ InitialMigration1588157391238, @@ -111,4 +112,5 @@ export const mysqlMigrations: Migration[] = [ DropRoleMapping1705429061930, RemoveFailedExecutionStatus1711018413374, MoveSshKeysToDatabase1711390882123, + RemoveNodesAccess1712044305787, ]; diff --git a/packages/cli/src/databases/migrations/postgresdb/index.ts b/packages/cli/src/databases/migrations/postgresdb/index.ts index 3b572c2e57..cbf63389a7 100644 --- a/packages/cli/src/databases/migrations/postgresdb/index.ts +++ b/packages/cli/src/databases/migrations/postgresdb/index.ts @@ -53,6 +53,7 @@ import { AddGlobalAdminRole1700571993961 } from '../common/1700571993961-AddGlob import { DropRoleMapping1705429061930 } from '../common/1705429061930-DropRoleMapping'; import { RemoveFailedExecutionStatus1711018413374 } from '../common/1711018413374-RemoveFailedExecutionStatus'; import { MoveSshKeysToDatabase1711390882123 } from '../common/1711390882123-MoveSshKeysToDatabase'; +import { RemoveNodesAccess1712044305787 } from '../common/1712044305787-RemoveNodesAccess'; export const postgresMigrations: Migration[] = [ InitialMigration1587669153312, @@ -109,4 +110,5 @@ export const postgresMigrations: Migration[] = [ DropRoleMapping1705429061930, RemoveFailedExecutionStatus1711018413374, MoveSshKeysToDatabase1711390882123, + RemoveNodesAccess1712044305787, ]; diff --git a/packages/cli/src/databases/migrations/sqlite/index.ts b/packages/cli/src/databases/migrations/sqlite/index.ts index bc25048b53..f26f070087 100644 --- a/packages/cli/src/databases/migrations/sqlite/index.ts +++ b/packages/cli/src/databases/migrations/sqlite/index.ts @@ -51,6 +51,7 @@ import { AddGlobalAdminRole1700571993961 } from '../common/1700571993961-AddGlob import { DropRoleMapping1705429061930 } from './1705429061930-DropRoleMapping'; import { RemoveFailedExecutionStatus1711018413374 } from '../common/1711018413374-RemoveFailedExecutionStatus'; import { MoveSshKeysToDatabase1711390882123 } from '../common/1711390882123-MoveSshKeysToDatabase'; +import { RemoveNodesAccess1712044305787 } from '../common/1712044305787-RemoveNodesAccess'; const sqliteMigrations: Migration[] = [ InitialMigration1588102412422, @@ -105,6 +106,7 @@ const sqliteMigrations: Migration[] = [ DropRoleMapping1705429061930, RemoveFailedExecutionStatus1711018413374, MoveSshKeysToDatabase1711390882123, + RemoveNodesAccess1712044305787, ]; export { sqliteMigrations }; diff --git a/packages/cli/src/databases/repositories/credentials.repository.ts b/packages/cli/src/databases/repositories/credentials.repository.ts index 0b11b40151..02ed714cad 100644 --- a/packages/cli/src/databases/repositories/credentials.repository.ts +++ b/packages/cli/src/databases/repositories/credentials.repository.ts @@ -46,7 +46,7 @@ export class CredentialsRepository extends Repository { type Select = Array; const defaultRelations = ['shared', 'shared.user']; - const defaultSelect: Select = ['id', 'name', 'type', 'nodesAccess', 'createdAt', 'updatedAt']; + const defaultSelect: Select = ['id', 'name', 'type', 'createdAt', 'updatedAt']; if (!listQueryOptions) return { select: defaultSelect, relations: defaultRelations }; diff --git a/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts index 759c69f74b..c52c0300d5 100644 --- a/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts @@ -25,7 +25,6 @@ import { SourceControlPreferencesService } from './sourceControlPreferences.serv import { writeFileSync } from 'fs'; import { SourceControlImportService } from './sourceControlImport.service.ee'; import type { User } from '@db/entities/User'; -import isEqual from 'lodash/isEqual'; import type { SourceControlGetStatus } from './types/sourceControlGetStatus'; import type { TagEntity } from '@db/entities/TagEntity'; import type { Variables } from '@db/entities/Variables'; @@ -384,7 +383,7 @@ export class SourceControlService { * Does a comparison between the local and remote workfolder based on NOT the git status, * but certain parameters within the items being synced. * For workflows, it compares the versionIds - * For credentials, it compares the name, type and nodeAccess + * For credentials, it compares the name and type * For variables, it compares the name * For tags, it compares the name and mapping * @returns either SourceControlledFile[] if verbose is false, @@ -565,12 +564,7 @@ export class SourceControlService { > = []; credLocalIds.forEach((local) => { const mismatchingCreds = credRemoteIds.find((remote) => { - return ( - remote.id === local.id && - (remote.name !== local.name || - remote.type !== local.type || - !isEqual(remote.nodesAccess, local.nodesAccess)) - ); + return remote.id === local.id && (remote.name !== local.name || remote.type !== local.type); }); if (mismatchingCreds) { credModifiedInEither.push({ diff --git a/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts index 30c0174fa1..eb82694930 100644 --- a/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts @@ -240,15 +240,14 @@ export class SourceControlExportService { } await Promise.all( credentialsToBeExported.map(async (sharing) => { - const { name, type, nodesAccess, data, id } = sharing.credentials; - const credentials = new Credentials({ id, name }, type, nodesAccess, data); + const { name, type, data, id } = sharing.credentials; + const credentials = new Credentials({ id, name }, type, data); const stub: ExportableCredential = { id, name, type, data: this.replaceCredentialData(credentials.getData()), - nodesAccess, ownedBy: sharing.user.email, }; diff --git a/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts index bf0adc6bb0..a81aaae17e 100644 --- a/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts @@ -142,13 +142,12 @@ export class SourceControlImportService { Array > { const localCredentials = await Container.get(CredentialsRepository).find({ - select: ['id', 'name', 'type', 'nodesAccess'], + select: ['id', 'name', 'type'], }); return localCredentials.map((local) => ({ id: local.id, name: local.name, type: local.type, - nodesAccess: local.nodesAccess, filename: getCredentialExportPath(local.id, this.credentialExportFolder), })) as Array; } @@ -339,14 +338,13 @@ export class SourceControlImportService { (e) => e.id === credential.id && e.type === credential.type, ); - const { name, type, data, id, nodesAccess } = credential; - const newCredentialObject = new Credentials({ id, name }, type, []); + const { name, type, data, id } = credential; + const newCredentialObject = new Credentials({ id, name }, type); if (existingCredential?.data) { newCredentialObject.data = existingCredential.data; } else { newCredentialObject.setData(data); } - newCredentialObject.nodesAccess = nodesAccess || existingCredential?.nodesAccess || []; this.logger.debug(`Updating credential id ${newCredentialObject.id as string}`); await Container.get(CredentialsRepository).upsert(newCredentialObject, ['id']); diff --git a/packages/cli/src/environments/sourceControl/types/exportableCredential.ts b/packages/cli/src/environments/sourceControl/types/exportableCredential.ts index 2bf8903cc9..36197da6ca 100644 --- a/packages/cli/src/environments/sourceControl/types/exportableCredential.ts +++ b/packages/cli/src/environments/sourceControl/types/exportableCredential.ts @@ -1,11 +1,10 @@ -import type { ICredentialDataDecryptedObject, ICredentialNodeAccess } from 'n8n-workflow'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; export interface ExportableCredential { id: string; name: string; type: string; data: ICredentialDataDecryptedObject; - nodesAccess: ICredentialNodeAccess[]; /** * Email of the user who owns this credential at the source instance. diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index e3f0048058..5946b07117 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -2,7 +2,6 @@ import type express from 'express'; import type { BannerName, ICredentialDataDecryptedObject, - ICredentialNodeAccess, IDataObject, INodeCredentialTestRequest, INodeCredentials, @@ -158,7 +157,6 @@ export declare namespace CredentialRequest { id: string; // delete if sent name: string; type: string; - nodesAccess: ICredentialNodeAccess[]; data: ICredentialDataDecryptedObject; }>; diff --git a/packages/cli/test/integration/commands/credentials.cmd.test.ts b/packages/cli/test/integration/commands/credentials.cmd.test.ts index d5beb03552..1ec68f7263 100644 --- a/packages/cli/test/integration/commands/credentials.cmd.test.ts +++ b/packages/cli/test/integration/commands/credentials.cmd.test.ts @@ -45,6 +45,5 @@ test('import:credentials should import a credential', async () => { expect(after.length).toBe(1); expect(after[0].name).toBe('cred-aws-test'); expect(after[0].id).toBe('123'); - expect(after[0].nodesAccess).toStrictEqual([]); mockExit.mockRestore(); }); diff --git a/packages/cli/test/integration/commands/importCredentials/credentials.json b/packages/cli/test/integration/commands/importCredentials/credentials.json index 136a2205b6..0e6269d267 100644 --- a/packages/cli/test/integration/commands/importCredentials/credentials.json +++ b/packages/cli/test/integration/commands/importCredentials/credentials.json @@ -9,7 +9,6 @@ "accessKeyId": "999999999999", "secretAccessKey": "aaaaaaaaaaaaa" }, - "type": "aws", - "nodesAccess": "" + "type": "aws" } ] diff --git a/packages/cli/test/integration/credentials.controller.test.ts b/packages/cli/test/integration/credentials.controller.test.ts index 806d30eb95..df88c2b12c 100644 --- a/packages/cli/test/integration/credentials.controller.test.ts +++ b/packages/cli/test/integration/credentials.controller.test.ts @@ -264,11 +264,10 @@ describe('GET /credentials', () => { }); function validateCredential(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) { - const { name, type, nodesAccess, sharedWith, ownedBy } = credential; + const { name, type, sharedWith, ownedBy } = credential; expect(typeof name).toBe('string'); expect(typeof type).toBe('string'); - expect(typeof nodesAccess[0].nodeType).toBe('string'); expect('data' in credential).toBe(false); if (sharedWith) expect(Array.isArray(sharedWith)).toBe(true); diff --git a/packages/cli/test/integration/credentials.ee.test.ts b/packages/cli/test/integration/credentials.ee.test.ts index e62c19338c..279f33c019 100644 --- a/packages/cli/test/integration/credentials.ee.test.ts +++ b/packages/cli/test/integration/credentials.ee.test.ts @@ -539,7 +539,6 @@ describe('PUT /credentials/:id/share', () => { function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) { expect(typeof credential.name).toBe('string'); expect(typeof credential.type).toBe('string'); - expect(typeof credential.nodesAccess[0].nodeType).toBe('string'); expect(credential.ownedBy).toBeDefined(); expect(Array.isArray(credential.sharedWith)).toBe(true); } diff --git a/packages/cli/test/integration/credentials.test.ts b/packages/cli/test/integration/credentials.test.ts index 122a46f0b3..aa40616ad8 100644 --- a/packages/cli/test/integration/credentials.test.ts +++ b/packages/cli/test/integration/credentials.test.ts @@ -96,21 +96,16 @@ describe('POST /credentials', () => { expect(response.statusCode).toBe(200); - const { id, name, type, nodesAccess, data: encryptedData } = response.body.data; + const { id, name, type, data: encryptedData } = response.body.data; expect(name).toBe(payload.name); expect(type).toBe(payload.type); - if (!payload.nodesAccess) { - fail('Payload did not contain a nodesAccess array'); - } - expect(nodesAccess[0].nodeType).toBe(payload.nodesAccess[0].nodeType); expect(encryptedData).not.toBe(payload.data); const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(payload.name); expect(credential.type).toBe(payload.type); - expect(credential.nodesAccess[0].nodeType).toBe(payload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(payload.data); const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ @@ -258,14 +253,10 @@ describe('PATCH /credentials/:id', () => { expect(response.statusCode).toBe(200); - const { id, name, type, nodesAccess, data: encryptedData } = response.body.data; + const { id, name, type, data: encryptedData } = response.body.data; expect(name).toBe(patchPayload.name); expect(type).toBe(patchPayload.type); - if (!patchPayload.nodesAccess) { - fail('Payload did not contain a nodesAccess array'); - } - expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); expect(encryptedData).not.toBe(patchPayload.data); @@ -273,7 +264,6 @@ describe('PATCH /credentials/:id', () => { expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); - expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(patchPayload.data); const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ @@ -304,7 +294,6 @@ describe('PATCH /credentials/:id', () => { const credentialObject = new Credentials( { id: credential.id, name: credential.name }, credential.type, - credential.nodesAccess, credential.data, ); expect(credentialObject.getData()).toStrictEqual(patchPayload.data); @@ -327,23 +316,17 @@ describe('PATCH /credentials/:id', () => { expect(response.statusCode).toBe(200); - const { id, name, type, nodesAccess, data: encryptedData } = response.body.data; + const { id, name, type, data: encryptedData } = response.body.data; expect(name).toBe(patchPayload.name); expect(type).toBe(patchPayload.type); - if (!patchPayload.nodesAccess) { - fail('Payload did not contain a nodesAccess array'); - } - expect(nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); - expect(encryptedData).not.toBe(patchPayload.data); const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); - expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(patchPayload.data); const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ @@ -545,11 +528,10 @@ describe('GET /credentials/:id', () => { }); function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) { - const { name, type, nodesAccess, sharedWith, ownedBy } = credential; + const { name, type, sharedWith, ownedBy } = credential; expect(typeof name).toBe('string'); expect(typeof type).toBe('string'); - expect(typeof nodesAccess?.[0].nodeType).toBe('string'); if (sharedWith) { expect(Array.isArray(sharedWith)).toBe(true); @@ -568,23 +550,15 @@ function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedB const INVALID_PAYLOADS = [ { type: randomName(), - nodesAccess: [{ nodeType: randomName() }], data: { accessToken: randomString(6, 16) }, }, { name: randomName(), - nodesAccess: [{ nodeType: randomName() }], data: { accessToken: randomString(6, 16) }, }, { name: randomName(), type: randomName(), - data: { accessToken: randomString(6, 16) }, - }, - { - name: randomName(), - type: randomName(), - nodesAccess: [{ nodeType: randomName() }], }, {}, undefined, diff --git a/packages/cli/test/integration/environments/source-control-import.service.test.ts b/packages/cli/test/integration/environments/source-control-import.service.test.ts index d0615f1dd4..fd3327cedd 100644 --- a/packages/cli/test/integration/environments/source-control-import.service.test.ts +++ b/packages/cli/test/integration/environments/source-control-import.service.test.ts @@ -54,7 +54,6 @@ describe('SourceControlImportService', () => { name: 'My Credential', type: 'someCredentialType', data: {}, - nodesAccess: [], ownedBy: member.email, // user at source instance owns credential }; @@ -90,7 +89,6 @@ describe('SourceControlImportService', () => { name: 'My Credential', type: 'someCredentialType', data: {}, - nodesAccess: [], ownedBy: null, }; @@ -126,7 +124,6 @@ describe('SourceControlImportService', () => { name: 'My Credential', type: 'someCredentialType', data: {}, - nodesAccess: [], ownedBy: 'user@test.com', // user at source instance owns credential }; diff --git a/packages/cli/test/integration/publicApi/credentials.test.ts b/packages/cli/test/integration/publicApi/credentials.test.ts index 6ce0723874..d028834638 100644 --- a/packages/cli/test/integration/publicApi/credentials.test.ts +++ b/packages/cli/test/integration/publicApi/credentials.test.ts @@ -258,7 +258,6 @@ const credentialPayload = (): CredentialPayload => ({ const dbCredential = () => { const credential = credentialPayload(); - credential.nodesAccess = [{ nodeType: credential.type }]; return credential; }; @@ -276,13 +275,6 @@ const INVALID_PAYLOADS = [ name: randomName(), type: randomName(), }, - { - name: randomName(), - type: 'ftp', - data: { - username: randomName(), - }, - }, {}, [], undefined, diff --git a/packages/cli/test/integration/security-audit/CredentialsRiskReporter.test.ts b/packages/cli/test/integration/security-audit/CredentialsRiskReporter.test.ts index 9a10e6e70c..c395147e1d 100644 --- a/packages/cli/test/integration/security-audit/CredentialsRiskReporter.test.ts +++ b/packages/cli/test/integration/security-audit/CredentialsRiskReporter.test.ts @@ -33,7 +33,6 @@ test('should report credentials not in any use', async () => { name: 'My Slack Credential', data: 'U2FsdGVkX18WjITBG4IDqrGB1xE/uzVNjtwDAG3lP7E=', type: 'slackApi', - nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; const workflowDetails = { @@ -79,7 +78,6 @@ test('should report credentials not in active use', async () => { name: 'My Slack Credential', data: 'U2FsdGVkX18WjITBG4IDqrGB1xE/uzVNjtwDAG3lP7E=', type: 'slackApi', - nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; const credential = await Container.get(CredentialsRepository).save(credentialDetails); @@ -124,7 +122,6 @@ test('should report credential in not recently executed workflow', async () => { name: 'My Slack Credential', data: 'U2FsdGVkX18WjITBG4IDqrGB1xE/uzVNjtwDAG3lP7E=', type: 'slackApi', - nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; const credential = await Container.get(CredentialsRepository).save(credentialDetails); @@ -192,7 +189,6 @@ test('should not report credentials in recently executed workflow', async () => name: 'My Slack Credential', data: 'U2FsdGVkX18WjITBG4IDqrGB1xE/uzVNjtwDAG3lP7E=', type: 'slackApi', - nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; const credential = await Container.get(CredentialsRepository).save(credentialDetails); diff --git a/packages/cli/test/integration/shared/db/credentials.ts b/packages/cli/test/integration/shared/db/credentials.ts index 2208e08936..4e77b2fcc2 100644 --- a/packages/cli/test/integration/shared/db/credentials.ts +++ b/packages/cli/test/integration/shared/db/credentials.ts @@ -21,7 +21,6 @@ const emptyAttributes = { name: 'test', type: 'test', data: '', - nodesAccess: [], }; export async function createManyCredentials( diff --git a/packages/cli/test/integration/shared/random.ts b/packages/cli/test/integration/shared/random.ts index 98befbaa75..62b5c73ee0 100644 --- a/packages/cli/test/integration/shared/random.ts +++ b/packages/cli/test/integration/shared/random.ts @@ -59,7 +59,6 @@ export const randomName = () => randomString(4, 8); export const randomCredentialPayload = (): CredentialPayload => ({ name: randomName(), type: randomName(), - nodesAccess: [{ nodeType: randomName() }], data: { accessToken: randomString(6, 16) }, }); diff --git a/packages/cli/test/integration/shared/types.ts b/packages/cli/test/integration/shared/types.ts index 2482beb95c..8355d6f39c 100644 --- a/packages/cli/test/integration/shared/types.ts +++ b/packages/cli/test/integration/shared/types.ts @@ -1,5 +1,5 @@ import type { Application } from 'express'; -import type { ICredentialDataDecryptedObject, ICredentialNodeAccess } from 'n8n-workflow'; +import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; import type { SuperAgentTest } from 'supertest'; import type { Server } from 'http'; @@ -52,7 +52,6 @@ export interface TestServer { export type CredentialPayload = { name: string; type: string; - nodesAccess?: ICredentialNodeAccess[]; data: ICredentialDataDecryptedObject; }; diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index fefb0161b1..5c9bdc2600 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -244,7 +244,7 @@ describe('DELETE /users/:id', () => { const savedWorkflow = await createWorkflow({ name: randomName() }, member); const savedCredential = await saveCredential( - { name: randomName(), type: '', data: {}, nodesAccess: [] }, + { name: randomName(), type: '', data: {} }, { user: member, role: 'credential:owner' }, ); @@ -286,7 +286,7 @@ describe('DELETE /users/:id', () => { const [savedWorkflow, savedCredential] = await Promise.all([ await createWorkflow({ name: randomName() }, member), await saveCredential( - { name: randomName(), type: '', data: {}, nodesAccess: [] }, + { name: randomName(), type: '', data: {} }, { user: member, role: 'credential:owner', diff --git a/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts b/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts index 59d9b8f636..6b4b55788a 100644 --- a/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts +++ b/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts @@ -39,7 +39,6 @@ describe('OAuth1CredentialController', () => { const credential = mock({ id: '1', name: 'Test Credential', - nodesAccess: [], type: 'oAuth1Api', }); diff --git a/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts b/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts index 9acbe305be..16e3e93345 100644 --- a/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts +++ b/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts @@ -43,7 +43,6 @@ describe('OAuth2CredentialController', () => { const credential = mock({ id: '1', name: 'Test Credential', - nodesAccess: [], type: 'oAuth2Api', }); diff --git a/packages/core/src/Credentials.ts b/packages/core/src/Credentials.ts index 7714df6898..1a54d96cd2 100644 --- a/packages/core/src/Credentials.ts +++ b/packages/core/src/Credentials.ts @@ -6,19 +6,6 @@ import { Cipher } from './Cipher'; export class Credentials extends ICredentials { private readonly cipher = Container.get(Cipher); - /** - * Returns if the given nodeType has access to data - */ - hasNodeAccess(nodeType: string): boolean { - for (const accessData of this.nodesAccess) { - if (accessData.nodeType === nodeType) { - return true; - } - } - - return false; - } - /** * Sets new credential object */ @@ -29,14 +16,7 @@ export class Credentials extends ICredentials { /** * Returns the decrypted credential object */ - getData(nodeType?: string): ICredentialDataDecryptedObject { - if (nodeType && !this.hasNodeAccess(nodeType)) { - throw new ApplicationError('Node does not have access to credential', { - tags: { nodeType, credentialType: this.type }, - extra: { credentialName: this.name }, - }); - } - + getData(): ICredentialDataDecryptedObject { if (this.data === undefined) { throw new ApplicationError('No data is set so nothing can be returned.'); } @@ -65,7 +45,6 @@ export class Credentials extends ICredentials { name: this.name, type: this.type, data: this.data, - nodesAccess: this.nodesAccess, }; } } diff --git a/packages/core/test/Credentials.test.ts b/packages/core/test/Credentials.test.ts index aca7787030..ada86a07b0 100644 --- a/packages/core/test/Credentials.test.ts +++ b/packages/core/test/Credentials.test.ts @@ -22,7 +22,7 @@ describe('Credentials', () => { describe('without nodeType set', () => { test('should be able to set and read key data without initial data set', () => { - const credentials = new Credentials({ id: null, name: 'testName' }, 'testType', []); + const credentials = new Credentials({ id: null, name: 'testName' }, 'testType'); const key = 'key1'; const newData = 1234; @@ -42,7 +42,6 @@ describe('Credentials', () => { const credentials = new Credentials( { id: null, name: 'testName' }, 'testType', - [], initialDataEncoded, ); @@ -56,46 +55,4 @@ describe('Credentials', () => { expect(credentials.getData().key1).toEqual(initialData); }); }); - - describe('with nodeType set', () => { - test('should be able to set and read key data without initial data set', () => { - const nodeAccess = [ - { - nodeType: 'base.noOp', - user: 'userName', - date: new Date(), - }, - ]; - - const credentials = new Credentials({ id: null, name: 'testName' }, 'testType', nodeAccess); - - const key = 'key1'; - const nodeType = 'base.noOp'; - const newData = 1234; - - setDataKey(credentials, key, newData); - - // Should be able to read with nodeType which has access - expect(credentials.getData(nodeType)[key]).toEqual(newData); - - // Should not be able to read with nodeType which does NOT have access - // expect(credentials.getData('base.otherNode')[key]).toThrowError(Error); - try { - credentials.getData('base.otherNode'); - expect(true).toBe(false); - } catch (e) { - expect(e.message).toBe('Node does not have access to credential'); - } - - // Get the data which will be saved in database - const dbData = credentials.getDataToSave(); - expect(dbData.name).toEqual('testName'); - expect(dbData.type).toEqual('testType'); - expect(dbData.nodesAccess).toEqual(nodeAccess); - // Compare only the first 6 characters as the rest seems to change with each execution - expect(dbData.data!.slice(0, 6)).toEqual( - 'U2FsdGVkX1+wpQWkj+YTzaPSNTFATjnlmFKIsUTZdhk='.slice(0, 6), - ); - }); - }); }); diff --git a/packages/editor-ui/src/__tests__/server/factories/credential.ts b/packages/editor-ui/src/__tests__/server/factories/credential.ts index b97bbbaea5..1cd28a06e6 100644 --- a/packages/editor-ui/src/__tests__/server/factories/credential.ts +++ b/packages/editor-ui/src/__tests__/server/factories/credential.ts @@ -12,9 +12,6 @@ export const credentialFactory = Factory.extend({ name() { return faker.company.name(); }, - nodesAccess() { - return []; - }, type() { return 'notionApi'; }, diff --git a/packages/editor-ui/src/components/CredentialCard.vue b/packages/editor-ui/src/components/CredentialCard.vue index ddce55096f..f9eb6cbe13 100644 --- a/packages/editor-ui/src/components/CredentialCard.vue +++ b/packages/editor-ui/src/components/CredentialCard.vue @@ -68,7 +68,6 @@ export default defineComponent({ updatedAt: '', type: '', name: '', - nodesAccess: [], sharedWith: [], ownedBy: {} as IUser, }), diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue index 86a97e5236..491a03e6b6 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue @@ -119,7 +119,6 @@ import type { ICredentialsResponse, IUser } from '@/Interface'; import type { CredentialInformation, ICredentialDataDecryptedObject, - ICredentialNodeAccess, ICredentialsDecrypted, ICredentialType, INode, @@ -165,10 +164,6 @@ import { isValidCredentialResponse, isCredentialModalState } from '@/utils/typeG import { isExpression, isTestableExpression } from '@/utils/expressions'; import { useExternalHooks } from '@/composables/useExternalHooks'; -interface NodeAccessMap { - [nodeType: string]: ICredentialNodeAccess | null; -} - export default defineComponent({ name: 'CredentialEdit', components: { @@ -212,7 +207,6 @@ export default defineComponent({ credentialName: '', credentialData: {} as ICredentialDataDecryptedObject, modalBus: createEventBus(), - nodeAccess: {} as NodeAccessMap, isDeleting: false, isSaving: false, isTesting: false, @@ -233,8 +227,6 @@ export default defineComponent({ isCredentialModalState(this.uiStore.modals[CREDENTIAL_EDIT_MODAL_KEY]) && this.uiStore.modals[CREDENTIAL_EDIT_MODAL_KEY].showAuthSelector === true; - this.setupNodeAccess(); - if (this.mode === 'new' && this.credentialTypeName) { this.credentialName = await this.credentialsStore.getNewCredentialName({ credentialTypeName: this.defaultCredentialTypeName, @@ -765,7 +757,6 @@ export default defineComponent({ name: this.credentialName, type: this.credentialTypeName!, data: credentialData, - nodesAccess: [], }; this.isRetesting = true; @@ -817,7 +808,6 @@ export default defineComponent({ name: this.credentialName, type: this.credentialTypeName!, data: data as unknown as ICredentialDataDecryptedObject, - nodesAccess: [], sharedWith, ownedBy, }; @@ -1091,7 +1081,6 @@ export default defineComponent({ if (credentialsForType) { this.selectedCredential = credentialsForType.name; this.resetCredentialData(); - this.setupNodeAccess(); // Update current node auth type so credentials dropdown can be displayed properly updateNodeAuthType(this.ndvStore.activeNode, type); // Also update credential name but only if the default name is still used @@ -1103,9 +1092,6 @@ export default defineComponent({ } } }, - setupNodeAccess(): void { - this.nodeAccess = {}; - }, resetCredentialData(): void { if (!this.credentialType) { return; diff --git a/packages/editor-ui/src/views/SetupWorkflowFromTemplateView/__tests__/setupTemplate.store.testData.ts b/packages/editor-ui/src/views/SetupWorkflowFromTemplateView/__tests__/setupTemplate.store.testData.ts index aafff75971..0696ed2b7c 100644 --- a/packages/editor-ui/src/views/SetupWorkflowFromTemplateView/__tests__/setupTemplate.store.testData.ts +++ b/packages/editor-ui/src/views/SetupWorkflowFromTemplateView/__tests__/setupTemplate.store.testData.ts @@ -51,7 +51,6 @@ export const newCredential = ( updatedAt: faker.date.past().toISOString(), id: faker.string.alphanumeric({ length: 16 }), name: faker.commerce.productName(), - nodesAccess: [], ...opts, }); @@ -61,16 +60,6 @@ export const credentialsTelegram1: ICredentialsResponse = { id: 'YaSKdvEcT1TSFrrr1', name: 'Telegram account', type: 'telegramApi', - nodesAccess: [ - { - nodeType: 'n8n-nodes-base.telegram', - date: new Date('2023-11-23T14:26:07.962Z'), - }, - { - nodeType: 'n8n-nodes-base.telegramTrigger', - date: new Date('2023-11-23T14:26:07.962Z'), - }, - ], ownedBy: { id: '713ef3e7-9e65-4b0a-893c-8a653cbb2c4f', email: 'user@n8n.io', @@ -86,16 +75,6 @@ export const credentialsTelegram2: ICredentialsResponse = { id: 'YaSKdvEcT1TSFrrr2', name: 'Telegram account', type: 'telegramApi', - nodesAccess: [ - { - nodeType: 'n8n-nodes-base.telegram', - date: new Date('2023-11-23T14:26:07.962Z'), - }, - { - nodeType: 'n8n-nodes-base.telegramTrigger', - date: new Date('2023-11-23T14:26:07.962Z'), - }, - ], ownedBy: { id: '713ef3e7-9e65-4b0a-893c-8a653cbb2c4f', email: 'user@n8n.io', diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 7a90966aca..8189bf84af 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -93,18 +93,10 @@ export abstract class ICredentials { data: string | undefined; - nodesAccess: ICredentialNodeAccess[]; - - constructor( - nodeCredentials: INodeCredentialsDetails, - type: string, - nodesAccess: ICredentialNodeAccess[], - data?: string, - ) { + constructor(nodeCredentials: INodeCredentialsDetails, type: string, data?: string) { this.id = nodeCredentials.id ?? undefined; this.name = nodeCredentials.name; this.type = type; - this.nodesAccess = nodesAccess; this.data = data; } @@ -112,8 +104,6 @@ export abstract class ICredentials { abstract getDataToSave(): ICredentialsEncrypted; - abstract hasNodeAccess(nodeType: string): boolean; - abstract setData(data: ICredentialDataDecryptedObject): void; } @@ -124,19 +114,10 @@ export interface IUser { lastName: string; } -// Defines which nodes are allowed to access the credentials and -// when that access got granted from which user -export interface ICredentialNodeAccess { - nodeType: string; - user?: string; - date?: Date; -} - export interface ICredentialsDecrypted { id: string; name: string; type: string; - nodesAccess: ICredentialNodeAccess[]; data?: ICredentialDataDecryptedObject; ownedBy?: IUser; sharedWith?: IUser[]; @@ -146,7 +127,6 @@ export interface ICredentialsEncrypted { id?: string; name: string; type: string; - nodesAccess: ICredentialNodeAccess[]; data?: string; } @@ -345,7 +325,6 @@ export interface ICredentialData { id?: string; name: string; data: string; // Contains the access data as encrypted JSON string - nodesAccess: ICredentialNodeAccess[]; } // The encrypted credentials which the nodes can access diff --git a/packages/workflow/test/Helpers.ts b/packages/workflow/test/Helpers.ts index db017a4b55..8b07f3d6aa 100644 --- a/packages/workflow/test/Helpers.ts +++ b/packages/workflow/test/Helpers.ts @@ -46,10 +46,6 @@ export interface INodeTypesObject { } export class Credentials extends ICredentials { - hasNodeAccess() { - return true; - } - setData(data: ICredentialDataDecryptedObject) { this.data = JSON.stringify(data); } @@ -71,7 +67,6 @@ export class Credentials extends ICredentials { name: this.name, type: this.type, data: this.data, - nodesAccess: this.nodesAccess, }; } }