mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-23 04:45:21 +02:00
211 lines
7.5 KiB
TypeScript
211 lines
7.5 KiB
TypeScript
import { mockInstance } from '@n8n/backend-test-utils';
|
|
import { InstanceSettingsLoaderConfig } from '@n8n/config';
|
|
import {
|
|
PERSONAL_SPACE_PUBLISHING_SETTING,
|
|
PERSONAL_SPACE_SHARING_SETTING,
|
|
} from '@n8n/permissions';
|
|
|
|
import { SecuritySettingsService } from '@/services/security-settings.service';
|
|
|
|
import { createOwner } from '../shared/db/users';
|
|
import type { SuperAgentTest } from '../shared/types';
|
|
import { setupTestServer } from '../shared/utils';
|
|
|
|
describe('SecuritySettingsController', () => {
|
|
const securitySettingsService = mockInstance(SecuritySettingsService);
|
|
const instanceSettingsLoaderConfig = mockInstance(InstanceSettingsLoaderConfig, {
|
|
securityPolicyManagedByEnv: false,
|
|
});
|
|
|
|
const testServer = setupTestServer({ endpointGroups: ['security-settings'] });
|
|
let ownerAgent: SuperAgentTest;
|
|
|
|
beforeAll(async () => {
|
|
const owner = await createOwner();
|
|
ownerAgent = testServer.authAgentFor(owner);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
testServer.license.enable('feat:personalSpacePolicy');
|
|
instanceSettingsLoaderConfig.securityPolicyManagedByEnv = false;
|
|
});
|
|
|
|
describe('GET /settings/security', () => {
|
|
it('should return 403 when personalSpacePolicy license is not active', async () => {
|
|
testServer.license.disable('feat:personalSpacePolicy');
|
|
await ownerAgent.get('/settings/security').expect(403);
|
|
});
|
|
|
|
it('should return security settings and all counts', async () => {
|
|
securitySettingsService.arePersonalSpaceSettingsEnabled.mockResolvedValue({
|
|
personalSpacePublishing: true,
|
|
personalSpaceSharing: false,
|
|
});
|
|
securitySettingsService.getPublishedPersonalWorkflowsCount.mockResolvedValue(5);
|
|
securitySettingsService.getSharedPersonalWorkflowsCount.mockResolvedValue(12);
|
|
securitySettingsService.getSharedPersonalCredentialsCount.mockResolvedValue(3);
|
|
|
|
const response = await ownerAgent.get('/settings/security').expect(200);
|
|
|
|
expect(response.body).toEqual({
|
|
data: {
|
|
personalSpacePublishing: true,
|
|
personalSpaceSharing: false,
|
|
publishedPersonalWorkflowsCount: 5,
|
|
sharedPersonalWorkflowsCount: 12,
|
|
sharedPersonalCredentialsCount: 3,
|
|
managedByEnv: false,
|
|
},
|
|
});
|
|
expect(securitySettingsService.arePersonalSpaceSettingsEnabled).toHaveBeenCalledTimes(1);
|
|
expect(securitySettingsService.getPublishedPersonalWorkflowsCount).toHaveBeenCalledTimes(1);
|
|
expect(securitySettingsService.getSharedPersonalWorkflowsCount).toHaveBeenCalledTimes(1);
|
|
expect(securitySettingsService.getSharedPersonalCredentialsCount).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should return 0 for all counts when no resources exist', async () => {
|
|
securitySettingsService.arePersonalSpaceSettingsEnabled.mockResolvedValue({
|
|
personalSpacePublishing: true,
|
|
personalSpaceSharing: true,
|
|
});
|
|
securitySettingsService.getPublishedPersonalWorkflowsCount.mockResolvedValue(0);
|
|
securitySettingsService.getSharedPersonalWorkflowsCount.mockResolvedValue(0);
|
|
securitySettingsService.getSharedPersonalCredentialsCount.mockResolvedValue(0);
|
|
|
|
const response = await ownerAgent.get('/settings/security').expect(200);
|
|
|
|
expect(response.body.data.publishedPersonalWorkflowsCount).toBe(0);
|
|
expect(response.body.data.sharedPersonalWorkflowsCount).toBe(0);
|
|
expect(response.body.data.sharedPersonalCredentialsCount).toBe(0);
|
|
});
|
|
|
|
it('should handle service errors gracefully', async () => {
|
|
securitySettingsService.arePersonalSpaceSettingsEnabled.mockRejectedValue(
|
|
new Error('Database connection failed'),
|
|
);
|
|
|
|
await ownerAgent.get('/settings/security').expect(500);
|
|
});
|
|
});
|
|
|
|
describe('POST /settings/security', () => {
|
|
it('should return 403 when personalSpacePolicy license is not active', async () => {
|
|
testServer.license.disable('feat:personalSpacePolicy');
|
|
await ownerAgent
|
|
.post('/settings/security')
|
|
.send({ personalSpacePublishing: true })
|
|
.expect(403);
|
|
});
|
|
|
|
it('should update only personalSpacePublishing when only that is set in body', async () => {
|
|
securitySettingsService.setPersonalSpaceSetting.mockResolvedValue(undefined);
|
|
|
|
const response = await ownerAgent
|
|
.post('/settings/security')
|
|
.send({ personalSpacePublishing: false })
|
|
.expect(200);
|
|
|
|
expect(response.body).toEqual({
|
|
data: { personalSpacePublishing: false },
|
|
});
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenCalledTimes(1);
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenCalledWith(
|
|
PERSONAL_SPACE_PUBLISHING_SETTING,
|
|
false,
|
|
);
|
|
});
|
|
|
|
it('should update only personalSpaceSharing when only that is set in body', async () => {
|
|
securitySettingsService.setPersonalSpaceSetting.mockResolvedValue(undefined);
|
|
const response = await ownerAgent
|
|
.post('/settings/security')
|
|
.send({ personalSpaceSharing: true })
|
|
.expect(200);
|
|
|
|
expect(response.body).toEqual({
|
|
data: { personalSpaceSharing: true },
|
|
});
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenCalledTimes(1);
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenCalledWith(
|
|
PERSONAL_SPACE_SHARING_SETTING,
|
|
true,
|
|
);
|
|
});
|
|
|
|
it('should update both settings when both are set in body', async () => {
|
|
securitySettingsService.setPersonalSpaceSetting.mockResolvedValue(undefined);
|
|
|
|
const response = await ownerAgent
|
|
.post('/settings/security')
|
|
.send({ personalSpacePublishing: true, personalSpaceSharing: false })
|
|
.expect(200);
|
|
|
|
expect(response.body).toEqual({
|
|
data: {
|
|
personalSpacePublishing: true,
|
|
personalSpaceSharing: false,
|
|
},
|
|
});
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenCalledTimes(2);
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenNthCalledWith(
|
|
1,
|
|
PERSONAL_SPACE_PUBLISHING_SETTING,
|
|
true,
|
|
);
|
|
expect(securitySettingsService.setPersonalSpaceSetting).toHaveBeenNthCalledWith(
|
|
2,
|
|
PERSONAL_SPACE_SHARING_SETTING,
|
|
false,
|
|
);
|
|
});
|
|
|
|
it('should call no service and return empty object when body has no settings', async () => {
|
|
const response = await ownerAgent.post('/settings/security').send({}).expect(200);
|
|
|
|
expect(response.body).toEqual({ data: {} });
|
|
expect(securitySettingsService.setPersonalSpaceSetting).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle service errors gracefully', async () => {
|
|
securitySettingsService.setPersonalSpaceSetting.mockRejectedValue(
|
|
new Error('Database connection failed'),
|
|
);
|
|
|
|
await ownerAgent
|
|
.post('/settings/security')
|
|
.send({ personalSpacePublishing: true })
|
|
.expect(500);
|
|
});
|
|
});
|
|
|
|
describe('when securityPolicyManagedByEnv is true', () => {
|
|
beforeEach(() => {
|
|
instanceSettingsLoaderConfig.securityPolicyManagedByEnv = true;
|
|
});
|
|
|
|
it('GET should return managedByEnv: true', async () => {
|
|
securitySettingsService.arePersonalSpaceSettingsEnabled.mockResolvedValue({
|
|
personalSpacePublishing: true,
|
|
personalSpaceSharing: true,
|
|
});
|
|
securitySettingsService.getPublishedPersonalWorkflowsCount.mockResolvedValue(0);
|
|
securitySettingsService.getSharedPersonalWorkflowsCount.mockResolvedValue(0);
|
|
securitySettingsService.getSharedPersonalCredentialsCount.mockResolvedValue(0);
|
|
|
|
const response = await ownerAgent.get('/settings/security').expect(200);
|
|
|
|
expect(response.body.data.managedByEnv).toBe(true);
|
|
});
|
|
|
|
it('POST should return 403 when settings are managed by env', async () => {
|
|
await ownerAgent
|
|
.post('/settings/security')
|
|
.send({ personalSpacePublishing: false })
|
|
.expect(403);
|
|
|
|
expect(securitySettingsService.setPersonalSpaceSetting).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|