Skip to content

Commit

Permalink
feat: trust SSL certificate by default to ease users onboarding (#472)
Browse files Browse the repository at this point in the history
  • Loading branch information
rap2hpoutre committed Sep 21, 2020
1 parent c351ab3 commit 2cf7e6b
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 24 deletions.
30 changes: 7 additions & 23 deletions services/database.js
Expand Up @@ -57,7 +57,6 @@ function Database() {

this.connect = (options) => {
const isSSL = options.dbSSL || options.ssl;
let connection;
const databaseDialect = getDialect(options.dbConnectionUrl, options.dbDialect);

if (databaseDialect === 'mongodb') {
Expand All @@ -66,30 +65,15 @@ function Database() {

const connectionOptionsSequelize = { logging: false };

// NOTICE: mysql2 does not accepts unwanted options anymore.
// See: https://github.com/sidorares/node-mysql2/pull/895
if (databaseDialect === 'mysql') {
// NOTICE: Add SSL options only if the user selected SSL mode.
if (isSSL) {
// TODO: Lumber should accept certificate file (CRT) to work with SSL.
// Since it requires to review onboarding, it is not implemented yet.
// See: https://www.npmjs.com/package/mysql#ssl-options
connectionOptionsSequelize.dialectOptions = {
ssl: { rejectUnauthorized: isSSL },
};
}
} else if (databaseDialect === 'mssql') {
connectionOptionsSequelize.dialectOptions = {
options: {
encrypt: isSSL,
},
};
} else {
connectionOptionsSequelize.dialectOptions = {
ssl: isSSL,
};
if (databaseDialect === 'mssql') {
connectionOptionsSequelize.dialectOptions = { options: { encrypt: isSSL } };
} else if (isSSL) {
// Add SSL options only if the user selected SSL mode.
// SSL Cerificate is always trusted during `lumber generate` command to ease their onboarding.
connectionOptionsSequelize.dialectOptions = { ssl: { rejectUnauthorized: false } };
}

let connection;
if (options.dbConnectionUrl) {
connection = new Sequelize(options.dbConnectionUrl, connectionOptionsSequelize);
} else {
Expand Down
2 changes: 2 additions & 0 deletions templates/app/env.hbs
Expand Up @@ -7,6 +7,8 @@ DATABASE_URL={{ databaseUrl }}
DATABASE_SCHEMA={{ dbSchema }}
{{/if}}
DATABASE_SSL={{ ssl }}
# This should be removed in production environment.
DATABASE_REJECT_UNAUTHORIZED=false

FOREST_AUTH_SECRET={{ forestAuthSecret }}
FOREST_ENV_SECRET={{ forestEnvSecret }}
6 changes: 5 additions & 1 deletion templates/app/models/index.hbs
Expand Up @@ -58,7 +58,11 @@ if (process.env.DATABASE_SSL && JSON.parse(process.env.DATABASE_SSL.toLowerCase(
{{else if isMSSQL}}
databaseOptions.dialectOptions.options = { encrypt: true };
{{else}}
databaseOptions.dialectOptions.ssl = true;
if (process.env.DATABASE_REJECT_UNAUTHORIZED === false) {
databaseOptions.dialectOptions.ssl = { rejectUnauthorized: false };
} else {
databaseOptions.dialectOptions.ssl = true;
}
{{/if}}
}

Expand Down
12 changes: 12 additions & 0 deletions test-expected/sequelize/dumper-output/env.expected
@@ -0,0 +1,12 @@
APPLICATION_PORT=1654

CORS_ORIGINS=

DATABASE_URL=postgres://localhost:27017
DATABASE_SCHEMA=public
DATABASE_SSL=false
# This should be removed in production environment.
DATABASE_REJECT_UNAUTHORIZED=false

FOREST_AUTH_SECRET=
FOREST_ENV_SECRET=
50 changes: 50 additions & 0 deletions test-expected/sequelize/dumper-output/index.expected.js
@@ -0,0 +1,50 @@
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');

if (!process.env.DATABASE_URL) {
console.error('Cannot connect to the database. Please declare the DATABASE_URL environment variable with the correct database connection string.');
process.exit();
}

const databaseOptions = {
logging: process.env.NODE_ENV === 'development' ? console.log : false,
pool: { maxConnections: 10, minConnections: 1 },
dialectOptions: {},
};

if (process.env.DATABASE_SSL && JSON.parse(process.env.DATABASE_SSL.toLowerCase())) {
if (process.env.DATABASE_REJECT_UNAUTHORIZED === false) {
databaseOptions.dialectOptions.ssl = { rejectUnauthorized: false };
} else {
databaseOptions.dialectOptions.ssl = true;
}
}

const sequelize = new Sequelize(process.env.DATABASE_URL, databaseOptions);
const db = {};

fs
.readdirSync(__dirname)
.filter((file) => {
return (file.indexOf('.') !== 0) && (file !== 'index.js');
})
.forEach((file) => {
try {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
} catch (error) {
console.error('Model creation error: ' + error);
}
});

Object.keys(db).forEach((modelName) => {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
22 changes: 22 additions & 0 deletions test/services/dumper/dumper-sequelize.test.js
Expand Up @@ -84,4 +84,26 @@ describe('services > dumper > sequelize', () => {
expect(generatedFile).toStrictEqual(expectedFile);
cleanOutput();
});

it('should generate the model index file', async () => {
expect.assertions(1);
const dumper = await getDumper();
await dumper.dump(simpleModel);
const generatedFile = fs.readFileSync('./test-output/sequelize/models/index.js', 'utf8');
const expectedFile = fs.readFileSync('./test-expected/sequelize/dumper-output/index.expected.js', 'utf-8');

expect(generatedFile).toStrictEqual(expectedFile);
cleanOutput();
});

it('should generate the env file', async () => {
expect.assertions(1);
const dumper = await getDumper();
await dumper.dump(simpleModel);
const generatedFile = fs.readFileSync('./test-output/sequelize/.env', 'utf8');
const expectedFile = fs.readFileSync('./test-expected/sequelize/dumper-output/env.expected', 'utf-8');

expect(generatedFile).toStrictEqual(expectedFile);
cleanOutput();
});
});

0 comments on commit 2cf7e6b

Please sign in to comment.