Skip to content

Commit

Permalink
fix(core): Return unredacted credentials from GET credentials/:id (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
despairblue authored Jan 7, 2025
1 parent 7df5eb1 commit ecabe34
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/cli/src/credentials/credentials.service.ee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class EnterpriseCredentialsService {
if (credential) {
// Decrypt the data if we found the credential with the `credential:update`
// scope.
decryptedData = this.credentialsService.decrypt(credential);
decryptedData = this.credentialsService.decrypt(credential, true);
} else {
// Otherwise try to find them with only the `credential:read` scope. In
// that case we return them without the decrypted data.
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/credentials/credentials.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ export class CredentialsService {
if (sharing) {
// Decrypt the data if we found the credential with the `credential:update`
// scope.
decryptedData = this.decrypt(sharing.credentials);
decryptedData = this.decrypt(sharing.credentials, true);
} else {
// Otherwise try to find them with only the `credential:read` scope. In
// that case we return them without the decrypted data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Container } from '@n8n/di';
import { In } from '@n8n/typeorm';

import config from '@/config';
import { CredentialsService } from '@/credentials/credentials.service';
import type { Project } from '@/databases/entities/project';
import type { ProjectRole } from '@/databases/entities/project-relation';
import type { User } from '@/databases/entities/user';
Expand Down Expand Up @@ -555,6 +556,22 @@ describe('GET /credentials/:id', () => {
expect(secondCredential.data).toBeDefined();
});

test('should not redact the data when `includeData:true` is passed', async () => {
const credentialService = Container.get(CredentialsService);
const redactSpy = jest.spyOn(credentialService, 'redact');
const savedCredential = await saveCredential(randomCredentialPayload(), {
user: owner,
});

const response = await authOwnerAgent
.get(`/credentials/${savedCredential.id}`)
.query({ includeData: true });

validateMainCredentialData(response.body.data);
expect(response.body.data.data).toBeDefined();
expect(redactSpy).not.toHaveBeenCalled();
});

test('should retrieve non-owned cred for owner', async () => {
const [member1, member2] = await createManyUsers(2, {
role: 'global:member',
Expand Down
18 changes: 18 additions & 0 deletions packages/cli/test/integration/credentials/credentials.api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Scope } from '@sentry/node';
import { Credentials } from 'n8n-core';
import { randomString } from 'n8n-workflow';

import { CredentialsService } from '@/credentials/credentials.service';
import type { Project } from '@/databases/entities/project';
import type { User } from '@/databases/entities/user';
import { CredentialsRepository } from '@/databases/repositories/credentials.repository';
Expand Down Expand Up @@ -1272,6 +1273,23 @@ describe('GET /credentials/:id', () => {
expect(secondResponse.body.data.data).toBeDefined();
});

test('should not redact the data when `includeData:true` is passed', async () => {
const credentialService = Container.get(CredentialsService);
const redactSpy = jest.spyOn(credentialService, 'redact');
const savedCredential = await saveCredential(randomCredentialPayload(), {
user: owner,
role: 'credential:owner',
});

const response = await authOwnerAgent
.get(`/credentials/${savedCredential.id}`)
.query({ includeData: true });

validateMainCredentialData(response.body.data);
expect(response.body.data.data).toBeDefined();
expect(redactSpy).not.toHaveBeenCalled();
});

test('should retrieve owned cred for member', async () => {
const savedCredential = await saveCredential(randomCredentialPayload(), {
user: member,
Expand Down

0 comments on commit ecabe34

Please sign in to comment.