diff --git a/packages/editor-ui/src/components/CredentialCard.test.ts b/packages/editor-ui/src/components/CredentialCard.test.ts
index 9ca589923..7b3abc6ac 100644
--- a/packages/editor-ui/src/components/CredentialCard.test.ts
+++ b/packages/editor-ui/src/components/CredentialCard.test.ts
@@ -85,4 +85,10 @@ describe('CredentialCard', () => {
}
expect(actions).toHaveTextContent('Move');
});
+
+ it('should set readOnly variant based on prop', () => {
+ const { getByRole } = renderComponent({ props: { readOnly: true } });
+ const heading = getByRole('heading');
+ expect(heading).toHaveTextContent('Read only');
+ });
});
diff --git a/packages/editor-ui/src/components/CredentialCard.vue b/packages/editor-ui/src/components/CredentialCard.vue
index 33ffefa37..958f236f1 100644
--- a/packages/editor-ui/src/components/CredentialCard.vue
+++ b/packages/editor-ui/src/components/CredentialCard.vue
@@ -138,16 +138,19 @@ function moveResource() {
{{ data.name }}
+
+ {{ locale.baseText('credentials.item.readonly') }}
+
{{ credentialType.displayName }} |
{{ $locale.baseText('credentials.item.updated') }} |
+ >{{ locale.baseText('credentials.item.updated') }} |
{{ $locale.baseText('credentials.item.created') }} {{ formattedCreatedAtDate }}
+ >{{ locale.baseText('credentials.item.created') }} {{ formattedCreatedAtDate }}
diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue
index 510176277..856f0c931 100644
--- a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue
+++ b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue
@@ -407,7 +407,7 @@ async function beforeClose() {
},
);
keepEditing = confirmAction === MODAL_CONFIRM;
- } else if (isOAuthType.value && !isOAuthConnected.value) {
+ } else if (credentialPermissions.value.update && isOAuthType.value && !isOAuthConnected.value) {
const confirmAction = await message.confirm(
i18n.baseText('credentialEdit.credentialEdit.confirmMessage.beforeClose2.message'),
i18n.baseText('credentialEdit.credentialEdit.confirmMessage.beforeClose2.headline'),
diff --git a/packages/editor-ui/src/components/WorkflowCard.test.ts b/packages/editor-ui/src/components/WorkflowCard.test.ts
index 735b20ada..c97cb8aaa 100644
--- a/packages/editor-ui/src/components/WorkflowCard.test.ts
+++ b/packages/editor-ui/src/components/WorkflowCard.test.ts
@@ -57,7 +57,7 @@ describe('WorkflowCard', () => {
it('should render a card with the workflow name and open workflow clicking on it', async () => {
const data = createWorkflow();
const { getByRole } = renderComponent({ props: { data } });
- const cardTitle = getByRole('heading', { level: 2, name: data.name });
+ const cardTitle = getByRole('heading', { level: 2, name: new RegExp(data.name) });
expect(cardTitle).toBeInTheDocument();
@@ -166,4 +166,12 @@ describe('WorkflowCard', () => {
}
expect(actions).toHaveTextContent('Move');
});
+
+ it('should show Read only mode', async () => {
+ const data = createWorkflow();
+ const { getByRole } = renderComponent({ props: { data } });
+
+ const heading = getByRole('heading');
+ expect(heading).toHaveTextContent('Read only');
+ });
});
diff --git a/packages/editor-ui/src/components/WorkflowCard.vue b/packages/editor-ui/src/components/WorkflowCard.vue
index f929bea62..cc0713e2b 100644
--- a/packages/editor-ui/src/components/WorkflowCard.vue
+++ b/packages/editor-ui/src/components/WorkflowCard.vue
@@ -236,16 +236,19 @@ function moveResource() {
{{ data.name }}
+
+ {{ locale.baseText('workflows.item.readonly') }}
+
{{ $locale.baseText('workflows.item.updated') }}
+ >{{ locale.baseText('workflows.item.updated') }}
|
{{ $locale.baseText('workflows.item.created') }} {{ formattedCreatedAtDate }}
+ >{{ locale.baseText('workflows.item.created') }} {{ formattedCreatedAtDate }}
;
@@ -64,6 +61,19 @@ const executionDataFactory = (): ExecutionSummaryWithScopes => ({
scopes: ['workflow:update'],
});
+const renderComponent = createComponentRenderer(WorkflowExecutionsPreview, {
+ global: {
+ stubs: {
+ // UN STUB router-link
+ 'router-link': RouterLink,
+ },
+ plugins: [router],
+ mocks: {
+ $route,
+ },
+ },
+});
+
describe('WorkflowExecutionsPreview.vue', () => {
let settingsStore: ReturnType;
let workflowsStore: ReturnType;
@@ -93,30 +103,26 @@ describe('WorkflowExecutionsPreview.vue', () => {
vi.spyOn(workflowsStore, 'getWorkflowById').mockReturnValue({ scopes } as IWorkflowDb);
- // Not using createComponentRenderer helper here because this component should not stub `router-link`
- const { getByTestId } = render(WorkflowExecutionsPreview, {
- props: {
- execution: executionData,
- },
- global: {
- plugins: [
- I18nPlugin,
- i18nInstance,
- PiniaVuePlugin,
- FontAwesomePlugin,
- GlobalComponentsPlugin,
- pinia,
- router,
- ],
- mocks: {
- $route,
- },
- },
- });
+ const { getByTestId } = renderComponent({ props: { execution: executionData } });
await userEvent.click(getByTestId('execution-debug-button'));
expect(router.currentRoute.value.path).toBe(path);
},
);
+
+ it('disables the stop execution button when the user cannot update', () => {
+ settingsStore.settings.enterprise = {
+ ...(settingsStore.settings.enterprise ?? {}),
+ };
+ vi.spyOn(workflowsStore, 'getWorkflowById').mockReturnValue({
+ scopes: undefined,
+ } as IWorkflowDb);
+
+ const { getByTestId } = renderComponent({
+ props: { execution: { ...executionData, status: 'running' } },
+ });
+
+ expect(getByTestId('stop-execution')).toBeDisabled();
+ });
});
diff --git a/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsPreview.vue b/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsPreview.vue
index 8fe995853..081c8a0d9 100644
--- a/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsPreview.vue
+++ b/packages/editor-ui/src/components/executions/workflow/WorkflowExecutionsPreview.vue
@@ -120,7 +120,13 @@ function onRetryButtonBlur(event: FocusEvent) {
{{ locale.baseText('executionDetails.runningMessage') }}
-
+
{{ locale.baseText('executionsList.stopExecution') }}
diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json
index d53c370db..2b5ba19c6 100644
--- a/packages/editor-ui/src/plugins/i18n/locales/en.json
+++ b/packages/editor-ui/src/plugins/i18n/locales/en.json
@@ -600,6 +600,7 @@
"credentials.item.updated": "Last updated",
"credentials.item.created": "Created",
"credentials.item.owner": "Owner",
+ "credentials.item.readonly": "Read only",
"credentials.search.placeholder": "Search credentials...",
"credentials.filters.type": "Type",
"credentials.filters.active": "Some credentials may be hidden since filters are applied.",
@@ -2206,6 +2207,7 @@
"workflows.item.move": "Move",
"workflows.item.updated": "Last updated",
"workflows.item.created": "Created",
+ "workflows.item.readonly": "Read only",
"workflows.search.placeholder": "Search workflows...",
"workflows.filters": "Filters",
"workflows.filters.tags": "Tags",
diff --git a/packages/editor-ui/src/views/CredentialsView.test.ts b/packages/editor-ui/src/views/CredentialsView.test.ts
index f2338f9d9..bc2b47a1a 100644
--- a/packages/editor-ui/src/views/CredentialsView.test.ts
+++ b/packages/editor-ui/src/views/CredentialsView.test.ts
@@ -76,5 +76,40 @@ describe('CredentialsView', () => {
null,
);
});
+
+ it('should disable cards based on permissions', () => {
+ vi.spyOn(credentialsStore, 'allCredentials', 'get').mockReturnValue([
+ {
+ id: '1',
+ name: 'test',
+ type: 'test',
+ createdAt: '2021-05-05T00:00:00Z',
+ updatedAt: '2021-05-05T00:00:00Z',
+ scopes: ['credential:update'],
+ },
+ {
+ id: '2',
+ name: 'test2',
+ type: 'test2',
+ createdAt: '2021-05-05T00:00:00Z',
+ updatedAt: '2021-05-05T00:00:00Z',
+ },
+ ]);
+
+ renderComponent();
+ expect(ResourcesListLayout.setup).toHaveBeenCalledWith(
+ expect.objectContaining({
+ resources: [
+ expect.objectContaining({
+ readOnly: false,
+ }),
+ expect.objectContaining({
+ readOnly: true,
+ }),
+ ],
+ }),
+ null,
+ );
+ });
});
});
diff --git a/packages/editor-ui/src/views/CredentialsView.vue b/packages/editor-ui/src/views/CredentialsView.vue
index 28f7e5655..31040e2b3 100644
--- a/packages/editor-ui/src/views/CredentialsView.vue
+++ b/packages/editor-ui/src/views/CredentialsView.vue
@@ -57,6 +57,7 @@ export default defineComponent({
scopes: credential.scopes,
type: credential.type,
sharedWithProjects: credential.sharedWithProjects,
+ readOnly: !getResourcePermissions(credential.scopes).credential.update,
}));
},
allCredentialTypes(): ICredentialType[] {
@@ -179,7 +180,12 @@ export default defineComponent({
-
+