diff --git a/charts/budibase/templates/app-service-deployment.yaml b/charts/budibase/templates/app-service-deployment.yaml index d9def8c641..86e255d331 100644 --- a/charts/budibase/templates/app-service-deployment.yaml +++ b/charts/budibase/templates/app-service-deployment.yaml @@ -110,6 +110,10 @@ spec: value: {{ .Values.globals.cookieDomain | quote }} - name: HTTP_MIGRATIONS value: {{ .Values.globals.httpMigrations | quote }} + - name: GOOGLE_CLIENT_ID + value: {{ .Values.globals.google.clientId | quote }} + - name: GOOGLE_CLIENT_SECRET + value: {{ .Values.globals.google.secret | quote }} image: budibase/apps:{{ .Values.globals.appVersion }} imagePullPolicy: Always name: bbapps diff --git a/packages/backend-core/src/middleware/passport/datasource/google.js b/packages/backend-core/src/middleware/passport/datasource/google.js index c7553cee50..5046815b1f 100644 --- a/packages/backend-core/src/middleware/passport/datasource/google.js +++ b/packages/backend-core/src/middleware/passport/datasource/google.js @@ -1,15 +1,29 @@ const google = require("../google") -const { Cookies } = require("../../../constants") +const { Cookies, Configs } = require("../../../constants") const { clearCookie, getCookie } = require("../../../utils") const { getDB } = require("../../../db") +const { getScopedConfig } = require("../../../db/utils") const environment = require("../../../environment") +const { getGlobalDB } = require("../../../tenancy") -async function preAuth(passport, ctx, next) { - // get the relevant config - const googleConfig = { +async function fetchGoogleCreds() { + // try and get the config from the tenant + const db = getGlobalDB() + const googleConfig = await getScopedConfig(db, { + type: Configs.GOOGLE, + }) + // or fall back to env variables + const config = googleConfig || { clientID: environment.GOOGLE_CLIENT_ID, clientSecret: environment.GOOGLE_CLIENT_SECRET, } + + return config +} + +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 strategy = await google.strategyFactory(googleConfig, callbackUrl) @@ -26,10 +40,7 @@ async function preAuth(passport, ctx, next) { async function postAuth(passport, ctx, next) { // get the relevant config - const config = { - clientID: environment.GOOGLE_CLIENT_ID, - clientSecret: environment.GOOGLE_CLIENT_SECRET, - } + const config = await fetchGoogleCreds() let callbackUrl = `${environment.PLATFORM_URL}/api/global/auth/datasource/google/callback` const strategy = await google.strategyFactory( diff --git a/packages/backend-core/src/middleware/passport/google.js b/packages/backend-core/src/middleware/passport/google.js index cb93844c31..8fd0961ea1 100644 --- a/packages/backend-core/src/middleware/passport/google.js +++ b/packages/backend-core/src/middleware/passport/google.js @@ -51,7 +51,10 @@ exports.strategyFactory = async function ( ) } catch (err) { console.error(err) - throw new Error("Error constructing google authentication strategy", err) + throw new Error( + `Error constructing google authentication strategy: ${err}`, + err + ) } } // expose for testing diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte index c94e750c29..66d7d43841 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte @@ -15,6 +15,7 @@ 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 @@ -160,6 +161,11 @@ Fetch tables + {#if integration.auth} + {#if integration.auth.type === "google"} + + {/if} + {/if} diff --git a/packages/server/src/api/controllers/integration.js b/packages/server/src/api/controllers/integration.js index 75fd9ce80e..f3f3309c02 100644 --- a/packages/server/src/api/controllers/integration.js +++ b/packages/server/src/api/controllers/integration.js @@ -1,8 +1,24 @@ +const { cloneDeep } = require("lodash") const { definitions } = require("../../integrations") +const { getTenantId } = require("@budibase/backend-core/tenancy") +const { SourceNames } = require("../../definitions/datasource") +const googlesheets = require("../../integrations/googlesheets") +const env = require("../../environment") exports.fetch = async function (ctx) { ctx.status = 200 - ctx.body = definitions + const defs = cloneDeep(definitions) + + // for google sheets integration google verification + if (env.EXCLUDE_QUOTAS_TENANTS) { + const excludedTenants = env.EXCLUDE_QUOTAS_TENANTS.split(",") + const tenantId = getTenantId() + if (excludedTenants.includes(tenantId)) { + defs[SourceNames.GOOGLE_SHEETS] = googlesheets.schema + } + } + + ctx.body = defs } exports.find = async function (ctx) { diff --git a/packages/server/src/environment.js b/packages/server/src/environment.js index 212a54b87c..bdbbbde79f 100644 --- a/packages/server/src/environment.js +++ b/packages/server/src/environment.js @@ -46,6 +46,8 @@ module.exports = { MULTI_TENANCY: process.env.MULTI_TENANCY, HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS, API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC, + GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, + GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET, // environment NODE_ENV: process.env.NODE_ENV, JEST_WORKER_ID: process.env.JEST_WORKER_ID, diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index bb2de26f5d..c58fdea551 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 env from "../environment" module GoogleSheetsModule { const { getGlobalDB } = require("@budibase/backend-core/tenancy") @@ -138,13 +139,27 @@ module GoogleSheetsModule { try { // Initialise oAuth client const db = getGlobalDB() - const googleConfig = await getScopedConfig(db, { + let googleConfig = await getScopedConfig(db, { type: Configs.GOOGLE, }) + + if (!googleConfig) { + googleConfig = { + clientID: env.GOOGLE_CLIENT_ID, + clientSecret: env.GOOGLE_CLIENT_SECRET, + } + } + const oauthClient = new OAuth2Client({ clientId: googleConfig.clientID, clientSecret: googleConfig.clientSecret, }) + oauthClient.on("tokens", tokens => { + oauthClient.setCredentials({ + refresh_token: googleConfig.refreshToken, + access_token: tokens.access_token, + }) + }) oauthClient.credentials.access_token = this.config.auth.accessToken oauthClient.credentials.refresh_token = this.config.auth.refreshToken this.client.useOAuth2Client(oauthClient) diff --git a/packages/server/src/integrations/index.ts b/packages/server/src/integrations/index.ts index 07f3211fcb..0a892d7317 100644 --- a/packages/server/src/integrations/index.ts +++ b/packages/server/src/integrations/index.ts @@ -42,6 +42,7 @@ const INTEGRATIONS = { [SourceNames.ARANGODB]: arangodb.integration, [SourceNames.REST]: rest.integration, [SourceNames.FIREBASE]: firebase.integration, + [SourceNames.GOOGLE_SHEETS]: googlesheets.integration, } // optionally add oracle integration if the oracle binary can be installed @@ -53,7 +54,6 @@ if (!(process.arch === "arm64" && process.platform === "darwin")) { if (environment.SELF_HOSTED) { DEFINITIONS[SourceNames.GOOGLE_SHEETS] = googlesheets.schema - INTEGRATIONS[SourceNames.GOOGLE_SHEETS] = googlesheets.integration } module.exports = {