From cb1bbf5fd395ec4855ac21d851b180c8526b698a Mon Sep 17 00:00:00 2001 From: adrian-martinez-onestic <162105928+adrian-martinez-onestic@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:40:52 +0200 Subject: [PATCH] feat(Google Cloud Firestore Node): Add support for service account and document creation with id (#9713) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ --- .../CloudFirestore/DocumentDescription.ts | 12 +++++++ .../CloudFirestore/GenericFunctions.ts | 20 +++++++---- .../GoogleFirebaseCloudFirestore.node.ts | 33 +++++++++++++++++++ .../nodes/Google/GenericFunctions.ts | 4 +++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/DocumentDescription.ts b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/DocumentDescription.ts index 0214911899..6363bc245c 100644 --- a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/DocumentDescription.ts +++ b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/DocumentDescription.ts @@ -109,6 +109,18 @@ export const documentFields: INodeProperties[] = [ description: 'Collection name', required: true, }, + { + displayName: 'Document ID', + name: 'documentId', + type: 'string', + displayOptions: { + show: { + resource: ['document'], + operation: ['create'], + }, + }, + default: '', + }, { displayName: 'Columns / Attributes', name: 'columns', diff --git a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts index 328fa246fe..5ac452f728 100644 --- a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts @@ -9,12 +9,12 @@ import type { import { NodeApiError } from 'n8n-workflow'; import moment from 'moment-timezone'; +import { getGoogleAccessToken } from '../../GenericFunctions'; export async function googleApiRequest( this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, resource: string, - body: any = {}, qs: IDataObject = {}, uri: string | null = null, @@ -37,12 +37,20 @@ export async function googleApiRequest( delete options.body; } + let credentialType = 'googleFirebaseCloudFirestoreOAuth2Api'; + const authentication = this.getNodeParameter('authentication', 0) as string; + + if (authentication === 'serviceAccount') { + const credentials = await this.getCredentials('googleApi'); + credentialType = 'googleApi'; + + const { access_token } = await getGoogleAccessToken.call(this, credentials, 'firestore'); + + (options.headers as IDataObject).Authorization = `Bearer ${access_token}`; + } + //@ts-ignore - return await this.helpers.requestOAuth2.call( - this, - 'googleFirebaseCloudFirestoreOAuth2Api', - options, - ); + return await this.helpers.requestWithAuthentication.call(this, credentialType, options); } catch (error) { throw new NodeApiError(this.getNode(), error as JsonObject); } diff --git a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GoogleFirebaseCloudFirestore.node.ts b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GoogleFirebaseCloudFirestore.node.ts index 0c20786c51..cb88bd94c5 100644 --- a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GoogleFirebaseCloudFirestore.node.ts +++ b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GoogleFirebaseCloudFirestore.node.ts @@ -40,9 +40,40 @@ export class GoogleFirebaseCloudFirestore implements INodeType { { name: 'googleFirebaseCloudFirestoreOAuth2Api', required: true, + displayOptions: { + show: { + authentication: ['googleFirebaseCloudFirestoreOAuth2Api'], + }, + }, + }, + { + name: 'googleApi', + required: true, + displayOptions: { + show: { + authentication: ['serviceAccount'], + }, + }, }, ], properties: [ + { + displayName: 'Authentication', + name: 'authentication', + type: 'options', + options: [ + { + // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased + name: 'OAuth2 (recommended)', + value: 'googleFirebaseCloudFirestoreOAuth2Api', + }, + { + name: 'Service Account', + value: 'serviceAccount', + }, + ], + default: 'googleFirebaseCloudFirestoreOAuth2Api', + }, { displayName: 'Resource', name: 'resource', @@ -157,6 +188,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType { items.map(async (item: IDataObject, i: number) => { const collection = this.getNodeParameter('collection', i) as string; const columns = this.getNodeParameter('columns', i) as string; + const documentId = this.getNodeParameter('documentId', i) as string; const columnList = columns.split(',').map((column) => column.trim()); const document = { fields: {} }; columnList.map((column) => { @@ -174,6 +206,7 @@ export class GoogleFirebaseCloudFirestore implements INodeType { 'POST', `/${projectId}/databases/${database}/documents/${collection}`, document, + { documentId }, ); responseData.id = (responseData.name as string).split('/').pop(); diff --git a/packages/nodes-base/nodes/Google/GenericFunctions.ts b/packages/nodes-base/nodes/Google/GenericFunctions.ts index 51ab4a0fb9..6cb75a2943 100644 --- a/packages/nodes-base/nodes/Google/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/GenericFunctions.ts @@ -52,6 +52,10 @@ const googleServiceAccountScopes = { 'https://www.googleapis.com/auth/cloud-translation', 'https://www.googleapis.com/auth/cloud-platform', ], + firestore: [ + 'https://www.googleapis.com/auth/datastore', + 'https://www.googleapis.com/auth/firebase', + ], }; type GoogleServiceAccount = keyof typeof googleServiceAccountScopes;