mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
feat(editor): Display custom roles in the project role dropdown (#18983)
Co-authored-by: Andreas Fitzek <andreas.fitzek@n8n.io>
This commit is contained in:
committed by
GitHub
parent
d0ffd6e659
commit
bf198f8263
@@ -1,4 +1,4 @@
|
||||
import type { AllRolesMap } from '@n8n/permissions';
|
||||
import { type AllRolesMap, PROJECT_OWNER_ROLE_SLUG } from '@n8n/permissions';
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, computed } from 'vue';
|
||||
import * as rolesApi from '@n8n/rest-api-client/api/roles';
|
||||
@@ -20,11 +20,11 @@ export const useRolesStore = defineStore('roles', () => {
|
||||
|
||||
const processedProjectRoles = computed<AllRolesMap['project']>(() =>
|
||||
roles.value.project
|
||||
.filter((role) => projectRoleOrderMap.value.has(role.slug))
|
||||
.filter((role) => role.slug !== PROJECT_OWNER_ROLE_SLUG)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
(projectRoleOrderMap.value.get(a.slug) ?? 0) -
|
||||
(projectRoleOrderMap.value.get(b.slug) ?? 0),
|
||||
(projectRoleOrderMap.value.get(a.slug) ?? Number.MAX_SAFE_INTEGER) -
|
||||
(projectRoleOrderMap.value.get(b.slug) ?? Number.MAX_SAFE_INTEGER),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { createProjectListItem } from '@/__tests__/data/projects';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import type { FrontendSettings } from '@n8n/api-types';
|
||||
import { ProjectTypes } from '@/types/projects.types';
|
||||
import { useRolesStore } from '@/stores/roles.store';
|
||||
|
||||
vi.mock('vue-router', () => {
|
||||
const params = {};
|
||||
@@ -40,6 +41,7 @@ let router: ReturnType<typeof useRouter>;
|
||||
let projectsStore: ReturnType<typeof useProjectsStore>;
|
||||
let usersStore: ReturnType<typeof useUsersStore>;
|
||||
let settingsStore: ReturnType<typeof useSettingsStore>;
|
||||
let rolesStore: ReturnType<typeof useRolesStore>;
|
||||
|
||||
describe('ProjectSettings', () => {
|
||||
beforeEach(() => {
|
||||
@@ -49,6 +51,7 @@ describe('ProjectSettings', () => {
|
||||
projectsStore = useProjectsStore();
|
||||
usersStore = useUsersStore();
|
||||
settingsStore = useSettingsStore();
|
||||
rolesStore = useRolesStore();
|
||||
|
||||
vi.spyOn(usersStore, 'fetchUsers').mockImplementation(async () => await Promise.resolve());
|
||||
vi.spyOn(projectsStore, 'getAvailableProjects').mockImplementation(async () => {});
|
||||
@@ -66,12 +69,49 @@ describe('ProjectSettings', () => {
|
||||
enabled: false,
|
||||
},
|
||||
} as FrontendSettings);
|
||||
vi.spyOn(rolesStore, 'processedProjectRoles', 'get').mockReturnValue([
|
||||
{
|
||||
slug: 'project:admin',
|
||||
displayName: 'Project Admin',
|
||||
description: 'Can manage project settings',
|
||||
licensed: true,
|
||||
roleType: 'project',
|
||||
scopes: ['project:read', 'project:write', 'project:delete'],
|
||||
systemRole: true,
|
||||
},
|
||||
{
|
||||
slug: 'project:editor',
|
||||
displayName: 'Project Editor',
|
||||
description: 'Can edit project settings',
|
||||
licensed: true,
|
||||
roleType: 'project',
|
||||
scopes: ['project:read', 'project:write'],
|
||||
systemRole: true,
|
||||
},
|
||||
{
|
||||
slug: 'project:custom',
|
||||
displayName: 'Custom',
|
||||
description: 'Can do some custom actions',
|
||||
licensed: true,
|
||||
roleType: 'project',
|
||||
scopes: ['workflow:list'],
|
||||
systemRole: false,
|
||||
},
|
||||
]);
|
||||
projectsStore.setCurrentProject({
|
||||
id: '123',
|
||||
type: 'team',
|
||||
name: 'Test Project',
|
||||
icon: { type: 'icon', value: 'folder' },
|
||||
relations: [],
|
||||
relations: [
|
||||
{
|
||||
id: '1',
|
||||
lastName: 'Doe',
|
||||
firstName: 'John',
|
||||
role: 'project:admin',
|
||||
email: 'admin@example.com',
|
||||
},
|
||||
],
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
scopes: [],
|
||||
@@ -132,4 +172,15 @@ describe('ProjectSettings', () => {
|
||||
expect(deleteProjectSpy).toHaveBeenCalledWith('123', undefined);
|
||||
expect(router.push).toHaveBeenCalledWith({ name: VIEWS.HOMEPAGE });
|
||||
});
|
||||
|
||||
it('should show role dropdown', async () => {
|
||||
const { getByTestId } = renderComponent();
|
||||
const roleDropdown = getByTestId('projects-settings-user-role-select');
|
||||
expect(roleDropdown).toBeVisible();
|
||||
const roleDropdownItems = await getDropdownItems(roleDropdown);
|
||||
expect(roleDropdownItems).toHaveLength(3);
|
||||
expect(roleDropdownItems[0]).toHaveTextContent('Admin');
|
||||
expect(roleDropdownItems[1]).toHaveTextContent('Editor');
|
||||
expect(roleDropdownItems[2]).toHaveTextContent('Custom');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ const projects = computed(() =>
|
||||
const projectRoles = computed(() =>
|
||||
rolesStore.processedProjectRoles.map((role) => ({
|
||||
...role,
|
||||
displayName: projectRoleTranslations.value[role.slug],
|
||||
displayName: projectRoleTranslations.value[role.slug] ?? role.displayName,
|
||||
})),
|
||||
);
|
||||
const firstLicensedRole = computed(() => projectRoles.value.find((role) => role.licensed)?.slug);
|
||||
|
||||
Reference in New Issue
Block a user