mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-01 01:07:04 +02:00
129 lines
3.9 KiB
TypeScript
129 lines
3.9 KiB
TypeScript
import { nanoid } from 'nanoid';
|
|
|
|
import { test, expect } from '../../../fixtures/base';
|
|
|
|
test.describe(
|
|
'Workflow Sharing',
|
|
{
|
|
annotation: [{ type: 'owner', description: 'Identity & Access' }],
|
|
},
|
|
() => {
|
|
test('should share workflow with another user via UI', async ({ n8n, api }) => {
|
|
const member = await api.publicApi.createUser({
|
|
email: `member-${nanoid()}@test.com`,
|
|
firstName: 'Test',
|
|
lastName: 'Member',
|
|
});
|
|
|
|
await n8n.navigate.toWorkflow('new');
|
|
const workflowName = `Test Workflow ${nanoid()}`;
|
|
await n8n.canvas.setWorkflowName(workflowName);
|
|
await n8n.canvas.addNode('Manual Trigger');
|
|
|
|
await n8n.canvas.openShareModal();
|
|
await n8n.workflowSharingModal.addUser(member.email);
|
|
await n8n.workflowSharingModal.save();
|
|
|
|
const memberN8n = await n8n.start.withUser(member);
|
|
await memberN8n.navigate.toWorkflows();
|
|
await expect(memberN8n.workflows.cards.getWorkflow(workflowName)).toBeVisible();
|
|
});
|
|
|
|
test('should share workflow with another user via API', async ({ api }) => {
|
|
const member = await api.publicApi.createUser({
|
|
email: `member-${nanoid()}@test.com`,
|
|
firstName: 'Test',
|
|
lastName: 'Member',
|
|
});
|
|
|
|
const workflow = await api.workflows.createWorkflow({
|
|
name: `Test Workflow ${nanoid()}`,
|
|
nodes: [
|
|
{
|
|
id: 'manual-trigger',
|
|
name: 'Manual Trigger',
|
|
type: 'n8n-nodes-base.manualTrigger',
|
|
position: [100, 200],
|
|
parameters: {},
|
|
typeVersion: 1,
|
|
},
|
|
],
|
|
connections: {},
|
|
});
|
|
|
|
const memberApi = await api.createApiForUser(member);
|
|
const memberProject = await memberApi.projects.getMyPersonalProject();
|
|
await api.workflows.shareWorkflow(workflow.id, [memberProject.id]);
|
|
|
|
const memberWorkflows = await memberApi.workflows.getWorkflows();
|
|
const sharedWorkflow = memberWorkflows.find((w: { id: string }) => w.id === workflow.id);
|
|
expect(sharedWorkflow).toBeTruthy();
|
|
expect(sharedWorkflow?.name).toBe(workflow.name);
|
|
});
|
|
|
|
test('should allow shared user to edit shared workflow', async ({ n8n, api }) => {
|
|
const member = await api.publicApi.createUser({
|
|
email: `member-${nanoid()}@test.com`,
|
|
firstName: 'Test',
|
|
lastName: 'Member',
|
|
});
|
|
|
|
const workflow = await api.workflows.createWorkflow({
|
|
name: `Test Workflow ${nanoid()}`,
|
|
nodes: [
|
|
{
|
|
id: 'manual-trigger',
|
|
name: 'Manual Trigger',
|
|
type: 'n8n-nodes-base.manualTrigger',
|
|
position: [100, 200],
|
|
parameters: {},
|
|
typeVersion: 1,
|
|
},
|
|
],
|
|
connections: {},
|
|
});
|
|
|
|
const memberApi = await api.createApiForUser(member);
|
|
const memberProject = await memberApi.projects.getMyPersonalProject();
|
|
await api.workflows.shareWorkflow(workflow.id, [memberProject.id]);
|
|
|
|
const memberN8n = await n8n.start.withUser(member);
|
|
await memberN8n.navigate.toWorkflow(workflow.id);
|
|
await expect(memberN8n.canvas.getCanvasNodes()).toHaveCount(1);
|
|
|
|
await memberN8n.canvas.addNode('Code', { action: 'Code in JavaScript', closeNDV: true });
|
|
await expect(memberN8n.canvas.getCanvasNodes()).toHaveCount(2);
|
|
});
|
|
|
|
test('should prevent access to workflow when user is not shared', async ({ api }) => {
|
|
await api.enableProjectFeatures();
|
|
|
|
const member = await api.publicApi.createUser({
|
|
email: `member-${nanoid()}@test.com`,
|
|
firstName: 'Test',
|
|
lastName: 'Member',
|
|
});
|
|
|
|
const workflow = await api.workflows.createWorkflow({
|
|
name: `Private Workflow ${nanoid()}`,
|
|
nodes: [
|
|
{
|
|
id: 'manual-trigger',
|
|
name: 'Manual Trigger',
|
|
type: 'n8n-nodes-base.manualTrigger',
|
|
position: [100, 200],
|
|
parameters: {},
|
|
typeVersion: 1,
|
|
},
|
|
],
|
|
connections: {},
|
|
});
|
|
|
|
const memberApi = await api.createApiForUser(member);
|
|
const response = await memberApi.request.get(`/rest/workflows/${workflow.id}`);
|
|
// With project features enabled, unauthorized access returns 403 (Forbidden)
|
|
expect(response.status()).toBe(403);
|
|
});
|
|
},
|
|
);
|