random route stuff
This commit is contained in:
parent
d27ff64a74
commit
9a63772401
8 changed files with 143 additions and 124 deletions
|
|
@ -22,6 +22,7 @@ const pairing = require('../lib/admin/pairing')
|
|||
const server = require('../lib/admin/server')
|
||||
const transactions = require('../lib/admin/transactions')
|
||||
const T = require('../lib/time')
|
||||
const logger = require('../lib/logger')
|
||||
|
||||
const NEVER = new Date(Date.now() + 100 * T.years)
|
||||
|
||||
|
|
@ -29,6 +30,9 @@ const devMode = argv.dev
|
|||
|
||||
let serverConfig
|
||||
|
||||
const version = require('../package.json').version
|
||||
logger.info('Version: %s', version)
|
||||
|
||||
try {
|
||||
const homeConfigPath = path.resolve(os.homedir(), '.lamassu', 'lamassu.json')
|
||||
serverConfig = JSON.parse(fs.readFileSync(homeConfigPath))
|
||||
|
|
@ -161,7 +165,9 @@ function register (req, res, next) {
|
|||
return login.register(otp)
|
||||
.then(r => {
|
||||
if (r.expired) return res.status(401).send('OTP expired, generate new registration link')
|
||||
if (!r.success) return res.status(401).send('Registration failed')
|
||||
|
||||
// Maybe user is using old registration key, attempt to authenticate
|
||||
if (!r.success) return next()
|
||||
|
||||
const cookieOpts = {
|
||||
httpOnly: true,
|
||||
|
|
|
|||
23
lib/app.js
23
lib/app.js
|
|
@ -1,7 +1,6 @@
|
|||
const fs = require('fs')
|
||||
const http = require('http')
|
||||
const https = require('https')
|
||||
const express = require('express')
|
||||
const argv = require('minimist')(process.argv.slice(2))
|
||||
|
||||
const routes = require('./routes')
|
||||
|
|
@ -11,7 +10,10 @@ const verifySchema = require('./verify-schema')
|
|||
const settingsLoader = require('./settings-loader')
|
||||
const options = require('./options')
|
||||
|
||||
const devMode = argv.dev || argv.http || options.http
|
||||
const devMode = argv.dev || options.http
|
||||
|
||||
const version = require('../package.json').version
|
||||
logger.info('Version: %s', version)
|
||||
|
||||
function run () {
|
||||
let count = 0
|
||||
|
|
@ -31,9 +33,6 @@ function run () {
|
|||
}
|
||||
|
||||
function runOnce () {
|
||||
const app = express()
|
||||
const localApp = express()
|
||||
|
||||
return verifySchema.valid()
|
||||
.then(() => settingsLoader.loadLatest())
|
||||
.then(settings => {
|
||||
|
|
@ -46,23 +45,15 @@ function runOnce () {
|
|||
}
|
||||
|
||||
const server = devMode
|
||||
? http.createServer(app)
|
||||
: https.createServer(httpsServerOptions, app)
|
||||
? http.createServer(routes.app)
|
||||
: https.createServer(httpsServerOptions, routes.app)
|
||||
|
||||
const port = 3000
|
||||
const localPort = 3030
|
||||
const localServer = http.createServer(localApp)
|
||||
const localServer = http.createServer(routes.localApp)
|
||||
|
||||
if (options.devMode) logger.info('In dev mode')
|
||||
|
||||
const opts = {
|
||||
app,
|
||||
localApp,
|
||||
devMode
|
||||
}
|
||||
|
||||
routes.init(opts)
|
||||
|
||||
server.listen(port, () => {
|
||||
console.log('lamassu-server listening on port ' +
|
||||
port + ' ' + (devMode ? '(http)' : '(https)'))
|
||||
|
|
|
|||
13
lib/db.js
13
lib/db.js
|
|
@ -1,4 +1,13 @@
|
|||
const pgp = require('pg-promise')()
|
||||
const Pgp = require('pg-promise')
|
||||
const psqlUrl = require('../lib/options').postgresql
|
||||
const logger = require('./logger')
|
||||
|
||||
module.exports = pgp(psqlUrl)
|
||||
const pgp = Pgp({
|
||||
pgNative: true,
|
||||
error: (_, e) => {
|
||||
if (e.cn) logger.error('Database not reachable.')
|
||||
}
|
||||
})
|
||||
|
||||
const db = pgp(psqlUrl)
|
||||
module.exports = db
|
||||
|
|
|
|||
|
|
@ -8,8 +8,4 @@ const logger = new winston.Logger({
|
|||
]
|
||||
})
|
||||
|
||||
// log version
|
||||
var version = require('../package.json').version
|
||||
logger.info('Version: %s', version)
|
||||
|
||||
module.exports = logger
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ function authorizeCaDownload (caToken) {
|
|||
function isPaired (deviceId) {
|
||||
const sql = 'select device_id from devices where device_id=$1 and paired=TRUE'
|
||||
|
||||
return db.one(sql, [deviceId])
|
||||
.then(() => true)
|
||||
return db.oneOrNone(sql, [deviceId])
|
||||
.then(row => row && row.device_id === deviceId)
|
||||
}
|
||||
|
||||
module.exports = {pair, authorizeCaDownload, isPaired}
|
||||
|
|
|
|||
182
lib/routes.js
182
lib/routes.js
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
const morgan = require('morgan')
|
||||
const helmet = require('helmet')
|
||||
const RateLimit = require('express-rate-limit')
|
||||
const bodyParser = require('body-parser')
|
||||
const BigNumber = require('bignumber.js')
|
||||
const _ = require('lodash/fp')
|
||||
const express = require('express')
|
||||
|
||||
const options = require('./options')
|
||||
const logger = require('./logger')
|
||||
|
|
@ -17,9 +17,7 @@ const settingsLoader = require('./settings-loader')
|
|||
const plugins = require('./plugins')
|
||||
const helpers = require('./route-helpers')
|
||||
const poller = require('./poller')
|
||||
const T = require('./time')
|
||||
|
||||
module.exports = {init}
|
||||
const argv = require('minimist')(process.argv.slice(2))
|
||||
|
||||
const CLOCK_SKEW = 60 * 1000
|
||||
const REQUEST_TTL = 3 * 60 * 1000
|
||||
|
|
@ -27,6 +25,8 @@ const REQUEST_TTL = 3 * 60 * 1000
|
|||
const pids = {}
|
||||
const reboots = {}
|
||||
|
||||
const devMode = argv.dev || options.http
|
||||
|
||||
function poll (req, res, next) {
|
||||
const deviceId = req.deviceId
|
||||
const deviceTime = req.deviceTime
|
||||
|
|
@ -153,7 +153,7 @@ function ca (req, res) {
|
|||
|
||||
return pairing.authorizeCaDownload(token)
|
||||
.then(ca => res.json({ca}))
|
||||
.catch(() => res.status(408).end())
|
||||
.catch(() => res.sendStatus(403))
|
||||
}
|
||||
|
||||
function pair (req, res, next) {
|
||||
|
|
@ -320,107 +320,91 @@ function authorize (req, res, next) {
|
|||
return next()
|
||||
}
|
||||
|
||||
throw httpError('Unauthorized', 403)
|
||||
return res.sendStatus(403)
|
||||
})
|
||||
.catch(next)
|
||||
}
|
||||
|
||||
function init (opts) {
|
||||
const skip = options.logLevel === 'debug'
|
||||
? () => false
|
||||
: (req, res) => _.includes(req.path, ['/poll', '/state']) && res.statusCode === 200
|
||||
const skip = options.logLevel === 'debug'
|
||||
? () => false
|
||||
: (req, res) => _.includes(req.path, ['/poll', '/state']) && res.statusCode === 200
|
||||
|
||||
const app = opts.app
|
||||
const localApp = opts.localApp
|
||||
const configRequiredRoutes = [
|
||||
'/poll',
|
||||
'/trade',
|
||||
'/send',
|
||||
'/cash_out',
|
||||
'/dispense_ack',
|
||||
'/event',
|
||||
'/verify_user',
|
||||
'/verify_transaction',
|
||||
'/phone_code'
|
||||
]
|
||||
|
||||
const authMiddleware = opts.devMode
|
||||
? (req, res, next) => next()
|
||||
: authorize
|
||||
const app = express()
|
||||
const localApp = express()
|
||||
|
||||
const configRequiredRoutes = [
|
||||
'/poll',
|
||||
'/trade',
|
||||
'/send',
|
||||
'/cash_out',
|
||||
'/dispense_ack',
|
||||
'/event',
|
||||
'/verify_user',
|
||||
'/verify_transaction',
|
||||
'/phone_code'
|
||||
]
|
||||
app.use(helmet({noCache: true}))
|
||||
app.use(bodyParser.json())
|
||||
app.use(morgan('dev', {skip}))
|
||||
|
||||
const limiter = new RateLimit({
|
||||
windowMs: T.minute,
|
||||
max: 10,
|
||||
delayMs: 0,
|
||||
delayAfter: 0,
|
||||
keyGenerator: () => 'everybody'
|
||||
// These two have their own authorization
|
||||
app.post('/pair', populateDeviceId, pair)
|
||||
app.get('/ca', ca)
|
||||
|
||||
app.use(populateDeviceId)
|
||||
if (!devMode) app.use(authorize)
|
||||
app.use(configRequiredRoutes, populateSettings)
|
||||
app.use(filterOldRequests)
|
||||
app.post('*', cacheAction)
|
||||
|
||||
app.get('/poll', poll)
|
||||
app.post('/trade', trade)
|
||||
app.post('/send', send)
|
||||
app.post('/state', stateChange)
|
||||
app.post('/cash_out', cashOut)
|
||||
app.post('/dispense_ack', dispenseAck)
|
||||
|
||||
app.post('/event', deviceEvent)
|
||||
app.post('/verify_user', verifyUser)
|
||||
app.post('/verify_transaction', verifyTx)
|
||||
|
||||
app.post('/phone_code', phoneCode)
|
||||
app.post('/update_phone', updatePhone)
|
||||
app.get('/phone_tx', fetchPhoneTx)
|
||||
app.post('/register_redeem/:txId', registerRedeem)
|
||||
app.get('/await_dispense/:txId', waitForDispense)
|
||||
app.post('/dispense', dispense)
|
||||
|
||||
app.use(errorHandler)
|
||||
|
||||
localApp.get('/pid', (req, res) => {
|
||||
const deviceId = req.query.device_id
|
||||
const pidRec = pids[deviceId]
|
||||
res.json(pidRec)
|
||||
})
|
||||
|
||||
localApp.post('/reboot', (req, res) => {
|
||||
const pid = req.body.pid
|
||||
const deviceId = req.body.deviceId
|
||||
|
||||
if (!deviceId || !pid) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
||||
reboots[deviceId] = pid
|
||||
res.sendStatus(200)
|
||||
})
|
||||
|
||||
localApp.post('/dbChange', (req, res, next) => {
|
||||
return settingsLoader.loadLatest()
|
||||
.then(poller.reload)
|
||||
.then(() => logger.info('Config reloaded'))
|
||||
.catch(err => {
|
||||
logger.error(err)
|
||||
res.sendStatus(500)
|
||||
})
|
||||
|
||||
app.use(morgan('dev', {skip}))
|
||||
app.use(helmet())
|
||||
app.use(populateDeviceId)
|
||||
app.use(configRequiredRoutes, populateSettings)
|
||||
app.use(bodyParser.json())
|
||||
app.use(filterOldRequests)
|
||||
app.post('*', cacheAction)
|
||||
|
||||
app.post('/pair', limiter, pair)
|
||||
app.get('/ca', limiter, ca)
|
||||
|
||||
app.get('/poll', authMiddleware, poll)
|
||||
|
||||
app.post('/trade', authMiddleware, trade)
|
||||
app.post('/send', authMiddleware, send)
|
||||
app.post('/state', authMiddleware, stateChange)
|
||||
app.post('/cash_out', authMiddleware, cashOut)
|
||||
app.post('/dispense_ack', authMiddleware, dispenseAck)
|
||||
|
||||
app.post('/event', authMiddleware, deviceEvent)
|
||||
app.post('/verify_user', authMiddleware, verifyUser)
|
||||
app.post('/verify_transaction', authMiddleware, verifyTx)
|
||||
|
||||
app.post('/phone_code', authMiddleware, phoneCode)
|
||||
app.post('/update_phone', authMiddleware, updatePhone)
|
||||
app.get('/phone_tx', authMiddleware, fetchPhoneTx)
|
||||
app.post('/register_redeem/:txId', authMiddleware, registerRedeem)
|
||||
app.get('/await_dispense/:txId', authMiddleware, waitForDispense)
|
||||
app.post('/dispense', authMiddleware, dispense)
|
||||
|
||||
app.use('*', errorHandler)
|
||||
|
||||
localApp.get('/pid', (req, res) => {
|
||||
const deviceId = req.query.device_id
|
||||
const pidRec = pids[deviceId]
|
||||
res.json(pidRec)
|
||||
})
|
||||
|
||||
localApp.post('/reboot', (req, res) => {
|
||||
const pid = req.body.pid
|
||||
const deviceId = req.body.deviceId
|
||||
|
||||
if (!deviceId || !pid) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
||||
reboots[deviceId] = pid
|
||||
res.sendStatus(200)
|
||||
})
|
||||
|
||||
localApp.post('/dbChange', (req, res, next) => {
|
||||
return settingsLoader.loadLatest()
|
||||
.then(poller.reload)
|
||||
.then(() => logger.info('Config reloaded'))
|
||||
.catch(err => {
|
||||
logger.error(err)
|
||||
res.sendStatus(500)
|
||||
})
|
||||
})
|
||||
|
||||
setInterval(pruneIdempotents, 60000)
|
||||
|
||||
return app
|
||||
}
|
||||
})
|
||||
|
||||
function populateDeviceId (req, res, next) {
|
||||
const deviceId = ((typeof req.connection.getPeerCertificate === 'function' &&
|
||||
|
|
@ -449,3 +433,7 @@ function populateSettings (req, res, next) {
|
|||
.then(() => next())
|
||||
.catch(next)
|
||||
}
|
||||
|
||||
setInterval(pruneIdempotents, 60000)
|
||||
|
||||
module.exports = {app, localApp}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
"node-hkdf-sync": "^1.0.0",
|
||||
"numeral": "^2.0.1",
|
||||
"pg": "^6.1.0",
|
||||
"pg-native": "^1.10.0",
|
||||
"pg-promise": "^5.4.4",
|
||||
"pify": "^2.3.0",
|
||||
"pretty-ms": "^2.1.0",
|
||||
|
|
|
|||
32
yarn.lock
32
yarn.lock
|
|
@ -192,7 +192,7 @@ bignumber.js@^3.0.0, bignumber.js@^3.0.1:
|
|||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-3.0.1.tgz#807652d10e39de37e9e3497247edc798bb746f76"
|
||||
|
||||
bindings@^1.2.1:
|
||||
bindings@1.2.1, bindings@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
|
||||
|
||||
|
|
@ -1480,6 +1480,13 @@ levn@~0.3.0:
|
|||
prelude-ls "~1.1.2"
|
||||
type-check "~0.3.2"
|
||||
|
||||
libpq@^1.7.0:
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/libpq/-/libpq-1.8.5.tgz#9ef5bb509e1658908c19474088031db3dc7d4e48"
|
||||
dependencies:
|
||||
bindings "1.2.1"
|
||||
nan "^2.3.0"
|
||||
|
||||
load-json-file@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
|
||||
|
|
@ -1641,7 +1648,7 @@ ms@0.7.2, ms@^0.7.1:
|
|||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
|
||||
|
||||
nan@^2.0.5, nan@^2.2.0:
|
||||
nan@^2.0.5, nan@^2.2.0, nan@^2.3.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.4.0.tgz#fb3c59d45fe4effe215f0b890f8adf6eb32d2232"
|
||||
|
||||
|
|
@ -1843,6 +1850,14 @@ pg-minify@0.4:
|
|||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-minify/-/pg-minify-0.4.1.tgz#a642c6bd256c7da833066590b1e414334a1f6e19"
|
||||
|
||||
pg-native@^1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-native/-/pg-native-1.10.0.tgz#abe299214afa2be51db5f5104e14770c738230fd"
|
||||
dependencies:
|
||||
libpq "^1.7.0"
|
||||
pg-types "1.6.0"
|
||||
readable-stream "1.0.31"
|
||||
|
||||
pg-pool@1.*:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.6.0.tgz#2e300199927b6d7db6be71e2e3435dddddf07b41"
|
||||
|
|
@ -1869,6 +1884,10 @@ pg-types@1.*:
|
|||
postgres-date "~1.0.0"
|
||||
postgres-interval "~1.0.0"
|
||||
|
||||
pg-types@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.6.0.tgz#3872a0f199143025497f4ee2a65fdaf00d7ea8b3"
|
||||
|
||||
pg@5.1:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-5.1.0.tgz#073b9b36763ad8a5478dbb85effef45e739ba9d8"
|
||||
|
|
@ -2061,6 +2080,15 @@ readable-stream@1.0.27-1:
|
|||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@1.0.31:
|
||||
version "1.0.31"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.31.tgz#8f2502e0bc9e3b0da1b94520aabb4e2603ecafae"
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.1"
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@1.1.x:
|
||||
version "1.1.14"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue