Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throwing error when credential does not exist to simplify node behavior #3112

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 15 additions & 23 deletions packages/core/src/NodeExecuteFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -874,13 +874,7 @@ export async function requestOAuth2(
oAuth2Options?: IOAuth2Options,
isN8nRequest = false,
) {
const credentials = (await this.getCredentials(
credentialsType,
)) as ICredentialDataDecryptedObject;

if (credentials === undefined) {
throw new Error('No credentials were returned!');
}
const credentials = await this.getCredentials(credentialsType);

if (credentials.oauthTokenData === undefined) {
throw new Error('OAuth credentials not connected!');
Expand Down Expand Up @@ -997,9 +991,7 @@ export async function requestOAuth1(
| IHttpRequestOptions,
isN8nRequest = false,
) {
const credentials = (await this.getCredentials(
credentialsType,
)) as ICredentialDataDecryptedObject;
const credentials = await this.getCredentials(credentialsType);

if (credentials === undefined) {
throw new Error('No credentials were returned!');
Expand Down Expand Up @@ -1269,7 +1261,7 @@ export async function getCredentials(
runIndex?: number,
connectionInputData?: INodeExecutionData[],
itemIndex?: number,
): Promise<ICredentialDataDecryptedObject | undefined> {
): Promise<ICredentialDataDecryptedObject> {
// Get the NodeType as it has the information if the credentials are required
const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
if (nodeType === undefined) {
Expand Down Expand Up @@ -1309,8 +1301,8 @@ export async function getCredentials(
node.parameters,
)
) {
// Credentials should not be displayed so return undefined even if they would be defined
return undefined;
// Credentials should not be displayed even if they would be defined
throw new NodeOperationError(node, 'Credentials not found');
}
}

Expand All @@ -1327,15 +1319,15 @@ export async function getCredentials(
throw new NodeOperationError(node, `Node does not have any credentials set for "${type}"!`);
}
} else {
// Credentials are not required so resolve with undefined
return undefined;
// Credentials are not required
throw new NodeOperationError(node, 'Node does not require credentials');
}
}

if (fullAccess && (!node.credentials || !node.credentials[type])) {
// Make sure that fullAccess nodes still behave like before that if they
// request access to credentials that are currently not set it returns undefined
return undefined;
throw new NodeOperationError(node, 'Credentials not found');
}

let expressionResolveValues: ICredentialsExpressionResolveValues | undefined;
Expand Down Expand Up @@ -1605,7 +1597,7 @@ export function getExecutePollFunctions(
__emit: (data: INodeExecutionData[][]): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecutePullFunctions.__emit function!');
},
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return getCredentials(workflow, node, type, additionalData, mode);
},
getMode: (): WorkflowExecuteMode => {
Expand Down Expand Up @@ -1759,7 +1751,7 @@ export function getExecuteTriggerFunctions(
emitError: (error: Error): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!');
},
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return getCredentials(workflow, node, type, additionalData, mode);
},
getNode: () => {
Expand Down Expand Up @@ -1949,7 +1941,7 @@ export function getExecuteFunctions(
async getCredentials(
type: string,
itemIndex?: number,
): Promise<ICredentialDataDecryptedObject | undefined> {
): Promise<ICredentialDataDecryptedObject> {
return getCredentials(
workflow,
node,
Expand Down Expand Up @@ -2193,7 +2185,7 @@ export function getExecuteSingleFunctions(
getContext(type: string): IContextObject {
return NodeHelpers.getContext(runExecutionData, type, node);
},
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return getCredentials(
workflow,
node,
Expand Down Expand Up @@ -2389,7 +2381,7 @@ export function getLoadOptionsFunctions(
): ILoadOptionsFunctions {
return ((workflow: Workflow, node: INode, path: string) => {
const that = {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return getCredentials(workflow, node, type, additionalData, 'internal');
},
getCurrentNodeParameter: (
Expand Down Expand Up @@ -2533,7 +2525,7 @@ export function getExecuteHookFunctions(
): IHookFunctions {
return ((workflow: Workflow, node: INode) => {
const that = {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return getCredentials(workflow, node, type, additionalData, mode);
},
getMode: (): WorkflowExecuteMode => {
Expand Down Expand Up @@ -2692,7 +2684,7 @@ export function getExecuteWebhookFunctions(
}
return additionalData.httpRequest.body;
},
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject> {
return getCredentials(workflow, node, type, additionalData, mode);
},
getHeaderData(): object {
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/ActiveCampaign/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ export interface IProduct {
*/
export async function activeCampaignApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, dataKey?: string): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('activeCampaignApi');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

if (query === undefined) {
query = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ export async function acuitySchedulingApiRequest(this: IHookFunctions | IExecute
try {
if (authenticationMethod === 'apiKey') {
const credentials = await this.getCredentials('acuitySchedulingApi');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

options.auth = {
user: credentials.userId as string,
Expand Down
4 changes: 0 additions & 4 deletions packages/nodes-base/nodes/Affinity/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ export async function affinityApiRequest(this: IExecuteFunctions | IWebhookFunct

const credentials = await this.getCredentials('affinityApi');

if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

const apiKey = `:${credentials.apiKey}`;

const endpoint = 'https://api.affinity.co';
Expand Down
14 changes: 7 additions & 7 deletions packages/nodes-base/nodes/AgileCrm/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
NodeApiError,
} from 'n8n-workflow';

import {
import {
IContactUpdate,
} from './ContactInterface';

Expand All @@ -31,11 +31,11 @@ export async function agileCrmApiRequest(this: IHookFunctions | IExecuteFunction
'Accept': 'application/json',
},
auth: {
username: credentials!.email as string,
password: credentials!.apiKey as string,
username: credentials.email as string,
password: credentials.apiKey as string,
},
qs: query,
uri: uri || `https://${credentials!.subdomain}.agilecrm.com/dev/${endpoint}`,
uri: uri || `https://${credentials.subdomain}.agilecrm.com/dev/${endpoint}`,
json: true,
};

Expand Down Expand Up @@ -83,16 +83,16 @@ export async function agileCrmApiRequestAllItems(this: IHookFunctions | ILoadOpt
export async function agileCrmApiRequestUpdate(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method = 'PUT', endpoint?: string, body: any = {}, query: IDataObject = {}, uri?: string): Promise<any> { // tslint:disable-line:no-any

const credentials = await this.getCredentials('agileCrmApi');
const baseUri = `https://${credentials!.subdomain}.agilecrm.com/dev/`;
const baseUri = `https://${credentials.subdomain}.agilecrm.com/dev/`;
const options: OptionsWithUri = {
method,
headers: {
'Accept': 'application/json',
},
body: { id: body.id },
auth: {
username: credentials!.email as string,
password: credentials!.apiKey as string,
username: credentials.email as string,
password: credentials.apiKey as string,
},
uri: uri || baseUri,
json: true,
Expand Down
4 changes: 0 additions & 4 deletions packages/nodes-base/nodes/Airtable/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ export interface IRecord {
export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IPollFunctions, method: string, endpoint: string, body: object, query?: IDataObject, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('airtableApi');

if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

query = query || {};

// For some reason for some endpoints the bearer auth does not work
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Amqp/Amqp.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ export class Amqp implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
try {
const credentials = await this.getCredentials('amqp');
if (!credentials) {
throw new NodeOperationError(this.getNode(), 'Credentials are mandatory!');
}

const sink = this.getNodeParameter('sink', 0, '') as string;
const applicationProperties = this.getNodeParameter('headerParametersJson', 0, {}) as string | object;
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Amqp/AmqpTrigger.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,6 @@ export class AmqpTrigger implements INodeType {
async trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {

const credentials = await this.getCredentials('amqp');
if (!credentials) {
throw new NodeOperationError(this.getNode(), 'Credentials are mandatory!');
}

const sink = this.getNodeParameter('sink', '') as string;
const clientname = this.getNodeParameter('clientname', '') as string;
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/Comprehend/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ function getEndpointForService(service: string, credentials: ICredentialDataDecr

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

// Concatenate path and instantiate URL object so it parses correctly query strings
const endpoint = new URL(getEndpointForService(service, credentials) + path);
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/DynamoDB/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ function getEndpointForService(service: string, credentials: ICredentialDataDecr

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: object | IRequestBody, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new Error('No credentials got returned!');
}

// Concatenate path and instantiate URL object so it parses correctly query strings
const endpoint = new URL(getEndpointForService(service, credentials) + path);
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ function getEndpointForService(service: string, credentials: ICredentialDataDecr

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

// Concatenate path and instantiate URL object so it parses correctly query strings
const endpoint = new URL(getEndpointForService(service, credentials) + path);
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/Rekognition/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ import {

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string | Buffer | IDataObject, query: IDataObject = {}, headers?: object, option: IDataObject = {}, region?: string): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

const endpoint = new URL(((credentials.rekognitionEndpoint as string || '').replace('{region}', credentials.region as string) || `https://${service}.${credentials.region}.amazonaws.com`) + path);

Expand Down
2 changes: 1 addition & 1 deletion packages/nodes-base/nodes/Aws/S3/AwsS3.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class AwsS3 implements INodeType {
if (additionalFields.grantWriteAcp) {
headers['x-amz-grant-write-acp'] = '';
}
let region = credentials!.region as string;
let region = credentials.region as string;

if (additionalFields.region) {
region = additionalFields.region as string;
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/S3/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ import {

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string | Buffer, query: IDataObject = {}, headers?: object, option: IDataObject = {}, region?: string): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

const endpoint = new URL(((credentials.s3Endpoint as string || '').replace('{region}', credentials.region as string) || `https://${service}.${credentials.region}.amazonaws.com`) + path);

Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/SES/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ import {

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

const endpoint = new URL(((credentials.sesEndpoint as string || '').replace('{region}', credentials.region as string) || `https://${service}.${credentials.region}.amazonaws.com`) + path);

Expand Down
5 changes: 1 addition & 4 deletions packages/nodes-base/nodes/Aws/Textract/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ function getEndpointForService(service: string, credentials: ICredentialDataDecr

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

// Concatenate path and instantiate URL object so it parses correctly query strings
const endpoint = new URL(getEndpointForService(service, credentials) + path);
Expand All @@ -69,7 +66,7 @@ export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | I
const errorMessage = error?.response?.data || error?.response?.body;
if (errorMessage.includes('AccessDeniedException')) {
const user = JSON.parse(errorMessage).Message.split(' ')[1];
throw new NodeApiError(this.getNode(), error, {
throw new NodeApiError(this.getNode(), error, {
message: 'Unauthorized — please check your AWS policy configuration',
description: `Make sure an identity-based policy allows user ${user} to perform textract:AnalyzeExpense` });
}
Expand Down
3 changes: 0 additions & 3 deletions packages/nodes-base/nodes/Aws/Transcribe/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ function getEndpointForService(service: string, credentials: ICredentialDataDecr

export async function awsApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions | IWebhookFunctions, service: string, method: string, path: string, body?: string, headers?: object): Promise<any> { // tslint:disable-line:no-any
const credentials = await this.getCredentials('aws');
if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

// Concatenate path and instantiate URL object so it parses correctly query strings
const endpoint = new URL(getEndpointForService(service, credentials) + path);
Expand Down
4 changes: 0 additions & 4 deletions packages/nodes-base/nodes/BambooHr/v1/transport/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ export async function apiRequest(
) {
const credentials = await this.getCredentials('bambooHrApi');

if (!credentials) {
throw new NodeOperationError(this.getNode(), 'No credentials returned!');
}

//set-up credentials
const apiKey = credentials.apiKey;
const subdomain = credentials.subdomain;
Expand Down
4 changes: 0 additions & 4 deletions packages/nodes-base/nodes/Bannerbear/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ export async function bannerbearApiRequest(this: IExecuteFunctions | IWebhookFun

const credentials = await this.getCredentials('bannerbearApi');

if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

const options: OptionsWithUri = {
headers: {
Accept: 'application/json',
Expand Down
4 changes: 0 additions & 4 deletions packages/nodes-base/nodes/Baserow/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ export async function baserowApiRequest(
) {
const credentials = await this.getCredentials('baserowApi') as BaserowCredentials;

if (credentials === undefined) {
throw new NodeOperationError(this.getNode(), 'No credentials got returned!');
}

const options: OptionsWithUri = {
headers: {
Authorization: `JWT ${jwtToken}`,
Expand Down
Loading