From 3519418b2480abad40322cb303cf0fb89a2630a6 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Fri, 20 Jan 2023 17:01:09 +0200 Subject: [PATCH 1/4] feat: add correct credential owner contact details for readonly credentials --- .../CredentialEdit/CredentialConfig.vue | 2 +- .../CredentialEdit/CredentialSharing.ee.vue | 2 +- .../src/components/NodeDetailsView.vue | 13 ++++++----- .../editor-ui/src/components/NodeSettings.vue | 22 +++++++++++++++---- .../src/plugins/i18n/locales/en.json | 3 ++- packages/editor-ui/src/stores/credentials.ts | 12 +++++++--- 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue index e366d92e39c3d..1e02ccebdeff7 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialConfig.vue @@ -222,7 +222,7 @@ export default mixins(restApi).extend({ return (this.credentialType as ICredentialType).name; }, credentialOwnerName(): string { - return this.credentialsStore.getCredentialOwnerName(`${this.credentialId}`); + return this.credentialsStore.getCredentialOwnerNameById(`${this.credentialId}`); }, documentationUrl(): string { const type = this.credentialType as ICredentialType; diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialSharing.ee.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialSharing.ee.vue index 181ecec202877..fb140ad521ee4 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialSharing.ee.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialSharing.ee.vue @@ -135,7 +135,7 @@ export default mixins(showMessage).extend({ ].concat(this.credentialData.sharedWith || []); }, credentialOwnerName(): string { - return this.credentialsStore.getCredentialOwnerName(`${this.credentialId}`); + return this.credentialsStore.getCredentialOwnerNameById(`${this.credentialId}`); }, }, methods: { diff --git a/packages/editor-ui/src/components/NodeDetailsView.vue b/packages/editor-ui/src/components/NodeDetailsView.vue index fcda16e6568a0..07e27bbfba90f 100644 --- a/packages/editor-ui/src/components/NodeDetailsView.vue +++ b/packages/editor-ui/src/components/NodeDetailsView.vue @@ -93,7 +93,7 @@ :dragging="isDragging" :sessionId="sessionId" :nodeType="activeNodeType" - :hasForeignCredential="hasForeignCredential" + :foreignCredentials="foreignCredentials" :readOnly="readOnly" :blockUI="blockUi && showTriggerPanel" :executable="!readOnly" @@ -375,11 +375,11 @@ export default mixins( blockUi(): boolean { return this.isWorkflowRunning || this.isExecutionWaitingForWebhook; }, - hasForeignCredential(): boolean { + foreignCredentials(): string[] { const credentials = (this.activeNode || {}).credentials; const usedCredentials = this.workflowsStore.usedCredentials; - let hasForeignCredential = false; + const foreignCredentials: string[] = []; if ( credentials && this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing) @@ -390,12 +390,15 @@ export default mixins( usedCredentials[credential.id] && !usedCredentials[credential.id].currentUserHasAccess ) { - hasForeignCredential = true; + foreignCredentials.push(credential.id); } }); } - return hasForeignCredential; + return foreignCredentials; + }, + hasForeignCredential(): boolean { + return this.foreignCredentials.length > 0; }, }, watch: { diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 83c665ea75bb2..c33ec16af647c 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -82,7 +82,7 @@ v-if="hasForeignCredential" :content=" $locale.baseText('nodeSettings.hasForeignCredential', { - interpolate: { owner: workflowOwnerName }, + interpolate: { owner: credentialOwnerName }, }) " /> @@ -191,6 +191,7 @@ import { useNodeTypesStore } from '@/stores/nodeTypes'; import { useHistoryStore } from '@/stores/history'; import { RenameNodeCommand } from '@/models/history'; import useWorkflowsEEStore from '@/stores/workflows.ee'; +import { useCredentialsStore } from '@/stores/credentials'; export default mixins(externalHooks, nodeHelpers).extend({ name: 'NodeSettings', @@ -209,6 +210,7 @@ export default mixins(externalHooks, nodeHelpers).extend({ useNodeTypesStore, useNDVStore, useUIStore, + useCredentialsStore, useWorkflowsStore, useWorkflowsEEStore, ), @@ -286,6 +288,18 @@ export default mixins(externalHooks, nodeHelpers).extend({ workflowOwnerName(): string { return this.workflowsEEStore.getWorkflowOwnerName(`${this.workflowsStore.workflowId}`); }, + hasForeignCredential(): boolean { + return this.foreignCredentials.length > 0; + }, + credentialOwnerName(): string { + const credential = this.node.credentials + ? Object.values(this.node.credentials).find((credential) => { + return credential.id === this.foreignCredentials[0]; + }) + : undefined; + + return this.credentialsStore.getCredentialOwnerName(credential); + }, }, props: { eventBus: {}, @@ -302,9 +316,9 @@ export default mixins(externalHooks, nodeHelpers).extend({ type: Boolean, default: false, }, - hasForeignCredential: { - type: Boolean, - default: false, + foreignCredentials: { + type: Array as PropType, + default: () => [], }, blockUI: { type: Boolean, diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 25ec639cb93fe..c4c34e634b217 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -779,7 +779,8 @@ "nodeSettings.useTheHttpRequestNode": "Use the HTTP Request node to make a custom API call. We'll take care of the {nodeTypeDisplayName} auth for you. Learn more", "nodeSettings.waitBetweenTries.description": "How long to wait between each attempt (in milliseconds)", "nodeSettings.waitBetweenTries.displayName": "Wait Between Tries (ms)", - "nodeSettings.hasForeignCredential": "To edit this node, either:
a) Ask credential owner to share the credential with you, or
b) Duplicate the node and add your own credential", + "nodeSettings.hasForeignCredential": "To edit this node, either:
a) Ask {owner} to share the credential with you, or
b) Duplicate the node and add your own credential", + "nodeSettings.hasForeignCredential.fallback": "the credential owner", "nodeView.addNode": "Add node", "nodeView.addATriggerNodeFirst": "Add a Trigger Node first", "nodeView.addOrEnableTriggerNode": "Add or enable a Trigger node to execute the workflow", diff --git a/packages/editor-ui/src/stores/credentials.ts b/packages/editor-ui/src/stores/credentials.ts index a8b7a64d544cc..5fcafc553b744 100644 --- a/packages/editor-ui/src/stores/credentials.ts +++ b/packages/editor-ui/src/stores/credentials.ts @@ -160,13 +160,19 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, { }; }, getCredentialOwnerName() { - return (credentialId: string): string => { - const credential = this.getCredentialById(credentialId); - return credential && credential.ownedBy && credential.ownedBy.firstName + return (credential: ICredentialsResponse | undefined): string => { + return credential?.ownedBy?.firstName ? `${credential.ownedBy.firstName} ${credential.ownedBy.lastName} (${credential.ownedBy.email})` : i18n.baseText('credentialEdit.credentialSharing.info.sharee.fallback'); }; }, + getCredentialOwnerNameById() { + return (credentialId: string): string => { + const credential = this.getCredentialById(credentialId); + + return this.getCredentialOwnerName(credential); + }; + }, }, actions: { setCredentialTypes(credentialTypes: ICredentialType[]): void { From 1f09881ec2d8f9019f595fba914358acac5f41a6 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Fri, 20 Jan 2023 17:06:41 +0200 Subject: [PATCH 2/4] chore: remove unnecessary translation --- packages/editor-ui/src/plugins/i18n/locales/en.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index c4c34e634b217..9683409a4b770 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -780,7 +780,6 @@ "nodeSettings.waitBetweenTries.description": "How long to wait between each attempt (in milliseconds)", "nodeSettings.waitBetweenTries.displayName": "Wait Between Tries (ms)", "nodeSettings.hasForeignCredential": "To edit this node, either:
a) Ask {owner} to share the credential with you, or
b) Duplicate the node and add your own credential", - "nodeSettings.hasForeignCredential.fallback": "the credential owner", "nodeView.addNode": "Add node", "nodeView.addATriggerNodeFirst": "Add a Trigger Node first", "nodeView.addOrEnableTriggerNode": "Add or enable a Trigger node to execute the workflow", From d3815ea19875e25b3d36364cd685d0eee465b9ca Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Mon, 13 Feb 2023 14:02:34 +0200 Subject: [PATCH 3/4] fix: update credential owner name to be retrieved using usedCredentials --- .../editor-ui/src/components/NodeSettings.vue | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index cd68a6a062f73..658d1076db58b 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -166,7 +166,14 @@ import { NodeParameterValue, deepCopy, } from 'n8n-workflow'; -import { INodeUi, INodeUpdatePropertiesInformation, IUpdateInformation } from '@/Interface'; +import { + ICredentialsResponse, + INodeUi, + INodeUpdatePropertiesInformation, + IUpdateInformation, + IUsedCredential, + IUser, +} from '@/Interface'; import { COMMUNITY_NODES_INSTALLATION_DOCS_URL, @@ -297,9 +304,16 @@ export default mixins(externalHooks, nodeHelpers).extend({ hasForeignCredential(): boolean { return this.foreignCredentials.length > 0; }, + usedCredentials(): IUsedCredential[] { + return Object.values(this.workflowsStore.usedCredentials).filter((credential) => { + return Object.values(this.node?.credentials || []).find((nodeCredential) => { + return nodeCredential.id === credential.id; + }); + }); + }, credentialOwnerName(): string { - const credential = this.node.credentials - ? Object.values(this.node.credentials).find((credential) => { + const credential = this.usedCredentials + ? Object.values(this.usedCredentials).find((credential) => { return credential.id === this.foreignCredentials[0]; }) : undefined; From 33a533791b315228babf88766653f162d5f19ec3 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Mon, 13 Feb 2023 14:08:52 +0200 Subject: [PATCH 4/4] fix: correct credentialownername getter typing --- packages/editor-ui/src/stores/credentials.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/stores/credentials.ts b/packages/editor-ui/src/stores/credentials.ts index 9791219f6cfcd..b3c071e2b882b 100644 --- a/packages/editor-ui/src/stores/credentials.ts +++ b/packages/editor-ui/src/stores/credentials.ts @@ -1,4 +1,4 @@ -import { INodeUi } from './../Interface'; +import { INodeUi, IUsedCredential } from './../Interface'; import { createNewCredential, deleteCredential, @@ -177,7 +177,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, { }; }, getCredentialOwnerName() { - return (credential: ICredentialsResponse | undefined): string => { + return (credential: ICredentialsResponse | IUsedCredential | undefined): string => { return credential?.ownedBy?.firstName ? `${credential.ownedBy.firstName} ${credential.ownedBy.lastName} (${credential.ownedBy.email})` : i18n.baseText('credentialEdit.credentialSharing.info.sharee.fallback');