validate min/max values on save

This commit is contained in:
Josh Harvey 2016-12-20 14:08:07 +02:00
parent 3f3671f138
commit 124e35d153
5 changed files with 61 additions and 28 deletions

View file

@ -87,10 +87,11 @@ app.post('/api/account', (req, res) => {
app.get('/api/config/:config', (req, res) =>
config.fetchConfigGroup(req.params.config).then(c => res.json(c)))
app.post('/api/config', (req, res) => {
app.post('/api/config', (req, res, next) => {
config.saveConfigGroup(req.body)
.then(c => res.json(c))
.then(() => dbNotify())
.catch(next)
})
app.get('/api/accounts/account/:account', (req, res) => {
@ -111,7 +112,7 @@ app.post('/api/machines', (req, res) => {
})
app.get('/api/status', (req, res, next) => {
return Promise.all([server.status(), config.validateConfig()])
return Promise.all([server.status(), config.validateCurrentConfig()])
.then(([serverStatus, invalidConfigGroups]) => res.send({
server: serverStatus,
invalidConfigGroups

View file

@ -101,7 +101,7 @@
},
{
"code": "min",
"min": 0
"min": 10
}
]
},

View file

@ -39,10 +39,8 @@ function selectedAccounts () {
const mapSchema = code => schemas[code]
return config.fetchConfig()
.then(data => {
if (!data) return []
const accountCodes = _.uniq(data.config.map(mapAccount)
.then(conf => {
const accountCodes = _.uniq(conf.map(mapAccount)
.filter(_.identity))
return _.sortBy(_.get('display'), accountCodes.map(mapSchema)

View file

@ -24,7 +24,7 @@ function fetchConfig () {
order by id desc limit 1`
return db.oneOrNone(sql, ['config'])
.then(row => row && row.data)
.then(row => row ? row.data.config : [])
}
function allScopes (cryptoScopes, machineScopes) {
@ -110,10 +110,43 @@ function getField (schema, group, fieldCode) {
const fetchMachines = () => machines.getMachines()
.then(machineList => machineList.map(r => r.deviceId))
function validateConfig () {
return Promise.all([fetchSchema(), fetchConfig(), fetchMachines()])
.then(([schema, configRec, machineList]) => {
const config = configRec ? configRec.config : []
function validateFieldParameter (value, validator) {
switch (validator.code) {
case 'required':
return true // We don't validate this here
case 'min':
return value >= validator.min
case 'max':
return value <= validator.max
default:
throw new Error('Unknown validation type: ' + validator.code)
}
}
// Validates specific field properties other than required property
function enforceValidConfigParameters (fieldInstances) {
return fetchSchema()
.then(schema => {
const pickField = fieldCode => schema.fields.find(r => r.code === fieldCode)
return fieldInstances.every(fieldInstance => {
const fieldCode = fieldInstance.fieldLocator.code
const field = pickField(fieldCode)
const fieldValue = fieldInstance.fieldValue
const isValid = field.fieldValidation
.every(validator => validateFieldParameter(fieldValue.value, validator))
if (isValid) return true
throw new Error('Invalid config value')
})
})
}
function validateConfig (config) {
return Promise.all([fetchSchema(), fetchMachines()])
.then(([schema, machineList]) => {
const cryptos = getCryptos(config, machineList)
return schema.groups.filter(group => {
return group.fields.some(fieldCode => {
@ -128,11 +161,15 @@ function validateConfig () {
.then(arr => arr.map(r => r.code))
}
function validateCurrentConfig () {
return fetchConfig()
.then(validateConfig)
}
function fetchConfigGroup (code) {
const fieldLocatorCodeEq = R.pathEq(['fieldLocator', 'code'])
return Promise.all([fetchSchema(), fetchData(), fetchConfig(), fetchMachines()])
.then(([schema, data, config, machineList]) => {
const configValues = config ? config.config : []
const groupSchema = schema.groups.find(r => r.code === code)
if (!groupSchema) throw new Error('No such group schema: ' + code)
@ -149,7 +186,7 @@ function fetchConfigGroup (code) {
const configFields = R.uniq(R.flatten(candidateFields)).filter(R.identity)
const values = configFields
.reduce((acc, configField) => acc.concat(configValues.filter(fieldLocatorCodeEq(configField))), [])
.reduce((acc, configField) => acc.concat(config.filter(fieldLocatorCodeEq(configField))), [])
groupSchema.fields = undefined
groupSchema.entries = schemaFields
@ -157,7 +194,7 @@ function fetchConfigGroup (code) {
return {
schema: groupSchema,
values: values,
selectedCryptos: getCryptos(configValues, machineList),
selectedCryptos: getCryptos(config, machineList),
data: data
}
})
@ -216,17 +253,15 @@ function fetchData () {
function dbSaveConfig (config) {
const sql = 'insert into user_config (type, data) values ($1, $2)'
return db.none(sql, ['config', config])
return db.none(sql, ['config', {config}])
}
function saveConfigGroup (results) {
if (results.values.length === 0) return fetchConfigGroup(results.groupCode)
return fetchConfig()
.then(config => {
if (!config) config = {config: []}
const oldValues = config.config
return enforceValidConfigParameters(results.values)
.then(fetchConfig)
.then(oldValues => {
results.values.forEach(newValue => {
const oldValueIndex = oldValues
.findIndex(old => old.fieldLocator.code === newValue.fieldLocator.code &&
@ -251,15 +286,14 @@ function saveConfigGroup (results) {
if (!R.isNil(newValue.fieldValue)) oldValues.push(newValue)
})
return dbSaveConfig(config)
return dbSaveConfig(oldValues)
.then(() => fetchConfigGroup(results.groupCode))
})
.catch(e => console.error(e.stack))
}
module.exports = {
fetchConfigGroup,
saveConfigGroup,
validateConfig,
validateCurrentConfig,
fetchConfig
}

View file

@ -25386,9 +25386,9 @@ var _user$project$Config$validateMax = F2(
case 'FieldPercentageValue':
return _elm_lang$core$Native_Utils.cmp(
_elm_lang$core$Basics$floor(_p6._0),
max) < 0;
max) < 1;
case 'FieldIntegerValue':
return _elm_lang$core$Native_Utils.cmp(_p6._0, max) < 0;
return _elm_lang$core$Native_Utils.cmp(_p6._0, max) < 1;
default:
return true;
}
@ -25400,9 +25400,9 @@ var _user$project$Config$validateMin = F2(
case 'FieldPercentageValue':
return _elm_lang$core$Native_Utils.cmp(
_elm_lang$core$Basics$ceiling(_p7._0),
min) > 0;
min) > -1;
case 'FieldIntegerValue':
return _elm_lang$core$Native_Utils.cmp(_p7._0, min) > 0;
return _elm_lang$core$Native_Utils.cmp(_p7._0, min) > -1;
default:
return true;
}