diff --git a/packages/nodes-base/credentials/MongoDb.credentials.ts b/packages/nodes-base/credentials/MongoDb.credentials.ts index b39c7016de..436e9f2e4f 100644 --- a/packages/nodes-base/credentials/MongoDb.credentials.ts +++ b/packages/nodes-base/credentials/MongoDb.credentials.ts @@ -1,8 +1,4 @@ -import { - ICredentialType, - NodePropertyTypes, -} from 'n8n-workflow'; - +import { ICredentialType, NodePropertyTypes } from 'n8n-workflow'; export class MongoDb implements ICredentialType { name = 'mongoDb'; @@ -12,34 +8,57 @@ export class MongoDb implements ICredentialType { displayName: 'Host', name: 'host', type: 'string' as NodePropertyTypes, - default: 'localhost', + default: 'localhost' }, { displayName: 'Database', name: 'database', type: 'string' as NodePropertyTypes, default: '', + description: + 'Note: the database should still be provided even if using an override connection string' }, { displayName: 'User', name: 'user', type: 'string' as NodePropertyTypes, - default: '', + default: '' }, { displayName: 'Password', name: 'password', type: 'string' as NodePropertyTypes, typeOptions: { - password: true, + password: true }, - default: '', + default: '' }, { displayName: 'Port', name: 'port', type: 'number' as NodePropertyTypes, - default: 27017, + default: 27017 }, + { + displayName: 'Override conn string', + name: 'shouldOverrideConnString', + type: 'boolean' as NodePropertyTypes, + default: false, + required: false, + description: + 'Whether to override the generated connection string. Credentials will also be ignored in this case.' + }, + { + displayName: 'Conn string override', + name: 'connStringOverrideVal', + type: 'string' as NodePropertyTypes, + typeOptions: { + rows: 1 + }, + default: '', + placeholder: `mongodb://USERNAMEHERE:PASSWORDHERE@localhost:27017/?authSource=admin&readPreference=primary&appname=n8n&ssl=false`, + required: false, + description: `If provided, the value here will be used as a MongoDB connection string, and the MongoDB credentials will be ignored` + } ]; } diff --git a/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts b/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts index 7dc8daa957..dbd7ab2929 100644 --- a/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts +++ b/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts @@ -7,47 +7,25 @@ import { } from 'n8n-workflow'; import { nodeDescription } from './mongo.node.options'; import { MongoClient } from 'mongodb'; -import { getItemCopy, buildParameterizedConnString } from './mongo.node.utils'; +import { + getItemCopy, + validateAndResolveMongoCredentials +} from './mongo.node.utils'; export class MongoDb implements INodeType { description: INodeTypeDescription = nodeDescription; async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { - const credentials = this.getCredentials('mongoDb'); + const { database, connectionString } = validateAndResolveMongoCredentials( + this.getCredentials('mongoDb') + ); - // user can optionally override connection string - const useOverriddenConnString = this.getNodeParameter( - 'shouldOverrideConnString', - 0 - ) as boolean; - - if (credentials === undefined) { - throw new Error('No credentials got returned!'); - } - - let connectionUri = ''; - if (useOverriddenConnString === true) { - const connStringInput = this.getNodeParameter( - 'connStringOverrideVal', - 0 - ) as string; - if (connStringInput && connStringInput.length > 0) { - connectionUri = connStringInput; - } else { - throw new Error( - 'Cannot override credentials: valid MongoDB connection string not provided ' - ); - } - } else { - connectionUri = buildParameterizedConnString(credentials); - } - - const client: MongoClient = await MongoClient.connect(connectionUri, { + const client: MongoClient = await MongoClient.connect(connectionString, { useNewUrlParser: true, useUnifiedTopology: true }); - const mdb = client.db(credentials.database as string); + const mdb = client.db(database as string); let returnItems = []; diff --git a/packages/nodes-base/nodes/MongoDb/mongo.node.options.ts b/packages/nodes-base/nodes/MongoDb/mongo.node.options.ts index 4a98eeabd5..190ff3de88 100644 --- a/packages/nodes-base/nodes/MongoDb/mongo.node.options.ts +++ b/packages/nodes-base/nodes/MongoDb/mongo.node.options.ts @@ -23,31 +23,6 @@ export const nodeDescription: INodeTypeDescription = { } ], properties: [ - { - displayName: 'Override conn string', - name: 'shouldOverrideConnString', - type: 'boolean', - default: false, - description: - 'Whether to override the generated connection string. Credentials will also be ignored in this case.' - }, - { - displayName: 'Conn string', - name: 'connStringOverrideVal', - type: 'string', - typeOptions: { - rows: 1 - }, - displayOptions: { - show: { - shouldOverrideConnString: [true] - } - }, - default: '', - placeholder: `mongodb://USERNAMEHERE:PASSWORDHERE@localhost:27017/?authSource=admin&readPreference=primary&appname=n8n&ssl=false`, - required: false, - description: `If "Override conn string" is checked, the value here will be used as a MongoDB connection string, and the MongoDB credentials will be ignored` - }, { displayName: 'Operation', name: 'operation', diff --git a/packages/nodes-base/nodes/MongoDb/mongo.node.types.ts b/packages/nodes-base/nodes/MongoDb/mongo.node.types.ts new file mode 100644 index 0000000000..2995fdd2a2 --- /dev/null +++ b/packages/nodes-base/nodes/MongoDb/mongo.node.types.ts @@ -0,0 +1,52 @@ +import { CredentialInformation } from 'n8n-workflow'; + +/** + * Credentials object for Mongo, if using individual parameters + */ +export interface IMongoParametricCredentials { + /** + * Whether to allow overriding the parametric credentials with a connection string + */ + shouldOverrideConnString: false | undefined | null; + host: string; + database: string; + user: string; + password: string; + port?: number; +} + +/** + * Credentials object for Mongo, if using override connection string + */ +export interface IMongoOverrideCredentials { + /** + * Whether to allow overriding the parametric credentials with a connection string + */ + shouldOverrideConnString: true; + /** + * If using an override connection string, this is where it will be. + */ + connStringOverrideVal: string; + database: string; +} + +/** + * Unified credential object type (whether params are overridden with a connection string or not) + */ +export type IMongoCredentialsType = + | IMongoParametricCredentials + | IMongoOverrideCredentials; + +/** + * Resolve the database and connection string from input credentials + */ +export type IMongoCredentials = { + /** + * Database name (used to create the Mongo client) + */ + database: string; + /** + * Generated connection string (after validating and figuring out overrides) + */ + connectionString: string; +}; diff --git a/packages/nodes-base/nodes/MongoDb/mongo.node.utils.ts b/packages/nodes-base/nodes/MongoDb/mongo.node.utils.ts index 54cae7d53c..1d682a450a 100644 --- a/packages/nodes-base/nodes/MongoDb/mongo.node.utils.ts +++ b/packages/nodes-base/nodes/MongoDb/mongo.node.utils.ts @@ -3,14 +3,19 @@ import { INodeExecutionData, ICredentialDataDecryptedObject } from 'n8n-workflow'; +import { + IMongoCredentialsType, + IMongoParametricCredentials, + IMongoCredentials +} from './mongo.node.types'; /** * Standard way of building the MongoDB connection string, unless overridden with a provided string * * @param {ICredentialDataDecryptedObject} credentials MongoDB credentials to use, unless conn string is overridden */ -export function buildParameterizedConnString( - credentials: ICredentialDataDecryptedObject +function buildParameterizedConnString( + credentials: IMongoParametricCredentials ): string { if (credentials.port) { return `mongodb://${credentials.user}:${credentials.password}@${credentials.host}:${credentials.port}`; @@ -19,6 +24,58 @@ export function buildParameterizedConnString( } } +/** + * Build mongoDb connection string and resolve database name. + * If a connection string override value is provided, that will be used in place of individual args + * + * @param {ICredentialDataDecryptedObject} credentials raw/input MongoDB credentials to use + */ +function buildMongoConnectionParams( + credentials: IMongoCredentialsType +): IMongoCredentials { + const sanitizedDbName = + credentials.database && credentials.database.trim().length > 0 + ? credentials.database.trim() + : ''; + if (credentials.shouldOverrideConnString) { + if ( + credentials.connStringOverrideVal && + credentials.connStringOverrideVal.trim().length > 0 + ) { + return { + connectionString: credentials.connStringOverrideVal.trim(), + database: sanitizedDbName + }; + } else { + throw new Error( + 'Cannot override credentials: valid MongoDB connection string not provided ' + ); + } + } else { + return { + connectionString: buildParameterizedConnString(credentials), + database: sanitizedDbName + }; + } +} + +/** + * Verify credentials. If ok, build mongoDb connection string and resolve database name. + * + * @param {ICredentialDataDecryptedObject} credentials raw/input MongoDB credentials to use + */ +export function validateAndResolveMongoCredentials( + credentials?: ICredentialDataDecryptedObject +): IMongoCredentials { + if (credentials == undefined) { + throw new Error('No credentials got returned!'); + } else { + return buildMongoConnectionParams( + (credentials as any) as IMongoCredentialsType + ); + } +} + /** * Returns of copy of the items which only contains the json data and * of that only the define properties