Files
n8n/packages/nodes-base/nodes/Google/GenericFunctions.ts
T
n8n-assistant[bot] 46c1a0e8f3 chore: Bundle/2.x (#33793)
Co-authored-by: Matsu <matias.huhta@n8n.io>
Co-authored-by: Stephen Wright <sjw948@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Bernhard Wittmann <bernhard.wittmann@n8n.io>
Co-authored-by: Nikhil Kuriakose <nikhil.kuriakose@n8n.io>
Co-authored-by: Albert Alises <albert.alises@gmail.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
Co-authored-by: Andreas Fitzek <andreas.fitzek@n8n.io>
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
Co-authored-by: Mike Repeć <mike.repec@n8n.io>
Co-authored-by: Elias Meire <elias@meire.dev>
Co-authored-by: bjorger <50590409+bjorger@users.noreply.github.com>
2026-07-08 08:48:55 +03:00

145 lines
4.0 KiB
TypeScript

import { formatPemBlock } from '@n8n/utils/format-pem-block';
import * as jwt from 'jsonwebtoken';
import { DateTime } from 'luxon';
import moment from 'moment-timezone';
import {
type IExecuteFunctions,
type IExecuteSingleFunctions,
type ILoadOptionsFunctions,
type ICredentialTestFunctions,
type IDataObject,
type IPollFunctions,
type IRequestOptions,
NodeOperationError,
} from 'n8n-workflow';
export const googleServiceAccountScopes = {
bigquery: ['https://www.googleapis.com/auth/bigquery'],
books: ['https://www.googleapis.com/auth/books'],
chat: ['https://www.googleapis.com/auth/chat.bot'],
docs: [
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
],
drive: [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.photos.readonly',
],
gmail: [
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.addons.current.action.compose',
'https://www.googleapis.com/auth/gmail.addons.current.message.action',
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
],
sheetV1: [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
],
sheetV2: [
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive.metadata',
],
sheetV2Trigger: [
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.metadata',
'https://www.googleapis.com/auth/drive.readonly',
],
slides: [
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/presentations',
],
translate: [
'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',
],
cloudStorage: [
'https://www.googleapis.com/auth/devstorage.full_control',
'https://www.googleapis.com/auth/cloud-platform',
],
vertex: ['https://www.googleapis.com/auth/cloud-platform'],
} as const;
export type GoogleServiceAccount = keyof typeof googleServiceAccountScopes;
export async function getGoogleAccessToken(
this:
| IExecuteFunctions
| IExecuteSingleFunctions
| ILoadOptionsFunctions
| ICredentialTestFunctions
| IPollFunctions,
credentials: IDataObject,
service: GoogleServiceAccount,
): Promise<IDataObject> {
//https://developers.google.com/identity/protocols/oauth2/service-account#httprest
const scopes = googleServiceAccountScopes[service];
const privateKey = formatPemBlock(credentials.privateKey as string);
credentials.email = ((credentials.email as string) || '').trim();
const now = moment().unix();
const signature = jwt.sign(
{
iss: credentials.email,
sub: credentials.delegatedEmail || credentials.email,
scope: scopes.join(' '),
aud: 'https://oauth2.googleapis.com/token',
iat: now,
exp: now + 3600,
},
privateKey,
{
algorithm: 'RS256',
header: {
typ: 'JWT',
alg: 'RS256',
},
},
);
const options: IRequestOptions = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
form: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signature,
},
uri: 'https://oauth2.googleapis.com/token',
json: true,
};
return await this.helpers.request(options);
}
export function validateAndSetDate(
filter: IDataObject,
key: string,
timezone: string,
context: IExecuteFunctions,
) {
const date = DateTime.fromISO(filter[key] as string);
if (date.isValid) {
filter[key] = date.setZone(timezone).toISO();
} else {
throw new NodeOperationError(
context.getNode(),
`The value "${filter[key] as string}" is not a valid DateTime.`,
);
}
}