mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat: Allow owner to share workflows/credentials they don't own (no-changelog) (#7869)
Github issue / Community forum post (link here to close automatically):
This commit is contained in:
@@ -23,7 +23,9 @@ const testServer = utils.setupTestServer({ endpointGroups: ['credentials'] });
|
||||
let globalMemberRole: Role;
|
||||
let owner: User;
|
||||
let member: User;
|
||||
let anotherMember: User;
|
||||
let authOwnerAgent: SuperAgentTest;
|
||||
let authAnotherMemberAgent: SuperAgentTest;
|
||||
let saveCredential: SaveCredentialFunction;
|
||||
|
||||
beforeAll(async () => {
|
||||
@@ -33,8 +35,10 @@ beforeAll(async () => {
|
||||
|
||||
owner = await createUser({ globalRole: globalOwnerRole });
|
||||
member = await createUser({ globalRole: globalMemberRole });
|
||||
anotherMember = await createUser({ globalRole: globalMemberRole });
|
||||
|
||||
authOwnerAgent = testServer.authAgentFor(owner);
|
||||
authAnotherMemberAgent = testServer.authAgentFor(anotherMember);
|
||||
|
||||
saveCredential = affixRoleToSaveCredential(credentialOwnerRole);
|
||||
});
|
||||
@@ -406,14 +410,65 @@ describe('PUT /credentials/:id/share', () => {
|
||||
expect(response.statusCode).toBe(403);
|
||||
});
|
||||
|
||||
test('should respond 403 for non-owned credentials', async () => {
|
||||
test('should respond 403 for non-owned credentials for shared members', async () => {
|
||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
|
||||
await shareCredentialWithUsers(savedCredential, [anotherMember]);
|
||||
|
||||
const response = await authAnotherMemberAgent
|
||||
.put(`/credentials/${savedCredential.id}/share`)
|
||||
.send({ shareWithIds: [owner.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
const sharedCredentials = await Container.get(SharedCredentialsRepository).find({
|
||||
where: { credentialsId: savedCredential.id },
|
||||
});
|
||||
expect(sharedCredentials).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('should respond 403 for non-owned credentials for non-shared members sharing with self', async () => {
|
||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
|
||||
const response = await authAnotherMemberAgent
|
||||
.put(`/credentials/${savedCredential.id}/share`)
|
||||
.send({ shareWithIds: [anotherMember.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
|
||||
const sharedCredentials = await Container.get(SharedCredentialsRepository).find({
|
||||
where: { credentialsId: savedCredential.id },
|
||||
});
|
||||
expect(sharedCredentials).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('should respond 403 for non-owned credentials for non-shared members sharing', async () => {
|
||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
const tempUser = await createUser({ globalRole: globalMemberRole });
|
||||
|
||||
const response = await authAnotherMemberAgent
|
||||
.put(`/credentials/${savedCredential.id}/share`)
|
||||
.send({ shareWithIds: [tempUser.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
|
||||
const sharedCredentials = await Container.get(SharedCredentialsRepository).find({
|
||||
where: { credentialsId: savedCredential.id },
|
||||
});
|
||||
expect(sharedCredentials).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('should respond 200 for non-owned credentials for owners', async () => {
|
||||
const savedCredential = await saveCredential(randomCredentialPayload(), { user: member });
|
||||
|
||||
const response = await authOwnerAgent
|
||||
.put(`/credentials/${savedCredential.id}/share`)
|
||||
.send({ shareWithIds: [member.id] });
|
||||
.send({ shareWithIds: [anotherMember.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
expect(response.statusCode).toBe(200);
|
||||
const sharedCredentials = await Container.get(SharedCredentialsRepository).find({
|
||||
where: { credentialsId: savedCredential.id },
|
||||
});
|
||||
expect(sharedCredentials).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('should ignore pending sharee', async () => {
|
||||
|
||||
@@ -20,7 +20,9 @@ import { affixRoleToSaveCredential, shareCredentialWithUsers } from './shared/db
|
||||
import { getCredentialOwnerRole, getGlobalMemberRole, getGlobalOwnerRole } from './shared/db/roles';
|
||||
import { createUser } from './shared/db/users';
|
||||
import { createWorkflow, getWorkflowSharing, shareWorkflowWithUsers } from './shared/db/workflows';
|
||||
import type { Role } from '@/databases/entities/Role';
|
||||
|
||||
let globalMemberRole: Role;
|
||||
let owner: User;
|
||||
let member: User;
|
||||
let anotherMember: User;
|
||||
@@ -43,7 +45,7 @@ const testServer = utils.setupTestServer({
|
||||
|
||||
beforeAll(async () => {
|
||||
const globalOwnerRole = await getGlobalOwnerRole();
|
||||
const globalMemberRole = await getGlobalMemberRole();
|
||||
globalMemberRole = await getGlobalMemberRole();
|
||||
const credentialOwnerRole = await getCredentialOwnerRole();
|
||||
|
||||
owner = await createUser({ globalRole: globalOwnerRole });
|
||||
@@ -152,6 +154,75 @@ describe('PUT /workflows/:id', () => {
|
||||
const secondSharedWorkflows = await getWorkflowSharing(workflow);
|
||||
expect(secondSharedWorkflows).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('PUT /workflows/:id/share should allow sharing by the owner of the workflow', async () => {
|
||||
const workflow = await createWorkflow({}, member);
|
||||
|
||||
const response = await authMemberAgent
|
||||
.put(`/workflows/${workflow.id}/share`)
|
||||
.send({ shareWithIds: [anotherMember.id] });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const sharedWorkflows = await getWorkflowSharing(workflow);
|
||||
expect(sharedWorkflows).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('PUT /workflows/:id/share should allow sharing by the instance owner', async () => {
|
||||
const workflow = await createWorkflow({}, member);
|
||||
|
||||
const response = await authOwnerAgent
|
||||
.put(`/workflows/${workflow.id}/share`)
|
||||
.send({ shareWithIds: [anotherMember.id] });
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
|
||||
const sharedWorkflows = await getWorkflowSharing(workflow);
|
||||
expect(sharedWorkflows).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('PUT /workflows/:id/share should not allow sharing by another shared member', async () => {
|
||||
const workflow = await createWorkflow({}, member);
|
||||
|
||||
await shareWorkflowWithUsers(workflow, [anotherMember]);
|
||||
|
||||
const response = await authAnotherMemberAgent
|
||||
.put(`/workflows/${workflow.id}/share`)
|
||||
.send({ shareWithIds: [anotherMember.id, owner.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
|
||||
const sharedWorkflows = await getWorkflowSharing(workflow);
|
||||
expect(sharedWorkflows).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('PUT /workflows/:id/share should not allow sharing with self by another non-shared member', async () => {
|
||||
const workflow = await createWorkflow({}, member);
|
||||
|
||||
const response = await authAnotherMemberAgent
|
||||
.put(`/workflows/${workflow.id}/share`)
|
||||
.send({ shareWithIds: [anotherMember.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
|
||||
const sharedWorkflows = await getWorkflowSharing(workflow);
|
||||
expect(sharedWorkflows).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('PUT /workflows/:id/share should not allow sharing by another non-shared member', async () => {
|
||||
const workflow = await createWorkflow({}, member);
|
||||
|
||||
const tempUser = await createUser({ globalRole: globalMemberRole });
|
||||
|
||||
const response = await authAnotherMemberAgent
|
||||
.put(`/workflows/${workflow.id}/share`)
|
||||
.send({ shareWithIds: [tempUser.id] });
|
||||
|
||||
expect(response.statusCode).toBe(403);
|
||||
|
||||
const sharedWorkflows = await getWorkflowSharing(workflow);
|
||||
expect(sharedWorkflows).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /workflows/new', () => {
|
||||
|
||||
Reference in New Issue
Block a user