diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts index 283a2726d5..956bffa795 100644 --- a/packages/server/src/api/controllers/datasource.ts +++ b/packages/server/src/api/controllers/datasource.ts @@ -126,8 +126,15 @@ export async function fetch(ctx: UserCtx) { export async function verify( ctx: UserCtx ) { - const datasource = ctx.request.body.datasource - const connector = (await getConnector(datasource)) as IntegrationBase + const { datasource } = ctx.request.body + const existingDatasource = await sdk.datasources.get(datasource._id!) + + const enrichedDatasource = sdk.datasources.mergeConfigs( + datasource, + existingDatasource + ) + + const connector = await getConnector(enrichedDatasource) if (!connector.testConnection) { ctx.throw(400, "Connection information verification not supported") } diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index 0b2be54fb3..a8fd966782 100644 --- a/packages/server/src/integrations/googlesheets.ts +++ b/packages/server/src/integrations/googlesheets.ts @@ -1,5 +1,5 @@ import { - DatasourceFeature, + ConnectionInfo, DatasourceFieldType, DatasourcePlus, FieldType, @@ -141,6 +141,19 @@ class GoogleSheetsIntegration implements DatasourcePlus { this.client = new GoogleSpreadsheet(spreadsheetId) } + async testConnection(): Promise { + try { + await this.connect() + await this.client.loadInfo() + return { connected: true } + } catch (e: any) { + return { + connected: false, + error: e.message as string, + } + } + } + getBindingIdentifier() { return "" } diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index 46a40b8b03..dc5fb66c55 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -1,4 +1,5 @@ import { + ConnectionInfo, DatasourceFeature, Integration, QueryType, @@ -71,6 +72,18 @@ class SnowflakeIntegration { this.client = new Snowflake(config) } + async testConnection(): Promise { + try { + await this.client.connect() + return { connected: true } + } catch (e: any) { + return { + connected: false, + error: e.message as string, + } + } + } + async internalQuery(query: SqlQuery) { await this.client.connect() try { diff --git a/packages/server/src/sdk/app/datasources/datasources.ts b/packages/server/src/sdk/app/datasources/datasources.ts index dee0a221aa..c886e6a15f 100644 --- a/packages/server/src/sdk/app/datasources/datasources.ts +++ b/packages/server/src/sdk/app/datasources/datasources.ts @@ -13,6 +13,7 @@ import { import { cloneDeep } from "lodash/fp" import { getEnvironmentVariables } from "../../utils" import { getDefinitions, getDefinition } from "../../../integrations" +import _ from "lodash" const ENV_VAR_PREFIX = "env." @@ -147,6 +148,11 @@ export function mergeConfigs(update: Datasource, old: Datasource) { } } } + + if (old.config?.auth) { + update.config = _.merge(old.config, update.config) + } + // update back to actual passwords for everything else for (let [key, value] of Object.entries(update.config)) { if (value !== PASSWORD_REPLACEMENT) {