From 7d2e2ee0f74fbe98c0e69ec1383e13af8b8cc035 Mon Sep 17 00:00:00 2001
From: Alex Grozav <alex@grozav.com>
Date: Mon, 12 Dec 2022 12:59:16 +0200
Subject: [PATCH] fix: Remove foreign credentials when copying nodes or
 duplicating workflow (#4880)

* fix: Remove foreign credentials when copying nodes or duplicating workflow

* chore: fix linting issue
---
 packages/editor-ui/src/Interface.ts           |  2 +-
 .../components/DuplicateWorkflowDialog.vue    |  4 +++-
 .../editor-ui/src/mixins/workflowHelpers.ts   | 19 +++++++++++++++++++
 packages/editor-ui/src/stores/workflows.ts    |  2 ++
 packages/editor-ui/src/views/NodeView.vue     |  3 +++
 5 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts
index f30ec43f21..1e0c2fbf84 100644
--- a/packages/editor-ui/src/Interface.ts
+++ b/packages/editor-ui/src/Interface.ts
@@ -315,7 +315,7 @@ export interface IWorkflowDb {
 	sharedWith?: Array<Partial<IUser>>;
 	ownedBy?: Partial<IUser>;
 	versionId: string;
-	usedCredentials?: Array<Partial<ICredentialsResponse>>;
+	usedCredentials?: IUsedCredential[];
 }
 
 // Identical to cli.Interfaces.ts
diff --git a/packages/editor-ui/src/components/DuplicateWorkflowDialog.vue b/packages/editor-ui/src/components/DuplicateWorkflowDialog.vue
index d81a4e5f55..cd63c8e719 100644
--- a/packages/editor-ui/src/components/DuplicateWorkflowDialog.vue
+++ b/packages/editor-ui/src/components/DuplicateWorkflowDialog.vue
@@ -125,8 +125,10 @@ export default mixins(showMessage, workflowHelpers, restApi).extend({
 			try {
 				let workflowToUpdate: IWorkflowDataUpdate | undefined;
 				if (currentWorkflowId !== PLACEHOLDER_EMPTY_WORKFLOW_ID) {
-					const { createdAt, updatedAt, ...workflow } = await this.restApi().getWorkflow(this.data.id);
+					const { createdAt, updatedAt, usedCredentials, ...workflow } = await this.restApi().getWorkflow(this.data.id);
 					workflowToUpdate = workflow;
+
+					this.removeForeignCredentialsFromWorkflow(workflowToUpdate, this.credentialsStore.allCredentials);
 				}
 
 				const saved = await this.saveAsNewWorkflow({
diff --git a/packages/editor-ui/src/mixins/workflowHelpers.ts b/packages/editor-ui/src/mixins/workflowHelpers.ts
index a28e42eaed..d7f7cc282b 100644
--- a/packages/editor-ui/src/mixins/workflowHelpers.ts
+++ b/packages/editor-ui/src/mixins/workflowHelpers.ts
@@ -67,6 +67,7 @@ import { useTemplatesStore } from '@/stores/templates';
 import { useNodeTypesStore } from '@/stores/nodeTypes';
 import useWorkflowsEEStore from "@/stores/workflows.ee";
 import {useUsersStore} from "@/stores/users";
+import {ICredentialMap, ICredentialsResponse, IUsedCredential} from "@/Interface";
 
 let cachedWorkflowKey: string | null = '';
 let cachedWorkflow: Workflow | null = null;
@@ -928,5 +929,23 @@ export const workflowHelpers = mixins(
 
 				return true;
 			},
+
+			removeForeignCredentialsFromWorkflow(workflow: IWorkflowData | IWorkflowDataUpdate, usableCredentials: ICredentialsResponse[]): void {
+			 	workflow.nodes.forEach((node: INode) => {
+					if (!node.credentials) {
+						return;
+					}
+
+					node.credentials = Object.entries(node.credentials)
+						.reduce<INodeCredentials>((acc, [credentialType, credential]) => {
+							const isUsableCredential = usableCredentials.some((ownCredential) => `${ownCredential.id}` === `${credential.id}`);
+							if (credential.id && isUsableCredential) {
+								acc[credentialType] = node.credentials![credentialType];
+							}
+
+							return acc;
+						}, {});
+				});
+			},
 		},
 	});
diff --git a/packages/editor-ui/src/stores/workflows.ts b/packages/editor-ui/src/stores/workflows.ts
index c410d15b5b..963de8c9e5 100644
--- a/packages/editor-ui/src/stores/workflows.ts
+++ b/packages/editor-ui/src/stores/workflows.ts
@@ -69,6 +69,7 @@ const createEmptyWorkflow = (): IWorkflowDb => ({
 	tags: [],
 	pinData: {},
 	versionId: '',
+	usedCredentials: [],
 });
 
 export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
@@ -269,6 +270,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, {
 		},
 
 		setUsedCredentials(data: IUsedCredential[]) {
+			this.workflow.usedCredentials = data;
 			this.usedCredentials = data.reduce<{ [name: string]: IUsedCredential }>((accu, credential) => {
 				accu[credential.id!] = credential;
 				return accu;
diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue
index caee181a37..d89338183b 100644
--- a/packages/editor-ui/src/views/NodeView.vue
+++ b/packages/editor-ui/src/views/NodeView.vue
@@ -1230,7 +1230,10 @@ export default mixins(
 						...data,
 					};
 
+					this.removeForeignCredentialsFromWorkflow(workflowToCopy, this.credentialsStore.allCredentials);
+
 					const nodeData = JSON.stringify(workflowToCopy, null, 2);
+
 					this.copyToClipboard(nodeData);
 					if (data.nodes.length > 0) {
 						if (!isCut) {