WIP
This commit is contained in:
parent
1771467474
commit
855546f886
7 changed files with 157 additions and 131 deletions
|
|
@ -1,39 +1,7 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
'use strict'
|
const app = require('../lib/app')
|
||||||
|
|
||||||
var fs = require('fs')
|
|
||||||
var options = require('../lib/options')
|
|
||||||
process.env.LAMASSU_ENV = process.env.LAMASSU_ENV || options.logLevel || 'info'
|
|
||||||
|
|
||||||
var createServer = require('../lib/app.js')
|
|
||||||
var argv = require('minimist')(process.argv.slice(2))
|
|
||||||
|
|
||||||
var port = process.env.PORT || 3000
|
|
||||||
var httpOnly = options.httpOnly || argv.http
|
|
||||||
|
|
||||||
if (!httpOnly) {
|
|
||||||
try {
|
|
||||||
options.https = {
|
|
||||||
key: fs.readFileSync(options.keyPath),
|
|
||||||
cert: fs.readFileSync(options.certPath)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log('Please configure your certificate.')
|
|
||||||
console.log(err)
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options.mock = argv.mock
|
|
||||||
|
|
||||||
console.log('DEBUG23')
|
|
||||||
|
|
||||||
process.on('unhandledRejection', err => console.log(err.stack))
|
process.on('unhandledRejection', err => console.log(err.stack))
|
||||||
|
|
||||||
createServer(options)
|
app.run()
|
||||||
.then(server => {
|
|
||||||
console.log('DEBUG22')
|
|
||||||
return server.listen(port, () => console.log('lamassu-server listening on port ' +
|
|
||||||
port + ' ' + (httpOnly ? '(http)' : '(https)')))
|
|
||||||
})
|
|
||||||
|
|
|
||||||
113
lib/app.js
113
lib/app.js
|
|
@ -1,33 +1,23 @@
|
||||||
var http = require('http')
|
const fs = require('fs')
|
||||||
var https = require('https')
|
const http = require('http')
|
||||||
var express = require('express')
|
const https = require('https')
|
||||||
var bodyParser = require('body-parser')
|
const express = require('express')
|
||||||
var routes = require('./routes')
|
const routes = require('./routes')
|
||||||
var plugins = require('./plugins')
|
const plugins = require('./plugins')
|
||||||
var logger = require('./logger')
|
const logger = require('./logger')
|
||||||
var configManager = require('./config-manager')
|
var argv = require('minimist')(process.argv.slice(2))
|
||||||
|
|
||||||
const helmet = require('helmet')
|
const configManager = require('./config-manager')
|
||||||
|
const options = require('./options')
|
||||||
|
|
||||||
const pair = require('./pair')
|
const devMode = argv.dev || argv.http || options.http
|
||||||
|
|
||||||
module.exports = function (options) {
|
function run () {
|
||||||
var app = express()
|
const app = express()
|
||||||
var server
|
const localApp = express()
|
||||||
|
|
||||||
app.use(helmet())
|
|
||||||
app.use(bodyParser.json())
|
|
||||||
|
|
||||||
const psqlUrl = options.postgresql
|
|
||||||
if (!psqlUrl) {
|
|
||||||
console.log('Missing postgresql entry in configuration file')
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const seedPath = options.seedPath || './seeds/seed.txt'
|
const seedPath = options.seedPath || './seeds/seed.txt'
|
||||||
plugins.init(psqlUrl, seedPath)
|
plugins.init(seedPath)
|
||||||
|
|
||||||
console.log('DEBUG6')
|
|
||||||
|
|
||||||
return configManager.load()
|
return configManager.load()
|
||||||
.then(config => {
|
.then(config => {
|
||||||
|
|
@ -35,42 +25,47 @@ module.exports = function (options) {
|
||||||
plugins.startPolling()
|
plugins.startPolling()
|
||||||
plugins.startCheckingNotification()
|
plugins.startCheckingNotification()
|
||||||
|
|
||||||
var authMiddleware
|
const httpsServerOptions = {
|
||||||
|
key: fs.readFileSync(options.keyPath),
|
||||||
if (options.https) {
|
cert: fs.readFileSync(options.certPath),
|
||||||
const serverOptions = {
|
requestCert: true
|
||||||
key: options.https.key,
|
|
||||||
cert: options.https.cert,
|
|
||||||
requestCert: true
|
|
||||||
}
|
|
||||||
|
|
||||||
server = https.createServer(serverOptions, app)
|
|
||||||
|
|
||||||
authMiddleware = function (req, res, next) {
|
|
||||||
const deviceId = req.connection.getPeerCertificate().fingerprint
|
|
||||||
console.log(deviceId)
|
|
||||||
|
|
||||||
return pair.isPaired(deviceId)
|
|
||||||
.then(r => {
|
|
||||||
if (r) {
|
|
||||||
req.deviceId = deviceId
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Unauthorized')
|
|
||||||
})
|
|
||||||
.catch(e => res.status(403).end())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
server = http.createServer(app)
|
|
||||||
|
|
||||||
authMiddleware = function (req, res, next) {
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mock) logger.info('In mock mode')
|
const server = devMode
|
||||||
|
? http.createServer(app)
|
||||||
|
: https.createServer(httpsServerOptions, app)
|
||||||
|
|
||||||
return server
|
const port = devMode
|
||||||
|
? 3000
|
||||||
|
: 443
|
||||||
|
|
||||||
|
const localPort = 3030
|
||||||
|
const localServer = http.createServer(localApp)
|
||||||
|
|
||||||
|
if (options.devMode) logger.info('In dev mode')
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
app,
|
||||||
|
localApp,
|
||||||
|
devMode,
|
||||||
|
plugins
|
||||||
|
}
|
||||||
|
|
||||||
|
routes.init(opts)
|
||||||
|
|
||||||
|
server.listen(port, () => {
|
||||||
|
console.log('lamassu-server listening on port ' +
|
||||||
|
port + ' ' + (devMode ? '(http)' : '(https)'))
|
||||||
|
})
|
||||||
|
|
||||||
|
localServer.listen(localPort, 'localhost', () => {
|
||||||
|
console.log('lamassu-server listening on local port ' + localPort)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err)
|
||||||
|
process.exit(1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {run}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ const coins = {
|
||||||
let alertFingerprint = null
|
let alertFingerprint = null
|
||||||
let lastAlertTime = null
|
let lastAlertTime = null
|
||||||
|
|
||||||
exports.init = function init (connectionString, seedPath) {
|
exports.init = function init (seedPath) {
|
||||||
const masterSeed = new Buffer(fs.readFileSync(seedPath, 'utf8').trim(), 'hex')
|
const masterSeed = new Buffer(fs.readFileSync(seedPath, 'utf8').trim(), 'hex')
|
||||||
hkdf = new HKDF('sha256', 'lamassu-server-salt', masterSeed)
|
hkdf = new HKDF('sha256', 'lamassu-server-salt', masterSeed)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const BigNumber = require('bignumber.js')
|
const BigNumber = require('bignumber.js')
|
||||||
|
const db = require('./db')
|
||||||
const pgp = require('pg-promise')()
|
const pgp = require('pg-promise')()
|
||||||
var psqlUrl = require('../lib/options').postgresql
|
|
||||||
|
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
|
|
||||||
|
|
@ -28,10 +28,6 @@ function getInsertQuery (tableName, fields) {
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
function connect () {
|
|
||||||
return pgp(psqlUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// logs inputted bill and overall tx status (if available)
|
// logs inputted bill and overall tx status (if available)
|
||||||
exports.recordBill = function recordBill (deviceId, rec) {
|
exports.recordBill = function recordBill (deviceId, rec) {
|
||||||
console.log('DEBUG10: %j', rec)
|
console.log('DEBUG10: %j', rec)
|
||||||
|
|
@ -61,8 +57,6 @@ exports.recordBill = function recordBill (deviceId, rec) {
|
||||||
|
|
||||||
console.log('DEBUG11: %j', values)
|
console.log('DEBUG11: %j', values)
|
||||||
|
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(getInsertQuery('bills', fields), values)
|
return db.none(getInsertQuery('bills', fields), values)
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
if (isUniqueViolation(err)) return logger.warn('Attempt to report bill twice')
|
if (isUniqueViolation(err)) return logger.warn('Attempt to report bill twice')
|
||||||
|
|
@ -75,7 +69,6 @@ exports.recordDeviceEvent = function recordDeviceEvent (deviceId, event) {
|
||||||
'note, device_time) VALUES ($1, $2, $3, $4)'
|
'note, device_time) VALUES ($1, $2, $3, $4)'
|
||||||
const values = [deviceId, event.eventType, event.note,
|
const values = [deviceId, event.eventType, event.note,
|
||||||
event.deviceTime]
|
event.deviceTime]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
}
|
}
|
||||||
|
|
@ -102,13 +95,11 @@ exports.addOutgoingTx = function addOutgoingTx (deviceId, tx) {
|
||||||
tx.error
|
tx.error
|
||||||
]
|
]
|
||||||
|
|
||||||
const db = connect()
|
|
||||||
return db.none(getInsertQuery('cash_in_txs', fields), values)
|
return db.none(getInsertQuery('cash_in_txs', fields), values)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.sentCoins = function sentCoins (tx, toSend, fee, error, txHash) {
|
exports.sentCoins = function sentCoins (tx, toSend, fee, error, txHash) {
|
||||||
const sql = 'update cash_in_txs set tx_hash=$1, error=$2 where id=$3'
|
const sql = 'update cash_in_txs set tx_hash=$1, error=$2 where id=$3'
|
||||||
const db = connect()
|
|
||||||
return db.none(sql, [txHash, error, tx.id])
|
return db.none(sql, [txHash, error, tx.id])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,7 +122,6 @@ exports.addInitialIncoming = function addInitialIncoming (deviceId, tx) {
|
||||||
tx.error
|
tx.error
|
||||||
]
|
]
|
||||||
|
|
||||||
const db = connect()
|
|
||||||
return db.none(getInsertQuery('cash_out_txs', fields), values)
|
return db.none(getInsertQuery('cash_out_txs', fields), values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +149,6 @@ function insertDispense (deviceId, tx, cartridges) {
|
||||||
false, tx.error
|
false, tx.error
|
||||||
]
|
]
|
||||||
|
|
||||||
const db = connect()
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +157,6 @@ exports.addIncomingPhone = function addIncomingPhone (tx, notified) {
|
||||||
WHERE id=$3
|
WHERE id=$3
|
||||||
AND phone IS NULL`
|
AND phone IS NULL`
|
||||||
const values = [tx.phone, notified, tx.id]
|
const values = [tx.phone, notified, tx.id]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.result(sql, values)
|
return db.result(sql, values)
|
||||||
.then(results => {
|
.then(results => {
|
||||||
|
|
@ -210,7 +198,6 @@ exports.fetchPhoneTxs = function fetchPhoneTxs (phone, dispenseTimeout) {
|
||||||
'AND (EXTRACT(EPOCH FROM (COALESCE(confirmation_time, now()) - created))) * 1000 < $3'
|
'AND (EXTRACT(EPOCH FROM (COALESCE(confirmation_time, now()) - created))) * 1000 < $3'
|
||||||
|
|
||||||
const values = [phone, false, dispenseTimeout]
|
const values = [phone, false, dispenseTimeout]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql, values)
|
return db.any(sql, values)
|
||||||
.then(rows => normalizeTxs(rows))
|
.then(rows => normalizeTxs(rows))
|
||||||
|
|
@ -218,7 +205,6 @@ exports.fetchPhoneTxs = function fetchPhoneTxs (phone, dispenseTimeout) {
|
||||||
|
|
||||||
exports.fetchTx = function fetchTx (txId) {
|
exports.fetchTx = function fetchTx (txId) {
|
||||||
const sql = 'SELECT * FROM cash_out_txs WHERE id=$1'
|
const sql = 'SELECT * FROM cash_out_txs WHERE id=$1'
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.one(sql, [txId])
|
return db.one(sql, [txId])
|
||||||
.then(row => normalizeTx(row))
|
.then(row => normalizeTx(row))
|
||||||
|
|
@ -227,7 +213,6 @@ exports.fetchTx = function fetchTx (txId) {
|
||||||
exports.addDispenseRequest = function addDispenseRequest (tx) {
|
exports.addDispenseRequest = function addDispenseRequest (tx) {
|
||||||
const sql = 'update cash_out_txs set dispensed=$1 where id=$2 and dispensed=$3'
|
const sql = 'update cash_out_txs set dispensed=$1 where id=$2 and dispensed=$3'
|
||||||
const values = [true, tx.id, false]
|
const values = [true, tx.id, false]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.result(sql, values)
|
return db.result(sql, values)
|
||||||
.then(results => {
|
.then(results => {
|
||||||
|
|
@ -245,7 +230,6 @@ exports.addDispense = function addDispense (deviceId, tx, cartridges) {
|
||||||
return insertDispense(deviceId, tx, cartridges)
|
return insertDispense(deviceId, tx, cartridges)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const sql2 = 'insert into cash_out_actions (cash_out_txs_id, action) values ($1, $2)'
|
const sql2 = 'insert into cash_out_actions (cash_out_txs_id, action) values ($1, $2)'
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql2, [tx.id, 'dispensed'])
|
return db.none(sql2, [tx.id, 'dispensed'])
|
||||||
})
|
})
|
||||||
|
|
@ -255,7 +239,6 @@ exports.cartridgeCounts = function cartridgeCounts (deviceId) {
|
||||||
const sql = 'SELECT id, count1, count2 FROM dispenses ' +
|
const sql = 'SELECT id, count1, count2 FROM dispenses ' +
|
||||||
'WHERE device_id=$1 AND refill=$2 ' +
|
'WHERE device_id=$1 AND refill=$2 ' +
|
||||||
'ORDER BY id DESC LIMIT 1'
|
'ORDER BY id DESC LIMIT 1'
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.oneOrNone(sql, [deviceId, true])
|
return db.oneOrNone(sql, [deviceId, true])
|
||||||
.then(row => {
|
.then(row => {
|
||||||
|
|
@ -272,7 +255,6 @@ exports.machineEvent = function machineEvent (rec) {
|
||||||
const values = [rec.id, rec.deviceId, rec.eventType, rec.note, rec.deviceTime]
|
const values = [rec.id, rec.deviceId, rec.eventType, rec.note, rec.deviceTime]
|
||||||
const deleteSql = 'DELETE FROM machine_events WHERE (EXTRACT(EPOCH FROM (now() - created))) * 1000 > $1'
|
const deleteSql = 'DELETE FROM machine_events WHERE (EXTRACT(EPOCH FROM (now() - created))) * 1000 > $1'
|
||||||
const deleteValues = [TTL]
|
const deleteValues = [TTL]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
.then(() => db.none(deleteSql, deleteValues))
|
.then(() => db.none(deleteSql, deleteValues))
|
||||||
|
|
@ -280,14 +262,12 @@ exports.machineEvent = function machineEvent (rec) {
|
||||||
|
|
||||||
exports.devices = function devices () {
|
exports.devices = function devices () {
|
||||||
const sql = 'SELECT device_id, name FROM devices'
|
const sql = 'SELECT device_id, name FROM devices'
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql)
|
return db.any(sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.machineEvents = function machineEvents () {
|
exports.machineEvents = function machineEvents () {
|
||||||
const sql = 'SELECT *, (EXTRACT(EPOCH FROM (now() - created))) * 1000 AS age FROM machine_events'
|
const sql = 'SELECT *, (EXTRACT(EPOCH FROM (now() - created))) * 1000 AS age FROM machine_events'
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql, [])
|
return db.any(sql, [])
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +281,6 @@ exports.fetchOpenTxs = function fetchOpenTxs (statuses, age) {
|
||||||
'FROM cash_out_txs ' +
|
'FROM cash_out_txs ' +
|
||||||
'WHERE ((EXTRACT(EPOCH FROM (now() - created))) * 1000)<$1 ' +
|
'WHERE ((EXTRACT(EPOCH FROM (now() - created))) * 1000)<$1 ' +
|
||||||
'AND status IN ' + _statuses
|
'AND status IN ' + _statuses
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql, [age])
|
return db.any(sql, [age])
|
||||||
.then(rows => normalizeTxs(rows))
|
.then(rows => normalizeTxs(rows))
|
||||||
|
|
@ -315,7 +294,6 @@ exports.fetchUnnotifiedTxs = function fetchUnnotifiedTxs (age, waitPeriod) {
|
||||||
AND phone IS NOT NULL
|
AND phone IS NOT NULL
|
||||||
AND status IN ('instant', 'confirmed')
|
AND status IN ('instant', 'confirmed')
|
||||||
AND (redeem=$4 OR ((EXTRACT(EPOCH FROM (now() - created))) * 1000)>$5)`
|
AND (redeem=$4 OR ((EXTRACT(EPOCH FROM (now() - created))) * 1000)>$5)`
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql, [age, false, false, true, waitPeriod])
|
return db.any(sql, [age, false, false, true, waitPeriod])
|
||||||
.then(rows => normalizeTxs(rows))
|
.then(rows => normalizeTxs(rows))
|
||||||
|
|
@ -336,7 +314,6 @@ exports.updateTxStatus = function updateTxStatus (tx, status) {
|
||||||
const TransactionMode = pgp.txMode.TransactionMode
|
const TransactionMode = pgp.txMode.TransactionMode
|
||||||
const isolationLevel = pgp.txMode.isolationLevel
|
const isolationLevel = pgp.txMode.isolationLevel
|
||||||
const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable})
|
const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable})
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
function transaction (t) {
|
function transaction (t) {
|
||||||
const sql = 'select status, confirmation_time from cash_out_txs where id=$1'
|
const sql = 'select status, confirmation_time from cash_out_txs where id=$1'
|
||||||
|
|
@ -381,7 +358,6 @@ exports.updateTxStatus = function updateTxStatus (tx, status) {
|
||||||
exports.updateRedeem = function updateRedeem (txId) {
|
exports.updateRedeem = function updateRedeem (txId) {
|
||||||
const sql = 'UPDATE cash_out_txs SET redeem=$1 WHERE id=$2'
|
const sql = 'UPDATE cash_out_txs SET redeem=$1 WHERE id=$2'
|
||||||
const values = [true, txId]
|
const values = [true, txId]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
@ -393,7 +369,6 @@ exports.updateRedeem = function updateRedeem (txId) {
|
||||||
exports.updateNotify = function updateNotify (tx) {
|
exports.updateNotify = function updateNotify (tx) {
|
||||||
const sql = 'UPDATE cash_out_txs SET notified=$1 WHERE id=$2'
|
const sql = 'UPDATE cash_out_txs SET notified=$1 WHERE id=$2'
|
||||||
const values = [true, tx.id]
|
const values = [true, tx.id]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
@ -410,7 +385,6 @@ function insertCachedRequest (deviceId, txId, path, method, body) {
|
||||||
'method',
|
'method',
|
||||||
'body'
|
'body'
|
||||||
]
|
]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
const sql = getInsertQuery('cached_responses', fields)
|
const sql = getInsertQuery('cached_responses', fields)
|
||||||
return db.none(sql, [deviceId, txId, path, method, body])
|
return db.none(sql, [deviceId, txId, path, method, body])
|
||||||
|
|
@ -424,7 +398,6 @@ exports.cachedResponse = function (deviceId, txId, path, method) {
|
||||||
and method=$4`
|
and method=$4`
|
||||||
|
|
||||||
const values = [deviceId, txId, path, method]
|
const values = [deviceId, txId, path, method]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return insertCachedRequest(deviceId, txId, path, method, {pendingRequest: true})
|
return insertCachedRequest(deviceId, txId, path, method, {pendingRequest: true})
|
||||||
.then(() => ({}))
|
.then(() => ({}))
|
||||||
|
|
@ -441,7 +414,6 @@ function pruneCachedResponses () {
|
||||||
where (EXTRACT(EPOCH FROM (now() - created))) * 1000 < $1`
|
where (EXTRACT(EPOCH FROM (now() - created))) * 1000 < $1`
|
||||||
|
|
||||||
const values = [CACHED_SESSION_TTL]
|
const values = [CACHED_SESSION_TTL]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
}
|
}
|
||||||
|
|
@ -455,7 +427,6 @@ exports.cacheResponse = function (deviceId, txId, path, method, body) {
|
||||||
and method=$5`
|
and method=$5`
|
||||||
|
|
||||||
const values = [body, deviceId, txId, path, method]
|
const values = [body, deviceId, txId, path, method]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.none(sql, values)
|
||||||
}
|
}
|
||||||
|
|
@ -463,7 +434,6 @@ exports.cacheResponse = function (deviceId, txId, path, method, body) {
|
||||||
exports.nextCashOutSerialHD = function nextCashOutSerialHD (txId, cryptoCode) {
|
exports.nextCashOutSerialHD = function nextCashOutSerialHD (txId, cryptoCode) {
|
||||||
const sql = `select hd_serial from cash_out_hds
|
const sql = `select hd_serial from cash_out_hds
|
||||||
where crypto_code=$1 order by hd_serial desc limit 1`
|
where crypto_code=$1 order by hd_serial desc limit 1`
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
const attempt = () => db.oneOrNone(sql, [cryptoCode])
|
const attempt = () => db.oneOrNone(sql, [cryptoCode])
|
||||||
.then(row => {
|
.then(row => {
|
||||||
|
|
@ -486,7 +456,6 @@ exports.fetchLiveHD = function fetchLiveHD () {
|
||||||
((extract(epoch from (now() - cash_out_txs.created))) * 1000)<$3`
|
((extract(epoch from (now() - cash_out_txs.created))) * 1000)<$3`
|
||||||
|
|
||||||
const values = ['confirmed', false, LIVE_SWEEP_TTL]
|
const values = ['confirmed', false, LIVE_SWEEP_TTL]
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql, values)
|
return db.any(sql, values)
|
||||||
}
|
}
|
||||||
|
|
@ -496,14 +465,12 @@ exports.fetchOldHD = function fetchLiveHD () {
|
||||||
where confirmed
|
where confirmed
|
||||||
order by last_checked
|
order by last_checked
|
||||||
limit 10`
|
limit 10`
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.any(sql)
|
return db.any(sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.markSwept = function markSwept (txId) {
|
exports.markSwept = function markSwept (txId) {
|
||||||
const sql = 'update cash_out_hds set swept=$1 where id=$2'
|
const sql = 'update cash_out_hds set swept=$1 where id=$2'
|
||||||
const db = connect()
|
|
||||||
|
|
||||||
return db.none(sql, [true, txId])
|
return db.none(sql, [true, txId])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const helmet = require('helmet')
|
||||||
|
const bodyParser = require('body-parser')
|
||||||
const BigNumber = require('bignumber.js')
|
const BigNumber = require('bignumber.js')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
const configManager = require('./config-manager')
|
const configManager = require('./config-manager')
|
||||||
|
|
@ -332,13 +334,34 @@ function filterOldRequests (req, res, next) {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function authorize (req, res, next) {
|
||||||
|
const deviceId = req.connection.getPeerCertificate().fingerprint
|
||||||
|
console.log(deviceId)
|
||||||
|
|
||||||
|
return pair.isPaired(deviceId)
|
||||||
|
.then(r => {
|
||||||
|
if (r) {
|
||||||
|
req.deviceId = deviceId
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Unauthorized')
|
||||||
|
})
|
||||||
|
.catch(e => res.status(403).end())
|
||||||
|
}
|
||||||
|
|
||||||
function init (opts) {
|
function init (opts) {
|
||||||
plugins = opts.plugins
|
plugins = opts.plugins
|
||||||
|
|
||||||
const authMiddleware = opts.authMiddleware
|
|
||||||
const app = opts.app
|
const app = opts.app
|
||||||
const localApp = opts.localApp
|
const localApp = opts.localApp
|
||||||
|
|
||||||
|
const authMiddleware = opts.devMode
|
||||||
|
? (req, res, next) => next()
|
||||||
|
: authorize
|
||||||
|
|
||||||
|
app.use(helmet())
|
||||||
|
app.use(bodyParser.json())
|
||||||
app.use(filterOldRequests)
|
app.use(filterOldRequests)
|
||||||
app.post('*', cacheAction)
|
app.post('*', cacheAction)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"license": "Unlicense",
|
"license": "Unlicense",
|
||||||
"author": "Lamassu (https://lamassu.is)",
|
"author": "Lamassu (https://lamassu.is)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"ajv": "^4.8.2",
|
||||||
"async": "~0.2.9",
|
"async": "~0.2.9",
|
||||||
"bignumber.js": "^2.3.0",
|
"bignumber.js": "^2.3.0",
|
||||||
"body-parser": "^1.15.1",
|
"body-parser": "^1.15.1",
|
||||||
|
|
@ -21,6 +22,7 @@
|
||||||
"lamassu-config": "lamassu/lamassu-config#alpha",
|
"lamassu-config": "lamassu/lamassu-config#alpha",
|
||||||
"lamassu-identitymind": "^1.2.9",
|
"lamassu-identitymind": "^1.2.9",
|
||||||
"lamassu-kraken": "^1.0.3",
|
"lamassu-kraken": "^1.0.3",
|
||||||
|
"lamassu-mock-wallet": "^1.0.0",
|
||||||
"lamassu-smtp2go": "^1.0.3",
|
"lamassu-smtp2go": "^1.0.3",
|
||||||
"lamassu-twilio": "^1.1.1",
|
"lamassu-twilio": "^1.1.1",
|
||||||
"migrate": "^0.2.2",
|
"migrate": "^0.2.2",
|
||||||
|
|
@ -48,6 +50,7 @@
|
||||||
"test": "mocha --recursive test"
|
"test": "mocha --recursive test"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"http-proxy": "^1.15.2"
|
"http-proxy": "^1.15.2",
|
||||||
|
"json-schema-generator": "^2.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
72
yarn.lock
72
yarn.lock
|
|
@ -7,6 +7,13 @@ accepts@~1.3.3:
|
||||||
mime-types "~2.1.11"
|
mime-types "~2.1.11"
|
||||||
negotiator "0.6.1"
|
negotiator "0.6.1"
|
||||||
|
|
||||||
|
ajv:
|
||||||
|
version "4.8.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.8.2.tgz#65486936ca36fea39a1504332a78bebd5d447bdc"
|
||||||
|
dependencies:
|
||||||
|
co "^4.6.0"
|
||||||
|
json-stable-stringify "^1.0.1"
|
||||||
|
|
||||||
ansi-regex@^2.0.0:
|
ansi-regex@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107"
|
||||||
|
|
@ -99,6 +106,10 @@ bl@~1.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
readable-stream "~2.0.5"
|
readable-stream "~2.0.5"
|
||||||
|
|
||||||
|
bluebird@*:
|
||||||
|
version "3.4.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f"
|
||||||
|
|
||||||
body-parser@^1.15.1:
|
body-parser@^1.15.1:
|
||||||
version "1.15.2"
|
version "1.15.2"
|
||||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.15.2.tgz#d7578cf4f1d11d5f6ea804cef35dc7a7ff6dae67"
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.15.2.tgz#d7578cf4f1d11d5f6ea804cef35dc7a7ff6dae67"
|
||||||
|
|
@ -165,6 +176,10 @@ chalk@^1.1.1:
|
||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
supports-color "^2.0.0"
|
supports-color "^2.0.0"
|
||||||
|
|
||||||
|
co@^4.6.0:
|
||||||
|
version "4.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||||
|
|
||||||
colors@1.0.x:
|
colors@1.0.x:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
||||||
|
|
@ -660,14 +675,40 @@ jsbn@~0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
|
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
|
||||||
|
|
||||||
|
json-promise@^1.1.8:
|
||||||
|
version "1.1.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-promise/-/json-promise-1.1.8.tgz#7b74120422d16ddb449aa3170403fc69ad416402"
|
||||||
|
dependencies:
|
||||||
|
bluebird "*"
|
||||||
|
|
||||||
|
json-schema-generator:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-schema-generator/-/json-schema-generator-2.0.3.tgz#e1a77df63cd0db4e1c8dfac03e08e2e4781502d3"
|
||||||
|
dependencies:
|
||||||
|
json-promise "^1.1.8"
|
||||||
|
mkdirp "^0.5.0"
|
||||||
|
optimist "^0.6.1"
|
||||||
|
pretty-data "^0.40.0"
|
||||||
|
request "^2.47.0"
|
||||||
|
|
||||||
json-schema@0.2.3:
|
json-schema@0.2.3:
|
||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||||
|
|
||||||
|
json-stable-stringify@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
|
||||||
|
dependencies:
|
||||||
|
jsonify "~0.0.0"
|
||||||
|
|
||||||
json-stringify-safe@~5.0.1:
|
json-stringify-safe@~5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||||
|
|
||||||
|
jsonify@~0.0.0:
|
||||||
|
version "0.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||||
|
|
||||||
jsonpointer@^4.0.0:
|
jsonpointer@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5"
|
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5"
|
||||||
|
|
@ -796,6 +837,10 @@ lamassu-kraken@^1.0.3:
|
||||||
lodash "^4.8.1"
|
lodash "^4.8.1"
|
||||||
promptly "^1.1.0"
|
promptly "^1.1.0"
|
||||||
|
|
||||||
|
lamassu-mock-wallet:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lamassu-mock-wallet/-/lamassu-mock-wallet-1.0.0.tgz#6d3ab723332e814fd50463c4917db1ce398845a8"
|
||||||
|
|
||||||
lamassu-smtp2go@^1.0.3:
|
lamassu-smtp2go@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lamassu-smtp2go/-/lamassu-smtp2go-1.0.3.tgz#dd9a3efcfb5f3d47016b4858536070a129b64958"
|
resolved "https://registry.yarnpkg.com/lamassu-smtp2go/-/lamassu-smtp2go-1.0.3.tgz#dd9a3efcfb5f3d47016b4858536070a129b64958"
|
||||||
|
|
@ -901,10 +946,20 @@ minimist@^1.1.3:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||||
|
|
||||||
|
minimist@~0.0.1:
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||||
|
|
||||||
minimist@0.0.8:
|
minimist@0.0.8:
|
||||||
version "0.0.8"
|
version "0.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||||
|
|
||||||
|
mkdirp@^0.5.0:
|
||||||
|
version "0.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||||
|
dependencies:
|
||||||
|
minimist "0.0.8"
|
||||||
|
|
||||||
ms@^0.7.1:
|
ms@^0.7.1:
|
||||||
version "0.7.2"
|
version "0.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
|
||||||
|
|
@ -978,6 +1033,13 @@ on-finished@~2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ee-first "1.1.1"
|
ee-first "1.1.1"
|
||||||
|
|
||||||
|
optimist@^0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
|
||||||
|
dependencies:
|
||||||
|
minimist "~0.0.1"
|
||||||
|
wordwrap "~0.0.2"
|
||||||
|
|
||||||
packet-reader@0.2.0:
|
packet-reader@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.2.0.tgz#819df4d010b82d5ea5671f8a1a3acf039bcd7700"
|
resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.2.0.tgz#819df4d010b82d5ea5671f8a1a3acf039bcd7700"
|
||||||
|
|
@ -1117,6 +1179,10 @@ postgres-interval@~1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
|
pretty-data@^0.40.0:
|
||||||
|
version "0.40.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/pretty-data/-/pretty-data-0.40.0.tgz#572aa8ea23467467ab94b6b5266a6fd9c8fddd72"
|
||||||
|
|
||||||
pretty-ms@^2.1.0:
|
pretty-ms@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-2.1.0.tgz#4257c256df3fb0b451d6affaab021884126981dc"
|
resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-2.1.0.tgz#4257c256df3fb0b451d6affaab021884126981dc"
|
||||||
|
|
@ -1241,7 +1307,7 @@ repeating@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-finite "^1.0.0"
|
is-finite "^1.0.0"
|
||||||
|
|
||||||
request@>=2.27.0:
|
request@^2.47.0, request@>=2.27.0:
|
||||||
version "2.78.0"
|
version "2.78.0"
|
||||||
resolved "https://registry.yarnpkg.com/request/-/request-2.78.0.tgz#e1c8dec346e1c81923b24acdb337f11decabe9cc"
|
resolved "https://registry.yarnpkg.com/request/-/request-2.78.0.tgz#e1c8dec346e1c81923b24acdb337f11decabe9cc"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -1551,6 +1617,10 @@ winston@^2.3.0:
|
||||||
isstream "0.1.x"
|
isstream "0.1.x"
|
||||||
stack-trace "0.0.x"
|
stack-trace "0.0.x"
|
||||||
|
|
||||||
|
wordwrap@~0.0.2:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
|
||||||
|
|
||||||
wreck@^3.0.0, wreck@~3.0.0:
|
wreck@^3.0.0, wreck@~3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wreck/-/wreck-3.0.0.tgz#5151840a6c46d785bc81035a2e67b4e33406ba11"
|
resolved "https://registry.yarnpkg.com/wreck/-/wreck-3.0.0.tgz#5151840a6c46d785bc81035a2e67b4e33406ba11"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue