n8n-nodes-service-account-google-drive
Version:
n8n node for Google Drive with Service Account authentication
205 lines • 8.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoogleDriveServiceAccountTrigger = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const googleapis_1 = require("googleapis");
const uuid_1 = require("uuid");
class GoogleDriveServiceAccountTrigger {
constructor() {
this.description = {
displayName: 'Google Drive Trigger (Service Account)',
name: 'googleDriveServiceAccountTrigger',
icon: 'file:googleDrive.svg',
group: ['trigger'],
version: 1,
subtitle: '={{$parameter["event"]}}',
description: 'Handle Google Drive events via webhooks',
defaults: {
name: 'Google Drive Trigger',
},
inputs: [],
outputs: ['main'],
credentials: [
{
name: 'googleDriveServiceAccountApi',
required: true,
},
],
webhooks: [
{
name: 'default',
httpMethod: 'POST',
responseMode: 'onReceived',
path: 'webhook',
},
],
properties: [
{
displayName: 'File or Folder ID',
name: 'fileId',
type: 'string',
default: '',
required: true,
description: 'The ID of the file or folder to watch for changes',
},
{
displayName: 'Events',
name: 'events',
type: 'multiOptions',
options: [
{
name: 'File Created',
value: 'add',
},
{
name: 'File Updated',
value: 'update',
},
{
name: 'File Deleted',
value: 'remove',
},
{
name: 'File Shared',
value: 'share',
},
],
default: ['add', 'update', 'remove'],
description: 'The events to listen for',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Include Subfolders',
name: 'includeSubfolders',
type: 'boolean',
default: true,
description: 'Whether to include changes in subfolders',
},
],
},
],
};
this.webhookMethods = {
default: {
async checkExists() {
const webhookData = this.getWorkflowStaticData('node');
if (webhookData.channelId === undefined) {
return false;
}
return true;
},
async create() {
const webhookUrl = this.getNodeWebhookUrl('default');
const fileId = this.getNodeParameter('fileId');
const credentials = await this.getCredentials('googleDriveServiceAccountApi');
if (!credentials) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials provided');
}
const serviceAccountEmail = credentials.serviceAccountEmail;
const privateKey = credentials.privateKey.replace(/\\n/g, '\n');
const impersonateEmail = credentials.impersonateEmail || undefined;
const auth = new googleapis_1.google.auth.JWT({
email: serviceAccountEmail,
key: privateKey,
scopes: ['https://www.googleapis.com/auth/drive'],
subject: impersonateEmail,
});
const drive = googleapis_1.google.drive({ version: 'v3', auth });
const channelId = (0, uuid_1.v4)();
const webhookData = this.getWorkflowStaticData('node');
try {
const response = await drive.files.watch({
fileId,
requestBody: {
id: channelId,
type: 'web_hook',
address: webhookUrl,
},
});
webhookData.channelId = channelId;
webhookData.resourceId = response.data.resourceId;
webhookData.expiration = response.data.expiration;
return true;
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to create webhook: ${error.message}`);
}
},
async delete() {
const webhookData = this.getWorkflowStaticData('node');
if (webhookData.channelId === undefined) {
return false;
}
const credentials = await this.getCredentials('googleDriveServiceAccountApi');
if (!credentials) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials provided');
}
const serviceAccountEmail = credentials.serviceAccountEmail;
const privateKey = credentials.privateKey.replace(/\\n/g, '\n');
const impersonateEmail = credentials.impersonateEmail || undefined;
const auth = new googleapis_1.google.auth.JWT({
email: serviceAccountEmail,
key: privateKey,
scopes: ['https://www.googleapis.com/auth/drive'],
subject: impersonateEmail,
});
const drive = googleapis_1.google.drive({ version: 'v3', auth });
try {
await drive.channels.stop({
requestBody: {
id: webhookData.channelId,
resourceId: webhookData.resourceId,
},
});
delete webhookData.channelId;
delete webhookData.resourceId;
delete webhookData.expiration;
return true;
}
catch (error) {
return false;
}
},
},
};
}
async webhook() {
const req = this.getRequestObject();
const headers = req.headers;
const events = this.getNodeParameter('events');
// Google sends a sync message when setting up the webhook
if (headers['x-goog-resource-state'] === 'sync') {
return {
workflowData: [[]],
};
}
const resourceState = headers['x-goog-resource-state'];
const resourceId = headers['x-goog-resource-id'];
const changed = headers['x-goog-changed'];
// Filter events
if (!events.includes(resourceState)) {
return {
workflowData: [[]],
};
}
return {
workflowData: [
this.helpers.returnJsonArray({
event: resourceState,
resourceId,
changed: changed ? changed.split(',') : [],
channelId: headers['x-goog-channel-id'],
timestamp: new Date().toISOString(),
}),
],
};
}
}
exports.GoogleDriveServiceAccountTrigger = GoogleDriveServiceAccountTrigger;
//# sourceMappingURL=GoogleDriveServiceAccountTrigger.node.js.map