mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
fix: When editing nodes only show the credentials in the dropdown that the user is allowed to use in that workflow (#9718)
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
import type { SuperAgentTest } from '../shared/types';
|
||||
import { mockInstance } from '../../shared/mocking';
|
||||
import { createTeamProject, linkUserToProject } from '../shared/db/projects';
|
||||
import { createWorkflow, shareWorkflowWithUsers } from '@test-integration/db/workflows';
|
||||
|
||||
const testServer = utils.setupTestServer({
|
||||
endpointGroups: ['credentials'],
|
||||
@@ -243,6 +244,256 @@ describe('GET /credentials', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /credentials/for-workflow', () => {
|
||||
describe('for team projects', () => {
|
||||
test.each([
|
||||
['workflowId', 'member', () => member],
|
||||
['projectId', 'member', () => member],
|
||||
['workflowId', 'owner', () => owner],
|
||||
['projectId', 'owner', () => owner],
|
||||
])(
|
||||
'it will only return the credentials in that project if "%s" is used as the query parameter and the actor is a "%s"',
|
||||
async (_, queryParam, actorGetter) => {
|
||||
const actor = actorGetter();
|
||||
// Credential in personal project that should not be returned
|
||||
await saveCredential(randomCredentialPayload(), { user: actor });
|
||||
|
||||
const teamProject = await createTeamProject();
|
||||
await linkUserToProject(actor, teamProject, 'project:viewer');
|
||||
const savedCredential = await saveCredential(randomCredentialPayload(), {
|
||||
project: teamProject,
|
||||
});
|
||||
const savedWorkflow = await createWorkflow({}, teamProject);
|
||||
|
||||
{
|
||||
const response = await testServer
|
||||
.authAgentFor(actor)
|
||||
.get('/credentials/for-workflow')
|
||||
.query(
|
||||
queryParam === 'workflowId'
|
||||
? { workflowId: savedWorkflow.id }
|
||||
: { projectId: teamProject.id },
|
||||
);
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(1);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: savedCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('for personal projects', () => {
|
||||
test.each(['projectId', 'workflowId'])(
|
||||
'it returns only personal credentials for a members, if "%s" is used as the query parameter',
|
||||
async (queryParam) => {
|
||||
const savedWorkflow = await createWorkflow({}, member);
|
||||
await shareWorkflowWithUsers(savedWorkflow, [anotherMember]);
|
||||
|
||||
// should be returned respectively
|
||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
const anotherSavedCredential = await saveCredential(randomCredentialPayload(), {
|
||||
user: anotherMember,
|
||||
});
|
||||
|
||||
// should not be returned
|
||||
await saveCredential(randomCredentialPayload(), { user: owner });
|
||||
const teamProject = await createTeamProject();
|
||||
await saveCredential(randomCredentialPayload(), { project: teamProject });
|
||||
|
||||
// member should only see their credential
|
||||
{
|
||||
const response = await testServer
|
||||
.authAgentFor(member)
|
||||
.get('/credentials/for-workflow')
|
||||
.query(
|
||||
queryParam === 'workflowId'
|
||||
? { workflowId: savedWorkflow.id }
|
||||
: { projectId: memberPersonalProject.id },
|
||||
);
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(1);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: savedCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// another member should only see their credential
|
||||
{
|
||||
const response = await testServer
|
||||
.authAgentFor(anotherMember)
|
||||
.get('/credentials/for-workflow')
|
||||
.query(
|
||||
queryParam === 'workflowId'
|
||||
? { workflowId: savedWorkflow.id }
|
||||
: { projectId: anotherMemberPersonalProject.id },
|
||||
);
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(1);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: anotherSavedCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
test('if the actor is a global owner and the workflow has not been shared with them, it returns all credentials of all projects the workflow is part of', async () => {
|
||||
const memberWorkflow = await createWorkflow({}, member);
|
||||
await shareWorkflowWithUsers(memberWorkflow, [owner]);
|
||||
|
||||
// should be returned
|
||||
const memberCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
const ownerCredential = await saveCredential(randomCredentialPayload(), { user: owner });
|
||||
|
||||
// should not be returned
|
||||
await saveCredential(randomCredentialPayload(), { user: anotherMember });
|
||||
const teamProject = await createTeamProject();
|
||||
await saveCredential(randomCredentialPayload(), { project: teamProject });
|
||||
|
||||
const response = await testServer
|
||||
.authAgentFor(owner)
|
||||
.get('/credentials/for-workflow')
|
||||
.query({ workflowId: memberWorkflow.id });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(2);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: memberCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: ownerCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('if the actor is a global owner and the workflow has been shared with them, it returns all credentials of all projects the workflow is part of', async () => {
|
||||
const memberWorkflow = await createWorkflow({}, member);
|
||||
await shareWorkflowWithUsers(memberWorkflow, [anotherMember]);
|
||||
|
||||
// should be returned
|
||||
const memberCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
const anotherMemberCredential = await saveCredential(randomCredentialPayload(), {
|
||||
user: anotherMember,
|
||||
});
|
||||
|
||||
// should not be returned
|
||||
await saveCredential(randomCredentialPayload(), { user: owner });
|
||||
const teamProject = await createTeamProject();
|
||||
await saveCredential(randomCredentialPayload(), { project: teamProject });
|
||||
|
||||
const response = await testServer
|
||||
.authAgentFor(owner)
|
||||
.get('/credentials/for-workflow')
|
||||
.query({ workflowId: memberWorkflow.id });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(2);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: memberCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: anotherMemberCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('if the projectId is passed by a global owner it will return all credentials in that project', async () => {
|
||||
// should be returned
|
||||
const memberCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
|
||||
// should not be returned
|
||||
await saveCredential(randomCredentialPayload(), { user: anotherMember });
|
||||
await saveCredential(randomCredentialPayload(), { user: owner });
|
||||
const teamProject = await createTeamProject();
|
||||
await saveCredential(randomCredentialPayload(), { project: teamProject });
|
||||
|
||||
const response = await testServer
|
||||
.authAgentFor(owner)
|
||||
.get('/credentials/for-workflow')
|
||||
.query({ projectId: memberPersonalProject.id });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(1);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: memberCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test.each(['workflowId', 'projectId'] as const)(
|
||||
'if the global owner owns the workflow it will return all credentials of all personal projects, when using "%s" as the query parameter',
|
||||
async (queryParam) => {
|
||||
const ownerWorkflow = await createWorkflow({}, owner);
|
||||
|
||||
// should be returned
|
||||
const memberCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
const anotherMemberCredential = await saveCredential(randomCredentialPayload(), {
|
||||
user: anotherMember,
|
||||
});
|
||||
const ownerCredential = await saveCredential(randomCredentialPayload(), { user: owner });
|
||||
|
||||
// should not be returned
|
||||
const teamProject = await createTeamProject();
|
||||
await saveCredential(randomCredentialPayload(), { project: teamProject });
|
||||
|
||||
const response = await testServer
|
||||
.authAgentFor(owner)
|
||||
.get('/credentials/for-workflow')
|
||||
.query(
|
||||
queryParam === 'workflowId'
|
||||
? { workflowId: ownerWorkflow.id }
|
||||
: { projectId: ownerPersonalProject.id },
|
||||
);
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.body.data).toHaveLength(3);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: memberCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: anotherMemberCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
expect(response.body.data).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: ownerCredential.id,
|
||||
scopes: expect.arrayContaining(['credential:read']),
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ----------------------------------------
|
||||
// GET /credentials/:id - fetch a certain credential
|
||||
// ----------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user