mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 21:07:28 -08:00
fix: Prevent workflow breaking when credential type is unknown (#6923)
This commit is contained in:
parent
297c3c91f2
commit
e83b93f293
|
@ -91,7 +91,7 @@ export default defineComponent({
|
||||||
currentUser(): IUser | null {
|
currentUser(): IUser | null {
|
||||||
return this.usersStore.currentUser;
|
return this.usersStore.currentUser;
|
||||||
},
|
},
|
||||||
credentialType(): ICredentialType {
|
credentialType(): ICredentialType | undefined {
|
||||||
return this.credentialsStore.getCredentialTypeByName(this.data.type);
|
return this.credentialsStore.getCredentialTypeByName(this.data.type);
|
||||||
},
|
},
|
||||||
credentialPermissions(): IPermissions | null {
|
credentialPermissions(): IPermissions | null {
|
||||||
|
|
|
@ -304,7 +304,7 @@ export default defineComponent({
|
||||||
|
|
||||||
// If there is already selected type, use it
|
// If there is already selected type, use it
|
||||||
if (this.selectedCredential !== '') {
|
if (this.selectedCredential !== '') {
|
||||||
return this.credentialsStore.getCredentialTypeByName(this.selectedCredential);
|
return this.credentialsStore.getCredentialTypeByName(this.selectedCredential) ?? null;
|
||||||
} else if (this.requiredCredentials) {
|
} else if (this.requiredCredentials) {
|
||||||
// Otherwise, use credential type that corresponds to the first auth option in the node definition
|
// Otherwise, use credential type that corresponds to the first auth option in the node definition
|
||||||
const nodeAuthOptions = getNodeAuthOptions(this.activeNodeType);
|
const nodeAuthOptions = getNodeAuthOptions(this.activeNodeType);
|
||||||
|
|
|
@ -109,6 +109,7 @@ export default defineComponent({
|
||||||
const supported = this.getSupportedSets(this.parameter.credentialTypes);
|
const supported = this.getSupportedSets(this.parameter.credentialTypes);
|
||||||
|
|
||||||
const checkedCredType = this.credentialsStore.getCredentialTypeByName(name);
|
const checkedCredType = this.credentialsStore.getCredentialTypeByName(name);
|
||||||
|
if (!checkedCredType) return false;
|
||||||
|
|
||||||
for (const property of supported.has) {
|
for (const property of supported.has) {
|
||||||
if (checkedCredType[property as keyof ICredentialType] !== undefined) {
|
if (checkedCredType[property as keyof ICredentialType] !== undefined) {
|
||||||
|
|
|
@ -291,14 +291,14 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
credentialTypesNodeDescription(): INodeCredentialDescription[] {
|
credentialTypesNodeDescription(): INodeCredentialDescription[] {
|
||||||
const node = this.node as INodeUi;
|
const node = this.node;
|
||||||
|
|
||||||
const credType = this.credentialsStore.getCredentialTypeByName(this.overrideCredType);
|
const credType = this.credentialsStore.getCredentialTypeByName(this.overrideCredType);
|
||||||
|
|
||||||
if (credType) return [credType];
|
if (credType) return [credType];
|
||||||
|
|
||||||
const activeNodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
const activeNodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
if (activeNodeType && activeNodeType.credentials) {
|
if (activeNodeType?.credentials) {
|
||||||
return activeNodeType.credentials;
|
return activeNodeType.credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,11 +308,12 @@ export default defineComponent({
|
||||||
const returnData: {
|
const returnData: {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
} = {};
|
} = {};
|
||||||
let credentialType: ICredentialType | null;
|
let credentialType: ICredentialType | undefined;
|
||||||
for (const credentialTypeName of this.credentialTypesNode) {
|
for (const credentialTypeName of this.credentialTypesNode) {
|
||||||
credentialType = this.credentialsStore.getCredentialTypeByName(credentialTypeName);
|
credentialType = this.credentialsStore.getCredentialTypeByName(credentialTypeName);
|
||||||
returnData[credentialTypeName] =
|
returnData[credentialTypeName] = credentialType
|
||||||
credentialType !== null ? credentialType.displayName : credentialTypeName;
|
? credentialType.displayName
|
||||||
|
: credentialTypeName;
|
||||||
}
|
}
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
|
@ -347,7 +348,7 @@ export default defineComponent({
|
||||||
options = options.concat(
|
options = options.concat(
|
||||||
this.credentialsStore.allUsableCredentialsByType[type].map((option: any) => ({
|
this.credentialsStore.allUsableCredentialsByType[type].map((option: any) => ({
|
||||||
...option,
|
...option,
|
||||||
typeDisplayName: this.credentialsStore.getCredentialTypeByName(type).displayName,
|
typeDisplayName: this.credentialsStore.getCredentialTypeByName(type)?.displayName,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -436,10 +437,9 @@ export default defineComponent({
|
||||||
|
|
||||||
const selectedCredentials = this.credentialsStore.getCredentialById(credentialId);
|
const selectedCredentials = this.credentialsStore.getCredentialById(credentialId);
|
||||||
const selectedCredentialsType = this.showAll ? selectedCredentials.type : credentialType;
|
const selectedCredentialsType = this.showAll ? selectedCredentials.type : credentialType;
|
||||||
const oldCredentials =
|
const oldCredentials = this.node.credentials?.[selectedCredentialsType]
|
||||||
this.node.credentials && this.node.credentials[selectedCredentialsType]
|
? this.node.credentials[selectedCredentialsType]
|
||||||
? this.node.credentials[selectedCredentialsType]
|
: {};
|
||||||
: {};
|
|
||||||
|
|
||||||
const selected = { id: selectedCredentials.id, name: selectedCredentials.name };
|
const selected = { id: selectedCredentials.id, name: selectedCredentials.name };
|
||||||
|
|
||||||
|
@ -513,9 +513,9 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
getIssues(credentialTypeName: string): string[] {
|
getIssues(credentialTypeName: string): string[] {
|
||||||
const node = this.node as INodeUi;
|
const node = this.node;
|
||||||
|
|
||||||
if (node.issues === undefined || node.issues.credentials === undefined) {
|
if (node.issues?.credentials === undefined) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,11 +526,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
isCredentialExisting(credentialType: string): boolean {
|
isCredentialExisting(credentialType: string): boolean {
|
||||||
if (
|
if (!this.node.credentials?.[credentialType]?.id) {
|
||||||
!this.node.credentials ||
|
|
||||||
!this.node.credentials[credentialType] ||
|
|
||||||
!this.node.credentials[credentialType].id
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const { id } = this.node.credentials[credentialType];
|
const { id } = this.node.credentials[credentialType];
|
||||||
|
|
|
@ -35,10 +35,12 @@ export default defineComponent({
|
||||||
const oauth1Api = this.$locale.baseText('generic.oauth1Api');
|
const oauth1Api = this.$locale.baseText('generic.oauth1Api');
|
||||||
const oauth2Api = this.$locale.baseText('generic.oauth2Api');
|
const oauth2Api = this.$locale.baseText('generic.oauth2Api');
|
||||||
|
|
||||||
return this.credentialsStore
|
return (
|
||||||
.getCredentialTypeByName(this.activeCredentialType)
|
this.credentialsStore
|
||||||
.displayName.replace(new RegExp(`${oauth1Api}|${oauth2Api}`), '')
|
.getCredentialTypeByName(this.activeCredentialType)
|
||||||
.trim();
|
?.displayName.replace(new RegExp(`${oauth1Api}|${oauth2Api}`), '')
|
||||||
|
.trim() || ''
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -126,7 +126,7 @@ export const nodeHelpers = defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hasNodeExecutionIssues(node) === true && !ignoreIssues.includes('execution')) {
|
if (this.hasNodeExecutionIssues(node) && !ignoreIssues.includes('execution')) {
|
||||||
if (nodeIssues === null) {
|
if (nodeIssues === null) {
|
||||||
nodeIssues = {};
|
nodeIssues = {};
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ export const nodeHelpers = defineComponent({
|
||||||
const foundIssues: INodeIssueObjectProperty = {};
|
const foundIssues: INodeIssueObjectProperty = {};
|
||||||
|
|
||||||
let userCredentials: ICredentialsResponse[] | null;
|
let userCredentials: ICredentialsResponse[] | null;
|
||||||
let credentialType: ICredentialType | null;
|
let credentialType: ICredentialType | undefined;
|
||||||
let credentialDisplayName: string;
|
let credentialDisplayName: string;
|
||||||
let selectedCredentials: INodeCredentialsDetails;
|
let selectedCredentials: INodeCredentialsDetails;
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ export const nodeHelpers = defineComponent({
|
||||||
selectedCredsAreUnusable(node, genericAuthType)
|
selectedCredsAreUnusable(node, genericAuthType)
|
||||||
) {
|
) {
|
||||||
const credential = this.credentialsStore.getCredentialTypeByName(genericAuthType);
|
const credential = this.credentialsStore.getCredentialTypeByName(genericAuthType);
|
||||||
return this.reportUnsetCredential(credential);
|
return credential ? this.reportUnsetCredential(credential) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -271,7 +271,7 @@ export const nodeHelpers = defineComponent({
|
||||||
|
|
||||||
if (selectedCredsDoNotExist(node, nodeCredentialType, stored)) {
|
if (selectedCredsDoNotExist(node, nodeCredentialType, stored)) {
|
||||||
const credential = this.credentialsStore.getCredentialTypeByName(nodeCredentialType);
|
const credential = this.credentialsStore.getCredentialTypeByName(nodeCredentialType);
|
||||||
return this.reportUnsetCredential(credential);
|
return credential ? this.reportUnsetCredential(credential) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ export const nodeHelpers = defineComponent({
|
||||||
selectedCredsAreUnusable(node, nodeCredentialType)
|
selectedCredsAreUnusable(node, nodeCredentialType)
|
||||||
) {
|
) {
|
||||||
const credential = this.credentialsStore.getCredentialTypeByName(nodeCredentialType);
|
const credential = this.credentialsStore.getCredentialTypeByName(nodeCredentialType);
|
||||||
return this.reportUnsetCredential(credential);
|
return credential ? this.reportUnsetCredential(credential) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const credentialTypeDescription of nodeType.credentials) {
|
for (const credentialTypeDescription of nodeType.credentials) {
|
||||||
|
@ -301,7 +301,7 @@ export const nodeHelpers = defineComponent({
|
||||||
credentialDisplayName = credentialType.displayName;
|
credentialDisplayName = credentialType.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.credentials || !node.credentials?.[credentialTypeDescription.name]) {
|
if (!node.credentials?.[credentialTypeDescription.name]) {
|
||||||
// Credentials are not set
|
// Credentials are not set
|
||||||
if (credentialTypeDescription.required) {
|
if (credentialTypeDescription.required) {
|
||||||
foundIssues[credentialTypeDescription.name] = [
|
foundIssues[credentialTypeDescription.name] = [
|
||||||
|
@ -312,9 +312,7 @@ export const nodeHelpers = defineComponent({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If they are set check if the value is valid
|
// If they are set check if the value is valid
|
||||||
selectedCredentials = node.credentials[
|
selectedCredentials = node.credentials[credentialTypeDescription.name];
|
||||||
credentialTypeDescription.name
|
|
||||||
] as INodeCredentialsDetails;
|
|
||||||
if (typeof selectedCredentials === 'string') {
|
if (typeof selectedCredentials === 'string') {
|
||||||
selectedCredentials = {
|
selectedCredentials = {
|
||||||
id: null,
|
id: null,
|
||||||
|
@ -409,16 +407,14 @@ export const nodeHelpers = defineComponent({
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const executionData = this.workflowsStore.getWorkflowExecution.data;
|
const executionData = this.workflowsStore.getWorkflowExecution.data;
|
||||||
if (!executionData || !executionData.resultData) {
|
if (!executionData?.resultData) {
|
||||||
// unknown status
|
// unknown status
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const runData = executionData.resultData.runData;
|
const runData = executionData.resultData.runData;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
runData === null ||
|
!runData?.[node.name]?.[runIndex].data ||
|
||||||
runData[node.name] === undefined ||
|
|
||||||
!runData[node.name][runIndex].data ||
|
|
||||||
runData[node.name][runIndex].data === undefined
|
runData[node.name][runIndex].data === undefined
|
||||||
) {
|
) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -457,12 +453,7 @@ export const nodeHelpers = defineComponent({
|
||||||
|
|
||||||
const runData: IRunData | null = workflowRunData;
|
const runData: IRunData | null = workflowRunData;
|
||||||
|
|
||||||
if (
|
if (!runData?.[node]?.[runIndex]?.data) {
|
||||||
runData === null ||
|
|
||||||
!runData[node] ||
|
|
||||||
!runData[node][runIndex] ||
|
|
||||||
!runData[node][runIndex].data
|
|
||||||
) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
import type { INodeUi, IUsedCredential } from '../Interface';
|
import type {
|
||||||
|
INodeUi,
|
||||||
|
IUsedCredential,
|
||||||
|
ICredentialMap,
|
||||||
|
ICredentialsDecryptedResponse,
|
||||||
|
ICredentialsResponse,
|
||||||
|
ICredentialsState,
|
||||||
|
ICredentialTypeMap,
|
||||||
|
} from '../Interface';
|
||||||
import {
|
import {
|
||||||
createNewCredential,
|
createNewCredential,
|
||||||
deleteCredential,
|
deleteCredential,
|
||||||
|
@ -15,19 +23,11 @@ import { setCredentialSharedWith } from '@/api/credentials.ee';
|
||||||
import { makeRestApiRequest } from '@/utils/apiUtils';
|
import { makeRestApiRequest } from '@/utils/apiUtils';
|
||||||
import { getAppNameFromCredType } from '@/utils/nodeTypesUtils';
|
import { getAppNameFromCredType } from '@/utils/nodeTypesUtils';
|
||||||
import { EnterpriseEditionFeature, STORES } from '@/constants';
|
import { EnterpriseEditionFeature, STORES } from '@/constants';
|
||||||
import type {
|
|
||||||
ICredentialMap,
|
|
||||||
ICredentialsDecryptedResponse,
|
|
||||||
ICredentialsResponse,
|
|
||||||
ICredentialsState,
|
|
||||||
ICredentialTypeMap,
|
|
||||||
} from '@/Interface';
|
|
||||||
import { i18n } from '@/plugins/i18n';
|
import { i18n } from '@/plugins/i18n';
|
||||||
import type {
|
import type {
|
||||||
ICredentialsDecrypted,
|
ICredentialsDecrypted,
|
||||||
ICredentialType,
|
ICredentialType,
|
||||||
INodeCredentialTestResult,
|
INodeCredentialTestResult,
|
||||||
INodeProperties,
|
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
IUser,
|
IUser,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
@ -77,7 +77,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
|
||||||
return (node: INodeUi): ICredentialsResponse[] => {
|
return (node: INodeUi): ICredentialsResponse[] => {
|
||||||
let credentials: ICredentialsResponse[] = [];
|
let credentials: ICredentialsResponse[] = [];
|
||||||
const nodeType = useNodeTypesStore().getNodeType(node.type, node.typeVersion);
|
const nodeType = useNodeTypesStore().getNodeType(node.type, node.typeVersion);
|
||||||
if (nodeType && nodeType.credentials) {
|
if (nodeType?.credentials) {
|
||||||
nodeType.credentials.forEach((cred) => {
|
nodeType.credentials.forEach((cred) => {
|
||||||
credentials = credentials.concat(this.allUsableCredentialsByType[cred.name]);
|
credentials = credentials.concat(this.allUsableCredentialsByType[cred.name]);
|
||||||
});
|
});
|
||||||
|
@ -106,7 +106,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getCredentialTypeByName() {
|
getCredentialTypeByName() {
|
||||||
return (type: string): ICredentialType => this.credentialTypes[type];
|
return (type: string): ICredentialType | undefined => this.credentialTypes[type];
|
||||||
},
|
},
|
||||||
getCredentialById() {
|
getCredentialById() {
|
||||||
return (id: string): ICredentialsResponse => this.credentials[id];
|
return (id: string): ICredentialsResponse => this.credentials[id];
|
||||||
|
@ -149,9 +149,10 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
|
||||||
},
|
},
|
||||||
getScopesByCredentialType() {
|
getScopesByCredentialType() {
|
||||||
return (credentialTypeName: string) => {
|
return (credentialTypeName: string) => {
|
||||||
const credentialType = this.getCredentialTypeByName(credentialTypeName) as {
|
const credentialType = this.getCredentialTypeByName(credentialTypeName);
|
||||||
properties: INodeProperties[];
|
if (!credentialType) {
|
||||||
};
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const scopeProperty = credentialType.properties.find((p) => p.name === 'scope');
|
const scopeProperty = credentialType.properties.find((p) => p.name === 'scope');
|
||||||
|
|
||||||
|
@ -232,7 +233,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
|
||||||
// enable oauth event to track change between modals
|
// enable oauth event to track change between modals
|
||||||
},
|
},
|
||||||
async fetchCredentialTypes(forceFetch: boolean): Promise<void> {
|
async fetchCredentialTypes(forceFetch: boolean): Promise<void> {
|
||||||
if (this.allCredentialTypes.length > 0 && forceFetch !== true) {
|
if (this.allCredentialTypes.length > 0 && !forceFetch) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rootStore = useRootStore();
|
const rootStore = useRootStore();
|
||||||
|
@ -337,8 +338,8 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
|
||||||
const { credentialTypeName } = params;
|
const { credentialTypeName } = params;
|
||||||
let newName = DEFAULT_CREDENTIAL_NAME;
|
let newName = DEFAULT_CREDENTIAL_NAME;
|
||||||
if (!TYPES_WITH_DEFAULT_NAME.includes(credentialTypeName)) {
|
if (!TYPES_WITH_DEFAULT_NAME.includes(credentialTypeName)) {
|
||||||
const { displayName } = this.getCredentialTypeByName(credentialTypeName);
|
const cred = this.getCredentialTypeByName(credentialTypeName);
|
||||||
newName = getAppNameFromCredType(displayName);
|
newName = cred ? getAppNameFromCredType(cred.displayName) : '';
|
||||||
newName =
|
newName =
|
||||||
newName.length > 0
|
newName.length > 0
|
||||||
? `${newName} ${DEFAULT_CREDENTIAL_POSTFIX}`
|
? `${newName} ${DEFAULT_CREDENTIAL_POSTFIX}`
|
||||||
|
|
|
@ -212,7 +212,7 @@ export const getNodeAuthOptions = (
|
||||||
const cred = getNodeCredentialForSelectedAuthType(nodeType, option.value);
|
const cred = getNodeCredentialForSelectedAuthType(nodeType, option.value);
|
||||||
if (cred) {
|
if (cred) {
|
||||||
hasOverrides =
|
hasOverrides =
|
||||||
useCredentialsStore().getCredentialTypeByName(cred.name).__overwrittenProperties !==
|
useCredentialsStore().getCredentialTypeByName(cred.name)?.__overwrittenProperties !==
|
||||||
undefined;
|
undefined;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue