random route stuff

This commit is contained in:
Josh Harvey 2016-12-21 19:51:20 +02:00
parent d27ff64a74
commit 9a63772401
8 changed files with 143 additions and 124 deletions

View file

@ -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,

View file

@ -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)'))

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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,23 +320,15 @@ 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 app = opts.app
const localApp = opts.localApp
const authMiddleware = opts.devMode
? (req, res, next) => next()
: authorize
const configRequiredRoutes = [
'/poll',
'/trade',
@ -349,45 +341,42 @@ function init (opts) {
'/phone_code'
]
const limiter = new RateLimit({
windowMs: T.minute,
max: 10,
delayMs: 0,
delayAfter: 0,
keyGenerator: () => 'everybody'
})
const app = express()
const localApp = express()
app.use(morgan('dev', {skip}))
app.use(helmet())
app.use(populateDeviceId)
app.use(configRequiredRoutes, populateSettings)
app.use(helmet({noCache: true}))
app.use(bodyParser.json())
app.use(morgan('dev', {skip}))
// 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.post('/pair', limiter, pair)
app.get('/ca', limiter, ca)
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.get('/poll', authMiddleware, poll)
app.post('/event', deviceEvent)
app.post('/verify_user', verifyUser)
app.post('/verify_transaction', verifyTx)
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('/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.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)
app.use(errorHandler)
localApp.get('/pid', (req, res) => {
const deviceId = req.query.device_id
@ -417,11 +406,6 @@ function init (opts) {
})
})
setInterval(pruneIdempotents, 60000)
return app
}
function populateDeviceId (req, res, next) {
const deviceId = ((typeof req.connection.getPeerCertificate === 'function' &&
req.connection.getPeerCertificate().fingerprint)) || null
@ -449,3 +433,7 @@ function populateSettings (req, res, next) {
.then(() => next())
.catch(next)
}
setInterval(pruneIdempotents, 60000)
module.exports = {app, localApp}

View file

@ -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",

View file

@ -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"