feat(database): support read ssl file in database config (#2689)
This commit is contained in:
		
							parent
							
								
									10e46b21f0
								
							
						
					
					
						commit
						de849b267c
					
				@ -6,7 +6,9 @@
 | 
				
			|||||||
  "main": "./lib/index.js",
 | 
					  "main": "./lib/index.js",
 | 
				
			||||||
  "types": "./lib/index.d.ts",
 | 
					  "types": "./lib/index.d.ts",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@nocobase/preset-nocobase": "0.14.0-alpha.3"
 | 
					    "@nocobase/preset-nocobase": "0.14.0-alpha.3",
 | 
				
			||||||
 | 
					    "@nocobase/server": "0.14.0-alpha.3",
 | 
				
			||||||
 | 
					    "@nocobase/database": "0.14.0-alpha.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@nocobase/client": "0.14.0-alpha.3"
 | 
					    "@nocobase/client": "0.14.0-alpha.3"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,52 +1,5 @@
 | 
				
			|||||||
import { IDatabaseOptions } from '@nocobase/database';
 | 
					import { parseDatabaseOptionsFromEnv } from '@nocobase/database';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getEnvValue(key, defaultValue?) {
 | 
					export async function parseDatabaseOptions() {
 | 
				
			||||||
  return process.env[key] || defaultValue;
 | 
					  return await parseDatabaseOptionsFromEnv();
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function extractSSLOptionsFromEnv() {
 | 
					 | 
				
			||||||
  const sslOptions = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const ca = getEnvValue('DB_DIALECT_OPTIONS_SSL_CA');
 | 
					 | 
				
			||||||
  const key = getEnvValue('DB_DIALECT_OPTIONS_SSL_KEY');
 | 
					 | 
				
			||||||
  const cert = getEnvValue('DB_DIALECT_OPTIONS_SSL_CERT');
 | 
					 | 
				
			||||||
  const rejectUnauthorized = getEnvValue('DB_DIALECT_OPTIONS_SSL_REJECT_UNAUTHORIZED');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (ca) sslOptions['ca'] = ca;
 | 
					 | 
				
			||||||
  if (key) sslOptions['key'] = key;
 | 
					 | 
				
			||||||
  if (cert) sslOptions['cert'] = cert;
 | 
					 | 
				
			||||||
  if (rejectUnauthorized) sslOptions['rejectUnauthorized'] = rejectUnauthorized === 'true';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return sslOptions;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const databaseOptions = {
 | 
					 | 
				
			||||||
  logging: process.env.DB_LOGGING == 'on' ? customLogger : false,
 | 
					 | 
				
			||||||
  dialect: process.env.DB_DIALECT as any,
 | 
					 | 
				
			||||||
  storage: process.env.DB_STORAGE,
 | 
					 | 
				
			||||||
  username: process.env.DB_USER,
 | 
					 | 
				
			||||||
  password: process.env.DB_PASSWORD,
 | 
					 | 
				
			||||||
  database: process.env.DB_DATABASE,
 | 
					 | 
				
			||||||
  host: process.env.DB_HOST,
 | 
					 | 
				
			||||||
  port: process.env.DB_PORT as any,
 | 
					 | 
				
			||||||
  timezone: process.env.DB_TIMEZONE,
 | 
					 | 
				
			||||||
  tablePrefix: process.env.DB_TABLE_PREFIX,
 | 
					 | 
				
			||||||
  schema: process.env.DB_SCHEMA,
 | 
					 | 
				
			||||||
  underscored: process.env.DB_UNDERSCORED === 'true',
 | 
					 | 
				
			||||||
} as IDatabaseOptions;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const sslOptions = extractSSLOptionsFromEnv();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (Object.keys(sslOptions).length) {
 | 
					 | 
				
			||||||
  databaseOptions.dialectOptions = databaseOptions.dialectOptions || {};
 | 
					 | 
				
			||||||
  databaseOptions.dialectOptions['ssl'] = sslOptions;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default databaseOptions;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function customLogger(queryString, queryObject) {
 | 
					 | 
				
			||||||
  console.log(queryString); // outputs a string
 | 
					 | 
				
			||||||
  if (queryObject?.bind) {
 | 
					 | 
				
			||||||
    console.log(queryObject.bind); // outputs an array
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,15 @@
 | 
				
			|||||||
import cache from './cache';
 | 
					import cache from './cache';
 | 
				
			||||||
import database from './database';
 | 
					import { parseDatabaseOptions } from './database';
 | 
				
			||||||
import logger from './logger';
 | 
					import logger from './logger';
 | 
				
			||||||
import plugins from './plugins';
 | 
					import plugins from './plugins';
 | 
				
			||||||
import resourcer from './resourcer';
 | 
					import resourcer from './resourcer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export async function getConfig() {
 | 
				
			||||||
  database,
 | 
					  return {
 | 
				
			||||||
  resourcer,
 | 
					    database: await parseDatabaseOptions(),
 | 
				
			||||||
  plugins,
 | 
					    resourcer,
 | 
				
			||||||
  cache,
 | 
					    plugins,
 | 
				
			||||||
  logger,
 | 
					    cache,
 | 
				
			||||||
};
 | 
					    logger,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,12 @@
 | 
				
			|||||||
import { Gateway } from '@nocobase/server';
 | 
					import { Gateway } from '@nocobase/server';
 | 
				
			||||||
import config from './config';
 | 
					import { getConfig } from './config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Gateway.getInstance().run({
 | 
					getConfig()
 | 
				
			||||||
  mainAppOptions: config,
 | 
					  .then((config) => {
 | 
				
			||||||
});
 | 
					    return Gateway.getInstance().run({
 | 
				
			||||||
 | 
					      mainAppOptions: config,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  .catch((e) => {
 | 
				
			||||||
 | 
					    console.error(e);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										92
									
								
								packages/core/database/src/helpers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								packages/core/database/src/helpers.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					import { IDatabaseOptions } from './database';
 | 
				
			||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getEnvValue(key, defaultValue?) {
 | 
				
			||||||
 | 
					  return process.env[key] || defaultValue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function isFilePath(value) {
 | 
				
			||||||
 | 
					  return fs.promises
 | 
				
			||||||
 | 
					    .stat(value)
 | 
				
			||||||
 | 
					    .then((stats) => stats.isFile())
 | 
				
			||||||
 | 
					    .catch((err) => {
 | 
				
			||||||
 | 
					      if (err.code === 'ENOENT') {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      throw err;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getValueOrFileContent(envVarName) {
 | 
				
			||||||
 | 
					  const value = getEnvValue(envVarName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!value) {
 | 
				
			||||||
 | 
					    return Promise.resolve(null);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return isFilePath(value)
 | 
				
			||||||
 | 
					    .then((isFile) => {
 | 
				
			||||||
 | 
					      if (isFile) {
 | 
				
			||||||
 | 
					        return fs.promises.readFile(value, 'utf8');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return value;
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .catch((error) => {
 | 
				
			||||||
 | 
					      console.error(`Failed to read file content for environment variable ${envVarName}.`);
 | 
				
			||||||
 | 
					      throw error;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function extractSSLOptionsFromEnv() {
 | 
				
			||||||
 | 
					  return Promise.all([
 | 
				
			||||||
 | 
					    getValueOrFileContent('DB_DIALECT_OPTIONS_SSL_MODE'),
 | 
				
			||||||
 | 
					    getValueOrFileContent('DB_DIALECT_OPTIONS_SSL_CA'),
 | 
				
			||||||
 | 
					    getValueOrFileContent('DB_DIALECT_OPTIONS_SSL_KEY'),
 | 
				
			||||||
 | 
					    getValueOrFileContent('DB_DIALECT_OPTIONS_SSL_CERT'),
 | 
				
			||||||
 | 
					    getValueOrFileContent('DB_DIALECT_OPTIONS_SSL_REJECT_UNAUTHORIZED'),
 | 
				
			||||||
 | 
					  ]).then(([mode, ca, key, cert, rejectUnauthorized]) => {
 | 
				
			||||||
 | 
					    const sslOptions = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mode) sslOptions['mode'] = mode;
 | 
				
			||||||
 | 
					    if (ca) sslOptions['ca'] = ca;
 | 
				
			||||||
 | 
					    if (key) sslOptions['key'] = key;
 | 
				
			||||||
 | 
					    if (cert) sslOptions['cert'] = cert;
 | 
				
			||||||
 | 
					    if (rejectUnauthorized) sslOptions['rejectUnauthorized'] = rejectUnauthorized === 'true';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return sslOptions;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function parseDatabaseOptionsFromEnv(): Promise<IDatabaseOptions> {
 | 
				
			||||||
 | 
					  const databaseOptions: IDatabaseOptions = {
 | 
				
			||||||
 | 
					    logging: process.env.DB_LOGGING == 'on' ? customLogger : false,
 | 
				
			||||||
 | 
					    dialect: process.env.DB_DIALECT as any,
 | 
				
			||||||
 | 
					    storage: process.env.DB_STORAGE,
 | 
				
			||||||
 | 
					    username: process.env.DB_USER,
 | 
				
			||||||
 | 
					    password: process.env.DB_PASSWORD,
 | 
				
			||||||
 | 
					    database: process.env.DB_DATABASE,
 | 
				
			||||||
 | 
					    host: process.env.DB_HOST,
 | 
				
			||||||
 | 
					    port: process.env.DB_PORT as any,
 | 
				
			||||||
 | 
					    timezone: process.env.DB_TIMEZONE,
 | 
				
			||||||
 | 
					    tablePrefix: process.env.DB_TABLE_PREFIX,
 | 
				
			||||||
 | 
					    schema: process.env.DB_SCHEMA,
 | 
				
			||||||
 | 
					    underscored: process.env.DB_UNDERSCORED === 'true',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const sslOptions = await extractSSLOptionsFromEnv();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (Object.keys(sslOptions).length) {
 | 
				
			||||||
 | 
					    databaseOptions.dialectOptions = databaseOptions.dialectOptions || {};
 | 
				
			||||||
 | 
					    databaseOptions.dialectOptions['ssl'] = sslOptions;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return databaseOptions;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function customLogger(queryString, queryObject) {
 | 
				
			||||||
 | 
					  console.log(queryString);
 | 
				
			||||||
 | 
					  if (queryObject?.bind) {
 | 
				
			||||||
 | 
					    console.log(queryObject.bind);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -41,3 +41,4 @@ export { snakeCase } from './utils';
 | 
				
			|||||||
export * from './value-parsers';
 | 
					export * from './value-parsers';
 | 
				
			||||||
export * from './view-collection';
 | 
					export * from './view-collection';
 | 
				
			||||||
export * from './view/view-inference';
 | 
					export * from './view/view-inference';
 | 
				
			||||||
 | 
					export * from './helpers';
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user