diff --git a/packages/backend-core/src/db/utils.js b/packages/backend-core/src/db/utils.js index c6ca1273bc..4632b709c0 100644 --- a/packages/backend-core/src/db/utils.js +++ b/packages/backend-core/src/db/utils.js @@ -445,3 +445,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 270af4dec8..96c7f99953 100644 --- a/packages/backend-core/src/middleware/passport/datasource/google.js +++ b/packages/backend-core/src/middleware/passport/datasource/google.js @@ -1,8 +1,8 @@ const google = require("../google") const { Cookies, Configs } = require("../../../constants") const { clearCookie, getCookie } = require("../../../utils") +const { getScopedConfig, getPlatformUrl } = require("../../../db/utils") const { doWithDB } = require("../../../db") -const { getScopedConfig } = require("../../../db/utils") const environment = require("../../../environment") const { getGlobalDB } = require("../../../tenancy") @@ -21,10 +21,20 @@ async function fetchGoogleCreds() { ) } +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,14 +51,15 @@ 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, (accessToken, refreshToken, profile, done) => { clearCookie(ctx, Cookies.DatasourceAuth) - done(null, { accessToken, refreshToken }) + done(null, { refreshToken }) } ) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte index 66d7d43841..c94e750c29 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte @@ -15,7 +15,6 @@ import ArrayRenderer from "components/common/renderers/ArrayRenderer.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte" import { goto } from "@roxi/routify" - import GoogleButton from "../_components/GoogleButton.svelte" export let datasource export let save @@ -161,11 +160,6 @@ Fetch tables - {#if integration.auth} - {#if integration.auth.type === "google"} - - {/if} - {/if} diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index c58fdea551..e6d79bfdde 100644 --- a/packages/server/src/integrations/googlesheets.ts +++ b/packages/server/src/integrations/googlesheets.ts @@ -16,6 +16,7 @@ module GoogleSheetsModule { const { getGlobalDB } = require("@budibase/backend-core/tenancy") const { getScopedConfig } = require("@budibase/backend-core/db") const { Configs } = require("@budibase/backend-core/constants") + const fetch = require("node-fetch") interface GoogleSheetsConfig { spreadsheetId: string @@ -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) {