Feat: implement per operator settings cache

Fix: fix linter-found issues

Chore: move findOperatorId to own middleware file

Chore: delete old routes.js file and rename new-routes.js to routes.js

Fix: PR fixes
This commit is contained in:
Cesar 2021-01-13 19:04:40 +00:00 committed by Josh Harvey
parent 85235eaa13
commit 558317e9f3
30 changed files with 232 additions and 860 deletions

View file

@ -16,4 +16,4 @@ const authorize = function (req, res, next) {
.catch(next)
}
module.exports = authorize
module.exports = authorize

View file

@ -1,7 +1,6 @@
const pairing = require('../pairing')
function ca (req, res) {
console.log("ca")
const token = req.query.token
return pairing.authorizeCaDownload(token)
@ -9,4 +8,4 @@ function ca (req, res) {
.catch(() => res.status(403).json({ error: 'forbidden' }))
}
module.exports = ca
module.exports = ca

View file

@ -12,4 +12,4 @@ function errorHandler (err, req, res, next) {
return res.status(statusCode).json(json)
}
module.exports = errorHandler
module.exports = errorHandler

View file

@ -24,4 +24,4 @@ function filterOldRequests (req, res, next) {
next()
}
module.exports = filterOldRequests
module.exports = filterOldRequests

View file

@ -0,0 +1,30 @@
const pify = require('pify')
const fs = pify(require('fs'))
const hkdf = require('futoin-hkdf')
const state = require('./state')
const mnemonicHelpers = require('../mnemonic-helpers')
const options = require('../options')
function computeOperatorId (masterSeed) {
return hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex')
}
function getMnemonic () {
if (state.mnemonic) return Promise.resolve(state.mnemonic)
return fs.readFile(options.mnemonicPath, 'utf8').then(mnemonic => {
state.mnemonic = mnemonic
return mnemonic
})
}
function findOperatorId (req, res, next) {
getMnemonic().then(mnemonic => {
return computeOperatorId(mnemonicHelpers.toEntropyBuffer(mnemonic))
}).then(id => {
res.locals.operatorId = id
}).catch(e => console.error('Error while computing operator id\n' + e))
next()
}
module.exports = findOperatorId

View file

@ -1,20 +0,0 @@
const pairing = require('../pairing')
function pair (req, res, next) {
console.log("pair")
const token = req.query.token
const deviceId = req.deviceId
const model = req.query.model
return pairing.pair(token, deviceId, model)
.then(valid => {
if (valid) {
return res.json({ status: 'paired' })
}
throw httpError('Pairing failed')
})
.catch(next)
}
module.exports = pair

View file

@ -1,7 +1,7 @@
const _ = require('lodash/fp')
const crypto = require('crypto')
function sha256 (buf) {
const crypto = require('crypto')
const hash = crypto.createHash('sha256')
hash.update(buf)
@ -19,4 +19,4 @@ const populateDeviceId = function (req, res, next) {
next()
}
module.exports = populateDeviceId
module.exports = populateDeviceId

View file

@ -6,26 +6,27 @@ const helpers = require('../route-helpers')
const SETTINGS_CACHE_REFRESH = 60 * 60 * 1000
const populateSettings = function (req, res, next) {
const operatorId = res.locals.operatorId
const versionId = req.headers['config-version']
if (versionId !== state.oldVersionId) {
state.oldVersionId = versionId
}
// Clear cache every hour
if (Date.now() - settingsCache.getTimestamp() > SETTINGS_CACHE_REFRESH) {
settingsCache.clearCache()
if (Date.now() - settingsCache.getTimestamp(operatorId) > SETTINGS_CACHE_REFRESH) {
settingsCache.clear(operatorId)
}
if (!versionId && settingsCache.getCache()) {
req.settings = settingsCache.getCache()
if (!versionId && settingsCache.getCache(operatorId)) {
req.settings = settingsCache.getCache(operatorId)
return next()
}
if (!versionId && !settingsCache.getCache()) {
if (!versionId && !settingsCache.getCache(operatorId)) {
return newSettingsLoader.loadLatest()
.then(settings => {
settingsCache.setCache(settings)
settingsCache.setTimestamp(Date.now())
settingsCache.setCache(operatorId, settings)
settingsCache.setTimestamp(operatorId, Date.now())
req.settings = settings
})
.then(() => next())
@ -39,4 +40,4 @@ const populateSettings = function (req, res, next) {
.catch(next)
}
module.exports = populateSettings
module.exports = populateSettings

View file

@ -1,19 +1,26 @@
const _ = require('lodash/fp')
const state = require('./state')
const getTimestamp = () => state.settingsCache.timestamp
const getTimestamp = (operatorId) => state.settingsCache[operatorId] ? state.settingsCache[operatorId].timestamp : null
const getCache = () => state.settingsCache.cache
const getCache = (operatorId) => state.settingsCache[operatorId] ? state.settingsCache[operatorId].cache : null
const setTimestamp = (newTimestamp) => state.settingsCache.timestamp = newTimestamp
const setTimestamp = (operatorId, newTimestamp) => {
state.settingsCache = _.set([operatorId, 'timestamp'], newTimestamp, state.settingsCache)
}
const setCache = (newCache) => state.settingsCache.cache = newCache
const setCache = (operatorId, newCache) => {
state.settingsCache = _.set([operatorId, 'cache'], newCache, state.settingsCache)
}
const clearCache = () => state.settingsCache.cache = null
const clear = (operatorId) => {
state.settingsCache = _.set([operatorId], null, state.settingsCache)
}
module.exports = {
getTimestamp,
getCache,
setTimestamp,
setCache,
clearCache
}
clear
}

View file

@ -1,12 +1,13 @@
module.exports = function () {
module.exports = (function () {
return {
oldVersionId: "unset",
oldVersionId: 'unset',
settingsCache: {},
canLogClockSkewMap: {},
canGetLastSeenMap: {},
pids: {},
reboots: {},
shutdowns: {},
restartServicesMap: {}
restartServicesMap: {},
mnemonic: null
}
}()
}())