diff --git a/backend/config/sqlite-test-db.json b/backend/config/sqlite-test-db.json new file mode 100644 index 00000000..28061211 --- /dev/null +++ b/backend/config/sqlite-test-db.json @@ -0,0 +1,26 @@ +{ + "database": { + "engine": "knex-native", + "knex": { + "client": "sqlite3", + "connection": { + "filename": "/app/backend/config/mydb.sqlite" + }, + "pool": { + "min": 0, + "max": 1, + "createTimeoutMillis": 3000, + "acquireTimeoutMillis": 30000, + "idleTimeoutMillis": 30000, + "reapIntervalMillis": 1000, + "createRetryIntervalMillis": 100, + "propagateCreateError": false + }, + "migrations": { + "tableName": "migrations", + "stub": "src/backend/lib/migrate_template.js", + "directory": "src/backend/migrations" + } + } + } +} diff --git a/backend/db.js b/backend/db.js index 1f4d5b02..ce5338f0 100644 --- a/backend/db.js +++ b/backend/db.js @@ -4,19 +4,27 @@ if (!config.has('database')) { throw new Error('Database config does not exist! Please read the instructions: https://github.com/jc21/nginx-proxy-manager/blob/master/doc/INSTALL.md'); } -let data = { - client: config.database.engine, - connection: { - host: config.database.host, - user: config.database.user, - password: config.database.password, - database: config.database.name, - port: config.database.port - }, - migrations: { - tableName: 'migrations' - } -}; +function generateDbConfig() { + if (config.database.engine === 'knex-native') { + return config.database.knex; + } else + return { + client: config.database.engine, + connection: { + host: config.database.host, + user: config.database.user, + password: config.database.password, + database: config.database.name, + port: config.database.port + }, + migrations: { + tableName: 'migrations' + } + }; +} + + +let data = generateDbConfig(); if (typeof config.database.version !== 'undefined') { data.version = config.database.version; diff --git a/backend/migrations/20190227065017_settings.js b/backend/migrations/20190227065017_settings.js index dc1d6850..7dc9c192 100644 --- a/backend/migrations/20190227065017_settings.js +++ b/backend/migrations/20190227065017_settings.js @@ -22,22 +22,6 @@ exports.up = function (knex/*, Promise*/) { }) .then(() => { logger.info('[' + migrate_name + '] setting Table created'); - - // TODO: add settings - let settingModel = require('../models/setting'); - - return settingModel - .query() - .insert({ - id: 'default-site', - name: 'Default Site', - description: 'What to show when Nginx is hit with an unknown Host', - value: 'congratulations', - meta: {} - }); - }) - .then(() => { - logger.info('[' + migrate_name + '] Default settings added'); }); }; diff --git a/backend/models/access_list.js b/backend/models/access_list.js index 1af9e832..8e63a2ae 100644 --- a/backend/models/access_list.js +++ b/backend/models/access_list.js @@ -6,13 +6,14 @@ const Model = require('objection').Model; const User = require('./user'); const AccessListAuth = require('./access_list_auth'); const AccessListClient = require('./access_list_client'); +const now = require('./now_helper'); Model.knex(db); class AccessList extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for meta if (typeof this.meta === 'undefined') { @@ -21,7 +22,7 @@ class AccessList extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/models/access_list_auth.js b/backend/models/access_list_auth.js index 20436ccd..932371f3 100644 --- a/backend/models/access_list_auth.js +++ b/backend/models/access_list_auth.js @@ -3,13 +3,14 @@ const db = require('../db'); const Model = require('objection').Model; +const now = require('./now_helper'); Model.knex(db); class AccessListAuth extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for meta if (typeof this.meta === 'undefined') { @@ -18,7 +19,7 @@ class AccessListAuth extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/models/access_list_client.js b/backend/models/access_list_client.js index 0386395c..e257213a 100644 --- a/backend/models/access_list_client.js +++ b/backend/models/access_list_client.js @@ -3,13 +3,14 @@ const db = require('../db'); const Model = require('objection').Model; +const now = require('./now_helper'); Model.knex(db); class AccessListClient extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for meta if (typeof this.meta === 'undefined') { @@ -18,7 +19,7 @@ class AccessListClient extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/models/audit-log.js b/backend/models/audit-log.js index 3d473fc1..a3a318c8 100644 --- a/backend/models/audit-log.js +++ b/backend/models/audit-log.js @@ -4,13 +4,14 @@ const db = require('../db'); const Model = require('objection').Model; const User = require('./user'); +const now = require('./now_helper'); Model.knex(db); class AuditLog extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for meta if (typeof this.meta === 'undefined') { @@ -19,7 +20,7 @@ class AuditLog extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/models/auth.js b/backend/models/auth.js index 9db62f5f..5ba5f380 100644 --- a/backend/models/auth.js +++ b/backend/models/auth.js @@ -5,6 +5,7 @@ const bcrypt = require('bcrypt'); const db = require('../db'); const Model = require('objection').Model; const User = require('./user'); +const now = require('./now_helper'); Model.knex(db); @@ -24,8 +25,8 @@ function encryptPassword () { class Auth extends Model { $beforeInsert (queryContext) { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for meta if (typeof this.meta === 'undefined') { @@ -36,7 +37,7 @@ class Auth extends Model { } $beforeUpdate (queryContext) { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); return encryptPassword.apply(this, queryContext); } diff --git a/backend/models/certificate.js b/backend/models/certificate.js index 2dcb7505..6084a995 100644 --- a/backend/models/certificate.js +++ b/backend/models/certificate.js @@ -4,17 +4,18 @@ const db = require('../db'); const Model = require('objection').Model; const User = require('./user'); +const now = require('./now_helper'); Model.knex(db); class Certificate extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for expires_on if (typeof this.expires_on === 'undefined') { - this.expires_on = Model.raw('NOW()'); + this.expires_on = now(); } // Default for domain_names @@ -31,7 +32,7 @@ class Certificate extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); // Sort domain_names if (typeof this.domain_names !== 'undefined') { diff --git a/backend/models/dead_host.js b/backend/models/dead_host.js index dc1109c8..6de42a33 100644 --- a/backend/models/dead_host.js +++ b/backend/models/dead_host.js @@ -5,13 +5,14 @@ const db = require('../db'); const Model = require('objection').Model; const User = require('./user'); const Certificate = require('./certificate'); +const now = require('./now_helper'); Model.knex(db); class DeadHost extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for domain_names if (typeof this.domain_names === 'undefined') { @@ -27,7 +28,7 @@ class DeadHost extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); // Sort domain_names if (typeof this.domain_names !== 'undefined') { diff --git a/backend/models/now_helper.js b/backend/models/now_helper.js new file mode 100644 index 00000000..a1258a86 --- /dev/null +++ b/backend/models/now_helper.js @@ -0,0 +1,13 @@ +const db = require('../db'); +const config = require('config'); +const Model = require('objection').Model; + +Model.knex(db); + +module.exports = function () { + if (config.database.knex && config.database.knex.client === 'sqlite3') { + return Model.raw('date(\'now\')'); + } else { + return Model.raw('NOW()'); + } +}; diff --git a/backend/models/proxy_host.js b/backend/models/proxy_host.js index a2c9beee..a7583088 100644 --- a/backend/models/proxy_host.js +++ b/backend/models/proxy_host.js @@ -6,13 +6,14 @@ const Model = require('objection').Model; const User = require('./user'); const AccessList = require('./access_list'); const Certificate = require('./certificate'); +const now = require('./now_helper'); Model.knex(db); class ProxyHost extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for domain_names if (typeof this.domain_names === 'undefined') { @@ -28,7 +29,7 @@ class ProxyHost extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); // Sort domain_names if (typeof this.domain_names !== 'undefined') { diff --git a/backend/models/redirection_host.js b/backend/models/redirection_host.js index 029b0c08..dd149b76 100644 --- a/backend/models/redirection_host.js +++ b/backend/models/redirection_host.js @@ -5,13 +5,14 @@ const db = require('../db'); const Model = require('objection').Model; const User = require('./user'); const Certificate = require('./certificate'); +const now = require('./now_helper'); Model.knex(db); class RedirectionHost extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for domain_names if (typeof this.domain_names === 'undefined') { @@ -27,7 +28,7 @@ class RedirectionHost extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); // Sort domain_names if (typeof this.domain_names !== 'undefined') { diff --git a/backend/models/stream.js b/backend/models/stream.js index 7b6c8a4b..ed65de0f 100644 --- a/backend/models/stream.js +++ b/backend/models/stream.js @@ -4,13 +4,14 @@ const db = require('../db'); const Model = require('objection').Model; const User = require('./user'); +const now = require('./now_helper'); Model.knex(db); class Stream extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for meta if (typeof this.meta === 'undefined') { @@ -19,7 +20,7 @@ class Stream extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/models/user.js b/backend/models/user.js index 8d1ef123..c76f7dbf 100644 --- a/backend/models/user.js +++ b/backend/models/user.js @@ -4,13 +4,14 @@ const db = require('../db'); const Model = require('objection').Model; const UserPermission = require('./user_permission'); +const now = require('./now_helper'); Model.knex(db); class User extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); // Default for roles if (typeof this.roles === 'undefined') { @@ -19,7 +20,7 @@ class User extends Model { } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/models/user_permission.js b/backend/models/user_permission.js index 836a23f5..bb87d5dc 100644 --- a/backend/models/user_permission.js +++ b/backend/models/user_permission.js @@ -3,17 +3,18 @@ const db = require('../db'); const Model = require('objection').Model; +const now = require('./now_helper'); Model.knex(db); class UserPermission extends Model { $beforeInsert () { - this.created_on = Model.raw('NOW()'); - this.modified_on = Model.raw('NOW()'); + this.created_on = now(); + this.modified_on = now(); } $beforeUpdate () { - this.modified_on = Model.raw('NOW()'); + this.modified_on = now(); } static get name () { diff --git a/backend/package.json b/backend/package.json index 1df362ee..43ac13f9 100644 --- a/backend/package.json +++ b/backend/package.json @@ -26,8 +26,10 @@ "nodemon": "^2.0.2", "objection": "^2.1.3", "path": "^0.12.7", + "pg": "^7.12.1", "restler": "^3.4.0", "signale": "^1.4.0", + "sqlite3": "^4.1.1", "temp-write": "^4.0.0", "unix-timestamp": "^0.2.0" }, diff --git a/backend/setup.js b/backend/setup.js index a3a6b175..db618add 100644 --- a/backend/setup.js +++ b/backend/setup.js @@ -5,111 +5,145 @@ const logger = require('./logger').setup; const userModel = require('./models/user'); const userPermissionModel = require('./models/user_permission'); const authModel = require('./models/auth'); +const settingModel = require('./models/setting'); const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG; +function setupJwt(resolve, reject) { + // Now go and check if the jwt gpg keys have been created and if not, create them + if (!config.has('jwt') || !config.has('jwt.key') || !config.has('jwt.pub')) { + logger.info('Creating a new JWT key pair...'); + + // jwt keys are not configured properly + const filename = config.util.getEnv('NODE_CONFIG_DIR') + '/' + (config.util.getEnv('NODE_ENV') || 'default') + '.json'; + let config_data = {}; + + try { + config_data = require(filename); + } catch (err) { + // do nothing + if (debug_mode) { + logger.debug(filename + ' config file could not be required'); + } + } + + // Now create the keys and save them in the config. + let key = new NodeRSA({b: 2048}); + key.generateKeyPair(); + + config_data.jwt = { + key: key.exportKey('private').toString(), + pub: key.exportKey('public').toString() + }; + + // Write config + fs.writeFile(filename, JSON.stringify(config_data, null, 2), (err) => { + if (err) { + logger.error('Could not write JWT key pair to config file: ' + filename); + reject(err); + } else { + logger.info('Wrote JWT key pair to config file: ' + filename); + + logger.warn('Restarting interface to apply new configuration'); + process.exit(0); + } + }); + + } else { + // JWT key pair exists + if (debug_mode) { + logger.debug('JWT Keypair already exists'); + } + + resolve(); + } +} + +function setupDefaultUser() { + (userModel + .query() + .select(userModel.raw('COUNT(`id`) as `count`')) + .where('is_deleted', 0) + .first() + ).then( (row) => { + if (!row.count) { + // Create a new user and set password + logger.info('Creating a new user: admin@example.com with password: changeme'); + + let data = { + is_deleted: 0, + email: 'admin@example.com', + name: 'Administrator', + nickname: 'Admin', + avatar: '', + roles: ['admin'] + }; + + return userModel + .query() + .insertAndFetch(data) + .then( (user) => { + return authModel + .query() + .insert({ + user_id: user.id, + type: 'password', + secret: 'changeme', + meta: {} + }) + .then(() => { + return userPermissionModel + .query() + .insert({ + user_id: user.id, + visibility: 'all', + proxy_hosts: 'manage', + redirection_hosts: 'manage', + dead_hosts: 'manage', + streams: 'manage', + access_lists: 'manage', + certificates: 'manage' + }); + }); + }) + .then(() => { + logger.info('Initial admin setup completed'); + }); + } else if (debug_mode) { + logger.debug('Admin user setup not required'); + } + }); +} + +function setupDefaultSettings() { + return settingModel + .query() + .select(userModel.raw('COUNT(`id`) as `count`')) + .first() + .then( (row) => { + if (!row.count) { + settingModel + .query() + .insert({ + id: 'default-site', + name: 'Default Site', + description: 'What to show when Nginx is hit with an unknown Host', + value: 'congratulations', + meta: {} + }).then(() => { + logger.info('Default settings added'); + }); + } if (debug_mode) { + logger.debug('Default setting setup not required'); + } + }); +} + module.exports = function () { return new Promise((resolve, reject) => { - // Now go and check if the jwt gpg keys have been created and if not, create them - if (!config.has('jwt') || !config.has('jwt.key') || !config.has('jwt.pub')) { - logger.info('Creating a new JWT key pair...'); - - // jwt keys are not configured properly - const filename = config.util.getEnv('NODE_CONFIG_DIR') + '/' + (config.util.getEnv('NODE_ENV') || 'default') + '.json'; - let config_data = {}; - - try { - config_data = require(filename); - } catch (err) { - // do nothing - if (debug_mode) { - logger.debug(filename + ' config file could not be required'); - } - } - - // Now create the keys and save them in the config. - let key = new NodeRSA({b: 2048}); - key.generateKeyPair(); - - config_data.jwt = { - key: key.exportKey('private').toString(), - pub: key.exportKey('public').toString() - }; - - // Write config - fs.writeFile(filename, JSON.stringify(config_data, null, 2), (err) => { - if (err) { - logger.error('Could not write JWT key pair to config file: ' + filename); - reject(err); - } else { - logger.info('Wrote JWT key pair to config file: ' + filename); - - logger.warn('Restarting interface to apply new configuration'); - process.exit(0); - } - }); - - } else { - // JWT key pair exists - if (debug_mode) { - logger.debug('JWT Keypair already exists'); - } - - resolve(); - } - }) - .then(() => { - return userModel - .query() - .select(userModel.raw('COUNT(`id`) as `count`')) - .where('is_deleted', 0) - .first(); - }) - .then((row) => { - if (!row.count) { - // Create a new user and set password - logger.info('Creating a new user: admin@example.com with password: changeme'); - - let data = { - is_deleted: 0, - email: 'admin@example.com', - name: 'Administrator', - nickname: 'Admin', - avatar: '', - roles: ['admin'] - }; - - return userModel - .query() - .insertAndFetch(data) - .then((user) => { - return authModel - .query() - .insert({ - user_id: user.id, - type: 'password', - secret: 'changeme', - meta: {} - }) - .then(() => { - return userPermissionModel - .query() - .insert({ - user_id: user.id, - visibility: 'all', - proxy_hosts: 'manage', - redirection_hosts: 'manage', - dead_hosts: 'manage', - streams: 'manage', - access_lists: 'manage', - certificates: 'manage' - }); - }); - }) - .then(() => { - logger.info('Initial setup completed'); - }); - } else if (debug_mode) { - logger.debug('Admin user setup not required'); - } - }); + return setupJwt(resolve, reject); + }).then(() => { + return setupDefaultUser(); + }).then(() => { + return setupDefaultSettings(); + }); }; diff --git a/backend/yarn.lock b/backend/yarn.lock index c423dce5..e12c0d77 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -325,6 +325,11 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== + busboy@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b" @@ -2198,6 +2203,11 @@ mysql@^2.18.1: safe-buffer "5.1.2" sqlstring "2.3.1" +nan@^2.12.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -2260,6 +2270,22 @@ node-pre-gyp@0.14.0: semver "^5.3.0" tar "^4.4.2" +node-pre-gyp@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054" + integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-rsa@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/node-rsa/-/node-rsa-1.0.8.tgz#29a4517380f3272cd2073ff4d4c1ca44127ea4ad" @@ -2514,6 +2540,11 @@ package-json@^4.0.0: registry-url "^3.0.3" semver "^5.1.0" +packet-reader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2603,11 +2634,63 @@ path@^0.12.7: process "^0.11.1" util "^0.10.3" +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= + pg-connection-string@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.1.0.tgz#e07258f280476540b24818ebb5dca29e101ca502" integrity sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg== +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-packet-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz#e45c3ae678b901a2873af1e17b92d787962ef914" + integrity sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg== + +pg-pool@^2.0.10: + version "2.0.10" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.10.tgz#842ee23b04e86824ce9d786430f8365082d81c4a" + integrity sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg== + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@^7.12.1: + version "7.18.2" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.18.2.tgz#4e219f05a00aff4db6aab1ba02f28ffa4513b0bb" + integrity sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA== + dependencies: + buffer-writer "2.0.0" + packet-reader "1.0.0" + pg-connection-string "0.1.3" + pg-packet-stream "^1.1.0" + pg-pool "^2.0.10" + pg-types "^2.1.0" + pgpass "1.x" + semver "4.3.2" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + dependencies: + split "^1.0.0" + picomatch@^2.0.4, picomatch@^2.0.7: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -2631,6 +2714,28 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= + +postgres-date@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.5.tgz#710b27de5f27d550f6e80b5d34f7ba189213c2ee" + integrity sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -2922,6 +3027,11 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= + semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -3074,11 +3184,26 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +split@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sqlite3@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-4.2.0.tgz#49026d665e9fc4f922e56fb9711ba5b4c85c4901" + integrity sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg== + dependencies: + nan "^2.12.1" + node-pre-gyp "^0.11.0" + sqlstring@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40" @@ -3221,7 +3346,7 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tar@^4.4.2: +tar@^4, tar@^4.4.2: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -3267,7 +3392,7 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -through@^2.3.6: +through@2, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -3577,6 +3702,11 @@ xmlbuilder@>=0.4.2: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.0.tgz#4c4c9109180937baeb839978b590250be09a4aef" integrity sha512-xae5hmPQnmSFhpiuV3NGXq+FWGOvWy/rIzxVLnRtSSABbPZWltTQCe6WlHDpCq5pGvnGwNsWnS1FdkW7Tx9FNQ== +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"