fix(core): Permission check for subworkflow properly checking for workflow settings (#7576)
The `sharing` related code is legacy that was not removed. Subworkflow execution should check workflow settings alone, and this is now reflected in the code. Github issue / Community forum post (link here to close automatically): https://community.n8n.io/t/bug-when-using-the-execute-workflow-node-when-workflow-is-shared/32207 --------- Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
This commit is contained in:
@@ -10,10 +10,8 @@ import { User } from '@db/entities/User';
|
||||
import { SharedWorkflow } from '@db/entities/SharedWorkflow';
|
||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||
import { NodeTypes } from '@/NodeTypes';
|
||||
import { UserService } from '@/services/user.service';
|
||||
import { PermissionChecker } from '@/UserManagement/PermissionChecker';
|
||||
import * as UserManagementHelper from '@/UserManagement/UserManagementHelper';
|
||||
import { WorkflowsService } from '@/workflows/workflows.services';
|
||||
import { OwnershipService } from '@/services/ownership.service';
|
||||
|
||||
import { mockInstance } from '../integration/shared/utils/';
|
||||
@@ -225,18 +223,12 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
|
||||
const nonOwnerMockRole = new Role();
|
||||
nonOwnerMockRole.name = 'editor';
|
||||
const sharedWorkflowNotOwner = new SharedWorkflow();
|
||||
sharedWorkflowNotOwner.role = nonOwnerMockRole;
|
||||
|
||||
const userService = mockInstance(UserService);
|
||||
const nonOwnerUser = new User();
|
||||
nonOwnerUser.id = uuid();
|
||||
|
||||
test('sets default policy from environment when subworkflow has none', async () => {
|
||||
config.set('workflows.callerPolicyDefaultOption', 'none');
|
||||
jest
|
||||
.spyOn(ownershipService, 'getWorkflowOwnerCached')
|
||||
.mockImplementation(async (workflowId) => {
|
||||
return fakeUser;
|
||||
});
|
||||
jest.spyOn(ownershipService, 'getWorkflowOwnerCached').mockResolvedValue(fakeUser);
|
||||
jest.spyOn(UserManagementHelper, 'isSharingEnabled').mockReturnValue(true);
|
||||
|
||||
const subworkflow = new Workflow({
|
||||
@@ -251,15 +243,9 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
).rejects.toThrow(`Target workflow ID ${subworkflow.id} may not be called`);
|
||||
});
|
||||
|
||||
test('if sharing is disabled, ensures that workflows are owner by same user', async () => {
|
||||
jest
|
||||
.spyOn(ownershipService, 'getWorkflowOwnerCached')
|
||||
.mockImplementation(async (workflowId) => fakeUser);
|
||||
test('if sharing is disabled, ensures that workflows are owned by same user and reject running workflows belonging to another user even if setting allows execution', async () => {
|
||||
jest.spyOn(ownershipService, 'getWorkflowOwnerCached').mockResolvedValue(nonOwnerUser);
|
||||
jest.spyOn(UserManagementHelper, 'isSharingEnabled').mockReturnValue(false);
|
||||
jest.spyOn(userService, 'findOne').mockImplementation(async () => fakeUser);
|
||||
jest.spyOn(WorkflowsService, 'getSharing').mockImplementation(async () => {
|
||||
return sharedWorkflowNotOwner;
|
||||
});
|
||||
|
||||
const subworkflow = new Workflow({
|
||||
nodes: [],
|
||||
@@ -267,6 +253,9 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
active: false,
|
||||
nodeTypes: mockNodeTypes,
|
||||
id: '2',
|
||||
settings: {
|
||||
callerPolicy: 'any',
|
||||
},
|
||||
});
|
||||
await expect(
|
||||
PermissionChecker.checkSubworkflowExecutePolicy(subworkflow, userId),
|
||||
@@ -284,16 +273,12 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('list of ids must include the parent workflow id', async () => {
|
||||
test('should throw if allowed list does not contain parent workflow id', async () => {
|
||||
const invalidParentWorkflowId = uuid();
|
||||
jest
|
||||
.spyOn(ownershipService, 'getWorkflowOwnerCached')
|
||||
.mockImplementation(async (workflowId) => fakeUser);
|
||||
jest.spyOn(UserManagementHelper, 'isSharingEnabled').mockReturnValue(true);
|
||||
jest.spyOn(userService, 'findOne').mockImplementation(async () => fakeUser);
|
||||
jest.spyOn(WorkflowsService, 'getSharing').mockImplementation(async () => {
|
||||
return sharedWorkflowNotOwner;
|
||||
});
|
||||
|
||||
const subworkflow = new Workflow({
|
||||
nodes: [],
|
||||
@@ -312,14 +297,8 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
});
|
||||
|
||||
test('sameOwner passes when both workflows are owned by the same user', async () => {
|
||||
jest
|
||||
.spyOn(ownershipService, 'getWorkflowOwnerCached')
|
||||
.mockImplementation(async (workflowId) => fakeUser);
|
||||
jest.spyOn(ownershipService, 'getWorkflowOwnerCached').mockImplementation(async () => fakeUser);
|
||||
jest.spyOn(UserManagementHelper, 'isSharingEnabled').mockReturnValue(false);
|
||||
jest.spyOn(userService, 'findOne').mockImplementation(async () => fakeUser);
|
||||
jest.spyOn(WorkflowsService, 'getSharing').mockImplementation(async () => {
|
||||
return sharedWorkflowOwner;
|
||||
});
|
||||
|
||||
const subworkflow = new Workflow({
|
||||
nodes: [],
|
||||
@@ -339,10 +318,6 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
.spyOn(ownershipService, 'getWorkflowOwnerCached')
|
||||
.mockImplementation(async (workflowId) => fakeUser);
|
||||
jest.spyOn(UserManagementHelper, 'isSharingEnabled').mockReturnValue(true);
|
||||
jest.spyOn(userService, 'findOne').mockImplementation(async () => fakeUser);
|
||||
jest.spyOn(WorkflowsService, 'getSharing').mockImplementation(async () => {
|
||||
return sharedWorkflowNotOwner;
|
||||
});
|
||||
|
||||
const subworkflow = new Workflow({
|
||||
nodes: [],
|
||||
@@ -365,10 +340,6 @@ describe('PermissionChecker.checkSubworkflowExecutePolicy', () => {
|
||||
.spyOn(ownershipService, 'getWorkflowOwnerCached')
|
||||
.mockImplementation(async (workflowId) => fakeUser);
|
||||
jest.spyOn(UserManagementHelper, 'isSharingEnabled').mockReturnValue(true);
|
||||
jest.spyOn(userService, 'findOne').mockImplementation(async () => fakeUser);
|
||||
jest.spyOn(WorkflowsService, 'getSharing').mockImplementation(async () => {
|
||||
return sharedWorkflowNotOwner;
|
||||
});
|
||||
|
||||
const subworkflow = new Workflow({
|
||||
nodes: [],
|
||||
|
||||
Reference in New Issue
Block a user