From f3f46f7b5b83f060beaf933ea3634c2e75feefc0 Mon Sep 17 00:00:00 2001 From: Josh Harvey Date: Sun, 7 May 2017 15:29:18 +0300 Subject: [PATCH] improve config saving; fix pairing bug --- lib/admin/pairing.js | 6 ++--- lib/config-validate.js | 6 ++++- lib/pairing.js | 26 +++++++++++++++++++-- lib/settings-loader.js | 52 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/lib/admin/pairing.js b/lib/admin/pairing.js index 4ea8601c..854505de 100644 --- a/lib/admin/pairing.js +++ b/lib/admin/pairing.js @@ -6,14 +6,12 @@ const baseX = require('base-x') const options = require('../options') const db = require('../db') +const pairing = require('../pairing') const ALPHA_BASE = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:' const bsAlpha = baseX(ALPHA_BASE) -function unpair (deviceId) { - const sql = 'delete from devices where device_id=$1' - return db.none(sql, [deviceId]) -} +const unpair = pairing.unpair function totem (hostname, name) { const caPath = options.caPath diff --git a/lib/config-validate.js b/lib/config-validate.js index 952e7e9e..b0c66578 100644 --- a/lib/config-validate.js +++ b/lib/config-validate.js @@ -3,6 +3,7 @@ const _ = require('lodash/fp') const configManager = require('./config-manager') const machines = require('./admin/machines') const schema = require('../lamassu-schema.json') +const logger = require('./logger') function allScopes (cryptoScopes, machineScopes) { const scopes = [] @@ -47,7 +48,9 @@ function satisfiesRequire (config, cryptos, machineList, field, refFields) { const isBlank = _.isNil(configManager.scopedValue(scope[0], scope[1], fieldCode, config)) const isRequired = refFields.length === 0 || isEnabled() - return isRequired ? !isBlank : true + const isValid = isRequired ? !isBlank : true + + return isValid }) } @@ -148,6 +151,7 @@ function validate (config) { .then(() => validateRequires(config)) .then(arr => { if (arr.length === 0) return config + logger.error('Invalid configuration: %j', arr) throw new Error('Invalid configuration') }) } diff --git a/lib/pairing.js b/lib/pairing.js index df8e79e2..cc8c5e33 100644 --- a/lib/pairing.js +++ b/lib/pairing.js @@ -4,6 +4,7 @@ const readFile = pify(fs.readFile) const db = require('./db') const options = require('./options') const logger = require('./logger') +const settingsLoader = require('./settings-loader') function pullToken (token) { const sql = `delete from pairing_tokens @@ -12,6 +13,26 @@ function pullToken (token) { return db.one(sql, [token]) } +function configureNewDevice (deviceId) { + const scope = {crypto: 'global', machine: deviceId} + const newFields = [settingsLoader.configAddField(scope, 'cashOutEnabled', false)] + + return settingsLoader.modifyConfig(newFields) +} + +function removeDeviceConfig (deviceId) { + const scope = {crypto: 'global', machine: deviceId} + const newFields = [settingsLoader.configDeleteField(scope, 'cashOutEnabled', false)] + + return settingsLoader.modifyConfig(newFields) +} + +function unpair (deviceId) { + const sql = 'delete from devices where device_id=$1' + return db.none(sql, [deviceId]) + .then(() => removeDeviceConfig(deviceId)) +} + function pair (token, deviceId) { return pullToken(token) .then(r => { @@ -21,7 +42,8 @@ function pair (token, deviceId) { on conflict (device_id) do update set name=$2, paired=TRUE, display=TRUE` - return db.none(insertSql, [deviceId, r.name]) + return configureNewDevice(deviceId) + .then(() => db.none(insertSql, [deviceId, r.name])) .then(() => true) }) .catch(err => { @@ -47,4 +69,4 @@ function isPaired (deviceId) { .then(row => row && row.device_id === deviceId) } -module.exports = {pair, authorizeCaDownload, isPaired} +module.exports = {pair, unpair, authorizeCaDownload, isPaired} diff --git a/lib/settings-loader.js b/lib/settings-loader.js index da8d9b55..1c87edf0 100644 --- a/lib/settings-loader.js +++ b/lib/settings-loader.js @@ -5,6 +5,7 @@ const _ = require('lodash/fp') const argv = require('minimist')(process.argv.slice(2)) const pify = require('pify') +const pgp = require('pg-promise')() const db = require('./db') const configValidate = require('./config-validate') @@ -39,7 +40,7 @@ function isEquivalentField (a, b) { // b overrides a function mergeValues (a, b) { - return _.unionWith(isEquivalentField, b, a) + return _.reject(r => _.isNil(r.fieldValue), _.unionWith(isEquivalentField, b, a)) } function load (versionId) { @@ -125,6 +126,50 @@ function save (config) { .catch(() => db.none(sql, ['config', {config}, false])) } +function configAddField (scope, fieldCode, value) { + return { + fieldLocator: { + fieldScope: { + crypto: scope.crypto, + machine: scope.machine + }, + code: fieldCode + }, + fieldValue: {value} + } +} + +function configDeleteField (scope, fieldCode) { + return { + fieldLocator: { + fieldScope: { + crypto: scope.crypto, + machine: scope.machine + }, + code: fieldCode + }, + fieldValue: null + } +} + +function modifyConfig (newFields) { + const TransactionMode = pgp.txMode.TransactionMode + const isolationLevel = pgp.txMode.isolationLevel + const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable}) + + function transaction (t) { + return loadLatest() + .then(settings => { + const oldConfig = settings.config + return save(mergeValues(oldConfig, newFields)) + }) + } + + transaction.txMode = tmSRD + + return db.tx(transaction) +} + module.exports = { settings, loadConfig, @@ -132,5 +177,8 @@ module.exports = { loadLatest, save, loadFixture, - mergeValues + mergeValues, + modifyConfig, + configAddField, + configDeleteField }