fix: Prevent workflow breaking when credential type is unknown (#6923)

This commit is contained in:
Mutasem Aldmour 2023-08-14 14:55:38 +02:00 committed by GitHub
parent 297c3c91f2
commit e83b93f293
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 60 deletions

View file

@ -91,7 +91,7 @@ export default defineComponent({
currentUser(): IUser | null {
return this.usersStore.currentUser;
},
credentialType(): ICredentialType {
credentialType(): ICredentialType | undefined {
return this.credentialsStore.getCredentialTypeByName(this.data.type);
},
credentialPermissions(): IPermissions | null {

View file

@ -304,7 +304,7 @@ export default defineComponent({
// If there is already selected type, use it
if (this.selectedCredential !== '') {
return this.credentialsStore.getCredentialTypeByName(this.selectedCredential);
return this.credentialsStore.getCredentialTypeByName(this.selectedCredential) ?? null;
} else if (this.requiredCredentials) {
// Otherwise, use credential type that corresponds to the first auth option in the node definition
const nodeAuthOptions = getNodeAuthOptions(this.activeNodeType);

View file

@ -109,6 +109,7 @@ export default defineComponent({
const supported = this.getSupportedSets(this.parameter.credentialTypes);
const checkedCredType = this.credentialsStore.getCredentialTypeByName(name);
if (!checkedCredType) return false;
for (const property of supported.has) {
if (checkedCredType[property as keyof ICredentialType] !== undefined) {

View file

@ -291,14 +291,14 @@ export default defineComponent({
});
},
credentialTypesNodeDescription(): INodeCredentialDescription[] {
const node = this.node as INodeUi;
const node = this.node;
const credType = this.credentialsStore.getCredentialTypeByName(this.overrideCredType);
if (credType) return [credType];
const activeNodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
if (activeNodeType && activeNodeType.credentials) {
if (activeNodeType?.credentials) {
return activeNodeType.credentials;
}
@ -308,11 +308,12 @@ export default defineComponent({
const returnData: {
[key: string]: string;
} = {};
let credentialType: ICredentialType | null;
let credentialType: ICredentialType | undefined;
for (const credentialTypeName of this.credentialTypesNode) {
credentialType = this.credentialsStore.getCredentialTypeByName(credentialTypeName);
returnData[credentialTypeName] =
credentialType !== null ? credentialType.displayName : credentialTypeName;
returnData[credentialTypeName] = credentialType
? credentialType.displayName
: credentialTypeName;
}
return returnData;
},
@ -347,7 +348,7 @@ export default defineComponent({
options = options.concat(
this.credentialsStore.allUsableCredentialsByType[type].map((option: any) => ({
...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 selectedCredentialsType = this.showAll ? selectedCredentials.type : credentialType;
const oldCredentials =
this.node.credentials && this.node.credentials[selectedCredentialsType]
? this.node.credentials[selectedCredentialsType]
: {};
const oldCredentials = this.node.credentials?.[selectedCredentialsType]
? this.node.credentials[selectedCredentialsType]
: {};
const selected = { id: selectedCredentials.id, name: selectedCredentials.name };
@ -513,9 +513,9 @@ export default defineComponent({
},
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 [];
}
@ -526,11 +526,7 @@ export default defineComponent({
},
isCredentialExisting(credentialType: string): boolean {
if (
!this.node.credentials ||
!this.node.credentials[credentialType] ||
!this.node.credentials[credentialType].id
) {
if (!this.node.credentials?.[credentialType]?.id) {
return false;
}
const { id } = this.node.credentials[credentialType];

View file

@ -35,10 +35,12 @@ export default defineComponent({
const oauth1Api = this.$locale.baseText('generic.oauth1Api');
const oauth2Api = this.$locale.baseText('generic.oauth2Api');
return this.credentialsStore
.getCredentialTypeByName(this.activeCredentialType)
.displayName.replace(new RegExp(`${oauth1Api}|${oauth2Api}`), '')
.trim();
return (
this.credentialsStore
.getCredentialTypeByName(this.activeCredentialType)
?.displayName.replace(new RegExp(`${oauth1Api}|${oauth2Api}`), '')
.trim() || ''
);
},
},
});

View file

@ -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) {
nodeIssues = {};
}
@ -245,7 +245,7 @@ export const nodeHelpers = defineComponent({
const foundIssues: INodeIssueObjectProperty = {};
let userCredentials: ICredentialsResponse[] | null;
let credentialType: ICredentialType | null;
let credentialType: ICredentialType | undefined;
let credentialDisplayName: string;
let selectedCredentials: INodeCredentialsDetails;
@ -258,7 +258,7 @@ export const nodeHelpers = defineComponent({
selectedCredsAreUnusable(node, genericAuthType)
) {
const credential = this.credentialsStore.getCredentialTypeByName(genericAuthType);
return this.reportUnsetCredential(credential);
return credential ? this.reportUnsetCredential(credential) : null;
}
if (
@ -271,7 +271,7 @@ export const nodeHelpers = defineComponent({
if (selectedCredsDoNotExist(node, nodeCredentialType, stored)) {
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)
) {
const credential = this.credentialsStore.getCredentialTypeByName(nodeCredentialType);
return this.reportUnsetCredential(credential);
return credential ? this.reportUnsetCredential(credential) : null;
}
for (const credentialTypeDescription of nodeType.credentials) {
@ -301,7 +301,7 @@ export const nodeHelpers = defineComponent({
credentialDisplayName = credentialType.displayName;
}
if (!node.credentials || !node.credentials?.[credentialTypeDescription.name]) {
if (!node.credentials?.[credentialTypeDescription.name]) {
// Credentials are not set
if (credentialTypeDescription.required) {
foundIssues[credentialTypeDescription.name] = [
@ -312,9 +312,7 @@ export const nodeHelpers = defineComponent({
}
} else {
// If they are set check if the value is valid
selectedCredentials = node.credentials[
credentialTypeDescription.name
] as INodeCredentialsDetails;
selectedCredentials = node.credentials[credentialTypeDescription.name];
if (typeof selectedCredentials === 'string') {
selectedCredentials = {
id: null,
@ -409,16 +407,14 @@ export const nodeHelpers = defineComponent({
return [];
}
const executionData = this.workflowsStore.getWorkflowExecution.data;
if (!executionData || !executionData.resultData) {
if (!executionData?.resultData) {
// unknown status
return [];
}
const runData = executionData.resultData.runData;
if (
runData === null ||
runData[node.name] === undefined ||
!runData[node.name][runIndex].data ||
!runData?.[node.name]?.[runIndex].data ||
runData[node.name][runIndex].data === undefined
) {
return [];
@ -457,12 +453,7 @@ export const nodeHelpers = defineComponent({
const runData: IRunData | null = workflowRunData;
if (
runData === null ||
!runData[node] ||
!runData[node][runIndex] ||
!runData[node][runIndex].data
) {
if (!runData?.[node]?.[runIndex]?.data) {
return [];
}

View file

@ -1,4 +1,12 @@
import type { INodeUi, IUsedCredential } from '../Interface';
import type {
INodeUi,
IUsedCredential,
ICredentialMap,
ICredentialsDecryptedResponse,
ICredentialsResponse,
ICredentialsState,
ICredentialTypeMap,
} from '../Interface';
import {
createNewCredential,
deleteCredential,
@ -15,19 +23,11 @@ import { setCredentialSharedWith } from '@/api/credentials.ee';
import { makeRestApiRequest } from '@/utils/apiUtils';
import { getAppNameFromCredType } from '@/utils/nodeTypesUtils';
import { EnterpriseEditionFeature, STORES } from '@/constants';
import type {
ICredentialMap,
ICredentialsDecryptedResponse,
ICredentialsResponse,
ICredentialsState,
ICredentialTypeMap,
} from '@/Interface';
import { i18n } from '@/plugins/i18n';
import type {
ICredentialsDecrypted,
ICredentialType,
INodeCredentialTestResult,
INodeProperties,
INodeTypeDescription,
IUser,
} from 'n8n-workflow';
@ -77,7 +77,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
return (node: INodeUi): ICredentialsResponse[] => {
let credentials: ICredentialsResponse[] = [];
const nodeType = useNodeTypesStore().getNodeType(node.type, node.typeVersion);
if (nodeType && nodeType.credentials) {
if (nodeType?.credentials) {
nodeType.credentials.forEach((cred) => {
credentials = credentials.concat(this.allUsableCredentialsByType[cred.name]);
});
@ -106,7 +106,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
);
},
getCredentialTypeByName() {
return (type: string): ICredentialType => this.credentialTypes[type];
return (type: string): ICredentialType | undefined => this.credentialTypes[type];
},
getCredentialById() {
return (id: string): ICredentialsResponse => this.credentials[id];
@ -149,9 +149,10 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
},
getScopesByCredentialType() {
return (credentialTypeName: string) => {
const credentialType = this.getCredentialTypeByName(credentialTypeName) as {
properties: INodeProperties[];
};
const credentialType = this.getCredentialTypeByName(credentialTypeName);
if (!credentialType) {
return [];
}
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
},
async fetchCredentialTypes(forceFetch: boolean): Promise<void> {
if (this.allCredentialTypes.length > 0 && forceFetch !== true) {
if (this.allCredentialTypes.length > 0 && !forceFetch) {
return;
}
const rootStore = useRootStore();
@ -337,8 +338,8 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, {
const { credentialTypeName } = params;
let newName = DEFAULT_CREDENTIAL_NAME;
if (!TYPES_WITH_DEFAULT_NAME.includes(credentialTypeName)) {
const { displayName } = this.getCredentialTypeByName(credentialTypeName);
newName = getAppNameFromCredType(displayName);
const cred = this.getCredentialTypeByName(credentialTypeName);
newName = cred ? getAppNameFromCredType(cred.displayName) : '';
newName =
newName.length > 0
? `${newName} ${DEFAULT_CREDENTIAL_POSTFIX}`

View file

@ -212,7 +212,7 @@ export const getNodeAuthOptions = (
const cred = getNodeCredentialForSelectedAuthType(nodeType, option.value);
if (cred) {
hasOverrides =
useCredentialsStore().getCredentialTypeByName(cred.name).__overwrittenProperties !==
useCredentialsStore().getCredentialTypeByName(cred.name)?.__overwrittenProperties !==
undefined;
}
return {