fix(editor): Fix main button create variable disable state based on scopes (#21521)

This commit is contained in:
Guillaume Jacquart 2025-11-04 11:06:23 +01:00 committed by GitHub
parent a2d6c8d65f
commit d2e623e205
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 45 additions and 3 deletions

View File

@ -3062,7 +3062,7 @@
"variables.empty.button": "Add first variable",
"variables.empty.button.disabled.tooltip": "Your current role in the project does not allow you to create variables",
"variables.empty.notAllowedToCreate.heading": "{name}, start using variables",
"variables.empty.notAllowedToCreate.description": "Ask your n8n instance owner to create the variables you need. Once configured, you can utilize them in your workflows using the syntax $vars.MY_VAR.",
"variables.empty.notAllowedToCreate.description": "Ask project editors or instance admin to create the variables you need. Once configured, you can utilize them in your workflows using the syntax $vars.MY_VAR.",
"variables.filters.active": "Some variables may be hidden since filters are applied.",
"variables.filters.active.reset": "Remove filters",
"variables.noResults": "No variables found",

View File

@ -14,6 +14,9 @@ import { waitFor, within } from '@testing-library/vue';
import { useSettingsStore } from '@/app/stores/settings.store';
import { useProjectPages } from '@/features/collaboration/projects/composables/useProjectPages';
import { useUIStore } from '@/app/stores/ui.store';
import { useUsersStore } from '@/features/settings/users/users.store';
import { mock } from 'vitest-mock-extended';
import type { IUser } from '@n8n/rest-api-client';
const mockPush = vi.fn();
vi.mock('vue-router', async () => {
@ -76,6 +79,7 @@ let projectsStore: ReturnType<typeof mockedStore<typeof useProjectsStore>>;
let settingsStore: ReturnType<typeof mockedStore<typeof useSettingsStore>>;
let uiStore: ReturnType<typeof mockedStore<typeof useUIStore>>;
let projectPages: ReturnType<typeof useProjectPages>;
let usersStore: ReturnType<typeof mockedStore<typeof useUsersStore>>;
describe('ProjectHeader', () => {
beforeEach(() => {
@ -83,6 +87,7 @@ describe('ProjectHeader', () => {
route = router.useRoute();
projectsStore = mockedStore(useProjectsStore);
settingsStore = mockedStore(useSettingsStore);
usersStore = mockedStore(useUsersStore);
uiStore = mockedStore(useUIStore);
projectPages = useProjectPages();
@ -527,5 +532,39 @@ describe('ProjectHeader', () => {
}),
);
});
it('should enable variable create button if project scope allows it', () => {
const project = createTestProject({
scopes: ['projectVariable:create'],
});
projectsStore.currentProject = project;
const { getByTestId } = renderComponent({ props: { mainButton: 'variable' } });
expect(getByTestId('add-resource-variable')).toBeInTheDocument();
expect(getByTestId('add-resource-variable')).toBeEnabled();
});
it('should enable create variable button if global scope allows it', () => {
usersStore.currentUser = mock<IUser>({
globalScopes: ['variable:create'],
});
const { getByTestId } = renderComponent({ props: { mainButton: 'variable' } });
expect(getByTestId('add-resource-variable')).toBeInTheDocument();
expect(getByTestId('add-resource-variable')).toBeEnabled();
});
it('should not enable variable create button if no scope allows it', () => {
const project = createTestProject({
scopes: [],
});
projectsStore.currentProject = project;
const { queryByTestId } = renderComponent({ props: { mainButton: 'variable' } });
expect(queryByTestId('add-resource-variable')).toBeDisabled();
});
});
});

View File

@ -77,7 +77,10 @@ const projectName = computed(() => {
const projectPermissions = computed(
() => getResourcePermissions(projectsStore.currentProject?.scopes).project,
);
const globalPermissions = computed(
const projectVariablePermissions = computed(
() => getResourcePermissions(projectsStore.currentProject?.scopes).projectVariable,
);
const globalVariablesPermissions = computed(
() => getResourcePermissions(usersStore.currentUser?.globalScopes).variable,
);
@ -164,7 +167,7 @@ const createVariableButton = computed(() => ({
size: 'mini' as const,
disabled:
sourceControlStore.preferences.branchReadOnly ||
(!projectPermissions.value.create && !globalPermissions.value.create),
(!projectVariablePermissions.value.create && !globalVariablesPermissions.value.create),
}));
const selectedMainButtonType = computed(() => props.mainButton ?? ACTION_TYPES.WORKFLOW);