mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
fix(core): Allow owner and admin to edit nodes with credentials that haven't been shared with them explicitly (#9922)
This commit is contained in:
parent
adb83155ca
commit
0f495986f8
|
@ -135,7 +135,11 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||||
workflowsPage.getters.workflowCards().should('have.length', 2);
|
workflowsPage.getters.workflowCards().should('have.length', 2);
|
||||||
workflowsPage.getters.workflowCard('Workflow W1').click();
|
workflowsPage.getters.workflowCard('Workflow W1').click();
|
||||||
workflowPage.actions.openNode('Notion');
|
workflowPage.actions.openNode('Notion');
|
||||||
ndv.getters.credentialInput().should('have.value', 'Credential C1').should('be.disabled');
|
ndv.getters
|
||||||
|
.credentialInput()
|
||||||
|
.find('input')
|
||||||
|
.should('have.value', 'Credential C1')
|
||||||
|
.should('be.enabled');
|
||||||
ndv.actions.close();
|
ndv.actions.close();
|
||||||
|
|
||||||
cy.waitForLoad();
|
cy.waitForLoad();
|
||||||
|
|
|
@ -63,11 +63,10 @@ export class CredentialsService {
|
||||||
user: User,
|
user: User,
|
||||||
options: {
|
options: {
|
||||||
listQueryOptions?: ListQuery.Options;
|
listQueryOptions?: ListQuery.Options;
|
||||||
onlyOwn?: boolean;
|
|
||||||
includeScopes?: string;
|
includeScopes?: string;
|
||||||
} = {},
|
} = {},
|
||||||
) {
|
) {
|
||||||
const returnAll = user.hasGlobalScope('credential:list') && !options.onlyOwn;
|
const returnAll = user.hasGlobalScope('credential:list');
|
||||||
const isDefaultSelect = !options.listQueryOptions?.select;
|
const isDefaultSelect = !options.listQueryOptions?.select;
|
||||||
|
|
||||||
let projectRelations: ProjectRelation[] | undefined = undefined;
|
let projectRelations: ProjectRelation[] | undefined = undefined;
|
||||||
|
|
|
@ -80,7 +80,10 @@ export class EnterpriseWorkflowService {
|
||||||
currentUser: User,
|
currentUser: User,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
workflow.usedCredentials = [];
|
workflow.usedCredentials = [];
|
||||||
const userCredentials = await this.credentialsService.getMany(currentUser, { onlyOwn: true });
|
const userCredentials = await this.credentialsService.getCredentialsAUserCanUseInAWorkflow(
|
||||||
|
currentUser,
|
||||||
|
{ workflowId: workflow.id },
|
||||||
|
);
|
||||||
const credentialIdsUsedByWorkflow = new Set<string>();
|
const credentialIdsUsedByWorkflow = new Set<string>();
|
||||||
workflow.nodes.forEach((node) => {
|
workflow.nodes.forEach((node) => {
|
||||||
if (!node.credentials) {
|
if (!node.credentials) {
|
||||||
|
|
|
@ -428,28 +428,38 @@ describe('GET /workflows/:workflowId', () => {
|
||||||
expect(responseWorkflow.sharedWithProjects).toHaveLength(0);
|
expect(responseWorkflow.sharedWithProjects).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return workflow with credentials saying owner does not have access when not shared', async () => {
|
test.each([
|
||||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
['owner', () => owner],
|
||||||
|
['admin', () => admin],
|
||||||
|
])(
|
||||||
|
'should return workflow with credentials saying %s does have access even when not shared',
|
||||||
|
async (_description, getActor) => {
|
||||||
|
const actor = getActor();
|
||||||
|
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||||
|
|
||||||
const workflowPayload = makeWorkflow({
|
const workflowPayload = makeWorkflow({
|
||||||
withPinData: false,
|
withPinData: false,
|
||||||
withCredential: { id: savedCredential.id, name: savedCredential.name },
|
withCredential: { id: savedCredential.id, name: savedCredential.name },
|
||||||
});
|
});
|
||||||
const workflow = await createWorkflow(workflowPayload, owner);
|
const workflow = await createWorkflow(workflowPayload, actor);
|
||||||
|
|
||||||
const response = await authOwnerAgent.get(`/workflows/${workflow.id}`).expect(200);
|
const response = await testServer
|
||||||
const responseWorkflow: WorkflowWithSharingsMetaDataAndCredentials = response.body.data;
|
.authAgentFor(actor)
|
||||||
|
.get(`/workflows/${workflow.id}`)
|
||||||
|
.expect(200);
|
||||||
|
const responseWorkflow: WorkflowWithSharingsMetaDataAndCredentials = response.body.data;
|
||||||
|
|
||||||
expect(responseWorkflow.usedCredentials).toMatchObject([
|
expect(responseWorkflow.usedCredentials).toMatchObject([
|
||||||
{
|
{
|
||||||
id: savedCredential.id,
|
id: savedCredential.id,
|
||||||
name: savedCredential.name,
|
name: savedCredential.name,
|
||||||
currentUserHasAccess: false, // although owner can see, they do not have access
|
currentUserHasAccess: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(responseWorkflow.sharedWithProjects).toHaveLength(0);
|
expect(responseWorkflow.sharedWithProjects).toHaveLength(0);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test('should return workflow with credentials for all users with or without access', async () => {
|
test('should return workflow with credentials for all users with or without access', async () => {
|
||||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||||
|
|
Loading…
Reference in a new issue