first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
import { ALL_ROLES } from '@n8n/permissions';
|
||||
import type { Role, Scope } from '@n8n/permissions';
|
||||
|
||||
import { createMember } from './shared/db/users';
|
||||
import type { SuperAgentTest } from './shared/types';
|
||||
import * as utils from './shared/utils/';
|
||||
import { Container } from '@n8n/di';
|
||||
import { AuthRolesService, SettingsRepository } from '@n8n/db';
|
||||
import { SecuritySettingsService } from '@/services/security-settings.service';
|
||||
import {
|
||||
PROJECT_SCOPE_MAP,
|
||||
PERSONAL_SPACE_SHARING_SETTING,
|
||||
PERSONAL_SPACE_PUBLISHING_SETTING,
|
||||
} from '@n8n/permissions';
|
||||
|
||||
const testServer = utils.setupTestServer({
|
||||
endpointGroups: ['role'],
|
||||
});
|
||||
|
||||
let memberAgent: SuperAgentTest;
|
||||
|
||||
const expectedCategories = ['global', 'project', 'credential', 'workflow'] as const;
|
||||
let expectedGlobalRoles: Role[];
|
||||
let expectedCredentialRoles: Role[];
|
||||
let expectedWorkflowRoles: Role[];
|
||||
|
||||
function checkForRole(role: Role, roles: Role[]) {
|
||||
const returnedRole = roles.find((r) => r.slug === role.slug);
|
||||
expect(returnedRole).toBeDefined();
|
||||
role.scopes.sort();
|
||||
returnedRole!.scopes.sort();
|
||||
returnedRole!.licensed = role.licensed;
|
||||
expect(returnedRole).toEqual({
|
||||
...role,
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
});
|
||||
}
|
||||
|
||||
function checkForScopes(roleSlug: string, scopes: Scope[], response: Role[]) {
|
||||
const role = response.find((r) => r.slug === roleSlug);
|
||||
expect(role).toBeDefined();
|
||||
role!.scopes.sort();
|
||||
expect(role!.scopes).toEqual(scopes.sort());
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
memberAgent = testServer.authAgentFor(await createMember());
|
||||
|
||||
expectedGlobalRoles = ALL_ROLES.global;
|
||||
expectedCredentialRoles = ALL_ROLES.credential;
|
||||
expectedWorkflowRoles = ALL_ROLES.workflow;
|
||||
});
|
||||
|
||||
describe('GET /roles/', () => {
|
||||
test('should return all role categories', async () => {
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
|
||||
const data: Record<string, string[]> = resp.body.data;
|
||||
|
||||
const categories = [...Object.keys(data)];
|
||||
expect(categories.length).toBe(expectedCategories.length);
|
||||
expect(expectedCategories.every((c) => categories.includes(c))).toBe(true);
|
||||
});
|
||||
|
||||
test('should return fixed global roles', async () => {
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
expect(Array.isArray(resp.body.data.global)).toBe(true);
|
||||
for (const role of expectedGlobalRoles) {
|
||||
checkForRole(role, resp.body.data.global);
|
||||
}
|
||||
});
|
||||
|
||||
describe('Project roles', () => {
|
||||
let securitySettingsService: SecuritySettingsService;
|
||||
let settingsRepository: SettingsRepository;
|
||||
|
||||
beforeEach(async () => {
|
||||
securitySettingsService = Container.get(SecuritySettingsService);
|
||||
settingsRepository = Container.get(SettingsRepository);
|
||||
await settingsRepository.delete({ key: PERSONAL_SPACE_PUBLISHING_SETTING.key });
|
||||
await settingsRepository.delete({ key: PERSONAL_SPACE_SHARING_SETTING.key });
|
||||
await Container.get(AuthRolesService).init();
|
||||
});
|
||||
|
||||
test('should default to adding sharing and publishing scopes when no security settings are set', async () => {
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
expect(resp.status).toBe(200);
|
||||
checkForScopes(
|
||||
'project:personalOwner',
|
||||
[
|
||||
...PROJECT_SCOPE_MAP['project:personalOwner'],
|
||||
...(PERSONAL_SPACE_SHARING_SETTING.scopes as Scope[]),
|
||||
...(PERSONAL_SPACE_PUBLISHING_SETTING.scopes as Scope[]),
|
||||
],
|
||||
resp.body.data.project,
|
||||
);
|
||||
});
|
||||
|
||||
test('should match fixed scopes when security settings are all explicitly disabled', async () => {
|
||||
await securitySettingsService.setPersonalSpaceSetting(
|
||||
PERSONAL_SPACE_PUBLISHING_SETTING,
|
||||
false,
|
||||
);
|
||||
await securitySettingsService.setPersonalSpaceSetting(PERSONAL_SPACE_SHARING_SETTING, false);
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
for (const role of ALL_ROLES.project) {
|
||||
checkForRole(role, resp.body.data.project);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return the list with project:personalOwner - workflow:publish scope when the personal project publish security setting is explicitly enabled', async () => {
|
||||
await securitySettingsService.setPersonalSpaceSetting(
|
||||
PERSONAL_SPACE_PUBLISHING_SETTING,
|
||||
true,
|
||||
);
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
checkForScopes(
|
||||
'project:personalOwner',
|
||||
[
|
||||
...PROJECT_SCOPE_MAP['project:personalOwner'],
|
||||
...(PERSONAL_SPACE_PUBLISHING_SETTING.scopes as Scope[]),
|
||||
...(PERSONAL_SPACE_SHARING_SETTING.scopes as Scope[]),
|
||||
],
|
||||
resp.body.data.project,
|
||||
);
|
||||
});
|
||||
|
||||
test('should return the list with project:personalOwner - sharing scopes when the personal project sharing security setting is explicitly enabled', async () => {
|
||||
await securitySettingsService.setPersonalSpaceSetting(PERSONAL_SPACE_SHARING_SETTING, true);
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
checkForScopes(
|
||||
'project:personalOwner',
|
||||
[
|
||||
...PROJECT_SCOPE_MAP['project:personalOwner'],
|
||||
...(PERSONAL_SPACE_PUBLISHING_SETTING.scopes as Scope[]),
|
||||
...(PERSONAL_SPACE_SHARING_SETTING.scopes as Scope[]),
|
||||
],
|
||||
resp.body.data.project,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('should return fixed credential sharing roles', async () => {
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
for (const role of expectedCredentialRoles) {
|
||||
checkForRole(role, resp.body.data.credential);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return fixed workflow sharing roles', async () => {
|
||||
const resp = await memberAgent.get('/roles/');
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
for (const role of expectedWorkflowRoles) {
|
||||
checkForRole(role, resp.body.data.workflow);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user