From 1163c4580a41d055d3ccd71d26ef58436b72d8de Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Sep 2022 13:33:00 +0530 Subject: [PATCH 1/6] fix(gui-v2): include host from NC_DB url Signed-off-by: Pranav C --- packages/nocodb/src/lib/utils/NcConfigFactory.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/nocodb/src/lib/utils/NcConfigFactory.ts b/packages/nocodb/src/lib/utils/NcConfigFactory.ts index d3aa41b63e..0569646ee0 100644 --- a/packages/nocodb/src/lib/utils/NcConfigFactory.ts +++ b/packages/nocodb/src/lib/utils/NcConfigFactory.ts @@ -317,7 +317,8 @@ export default class NcConfigFactory implements NcConfig { client: url.protocol.replace(':', ''), connection: { ...defaultConnectionConfig, - ...parsedQuery + ...parsedQuery, + host: url.hostname }, acquireConnectionTimeout: 600000, ...(url.searchParams.has('search_path') @@ -658,9 +659,9 @@ export default class NcConfigFactory implements NcConfig { if (rtConfig) { const { driver, ...connectionConfig } = parsedConfig; - + const client = driverClientMapping[driver] || driver; - + const avoidSSL = ['localhost', '127.0.0.1', 'host.docker.internal', '172.17. 0.1'] if (client === 'pg' && !connectionConfig?.ssl && !avoidSSL.includes(connectionConfig.host)) { From 9c557c90435c57ee6691105ce483e94eef53ac99 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Sep 2022 13:39:20 +0530 Subject: [PATCH 2/6] fix(gui-v2): include host from NC_DB url Signed-off-by: Pranav C --- .../nocodb/src/lib/utils/NcConfigFactory.ts | 75 +++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/packages/nocodb/src/lib/utils/NcConfigFactory.ts b/packages/nocodb/src/lib/utils/NcConfigFactory.ts index 0569646ee0..71b8363821 100644 --- a/packages/nocodb/src/lib/utils/NcConfigFactory.ts +++ b/packages/nocodb/src/lib/utils/NcConfigFactory.ts @@ -59,23 +59,23 @@ const knownQueryParams = [ }, { parameter: 'keyFilePath', - aliases: [] + aliases: [], }, { parameter: 'certFilePath', - aliases: [] + aliases: [], }, { parameter: 'caFilePath', - aliases: [] + aliases: [], }, { parameter: 'ssl', - aliases: [] + aliases: [], }, { parameter: 'options', - aliases: ['opt', 'opts'] + aliases: ['opt', 'opts'], }, ]; @@ -195,9 +195,11 @@ export default class NcConfigFactory implements NcConfig { }, } as any; } else { - const parsedQuery = {} + const parsedQuery = {}; for (const [key, value] of url.searchParams.entries()) { - const fnd = knownQueryParams.find((param) => param.parameter === key || param.aliases.includes(key)) + const fnd = knownQueryParams.find( + (param) => param.parameter === key || param.aliases.includes(key) + ); if (fnd) { parsedQuery[fnd.parameter] = value; } else { @@ -209,7 +211,8 @@ export default class NcConfigFactory implements NcConfig { client: url.protocol.replace(':', ''), connection: { ...defaultConnectionConfig, - ...parsedQuery + ...parsedQuery, + host: url.hostname, }, // pool: { // min: 1, @@ -303,9 +306,11 @@ export default class NcConfigFactory implements NcConfig { : {}), }; } else { - const parsedQuery = {} + const parsedQuery = {}; for (const [key, value] of url.searchParams.entries()) { - const fnd = knownQueryParams.find((param) => param.parameter === key || param.aliases.includes(key)) + const fnd = knownQueryParams.find( + (param) => param.parameter === key || param.aliases.includes(key) + ); if (fnd) { parsedQuery[fnd.parameter] = value; } else { @@ -318,7 +323,7 @@ export default class NcConfigFactory implements NcConfig { connection: { ...defaultConnectionConfig, ...parsedQuery, - host: url.hostname + host: url.hostname, }, acquireConnectionTimeout: 600000, ...(url.searchParams.has('search_path') @@ -637,7 +642,7 @@ export default class NcConfigFactory implements NcConfig { } } - public static extractXcUrlFromJdbc(url: string, rtConfig: boolean = false) { + public static extractXcUrlFromJdbc(url: string, rtConfig = false) { // drop the jdbc prefix if (url.startsWith('jdbc:')) { url = url.substring(5); @@ -645,9 +650,19 @@ export default class NcConfigFactory implements NcConfig { const config = parseDbUrl(url); - const parsedConfig: { driver?: string, host?: string, port?: string, database?: string, user?:string, password?: string, ssl?: string } = {} + const parsedConfig: { + driver?: string; + host?: string; + port?: string; + database?: string; + user?: string; + password?: string; + ssl?: string; + } = {}; for (const [key, value] of Object.entries(config)) { - const fnd = knownQueryParams.find((param) => param.parameter === key || param.aliases.includes(key)) + const fnd = knownQueryParams.find( + (param) => param.parameter === key || param.aliases.includes(key) + ); if (fnd) { parsedConfig[fnd.parameter] = value; } else { @@ -655,28 +670,42 @@ export default class NcConfigFactory implements NcConfig { } } - if (!parsedConfig?.port) parsedConfig.port = defaultClientPortMapping[driverClientMapping[parsedConfig.driver] || parsedConfig.driver]; + if (!parsedConfig?.port) + parsedConfig.port = + defaultClientPortMapping[ + driverClientMapping[parsedConfig.driver] || parsedConfig.driver + ]; if (rtConfig) { const { driver, ...connectionConfig } = parsedConfig; const client = driverClientMapping[driver] || driver; - const avoidSSL = ['localhost', '127.0.0.1', 'host.docker.internal', '172.17. 0.1'] + const avoidSSL = [ + 'localhost', + '127.0.0.1', + 'host.docker.internal', + '172.17. 0.1', + ]; - if (client === 'pg' && !connectionConfig?.ssl && !avoidSSL.includes(connectionConfig.host)) { + if ( + client === 'pg' && + !connectionConfig?.ssl && + !avoidSSL.includes(connectionConfig.host) + ) { connectionConfig.ssl = 'true'; } return { client: client, connection: { - ...connectionConfig - } + ...connectionConfig, + }, } as any; } - const { driver, host, port, database, user, password, ...extra } = parsedConfig; + const { driver, host, port, database, user, password, ...extra } = + parsedConfig; const extraParams = []; @@ -684,7 +713,11 @@ export default class NcConfigFactory implements NcConfig { extraParams.push(`${key}=${value}`); } - const res = `${driverClientMapping[driver] || driver}://${host}${port ? `:${port}` : ''}?${user ? `u=${user}&` : ''}${password ? `p=${password}&` : ''}${database ? `d=${database}&` : ''}${extraParams.join('&')}`; + const res = `${driverClientMapping[driver] || driver}://${host}${ + port ? `:${port}` : '' + }?${user ? `u=${user}&` : ''}${password ? `p=${password}&` : ''}${ + database ? `d=${database}&` : '' + }${extraParams.join('&')}`; return res; } From a828a4be434ec26e1a89f5540656bccbb4de6742 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Sep 2022 13:53:30 +0530 Subject: [PATCH 3/6] fix(gui-v2): use relative path as base url to avoid issue when using proxy Signed-off-by: Pranav C --- packages/nc-gui/composables/useApi/index.ts | 5 +++-- packages/nc-gui/composables/useGlobal/state.ts | 3 ++- packages/nc-gui/lib/constants.ts | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/composables/useApi/index.ts b/packages/nc-gui/composables/useApi/index.ts index 444c1bb401..532d785871 100644 --- a/packages/nc-gui/composables/useApi/index.ts +++ b/packages/nc-gui/composables/useApi/index.ts @@ -3,14 +3,15 @@ import { Api } from 'nocodb-sdk' import type { Ref } from 'vue' import type { CreateApiOptions, UseApiProps, UseApiReturn } from './types' import { addAxiosInterceptors } from './interceptors' +import { BASE_URL } from '~/lib' import { createEventHook, ref, unref, useCounter, useGlobal, useNuxtApp } from '#imports' -export function createApiInstance(options: CreateApiOptions = {}): Api { +export function createApiInstance({ baseURL = BASE_URL }: CreateApiOptions = {}): Api { const { appInfo } = $(useGlobal()) return addAxiosInterceptors( new Api({ - baseURL: options.baseURL ?? appInfo.ncSiteUrl, + baseURL: baseURL ?? appInfo.ncSiteUrl, }), ) } diff --git a/packages/nc-gui/composables/useGlobal/state.ts b/packages/nc-gui/composables/useGlobal/state.ts index 037a9f84ca..56316f62fb 100644 --- a/packages/nc-gui/composables/useGlobal/state.ts +++ b/packages/nc-gui/composables/useGlobal/state.ts @@ -2,6 +2,7 @@ import { usePreferredLanguages, useStorage } from '@vueuse/core' import { useJwt } from '@vueuse/integrations/useJwt' import type { JwtPayload } from 'jwt-decode' import type { AppInfo, State, StoredState } from './types' +import { BASE_URL } from '~/lib' import { computed, ref, toRefs, useCounter, useNuxtApp, useTimestamp } from '#imports' import type { User } from '~/lib' @@ -77,7 +78,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State { }) const appInfo = ref({ - ncSiteUrl: process.env.NC_BACKEND_URL || (process.env.NODE_ENV === 'production' ? '..' : 'http://localhost:8080'), + ncSiteUrl: BASE_URL, authType: 'jwt', connectToExternalDB: false, defaultLimit: 0, diff --git a/packages/nc-gui/lib/constants.ts b/packages/nc-gui/lib/constants.ts index 7b6465b2aa..875684598d 100644 --- a/packages/nc-gui/lib/constants.ts +++ b/packages/nc-gui/lib/constants.ts @@ -1,3 +1,4 @@ export const NOCO = 'noco' export const USER_PROJECT_ROLES = 'user_project_roles' export const SYSTEM_COLUMNS = ['id', 'title', 'created_at', 'updated_at'] +export const BASE_URL = process.env.NC_BACKEND_URL || (process.env.NODE_ENV === 'production' ? '..' : 'http://localhost:8080') From 367dd091430b9683196e9dee1700e656b74be13a Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Sep 2022 14:24:56 +0530 Subject: [PATCH 4/6] fix(gui-v2): typo correction Signed-off-by: Pranav C --- packages/nocodb/src/lib/utils/NcConfigFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/utils/NcConfigFactory.ts b/packages/nocodb/src/lib/utils/NcConfigFactory.ts index 71b8363821..b267322c8a 100644 --- a/packages/nocodb/src/lib/utils/NcConfigFactory.ts +++ b/packages/nocodb/src/lib/utils/NcConfigFactory.ts @@ -685,7 +685,7 @@ export default class NcConfigFactory implements NcConfig { 'localhost', '127.0.0.1', 'host.docker.internal', - '172.17. 0.1', + '172.17.0.1', ]; if ( From 92b19a481ea90a4d36b95512cf2b5b8701f292be Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Sep 2022 15:58:31 +0530 Subject: [PATCH 5/6] fix(gui-v2): allow providing all non null/undefined value under ssl object value Signed-off-by: Pranav C --- packages/nc-gui/pages/index/index/create-external.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/pages/index/index/create-external.vue b/packages/nc-gui/pages/index/index/create-external.vue index 4943d09ddf..e73d5c004b 100644 --- a/packages/nc-gui/pages/index/index/create-external.vue +++ b/packages/nc-gui/pages/index/index/create-external.vue @@ -181,7 +181,7 @@ function getConnectionConfig() { if ('ssl' in connection && connection.ssl) { if ( formState.sslUse === SSLUsage.No || - (typeof connection.ssl === 'object' && Object.values(connection.ssl).every((v) => !v)) + (typeof connection.ssl === 'object' && Object.values(connection.ssl).every((v) => v === null || v === undefined)) ) { delete connection.ssl } From def45f99d8c320f0e5728e7d33a56fcec99d62ed Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Sep 2022 16:38:53 +0530 Subject: [PATCH 6/6] fix(gui-v2): add mariadb mysql mapping and add test for DATABASE_URL Signed-off-by: Pranav C --- .../__tests__/noco/NcConfigFactory.test.ts | 29 +++++++++++++++++++ .../nocodb/src/lib/utils/NcConfigFactory.ts | 1 + 2 files changed, 30 insertions(+) diff --git a/packages/nocodb/src/__tests__/noco/NcConfigFactory.test.ts b/packages/nocodb/src/__tests__/noco/NcConfigFactory.test.ts index 10956a2188..04394bff8d 100644 --- a/packages/nocodb/src/__tests__/noco/NcConfigFactory.test.ts +++ b/packages/nocodb/src/__tests__/noco/NcConfigFactory.test.ts @@ -38,6 +38,35 @@ describe('Config Factory Tests', () => { expect(dbConfig).to.deep.equal(rest); done(); }); + + it('Generate config from DATABASE_URL', function (done) { + // postgres url + const ncDbUrl = NcConfigFactory.extractXcUrlFromJdbc( + 'postgres://username:password@host:5432/db' + ); + expect(ncDbUrl).to.be.equal('pg://host:5432?u=username&p=password&d=db&'); + + // postgres url without port + const ncDbUrl1 = NcConfigFactory.extractXcUrlFromJdbc( + 'postgres://username:password@host/db' + ); + expect(ncDbUrl1).to.be.equal('pg://host:5432?u=username&p=password&d=db&'); + + // mysql url + const ncDbUrl2 = NcConfigFactory.extractXcUrlFromJdbc( + 'jdbc:mysql://localhost/sample_db' + ); + expect(ncDbUrl2).to.be.equal('mysql2://localhost:3306?d=sample_db&'); + + // mariadb url + const ncDbUrl3 = NcConfigFactory.extractXcUrlFromJdbc( + 'jdbc:mariadb://localhost/sample_db' + ); + expect(ncDbUrl3).to.be.equal('mysql2://localhost:3306?d=sample_db&'); + + done(); + }); + it('Connection string with nested property', function (done) { const dbConfig = NcConfigFactory.metaUrlToDbConfig( `pg://localhost:5432?u=postgres&p=xgene&d=abcde&pool.min=1&pool.max=2&ssl.rejectUnauthorized=false` diff --git a/packages/nocodb/src/lib/utils/NcConfigFactory.ts b/packages/nocodb/src/lib/utils/NcConfigFactory.ts index b267322c8a..3cfc471ca7 100644 --- a/packages/nocodb/src/lib/utils/NcConfigFactory.ts +++ b/packages/nocodb/src/lib/utils/NcConfigFactory.ts @@ -20,6 +20,7 @@ const { const driverClientMapping = { mysql: 'mysql2', + mariadb: 'mysql2', postgres: 'pg', postgresql: 'pg', sqlite: 'sqlite3',