Browse Source

wip

Signed-off-by: Pranav C <pranavxc@gmail.com>
fix/heroku-bugs
Pranav C 2 years ago
parent
commit
dfeb6fd95b
  1. 1
      packages/nc-gui/components.d.ts
  2. 56
      packages/nc-gui/pages/index/index/create-external.vue
  3. 2
      packages/nc-gui/utils/projectCreateUtils.ts
  4. 379
      packages/nocodb/src/lib/utils/NcConfigFactory.ts

1
packages/nc-gui/components.d.ts vendored

@ -156,6 +156,7 @@ declare module '@vue/runtime-core' {
MdiFileDocumentOutline: typeof import('~icons/mdi/file-document-outline')['default'] MdiFileDocumentOutline: typeof import('~icons/mdi/file-document-outline')['default']
MdiFileExcel: typeof import('~icons/mdi/file-excel')['default'] MdiFileExcel: typeof import('~icons/mdi/file-excel')['default']
MdiFileEyeOutline: typeof import('~icons/mdi/file-eye-outline')['default'] MdiFileEyeOutline: typeof import('~icons/mdi/file-eye-outline')['default']
MdiFilePdf: typeof import('~icons/mdi/file-pdf')['default']
MdiFilePlusOutline: typeof import('~icons/mdi/file-plus-outline')['default'] MdiFilePlusOutline: typeof import('~icons/mdi/file-plus-outline')['default']
MdiFileUploadOutline: typeof import('~icons/mdi/file-upload-outline')['default'] MdiFileUploadOutline: typeof import('~icons/mdi/file-upload-outline')['default']
MdiFilterOutline: typeof import('~icons/mdi/filter-outline')['default'] MdiFilterOutline: typeof import('~icons/mdi/filter-outline')['default']

56
packages/nc-gui/pages/index/index/create-external.vue

@ -76,20 +76,20 @@ const validators = computed(() => {
'dataSource.client': [fieldRequiredValidator], 'dataSource.client': [fieldRequiredValidator],
...(formState.dataSource.client === ClientType.SQLITE ...(formState.dataSource.client === ClientType.SQLITE
? { ? {
'dataSource.connection.connection.filename': [fieldRequiredValidator], 'dataSource.connection.connection.filename': [fieldRequiredValidator],
} }
: { : {
'dataSource.connection.host': [fieldRequiredValidator], 'dataSource.connection.host': [fieldRequiredValidator],
'dataSource.connection.port': [fieldRequiredValidator], 'dataSource.connection.port': [fieldRequiredValidator],
'dataSource.connection.user': [fieldRequiredValidator], 'dataSource.connection.user': [fieldRequiredValidator],
'dataSource.connection.password': [fieldRequiredValidator], 'dataSource.connection.password': [fieldRequiredValidator],
'dataSource.connection.database': [fieldRequiredValidator], 'dataSource.connection.database': [fieldRequiredValidator],
...([ClientType.PG, ClientType.MSSQL].includes(formState.dataSource.client) ...([ClientType.PG, ClientType.MSSQL].includes(formState.dataSource.client)
? { ? {
'dataSource.searchPath.0': [fieldRequiredValidator], 'dataSource.searchPath.0': [fieldRequiredValidator],
} }
: {}), : {}),
}), }),
} }
}) })
@ -112,7 +112,9 @@ const onSSLModeChange = ((mode: SSLUsage) => {
delete connection.ssl delete connection.ssl
break break
case SSLUsage.Allowed: case SSLUsage.Allowed:
connection.ssl = 'true' connection.ssl = {
rejectUnauthorized: false,
}
break break
default: default:
connection.ssl = { connection.ssl = {
@ -129,7 +131,7 @@ const updateSSLUse = () => {
if (formState.dataSource.client !== ClientType.SQLITE) { if (formState.dataSource.client !== ClientType.SQLITE) {
const connection = formState.dataSource.connection as DefaultConnection const connection = formState.dataSource.connection as DefaultConnection
if (connection.ssl) { if (connection.ssl) {
if (typeof connection.ssl === 'string') { if (typeof connection.ssl === 'object' && !connection.ssl.rejectUnauthorized) {
formState.sslUse = SSLUsage.Allowed formState.sslUse = SSLUsage.Allowed
} else { } else {
formState.sslUse = SSLUsage.Preferred formState.sslUse = SSLUsage.Preferred
@ -335,7 +337,8 @@ onMounted(() => {
<div <div
class="create-external bg-white relative flex flex-col justify-center gap-2 w-full p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)" class="create-external bg-white relative flex flex-col justify-center gap-2 w-full p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
> >
<general-noco-icon class="color-transition hover:(ring ring-accent)" :class="[isLoading ? 'animated-bg-gradient' : '']" /> <general-noco-icon class="color-transition hover:(ring ring-accent)"
:class="[isLoading ? 'animated-bg-gradient' : '']" />
<div <div
class="color-transition transform group absolute top-5 left-5 text-4xl rounded-full bg-white cursor-pointer" class="color-transition transform group absolute top-5 left-5 text-4xl rounded-full bg-white cursor-pointer"
@ -361,7 +364,7 @@ onMounted(() => {
<a-form-item :label="$t('labels.dbType')" v-bind="validateInfos['dataSource.client']"> <a-form-item :label="$t('labels.dbType')" v-bind="validateInfos['dataSource.client']">
<a-select v-model:value="formState.dataSource.client" class="nc-extdb-db-type" @change="onClientChange"> <a-select v-model:value="formState.dataSource.client" class="nc-extdb-db-type" @change="onClientChange">
<a-select-option v-for="client in clientTypes" :key="client.value" :value="client.value" <a-select-option v-for="client in clientTypes" :key="client.value" :value="client.value"
>{{ client.text }} >{{ client.text }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
@ -378,7 +381,8 @@ onMounted(() => {
<template v-else> <template v-else>
<!-- Host Address --> <!-- Host Address -->
<a-form-item :label="$t('labels.hostAddress')" v-bind="validateInfos['dataSource.connection.host']"> <a-form-item :label="$t('labels.hostAddress')" v-bind="validateInfos['dataSource.connection.host']">
<a-input v-model:value="(formState.dataSource.connection as DefaultConnection).host" class="nc-extdb-host-address" /> <a-input v-model:value="(formState.dataSource.connection as DefaultConnection).host"
class="nc-extdb-host-address" />
</a-form-item> </a-form-item>
<!-- Port Number --> <!-- Port Number -->
@ -391,7 +395,8 @@ onMounted(() => {
<!-- Username --> <!-- Username -->
<a-form-item :label="$t('labels.username')" v-bind="validateInfos['dataSource.connection.user']"> <a-form-item :label="$t('labels.username')" v-bind="validateInfos['dataSource.connection.user']">
<a-input v-model:value="(formState.dataSource.connection as DefaultConnection).user" class="nc-extdb-host-user" /> <a-input v-model:value="(formState.dataSource.connection as DefaultConnection).user"
class="nc-extdb-host-user" />
</a-form-item> </a-form-item>
<!-- Password --> <!-- Password -->
@ -434,7 +439,8 @@ onMounted(() => {
</template> </template>
<a-form-item label="SSL mode"> <a-form-item label="SSL mode">
<a-select v-model:value="formState.sslUse" @select="onSSLModeChange"> <a-select v-model:value="formState.sslUse" @select="onSSLModeChange">
<a-select-option v-for="opt in Object.values(SSLUsage)" :key="opt" :value="opt">{{ opt }}</a-select-option> <a-select-option v-for="opt in Object.values(SSLUsage)" :key="opt" :value="opt">{{ opt }}
</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
@ -476,14 +482,16 @@ onMounted(() => {
<input ref="caFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.ca, caFileInput)" /> <input ref="caFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.ca, caFileInput)" />
<input ref="certFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.cert, certFileInput)" /> <input ref="certFileInput" type="file" class="!hidden"
@change="onFileSelect(CertTypes.cert, certFileInput)" />
<input ref="keyFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.key, keyFileInput)" /> <input ref="keyFileInput" type="file" class="!hidden" @change="onFileSelect(CertTypes.key, keyFileInput)" />
<a-divider /> <a-divider />
<!-- Extra connection parameters --> <!-- Extra connection parameters -->
<a-form-item class="mb-2" :label="$t('labels.extraConnectionParameters')" v-bind="validateInfos.extraParameters"> <a-form-item class="mb-2" :label="$t('labels.extraConnectionParameters')"
v-bind="validateInfos.extraParameters">
<a-card> <a-card>
<div v-for="(item, index) of formState.extraParameters" :key="index"> <div v-for="(item, index) of formState.extraParameters" :key="index">
<div class="flex py-1 items-center gap-1"> <div class="flex py-1 items-center gap-1">
@ -497,7 +505,9 @@ onMounted(() => {
</div> </div>
</div> </div>
<a-button type="dashed" class="w-full caption mt-2" @click="addNewParam"> <a-button type="dashed" class="w-full caption mt-2" @click="addNewParam">
<div class="flex items-center justify-center"><MdiPlus /></div> <div class="flex items-center justify-center">
<MdiPlus />
</div>
</a-button> </a-button>
</a-card> </a-card>
</a-form-item> </a-form-item>

2
packages/nc-gui/utils/projectCreateUtils.ts

@ -21,7 +21,7 @@ export interface DefaultConnection {
user: string user: string
password: string password: string
port: number | string port: number | string
ssl?: Record<CertTypes, string> | 'true' ssl?: Record<CertTypes | 'rejectUnauthorized', string | boolean> | 'true'
} }
export interface SQLiteConnection { export interface SQLiteConnection {

379
packages/nocodb/src/lib/utils/NcConfigFactory.ts

@ -1,22 +1,22 @@
import fs from 'fs'; import fs from 'fs'
import parseDbUrl from 'parse-database-url'; import parseDbUrl from 'parse-database-url'
import { URL } from 'url'; import { URL } from 'url'
import { import {
AuthConfig, AuthConfig,
DbConfig, DbConfig,
MailerConfig, MailerConfig,
NcConfig, NcConfig,
} from '../../interface/config'; } from '../../interface/config'
import * as path from 'path'; import * as path from 'path'
import SqlClientFactory from '../db/sql-client/lib/SqlClientFactory'; import SqlClientFactory from '../db/sql-client/lib/SqlClientFactory'
const { const {
uniqueNamesGenerator, uniqueNamesGenerator,
starWars, starWars,
adjectives, adjectives,
animals, animals,
} = require('unique-names-generator'); } = require('unique-names-generator')
const driverClientMapping = { const driverClientMapping = {
mysql: 'mysql2', mysql: 'mysql2',
@ -25,7 +25,7 @@ const driverClientMapping = {
postgresql: 'pg', postgresql: 'pg',
sqlite: 'sqlite3', sqlite: 'sqlite3',
mssql: 'mssql', mssql: 'mssql',
}; }
const defaultClientPortMapping = { const defaultClientPortMapping = {
mysql: 3306, mysql: 3306,
@ -33,13 +33,13 @@ const defaultClientPortMapping = {
postgres: 5432, postgres: 5432,
pg: 5432, pg: 5432,
mssql: 1433, mssql: 1433,
}; }
const defaultConnectionConfig: any = { const defaultConnectionConfig: any = {
// https://github.com/knex/knex/issues/97 // https://github.com/knex/knex/issues/97
// timezone: process.env.NC_TIMEZONE || 'UTC', // timezone: process.env.NC_TIMEZONE || 'UTC',
dateStrings: true, dateStrings: true,
}; }
const knownQueryParams = [ const knownQueryParams = [
{ {
@ -78,51 +78,51 @@ const knownQueryParams = [
parameter: 'options', parameter: 'options',
aliases: ['opt', 'opts'], aliases: ['opt', 'opts'],
}, },
]; ]
export default class NcConfigFactory implements NcConfig { export default class NcConfigFactory implements NcConfig {
public static make(): NcConfig { public static make(): NcConfig {
this.jdbcToXcUrl(); this.jdbcToXcUrl()
const ncConfig = new NcConfigFactory(); const ncConfig = new NcConfigFactory()
ncConfig.auth = { ncConfig.auth = {
jwt: { jwt: {
secret: process.env.NC_AUTH_JWT_SECRET, secret: process.env.NC_AUTH_JWT_SECRET,
}, },
}; }
ncConfig.port = +(process?.env?.PORT ?? 8080); ncConfig.port = +(process?.env?.PORT ?? 8080)
ncConfig.env = '_noco'; // process.env?.NODE_ENV || 'dev'; ncConfig.env = '_noco' // process.env?.NODE_ENV || 'dev';
ncConfig.workingEnv = '_noco'; // process.env?.NODE_ENV || 'dev'; ncConfig.workingEnv = '_noco' // process.env?.NODE_ENV || 'dev';
// ncConfig.toolDir = this.getToolDir(); // ncConfig.toolDir = this.getToolDir();
ncConfig.projectType = ncConfig.projectType =
ncConfig?.envs?.[ncConfig.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest'; ncConfig?.envs?.[ncConfig.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest'
if (ncConfig.meta?.db?.connection?.filename) { if (ncConfig.meta?.db?.connection?.filename) {
ncConfig.meta.db.connection.filename = path.join( ncConfig.meta.db.connection.filename = path.join(
this.getToolDir(), this.getToolDir(),
ncConfig.meta.db.connection.filename ncConfig.meta.db.connection.filename,
); )
} }
if (process.env.NC_DB) { if (process.env.NC_DB) {
ncConfig.meta.db = this.metaUrlToDbConfig(process.env.NC_DB); ncConfig.meta.db = this.metaUrlToDbConfig(process.env.NC_DB)
} else if (process.env.NC_DB_JSON) { } else if (process.env.NC_DB_JSON) {
ncConfig.meta.db = JSON.parse(process.env.NC_DB_JSON); ncConfig.meta.db = JSON.parse(process.env.NC_DB_JSON)
} else if (process.env.NC_DB_JSON_FILE) { } else if (process.env.NC_DB_JSON_FILE) {
const filePath = process.env.NC_DB_JSON_FILE; const filePath = process.env.NC_DB_JSON_FILE
if (!fs.existsSync(filePath)) { if (!fs.existsSync(filePath)) {
throw new Error(`NC_DB_JSON_FILE not found: ${filePath}`); throw new Error(`NC_DB_JSON_FILE not found: ${filePath}`)
} }
const fileContent = fs.readFileSync(filePath, { encoding: 'utf8' }); const fileContent = fs.readFileSync(filePath, { encoding: 'utf8' })
ncConfig.meta.db = JSON.parse(fileContent); ncConfig.meta.db = JSON.parse(fileContent)
} }
if (process.env.NC_TRY) { if (process.env.NC_TRY) {
ncConfig.try = true; ncConfig.try = true
ncConfig.meta.db = { ncConfig.meta.db = {
client: 'sqlite3', client: 'sqlite3',
connection: ':memory:', connection: ':memory:',
@ -132,54 +132,54 @@ export default class NcConfigFactory implements NcConfig {
// disposeTimeout: 360000*1000, // disposeTimeout: 360000*1000,
idleTimeoutMillis: 360000 * 1000, idleTimeoutMillis: 360000 * 1000,
}, },
} as any; } as any
} }
if (process.env.NC_PUBLIC_URL) { if (process.env.NC_PUBLIC_URL) {
ncConfig.envs['_noco'].publicUrl = process.env.NC_PUBLIC_URL; ncConfig.envs['_noco'].publicUrl = process.env.NC_PUBLIC_URL
// ncConfig.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL; // ncConfig.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL;
ncConfig.publicUrl = process.env.NC_PUBLIC_URL; ncConfig.publicUrl = process.env.NC_PUBLIC_URL
} }
if (process.env.NC_DASHBOARD_URL) { if (process.env.NC_DASHBOARD_URL) {
ncConfig.dashboardPath = process.env.NC_DASHBOARD_URL; ncConfig.dashboardPath = process.env.NC_DASHBOARD_URL
} }
return ncConfig; return ncConfig
} }
public static getToolDir() { public static getToolDir() {
return process.env.NC_TOOL_DIR || process.cwd(); return process.env.NC_TOOL_DIR || process.cwd()
} }
public static hasDbUrl(): boolean { public static hasDbUrl(): boolean {
return Object.keys(process.env).some((envKey) => return Object.keys(process.env).some((envKey) =>
envKey.startsWith('NC_DB_URL') envKey.startsWith('NC_DB_URL'),
); )
} }
public static makeFromUrls(urls: string[]): NcConfig { public static makeFromUrls(urls: string[]): NcConfig {
const config = new NcConfigFactory(); const config = new NcConfigFactory()
// config.envs[process.env.NODE_ENV || 'dev'].db = []; // config.envs[process.env.NODE_ENV || 'dev'].db = [];
config.envs['_noco'].db = []; config.envs['_noco'].db = []
for (const [i, url] of Object.entries(urls)) { for (const [i, url] of Object.entries(urls)) {
// config.envs[process.env.NODE_ENV || 'dev'].db.push(this.urlToDbConfig(url, i)); // config.envs[process.env.NODE_ENV || 'dev'].db.push(this.urlToDbConfig(url, i));
config.envs['_noco'].db.push(this.urlToDbConfig(url, i)); config.envs['_noco'].db.push(this.urlToDbConfig(url, i))
} }
return config; return config
} }
public static urlToDbConfig( public static urlToDbConfig(
urlString: string, urlString: string,
key = '', key = '',
config?: NcConfigFactory, config?: NcConfigFactory,
type?: string type?: string,
): DbConfig { ): DbConfig {
const url = new URL(urlString); const url = new URL(urlString)
let dbConfig: DbConfig; let dbConfig: DbConfig
if (url.protocol.startsWith('sqlite3')) { if (url.protocol.startsWith('sqlite3')) {
dbConfig = { dbConfig = {
@ -194,17 +194,17 @@ export default class NcConfigFactory implements NcConfig {
url.searchParams.get('d') || url.searchParams.get('database'), url.searchParams.get('d') || url.searchParams.get('database'),
useNullAsDefault: true, useNullAsDefault: true,
}, },
} as any; } as any
} else { } else {
const parsedQuery = {}; const parsedQuery = {}
for (const [key, value] of url.searchParams.entries()) { for (const [key, value] of url.searchParams.entries()) {
const fnd = knownQueryParams.find( const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key) (param) => param.parameter === key || param.aliases.includes(key),
); )
if (fnd) { if (fnd) {
parsedQuery[fnd.parameter] = value; parsedQuery[fnd.parameter] = value
} else { } else {
parsedQuery[key] = value; parsedQuery[key] = value
} }
} }
@ -220,10 +220,10 @@ export default class NcConfigFactory implements NcConfig {
// max: 1 // max: 1
// }, // },
acquireConnectionTimeout: 600000, acquireConnectionTimeout: 600000,
} as any; } as any
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) { if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) {
dbConfig.connection.ssl = true; dbConfig.connection.ssl = true
} }
if ( if (
@ -235,7 +235,7 @@ export default class NcConfigFactory implements NcConfig {
keyFilePath: url.searchParams.get('keyFilePath'), keyFilePath: url.searchParams.get('keyFilePath'),
certFilePath: url.searchParams.get('certFilePath'), certFilePath: url.searchParams.get('certFilePath'),
caFilePath: url.searchParams.get('caFilePath'), caFilePath: url.searchParams.get('caFilePath'),
}; }
} }
} }
@ -243,7 +243,7 @@ export default class NcConfigFactory implements NcConfig {
config.title = config.title =
url.searchParams.get('t') || url.searchParams.get('t') ||
url.searchParams.get('title') || url.searchParams.get('title') ||
this.generateRandomTitle(); this.generateRandomTitle()
} }
Object.assign(dbConfig, { Object.assign(dbConfig, {
@ -268,28 +268,28 @@ export default class NcConfigFactory implements NcConfig {
name: 'nc_evolutions', name: 'nc_evolutions',
}, },
}, },
}); })
return dbConfig; return dbConfig
} }
private static generateRandomTitle(): string { private static generateRandomTitle(): string {
return uniqueNamesGenerator({ return uniqueNamesGenerator({
dictionaries: [[starWars], [adjectives, animals]][ dictionaries: [[starWars], [adjectives, animals]][
Math.floor(Math.random() * 2) Math.floor(Math.random() * 2)
], ],
}) })
.toLowerCase() .toLowerCase()
.replace(/[ -]/g, '_'); .replace(/[ -]/g, '_')
} }
static metaUrlToDbConfig(urlString) { static metaUrlToDbConfig(urlString) {
const url = new URL(urlString); const url = new URL(urlString)
let dbConfig; let dbConfig
if (url.protocol.startsWith('sqlite3')) { if (url.protocol.startsWith('sqlite3')) {
const db = url.searchParams.get('d') || url.searchParams.get('database'); const db = url.searchParams.get('d') || url.searchParams.get('database')
dbConfig = { dbConfig = {
client: 'sqlite3', client: 'sqlite3',
connection: { connection: {
@ -297,25 +297,25 @@ export default class NcConfigFactory implements NcConfig {
}, },
...(db === ':memory:' ...(db === ':memory:'
? { ? {
pool: { pool: {
min: 1, min: 1,
max: 1, max: 1,
// disposeTimeout: 360000*1000, // disposeTimeout: 360000*1000,
idleTimeoutMillis: 360000 * 1000, idleTimeoutMillis: 360000 * 1000,
}, },
} }
: {}), : {}),
}; }
} else { } else {
const parsedQuery = {}; const parsedQuery = {}
for (const [key, value] of url.searchParams.entries()) { for (const [key, value] of url.searchParams.entries()) {
const fnd = knownQueryParams.find( const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key) (param) => param.parameter === key || param.aliases.includes(key),
); )
if (fnd) { if (fnd) {
parsedQuery[fnd.parameter] = value; parsedQuery[fnd.parameter] = value
} else { } else {
parsedQuery[key] = value; parsedQuery[key] = value
} }
} }
@ -329,22 +329,22 @@ export default class NcConfigFactory implements NcConfig {
acquireConnectionTimeout: 600000, acquireConnectionTimeout: 600000,
...(url.searchParams.has('search_path') ...(url.searchParams.has('search_path')
? { ? {
searchPath: url.searchParams.get('search_path').split(','), searchPath: url.searchParams.get('search_path').split(','),
} }
: {}), : {}),
}; }
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) { if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) {
dbConfig.connection.ssl = true; dbConfig.connection.ssl = true
} }
} }
url.searchParams.forEach((_value, key) => { url.searchParams.forEach((_value, key) => {
let value: any = _value; let value: any = _value
if (value === 'true') { if (value === 'true') {
value = true; value = true
} else if (value === 'false') { } else if (value === 'false') {
value = false; value = false
} else if (/^\d+$/.test(value)) { } else if (/^\d+$/.test(value)) {
value = +value; value = +value
} }
// todo: implement config read from JSON file or JSON env val read // todo: implement config read from JSON file or JSON env val read
if ( if (
@ -359,10 +359,10 @@ export default class NcConfigFactory implements NcConfig {
].includes(key) ].includes(key)
) { ) {
key.split('.').reduce((obj, k, i, arr) => { key.split('.').reduce((obj, k, i, arr) => {
return (obj[k] = i === arr.length - 1 ? value : obj[k] || {}); return (obj[k] = i === arr.length - 1 ? value : obj[k] || {})
}, dbConfig); }, dbConfig)
} }
}); })
if ( if (
dbConfig?.connection?.ssl && dbConfig?.connection?.ssl &&
@ -371,12 +371,12 @@ export default class NcConfigFactory implements NcConfig {
if (dbConfig.connection.ssl.caFilePath && !dbConfig.connection.ssl.ca) { if (dbConfig.connection.ssl.caFilePath && !dbConfig.connection.ssl.ca) {
dbConfig.connection.ssl.ca = fs dbConfig.connection.ssl.ca = fs
.readFileSync(dbConfig.connection.ssl.caFilePath) .readFileSync(dbConfig.connection.ssl.caFilePath)
.toString(); .toString()
} }
if (dbConfig.connection.ssl.keyFilePath && !dbConfig.connection.ssl.key) { if (dbConfig.connection.ssl.keyFilePath && !dbConfig.connection.ssl.key) {
dbConfig.connection.ssl.key = fs dbConfig.connection.ssl.key = fs
.readFileSync(dbConfig.connection.ssl.keyFilePath) .readFileSync(dbConfig.connection.ssl.keyFilePath)
.toString(); .toString()
} }
if ( if (
dbConfig.connection.ssl.certFilePath && dbConfig.connection.ssl.certFilePath &&
@ -384,29 +384,32 @@ export default class NcConfigFactory implements NcConfig {
) { ) {
dbConfig.connection.ssl.cert = fs dbConfig.connection.ssl.cert = fs
.readFileSync(dbConfig.connection.ssl.certFilePath) .readFileSync(dbConfig.connection.ssl.certFilePath)
.toString(); .toString()
}
if (dbConfig?.connection?.ssl === 'rejectUnauthorized') {
dbConfig.connection.ssl = { rejectUnauthorized: false }
} }
} }
return dbConfig; return dbConfig
} }
public static makeProjectConfigFromUrl(url, type?: string): NcConfig { public static makeProjectConfigFromUrl(url, type?: string): NcConfig {
const config = new NcConfigFactory(); const config = new NcConfigFactory()
const dbConfig = this.urlToDbConfig(url, '', config, type); const dbConfig = this.urlToDbConfig(url, '', config, type)
// config.envs[process.env.NODE_ENV || 'dev'].db.push(dbConfig); // config.envs[process.env.NODE_ENV || 'dev'].db.push(dbConfig);
config.envs['_noco'].db.push(dbConfig); config.envs['_noco'].db.push(dbConfig)
if (process.env.NC_AUTH_ADMIN_SECRET) { if (process.env.NC_AUTH_ADMIN_SECRET) {
config.auth = { config.auth = {
masterKey: { masterKey: {
secret: process.env.NC_AUTH_ADMIN_SECRET, secret: process.env.NC_AUTH_ADMIN_SECRET,
}, },
}; }
} else if (process.env.NC_NO_AUTH) { } else if (process.env.NC_NO_AUTH) {
config.auth = { config.auth = {
disabled: true, disabled: true,
}; }
// } else if (config?.envs?.[process.env.NODE_ENV || 'dev']?.db?.[0]) { // } else if (config?.envs?.[process.env.NODE_ENV || 'dev']?.db?.[0]) {
} else if (config?.envs?.['_noco']?.db?.[0]) { } else if (config?.envs?.['_noco']?.db?.[0]) {
config.auth = { config.auth = {
@ -417,15 +420,15 @@ export default class NcConfigFactory implements NcConfig {
config.envs['_noco'].db[0].meta.dbAlias, config.envs['_noco'].db[0].meta.dbAlias,
secret: process.env.NC_AUTH_JWT_SECRET, secret: process.env.NC_AUTH_JWT_SECRET,
}, },
}; }
} }
if (process.env.NC_DB) { if (process.env.NC_DB) {
config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB); config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB)
} }
if (process.env.NC_TRY) { if (process.env.NC_TRY) {
config.try = true; config.try = true
config.meta.db = { config.meta.db = {
client: 'sqlite3', client: 'sqlite3',
connection: ':memory:', connection: ':memory:',
@ -435,7 +438,7 @@ export default class NcConfigFactory implements NcConfig {
// disposeTimeout: 360000*1000, // disposeTimeout: 360000*1000,
idleTimeoutMillis: 360000 * 1000, idleTimeoutMillis: 360000 * 1000,
}, },
} as any; } as any
} }
if (process.env.NC_MAILER) { if (process.env.NC_MAILER) {
@ -450,35 +453,35 @@ export default class NcConfigFactory implements NcConfig {
pass: process.env.NC_MAILER_PASS, pass: process.env.NC_MAILER_PASS,
}, },
}, },
}; }
} }
if (process.env.NC_PUBLIC_URL) { if (process.env.NC_PUBLIC_URL) {
// config.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL; // config.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL;
config.envs['_noco'].publicUrl = process.env.NC_PUBLIC_URL; config.envs['_noco'].publicUrl = process.env.NC_PUBLIC_URL
config.publicUrl = process.env.NC_PUBLIC_URL; config.publicUrl = process.env.NC_PUBLIC_URL
} }
config.port = +(process?.env?.PORT ?? 8080); config.port = +(process?.env?.PORT ?? 8080)
// config.env = process.env?.NODE_ENV || 'dev'; // config.env = process.env?.NODE_ENV || 'dev';
// config.workingEnv = process.env?.NODE_ENV || 'dev'; // config.workingEnv = process.env?.NODE_ENV || 'dev';
config.env = '_noco'; config.env = '_noco'
config.workingEnv = '_noco'; config.workingEnv = '_noco'
config.toolDir = this.getToolDir(); config.toolDir = this.getToolDir()
config.projectType = config.projectType =
type || type ||
config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type ||
'rest'; 'rest'
return config; return config
} }
public static makeProjectConfigFromConnection( public static makeProjectConfigFromConnection(
dbConnectionConfig: any, dbConnectionConfig: any,
type?: string type?: string,
): NcConfig { ): NcConfig {
const config = new NcConfigFactory(); const config = new NcConfigFactory()
let dbConfig = dbConnectionConfig; let dbConfig = dbConnectionConfig
if (dbConfig.client === 'sqlite3') { if (dbConfig.client === 'sqlite3') {
dbConfig = { dbConfig = {
@ -488,11 +491,11 @@ export default class NcConfigFactory implements NcConfig {
database: dbConnectionConfig.connection.filename, database: dbConnectionConfig.connection.filename,
useNullAsDefault: true, useNullAsDefault: true,
}, },
}; }
} }
// todo: // todo:
const key = ''; const key = ''
Object.assign(dbConfig, { Object.assign(dbConfig, {
meta: { meta: {
tn: 'nc_evolutions', tn: 'nc_evolutions',
@ -508,21 +511,21 @@ export default class NcConfigFactory implements NcConfig {
name: 'nc_evolutions', name: 'nc_evolutions',
}, },
}, },
}); })
// config.envs[process.env.NODE_ENV || 'dev'].db.push(dbConfig); // config.envs[process.env.NODE_ENV || 'dev'].db.push(dbConfig);
config.envs['_noco'].db.push(dbConfig); config.envs['_noco'].db.push(dbConfig)
if (process.env.NC_AUTH_ADMIN_SECRET) { if (process.env.NC_AUTH_ADMIN_SECRET) {
config.auth = { config.auth = {
masterKey: { masterKey: {
secret: process.env.NC_AUTH_ADMIN_SECRET, secret: process.env.NC_AUTH_ADMIN_SECRET,
}, },
}; }
} else if (process.env.NC_NO_AUTH) { } else if (process.env.NC_NO_AUTH) {
config.auth = { config.auth = {
disabled: true, disabled: true,
}; }
// } else if (config?.envs?.[process.env.NODE_ENV || 'dev']?.db?.[0]) { // } else if (config?.envs?.[process.env.NODE_ENV || 'dev']?.db?.[0]) {
} else if (config?.envs?.['_noco']?.db?.[0]) { } else if (config?.envs?.['_noco']?.db?.[0]) {
config.auth = { config.auth = {
@ -533,15 +536,15 @@ export default class NcConfigFactory implements NcConfig {
config.envs['_noco'].db[0].meta.dbAlias, config.envs['_noco'].db[0].meta.dbAlias,
secret: process.env.NC_AUTH_JWT_SECRET, secret: process.env.NC_AUTH_JWT_SECRET,
}, },
}; }
} }
if (process.env.NC_DB) { if (process.env.NC_DB) {
config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB); config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB)
} }
if (process.env.NC_TRY) { if (process.env.NC_TRY) {
config.try = true; config.try = true
config.meta.db = { config.meta.db = {
client: 'sqlite3', client: 'sqlite3',
connection: ':memory:', connection: ':memory:',
@ -551,27 +554,27 @@ export default class NcConfigFactory implements NcConfig {
// disposeTimeout: 360000*1000, // disposeTimeout: 360000*1000,
idleTimeoutMillis: 360000 * 1000, idleTimeoutMillis: 360000 * 1000,
}, },
} as any; } as any
} }
if (process.env.NC_PUBLIC_URL) { if (process.env.NC_PUBLIC_URL) {
// config.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL; // config.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL;
config.envs['_noco'].publicUrl = process.env.NC_PUBLIC_URL; config.envs['_noco'].publicUrl = process.env.NC_PUBLIC_URL
config.publicUrl = process.env.NC_PUBLIC_URL; config.publicUrl = process.env.NC_PUBLIC_URL
} }
config.port = +(process?.env?.PORT ?? 8080); config.port = +(process?.env?.PORT ?? 8080)
// config.env = process.env?.NODE_ENV || 'dev'; // config.env = process.env?.NODE_ENV || 'dev';
// config.workingEnv = process.env?.NODE_ENV || 'dev'; // config.workingEnv = process.env?.NODE_ENV || 'dev';
config.env = '_noco'; config.env = '_noco'
config.workingEnv = '_noco'; config.workingEnv = '_noco'
config.toolDir = process.env.NC_TOOL_DIR || process.cwd(); config.toolDir = process.env.NC_TOOL_DIR || process.cwd()
config.projectType = config.projectType =
type || type ||
config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type ||
'rest'; 'rest'
return config; return config
} }
public static async metaDbCreateIfNotExist(args: NcConfig) { public static async metaDbCreateIfNotExist(args: NcConfig) {
@ -579,14 +582,14 @@ export default class NcConfigFactory implements NcConfig {
const metaSqlClient = SqlClientFactory.create({ const metaSqlClient = SqlClientFactory.create({
...args.meta.db, ...args.meta.db,
connection: args.meta.db, connection: args.meta.db,
}); })
await metaSqlClient.createDatabaseIfNotExists({ await metaSqlClient.createDatabaseIfNotExists({
database: args.meta.db?.connection?.filename, database: args.meta.db?.connection?.filename,
}); })
} else { } else {
const metaSqlClient = SqlClientFactory.create(args.meta.db); const metaSqlClient = SqlClientFactory.create(args.meta.db)
await metaSqlClient.createDatabaseIfNotExists(args.meta.db?.connection); await metaSqlClient.createDatabaseIfNotExists(args.meta.db?.connection)
await metaSqlClient.knex.destroy(); await metaSqlClient.knex.destroy()
} }
/* const dbPath = path.join(args.toolDir, 'xc.db') /* const dbPath = path.join(args.toolDir, 'xc.db')
@ -597,21 +600,21 @@ export default class NcConfigFactory implements NcConfig {
}*/ }*/
} }
public version = '0.6'; public version = '0.6'
public port: number; public port: number
public auth?: AuthConfig; public auth?: AuthConfig
public env: 'production' | 'dev' | 'test' | string; public env: 'production' | 'dev' | 'test' | string
public workingEnv: string; public workingEnv: string
public toolDir: string; public toolDir: string
public envs: { public envs: {
[p: string]: { db: DbConfig[]; api?: any; publicUrl?: string }; [p: string]: { db: DbConfig[]; api?: any; publicUrl?: string };
}; }
// public projectType: "rest" | "graphql" | "grpc"; // public projectType: "rest" | "graphql" | "grpc";
public queriesFolder: string | string[] = ''; public queriesFolder: string | string[] = ''
public seedsFolder: string | string[]; public seedsFolder: string | string[]
public title: string; public title: string
public publicUrl: string; public publicUrl: string
public projectType; public projectType
public meta = { public meta = {
db: { db: {
client: 'sqlite3', client: 'sqlite3',
@ -619,37 +622,38 @@ export default class NcConfigFactory implements NcConfig {
filename: 'noco.db', filename: 'noco.db',
}, },
}, },
}; }
public mailer: MailerConfig; public mailer: MailerConfig
public try = false; public try = false
public dashboardPath = '/dashboard'; public dashboardPath = '/dashboard'
constructor() { constructor() {
this.envs = { _noco: { db: [] } }; this.envs = { _noco: { db: [] } }
} }
public static jdbcToXcUrl() { public static jdbcToXcUrl() {
if (process.env.NC_DATABASE_URL_FILE || process.env.DATABASE_URL_FILE) { if (process.env.NC_DATABASE_URL_FILE || process.env.DATABASE_URL_FILE) {
const database_url = fs.readFileSync( const database_url = fs.readFileSync(
process.env.NC_DATABASE_URL_FILE || process.env.DATABASE_URL_FILE, process.env.NC_DATABASE_URL_FILE || process.env.DATABASE_URL_FILE,
'utf-8' 'utf-8',
); )
process.env.NC_DB = this.extractXcUrlFromJdbc(database_url); process.env.NC_DB = this.extractXcUrlFromJdbc(database_url)
} else if (process.env.NC_DATABASE_URL || process.env.DATABASE_URL) { } else if (process.env.NC_DATABASE_URL || process.env.DATABASE_URL) {
process.env.NC_DB = this.extractXcUrlFromJdbc( process.env.NC_DB = this.extractXcUrlFromJdbc(
process.env.NC_DATABASE_URL || process.env.DATABASE_URL process.env.NC_DATABASE_URL || process.env.DATABASE_URL,
); )
} }
} }
public static extractXcUrlFromJdbc(url: string, rtConfig = false) { public static extractXcUrlFromJdbc(url: string, rtConfig = false) {
// drop the jdbc prefix // drop the jdbc prefix
if (url.startsWith('jdbc:')) { if (url.startsWith('jdbc:')) {
url = url.substring(5); url = url.substring(5)
} }
const extraParams = []
const config = parseDbUrl(url); const config = parseDbUrl(url)
const parsedConfig: { const parsedConfig: {
driver?: string; driver?: string;
@ -658,69 +662,72 @@ export default class NcConfigFactory implements NcConfig {
database?: string; database?: string;
user?: string; user?: string;
password?: string; password?: string;
ssl?: string; ssl?: string | Record<string, any>;
} = {}; } = {}
for (const [key, value] of Object.entries(config)) { for (const [key, value] of Object.entries(config)) {
const fnd = knownQueryParams.find( const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key) (param) => param.parameter === key || param.aliases.includes(key),
); )
if (fnd) { if (fnd) {
parsedConfig[fnd.parameter] = value; parsedConfig[fnd.parameter] = value
} else { } else {
parsedConfig[key] = value; parsedConfig[key] = value
} }
} }
if (!parsedConfig?.port) if (!parsedConfig?.port)
parsedConfig.port = parsedConfig.port =
defaultClientPortMapping[ defaultClientPortMapping[
driverClientMapping[parsedConfig.driver] || parsedConfig.driver driverClientMapping[parsedConfig.driver] || parsedConfig.driver
]; ]
if (rtConfig) { const { driver, ...connectionConfig } = parsedConfig
const { driver, ...connectionConfig } = parsedConfig;
const client = driverClientMapping[driver] || driver; const client = driverClientMapping[driver] || driver
const avoidSSL = [ const avoidSSL = [
'localhost', 'localhost',
'127.0.0.1', '127.0.0.1',
'host.docker.internal', 'host.docker.internal',
'172.17.0.1', '172.17.0.1',
]; ]
if ( if (
client === 'pg' && client === 'pg' &&
!connectionConfig?.ssl && !connectionConfig?.ssl &&
!avoidSSL.includes(connectionConfig.host) !avoidSSL.includes(connectionConfig.host)
) { ) {
connectionConfig.ssl = 'true'; connectionConfig.ssl = {
rejectUnauthorized: false,
} }
parsedConfig['connection.ssl'] = 'rejectUnauthorized'
}
if (rtConfig) {
return { return {
client: client, client: client,
connection: { connection: {
...connectionConfig, ...connectionConfig,
}, },
} as any; } as any
} }
const { driver, host, port, database, user, password, ...extra } =
parsedConfig;
const extraParams = []; const { host, port, database, user, password, ...extra } =
parsedConfig
for (const [key, value] of Object.entries(extra)) { for (const [key, value] of Object.entries(extra)) {
extraParams.push(`${key}=${value}`); extraParams.push(`${key}=${value}`)
} }
const res = `${driverClientMapping[driver] || driver}://${host}${ const res = `${driverClientMapping[driver] || driver}://${host}${
port ? `:${port}` : '' port ? `:${port}` : ''
}?${user ? `u=${user}&` : ''}${password ? `p=${password}&` : ''}${ }?${user ? `u=${user}&` : ''}${password ? `p=${password}&` : ''}${
database ? `d=${database}&` : '' database ? `d=${database}&` : ''
}${extraParams.join('&')}`; }${extraParams.join('&')}`
return res; return res
} }
// public static initOneClickDeployment() { // public static initOneClickDeployment() {
@ -731,7 +738,7 @@ export default class NcConfigFactory implements NcConfig {
// } // }
} }
export { defaultConnectionConfig }; export { defaultConnectionConfig }
/** /**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd * @copyright Copyright (c) 2021, Xgene Cloud Ltd

Loading…
Cancel
Save