From 33717ceb303f3092ad3fe1c1e4526d869447c13c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Sun, 24 Apr 2022 23:32:47 +0100 Subject: [PATCH] auto fetch access token in gsheets integration --- packages/backend-core/src/db/utils.js | 1 + .../middleware/passport/datasource/google.js | 17 ++++-- .../server/src/integrations/googlesheets.ts | 54 ++++++++++++++++--- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/packages/backend-core/src/db/utils.js b/packages/backend-core/src/db/utils.js index feb17c4129..b0b7794096 100644 --- a/packages/backend-core/src/db/utils.js +++ b/packages/backend-core/src/db/utils.js @@ -460,3 +460,4 @@ exports.getConfigParams = getConfigParams exports.getScopedFullConfig = getScopedFullConfig exports.generateNewUsageQuotaDoc = generateNewUsageQuotaDoc exports.generateDevInfoID = generateDevInfoID +exports.getPlatformUrl = getPlatformUrl diff --git a/packages/backend-core/src/middleware/passport/datasource/google.js b/packages/backend-core/src/middleware/passport/datasource/google.js index 5046815b1f..ff305b01b3 100644 --- a/packages/backend-core/src/middleware/passport/datasource/google.js +++ b/packages/backend-core/src/middleware/passport/datasource/google.js @@ -2,7 +2,7 @@ const google = require("../google") const { Cookies, Configs } = require("../../../constants") const { clearCookie, getCookie } = require("../../../utils") const { getDB } = require("../../../db") -const { getScopedConfig } = require("../../../db/utils") +const { getScopedConfig, getPlatformUrl } = require("../../../db/utils") const environment = require("../../../environment") const { getGlobalDB } = require("../../../tenancy") @@ -21,10 +21,20 @@ async function fetchGoogleCreds() { return config } +async function platformUrl() { + const db = getGlobalDB() + const publicConfig = await getScopedConfig(db, { + type: Configs.SETTINGS, + }) + return getPlatformUrl(publicConfig) +} + async function preAuth(passport, ctx, next) { // get the relevant config const googleConfig = await fetchGoogleCreds() - let callbackUrl = `${environment.PLATFORM_URL}/api/global/auth/datasource/google/callback` + const platUrl = await platformUrl() + + let callbackUrl = `${platUrl}/api/global/auth/datasource/google/callback` const strategy = await google.strategyFactory(googleConfig, callbackUrl) if (!ctx.query.appId || !ctx.query.datasourceId) { @@ -41,8 +51,9 @@ async function preAuth(passport, ctx, next) { async function postAuth(passport, ctx, next) { // get the relevant config const config = await fetchGoogleCreds() + const platUrl = await platformUrl() - let callbackUrl = `${environment.PLATFORM_URL}/api/global/auth/datasource/google/callback` + let callbackUrl = `${platUrl}/api/global/auth/datasource/google/callback` const strategy = await google.strategyFactory( config, callbackUrl, diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index c58fdea551..f6d800da7a 100644 --- a/packages/server/src/integrations/googlesheets.ts +++ b/packages/server/src/integrations/googlesheets.ts @@ -10,6 +10,7 @@ import { Table, TableSchema } from "../definitions/common" import { buildExternalTableId } from "./utils" import { DataSourceOperation, FieldTypes } from "../constants" import { GoogleSpreadsheet } from "google-spreadsheet" +import fetch from "node-fetch" import env from "../environment" module GoogleSheetsModule { @@ -28,6 +29,16 @@ module GoogleSheetsModule { refreshToken: string } + interface AuthTokenRequest { + client_id: string + client_secret: string + refresh_token: string + } + + interface AuthTokenResponse { + access_token: string + } + const SCHEMA: Integration = { plus: true, auth: { @@ -40,6 +51,7 @@ module GoogleSheetsModule { friendlyName: "Google Sheets", datasource: { spreadsheetId: { + display: "Google Sheet URL", type: DatasourceFieldTypes.STRING, required: true, }, @@ -135,6 +147,30 @@ module GoogleSheetsModule { return parts.length > 5 ? parts[5] : spreadsheetId } + async fetchAccessToken( + payload: AuthTokenRequest + ): Promise { + const response = await fetch( + "https://www.googleapis.com/oauth2/v4/token", + { + method: "POST", + body: JSON.stringify({ + ...payload, + grant_type: "refresh_token", + }), + headers: { + "Content-Type": "application/json", + }, + } + ) + + if (response.status !== 200) { + throw new Error("Error authenticating with google sheets.") + } + + return response.json() + } + async connect() { try { // Initialise oAuth client @@ -154,14 +190,18 @@ module GoogleSheetsModule { clientId: googleConfig.clientID, clientSecret: googleConfig.clientSecret, }) - oauthClient.on("tokens", tokens => { - oauthClient.setCredentials({ - refresh_token: googleConfig.refreshToken, - access_token: tokens.access_token, - }) + + const tokenResponse = await this.fetchAccessToken({ + client_id: googleConfig.clientID, + client_secret: googleConfig.clientSecret, + refresh_token: this.config.auth.refreshToken, }) - oauthClient.credentials.access_token = this.config.auth.accessToken - oauthClient.credentials.refresh_token = this.config.auth.refreshToken + + oauthClient.setCredentials({ + refresh_token: this.config.auth.refreshToken, + access_token: tokenResponse.access_token, + }) + this.client.useOAuth2Client(oauthClient) await this.client.loadInfo() } catch (err) {