feat(editor): Add correct credential owner contact details for readonly credentials (#5208)

* feat: add correct credential owner contact details for readonly credentials

* chore: remove unnecessary translation

* fix: update credential owner name to be retrieved using usedCredentials

* fix: correct credentialownername getter typing
This commit is contained in:
Alex Grozav
2023-02-14 16:13:22 +02:00
committed by GitHub
parent 246189f6da
commit 36108f82a1
6 changed files with 54 additions and 17 deletions

View File

@@ -266,7 +266,7 @@ export default mixins(restApi).extend({
return (this.credentialType as ICredentialType).name; return (this.credentialType as ICredentialType).name;
}, },
credentialOwnerName(): string { credentialOwnerName(): string {
return this.credentialsStore.getCredentialOwnerName(`${this.credentialId}`); return this.credentialsStore.getCredentialOwnerNameById(`${this.credentialId}`);
}, },
documentationUrl(): string { documentationUrl(): string {
const type = this.credentialType as ICredentialType; const type = this.credentialType as ICredentialType;

View File

@@ -137,7 +137,7 @@ export default mixins(showMessage).extend({
].concat(this.credentialData.sharedWith || []); ].concat(this.credentialData.sharedWith || []);
}, },
credentialOwnerName(): string { credentialOwnerName(): string {
return this.credentialsStore.getCredentialOwnerName(`${this.credentialId}`); return this.credentialsStore.getCredentialOwnerNameById(`${this.credentialId}`);
}, },
}, },
methods: { methods: {

View File

@@ -93,7 +93,7 @@
:dragging="isDragging" :dragging="isDragging"
:sessionId="sessionId" :sessionId="sessionId"
:nodeType="activeNodeType" :nodeType="activeNodeType"
:hasForeignCredential="hasForeignCredential" :foreignCredentials="foreignCredentials"
:readOnly="readOnly" :readOnly="readOnly"
:blockUI="blockUi && showTriggerPanel" :blockUI="blockUi && showTriggerPanel"
:executable="!readOnly" :executable="!readOnly"
@@ -375,11 +375,11 @@ export default mixins(
blockUi(): boolean { blockUi(): boolean {
return this.isWorkflowRunning || this.isExecutionWaitingForWebhook; return this.isWorkflowRunning || this.isExecutionWaitingForWebhook;
}, },
hasForeignCredential(): boolean { foreignCredentials(): string[] {
const credentials = (this.activeNode || {}).credentials; const credentials = (this.activeNode || {}).credentials;
const usedCredentials = this.workflowsStore.usedCredentials; const usedCredentials = this.workflowsStore.usedCredentials;
let hasForeignCredential = false; const foreignCredentials: string[] = [];
if ( if (
credentials && credentials &&
this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing) this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)
@@ -390,12 +390,15 @@ export default mixins(
usedCredentials[credential.id] && usedCredentials[credential.id] &&
!usedCredentials[credential.id].currentUserHasAccess !usedCredentials[credential.id].currentUserHasAccess
) { ) {
hasForeignCredential = true; foreignCredentials.push(credential.id);
} }
}); });
} }
return hasForeignCredential; return foreignCredentials;
},
hasForeignCredential(): boolean {
return this.foreignCredentials.length > 0;
}, },
}, },
watch: { watch: {

View File

@@ -82,7 +82,7 @@
v-if="hasForeignCredential" v-if="hasForeignCredential"
:content=" :content="
$locale.baseText('nodeSettings.hasForeignCredential', { $locale.baseText('nodeSettings.hasForeignCredential', {
interpolate: { owner: workflowOwnerName }, interpolate: { owner: credentialOwnerName },
}) })
" "
/> />
@@ -166,7 +166,14 @@ import {
NodeParameterValue, NodeParameterValue,
deepCopy, deepCopy,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { INodeUi, INodeUpdatePropertiesInformation, IUpdateInformation } from '@/Interface'; import {
ICredentialsResponse,
INodeUi,
INodeUpdatePropertiesInformation,
IUpdateInformation,
IUsedCredential,
IUser,
} from '@/Interface';
import { import {
COMMUNITY_NODES_INSTALLATION_DOCS_URL, COMMUNITY_NODES_INSTALLATION_DOCS_URL,
@@ -197,6 +204,7 @@ import { useNodeTypesStore } from '@/stores/nodeTypes';
import { useHistoryStore } from '@/stores/history'; import { useHistoryStore } from '@/stores/history';
import { RenameNodeCommand } from '@/models/history'; import { RenameNodeCommand } from '@/models/history';
import useWorkflowsEEStore from '@/stores/workflows.ee'; import useWorkflowsEEStore from '@/stores/workflows.ee';
import { useCredentialsStore } from '@/stores/credentials';
export default mixins(externalHooks, nodeHelpers).extend({ export default mixins(externalHooks, nodeHelpers).extend({
name: 'NodeSettings', name: 'NodeSettings',
@@ -215,6 +223,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
useNodeTypesStore, useNodeTypesStore,
useNDVStore, useNDVStore,
useUIStore, useUIStore,
useCredentialsStore,
useWorkflowsStore, useWorkflowsStore,
useWorkflowsEEStore, useWorkflowsEEStore,
), ),
@@ -292,6 +301,25 @@ export default mixins(externalHooks, nodeHelpers).extend({
workflowOwnerName(): string { workflowOwnerName(): string {
return this.workflowsEEStore.getWorkflowOwnerName(`${this.workflowsStore.workflowId}`); return this.workflowsEEStore.getWorkflowOwnerName(`${this.workflowsStore.workflowId}`);
}, },
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.usedCredentials
? Object.values(this.usedCredentials).find((credential) => {
return credential.id === this.foreignCredentials[0];
})
: undefined;
return this.credentialsStore.getCredentialOwnerName(credential);
},
}, },
props: { props: {
eventBus: {}, eventBus: {},
@@ -308,9 +336,9 @@ export default mixins(externalHooks, nodeHelpers).extend({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
hasForeignCredential: { foreignCredentials: {
type: Boolean, type: Array as PropType<string[]>,
default: false, default: () => [],
}, },
blockUI: { blockUI: {
type: Boolean, type: Boolean,

View File

@@ -785,7 +785,7 @@
"nodeSettings.useTheHttpRequestNode": "Use the <b>HTTP Request</b> node to make a custom API call. We'll take care of the {nodeTypeDisplayName} auth for you. <a target=\"_blank\" href=\"https://docs.n8n.io/integrations/custom-operations/\">Learn more</a>", "nodeSettings.useTheHttpRequestNode": "Use the <b>HTTP Request</b> node to make a custom API call. We'll take care of the {nodeTypeDisplayName} auth for you. <a target=\"_blank\" href=\"https://docs.n8n.io/integrations/custom-operations/\">Learn more</a>",
"nodeSettings.waitBetweenTries.description": "How long to wait between each attempt (in milliseconds)", "nodeSettings.waitBetweenTries.description": "How long to wait between each attempt (in milliseconds)",
"nodeSettings.waitBetweenTries.displayName": "Wait Between Tries (ms)", "nodeSettings.waitBetweenTries.displayName": "Wait Between Tries (ms)",
"nodeSettings.hasForeignCredential": "To edit this node, either:<br/>a) Ask credential owner to share the credential with you, or<br/>b) Duplicate the node and add your own credential", "nodeSettings.hasForeignCredential": "To edit this node, either:<br/>a) Ask {owner} to share the credential with you, or<br/>b) Duplicate the node and add your own credential",
"nodeView.addNode": "Add node", "nodeView.addNode": "Add node",
"nodeView.addATriggerNodeFirst": "Add a <a data-action='showNodeCreator'>Trigger Node</a> first", "nodeView.addATriggerNodeFirst": "Add a <a data-action='showNodeCreator'>Trigger Node</a> first",
"nodeView.addOrEnableTriggerNode": "<a data-action='showNodeCreator'>Add</a> or enable a Trigger node to execute the workflow", "nodeView.addOrEnableTriggerNode": "<a data-action='showNodeCreator'>Add</a> or enable a Trigger node to execute the workflow",

View File

@@ -1,4 +1,4 @@
import { INodeUi } from './../Interface'; import { INodeUi, IUsedCredential } from './../Interface';
import { import {
createNewCredential, createNewCredential,
deleteCredential, deleteCredential,
@@ -177,13 +177,19 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
}; };
}, },
getCredentialOwnerName() { getCredentialOwnerName() {
return (credentialId: string): string => { return (credential: ICredentialsResponse | IUsedCredential | undefined): string => {
const credential = this.getCredentialById(credentialId); return credential?.ownedBy?.firstName
return credential && credential.ownedBy && credential.ownedBy.firstName
? `${credential.ownedBy.firstName} ${credential.ownedBy.lastName} (${credential.ownedBy.email})` ? `${credential.ownedBy.firstName} ${credential.ownedBy.lastName} (${credential.ownedBy.email})`
: i18n.baseText('credentialEdit.credentialSharing.info.sharee.fallback'); : i18n.baseText('credentialEdit.credentialSharing.info.sharee.fallback');
}; };
}, },
getCredentialOwnerNameById() {
return (credentialId: string): string => {
const credential = this.getCredentialById(credentialId);
return this.getCredentialOwnerName(credential);
};
},
}, },
actions: { actions: {
setCredentialTypes(credentialTypes: ICredentialType[]): void { setCredentialTypes(credentialTypes: ICredentialType[]): void {