Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(editor): Remove "move" action from workflow and credential on community plan #10057

Merged
2 changes: 2 additions & 0 deletions packages/cli/src/controllers/e2e.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ export class E2EController {
// eslint-disable-next-line @typescript-eslint/unbound-method
license.getFeatureValue<NumericLicenseFeature> = (feature: NumericLicenseFeature) =>
this.numericFeatures[feature] ?? UNLIMITED_LICENSE_QUOTA;

license.getPlanName = () => 'Enterprise';
}

@Post('/reset', { skipAuth: true })
Expand Down
30 changes: 30 additions & 0 deletions packages/editor-ui/src/components/CredentialCard.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { setActivePinia } from 'pinia';
import { within } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
import { createTestingPinia } from '@pinia/testing';
import { createComponentRenderer } from '@/__tests__/render';
import CredentialCard from '@/components/CredentialCard.vue';
import type { ICredentialsResponse } from '@/Interface';
import type { ProjectSharingData } from '@/types/projects.types';
import { useSettingsStore } from '@/stores/settings.store';

const renderComponent = createComponentRenderer(CredentialCard);

Expand All @@ -19,9 +22,12 @@ const createCredential = (overrides = {}): ICredentialsResponse => ({
});

describe('CredentialCard', () => {
let settingsStore: ReturnType<typeof useSettingsStore>;

beforeEach(() => {
const pinia = createTestingPinia();
setActivePinia(pinia);
settingsStore = useSettingsStore();
});

it('should render name and home project name', () => {
Expand Down Expand Up @@ -55,4 +61,28 @@ describe('CredentialCard', () => {
expect(heading).toHaveTextContent(data.name);
expect(badge).toHaveTextContent('John Doe');
});

it('should show Move action only if there is resource permission and not on community plan', async () => {
vi.spyOn(settingsStore, 'isCommunityPlan', 'get').mockReturnValue(false);

const data = createCredential({
scopes: ['credential:move'],
});
const { getByTestId } = renderComponent({ props: { data } });
const cardActions = getByTestId('credential-card-actions');

expect(cardActions).toBeInTheDocument();

const cardActionsOpener = within(cardActions).getByRole('button');
expect(cardActionsOpener).toBeInTheDocument();

const controllingId = cardActionsOpener.getAttribute('aria-controls');

await userEvent.click(cardActions);
const actions = document.querySelector(`#${controllingId}`);
if (!actions) {
throw new Error('Actions menu not found');
}
expect(actions).toHaveTextContent('Move');
});
});
4 changes: 3 additions & 1 deletion packages/editor-ui/src/components/CredentialCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useProjectsStore } from '@/stores/projects.store';
import ProjectCardBadge from '@/components/Projects/ProjectCardBadge.vue';
import { useI18n } from '@/composables/useI18n';
import { ResourceType } from '@/utils/projects.utils';
import { useSettingsStore } from '@/stores/settings.store';

const CREDENTIAL_LIST_ITEM_ACTIONS = {
OPEN: 'open',
Expand Down Expand Up @@ -45,6 +46,7 @@ const message = useMessage();
const uiStore = useUIStore();
const credentialsStore = useCredentialsStore();
const projectsStore = useProjectsStore();
const settingsStore = useSettingsStore();

const resourceTypeLabel = computed(() => locale.baseText('generic.credential').toLowerCase());
const credentialType = computed(() => credentialsStore.getCredentialTypeByName(props.data.type));
Expand All @@ -64,7 +66,7 @@ const actions = computed(() => {
});
}

if (credentialPermissions.value.move) {
if (credentialPermissions.value.move && !settingsStore.isCommunityPlan) {
items.push({
label: locale.baseText('credentials.item.move'),
value: CREDENTIAL_LIST_ITEM_ACTIONS.MOVE,
Expand Down
38 changes: 33 additions & 5 deletions packages/editor-ui/src/components/WorkflowCard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { VIEWS } from '@/constants';
import WorkflowCard from '@/components/WorkflowCard.vue';
import type { IWorkflowDb } from '@/Interface';
import { useRouter } from 'vue-router';
import { useSettingsStore } from '@/stores/settings.store';

vi.mock('vue-router', () => {
const push = vi.fn();
Expand Down Expand Up @@ -39,12 +40,14 @@ describe('WorkflowCard', () => {
let pinia: ReturnType<typeof createPinia>;
let windowOpenSpy: MockInstance;
let router: ReturnType<typeof useRouter>;
let settingsStore: ReturnType<typeof useSettingsStore>;

beforeEach(async () => {
pinia = createPinia();
setActivePinia(pinia);
router = useRouter();
windowOpenSpy = vi.spyOn(window, 'open');
settingsStore = useSettingsStore();
windowOpenSpy = vi.spyOn(window, 'open').mockImplementation(() => null);
});

afterEach(() => {
Expand Down Expand Up @@ -95,10 +98,11 @@ describe('WorkflowCard', () => {
});

const actions = document.querySelector(`#${controllingId}`);
await waitFor(() => {
expect(actions).toBeInTheDocument();
});
await userEvent.click(actions!.querySelectorAll('li')[0]);
if (!actions) {
throw new Error('Actions menu not found');
}
await userEvent.click(actions.querySelectorAll('li')[0]);
expect(actions).not.toHaveTextContent('Move');
await waitFor(() => {
expect(router.push).toHaveBeenCalledWith({
name: VIEWS.WORKFLOW,
Expand Down Expand Up @@ -138,4 +142,28 @@ describe('WorkflowCard', () => {
expect(heading).toHaveTextContent(data.name);
expect(badge).toHaveTextContent('John Doe');
});

it('should show Move action only if there is resource permission and not on community plan', async () => {
vi.spyOn(settingsStore, 'isCommunityPlan', 'get').mockReturnValue(false);

const data = createWorkflow({
scopes: ['workflow:move'],
});
const { getByTestId } = renderComponent({ props: { data } });
const cardActions = getByTestId('workflow-card-actions');

expect(cardActions).toBeInTheDocument();

const cardActionsOpener = within(cardActions).getByRole('button');
expect(cardActionsOpener).toBeInTheDocument();

const controllingId = cardActionsOpener.getAttribute('aria-controls');

await userEvent.click(cardActions);
const actions = document.querySelector(`#${controllingId}`);
if (!actions) {
throw new Error('Actions menu not found');
}
expect(actions).toHaveTextContent('Move');
});
});
2 changes: 1 addition & 1 deletion packages/editor-ui/src/components/WorkflowCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const actions = computed(() => {
});
}

if (workflowPermissions.value.move) {
if (workflowPermissions.value.move && !settingsStore.isCommunityPlan) {
items.push({
label: locale.baseText('workflows.item.move'),
value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE,
Expand Down
11 changes: 5 additions & 6 deletions packages/editor-ui/src/composables/useDebugInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ export function useDebugInfo() {
: store.databaseType,
executionMode: store.isQueueModeEnabled ? 'scaling' : 'regular',
concurrency: store.settings.concurrency,
license:
store.planName === 'Community'
? (store.planName.toLowerCase() as 'community')
: store.settings.license.environment === 'production'
? 'enterprise (production)'
: 'enterprise (sandbox)',
license: store.isCommunityPlan
? 'community'
: store.settings.license.environment === 'production'
? 'enterprise (production)'
: 'enterprise (sandbox)',
consumerId: store.consumerId,
} as const;
};
Expand Down
7 changes: 5 additions & 2 deletions packages/editor-ui/src/stores/settings.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,13 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, {
return this.settings.databaseType;
},
planName(): string {
return this.settings.license.planName ?? 'Community';
return this.settings.license?.planName ?? 'Community';
},
isCommunityPlan(): boolean {
return this.planName.toLowerCase() === 'community';
},
consumerId(): string {
return this.settings.license.consumerId;
return this.settings.license?.consumerId ?? 'unknown';
},
binaryDataMode(): 'default' | 'filesystem' | 's3' {
return this.settings.binaryDataMode;
Expand Down
Loading