chore: undo $ prepend on queries

This commit is contained in:
Taranto 2021-07-22 11:06:39 +01:00 committed by Josh Harvey
parent f3f2bb01b0
commit ba4117173e
50 changed files with 215 additions and 227 deletions

View file

@ -5,11 +5,11 @@ var psqlUrl = require('../lib/options').postgresql
var db = pgp(psqlUrl) var db = pgp(psqlUrl)
db.$manyOrNone(`select * from transactions where incoming=false db.manyOrNone(`select * from transactions where incoming=false
and stage='final_request' and authority='machine'`) and stage='final_request' and authority='machine'`)
.then(rs => .then(rs =>
db.tx(t => db.tx(t =>
t.batch(rs.map(r => db.$none(`insert into cash_in_txs (session_id, t.batch(rs.map(r => db.none(`insert into cash_in_txs (session_id,
device_fingerprint, to_address, crypto_atoms, crypto_code, fiat, device_fingerprint, to_address, crypto_atoms, crypto_code, fiat,
currency_code, fee, tx_hash, error, created) values ($1, $2, $3, $4, $5, currency_code, fee, tx_hash, error, created) values ($1, $2, $3, $4, $5,
$6, $7, $8, $9, $10, $11)`, [r.session_id, r.device_fingerprint, $6, $7, $8, $9, $10, $11)`, [r.session_id, r.device_fingerprint,
@ -18,11 +18,11 @@ db.$manyOrNone(`select * from transactions where incoming=false
) )
) )
) )
.then(() => db.$manyOrNone(`select * from transactions where incoming=true .then(() => db.manyOrNone(`select * from transactions where incoming=true
and stage='initial_request' and authority='pending'`)) and stage='initial_request' and authority='pending'`))
.then(rs => .then(rs =>
db.tx(t => db.tx(t =>
t.batch(rs.map(r => db.$none(`insert into cash_out_txs (session_id, t.batch(rs.map(r => db.none(`insert into cash_out_txs (session_id,
device_fingerprint, to_address, crypto_atoms, crypto_code, fiat, device_fingerprint, to_address, crypto_atoms, crypto_code, fiat,
currency_code, tx_hash, phone, error, created) values ($1, $2, $3, $4, $5, currency_code, tx_hash, phone, error, created) values ($1, $2, $3, $4, $5,
$6, $7, $8, $9, $10, $11)`, [r.session_id, r.device_fingerprint, $6, $7, $8, $9, $10, $11)`, [r.session_id, r.device_fingerprint,
@ -31,13 +31,13 @@ db.$manyOrNone(`select * from transactions where incoming=false
) )
) )
) )
.then(() => db.$manyOrNone(`select * from transactions where incoming=true .then(() => db.manyOrNone(`select * from transactions where incoming=true
and stage='dispense' and authority='authorized'`)) and stage='dispense' and authority='authorized'`))
.then(rs => .then(rs =>
db.tx(t => db.tx(t =>
t.batch(rs.map(r => t.batch(rs.map(r =>
db.$none(`update cash_out_txs set dispensed=true where session_id=$1`, [r.session_id]) db.none(`update cash_out_txs set dispensed=true where session_id=$1`, [r.session_id])
.then(() => db.$none(`insert into cash_out_actions (session_id, action, .then(() => db.none(`insert into cash_out_actions (session_id, action,
created) values ($1, $2, $3)`, [r.session_id, 'dispensed', r.created])) created) values ($1, $2, $3)`, [r.session_id, 'dispensed', r.created]))
)) ))
) )

View file

@ -23,12 +23,12 @@ const getMigrateFile = () => {
const store = defaultStore() const store = defaultStore()
asyncLocalStorage.run(store, () => { asyncLocalStorage.run(store, () => {
db.$none(createMigration) db.none(createMigration)
.then(() => Promise.all([db.$oneOrNone(select), getMigrateFile()])) .then(() => Promise.all([db.oneOrNone(select), getMigrateFile()]))
.then(([qResult, migrateFile]) => { .then(([qResult, migrateFile]) => {
process.env.SKIP_SERVER_LOGS = !(qResult && qResult.data.migrations.find(({ title }) => title === '1572524820075-server-support-logs.js')) process.env.SKIP_SERVER_LOGS = !(qResult && qResult.data.migrations.find(({ title }) => title === '1572524820075-server-support-logs.js'))
if (!qResult && migrateFile) { if (!qResult && migrateFile) {
return db.$none('insert into migrations (id, data) values (1, $1)', [migrateFile]) return db.none('insert into migrations (id, data) values (1, $1)', [migrateFile])
} }
}) })
.then(() => migrate.run()) .then(() => migrate.run())

View file

@ -7,7 +7,7 @@ const psqlUrl = require('../lib/options').postgresql
const db = pgp(psqlUrl) const db = pgp(psqlUrl)
db.$many('select data from user_config', 'exchanges') db.many('select data from user_config', 'exchanges')
.then(rows => { .then(rows => {
const config = rows.filter(r => r.type === 'exchanges')[0].data const config = rows.filter(r => r.type === 'exchanges')[0].data
const brain = rows.filter(r => r.type === 'unit')[0].data const brain = rows.filter(r => r.type === 'unit')[0].data
@ -33,7 +33,7 @@ db.$many('select data from user_config', 'exchanges')
accounts: settings.plugins.settings accounts: settings.plugins.settings
} }
db.$none('insert into user_config (type, data) values ($1, $2)', ['global', newConfig]) db.none('insert into user_config (type, data) values ($1, $2)', ['global', newConfig])
.then(() => { .then(() => {
console.log('Success.') console.log('Success.')
process.exit(0) process.exit(0)

View file

@ -18,7 +18,7 @@ function loadSchemas () {
const schemas = loadSchemas() const schemas = loadSchemas()
function fetchAccounts () { function fetchAccounts () {
return db.$oneOrNone('select data from user_config where type=$1 and schema_version=$2', ['accounts', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.oneOrNone('select data from user_config where type=$1 and schema_version=$2', ['accounts', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => { .then(row => {
// Hard code this for now // Hard code this for now
const accounts = [{ const accounts = [{
@ -31,7 +31,7 @@ function fetchAccounts () {
return row return row
? Promise.resolve(row.data.accounts) ? Promise.resolve(row.data.accounts)
: db.$none('insert into user_config (type, data, valid) values ($1, $2, $3)', ['accounts', {accounts}, true]) : db.none('insert into user_config (type, data, valid) values ($1, $2, $3)', ['accounts', {accounts}, true])
.then(fetchAccounts) .then(fetchAccounts)
}) })
} }
@ -102,7 +102,7 @@ function getAccount (accountCode) {
} }
function save (accounts) { function save (accounts) {
return db.$none('update user_config set data=$1 where type=$2 and schema_version=$3', [{accounts: accounts}, 'accounts', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.none('update user_config set data=$1 where type=$2 and schema_version=$3', [{accounts: accounts}, 'accounts', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
} }
function updateAccounts (newAccount, accounts) { function updateAccounts (newAccount, accounts) {

View file

@ -104,7 +104,7 @@ function getGroupField (group, fieldCode) {
// Note: We can't use machine-loader because it relies on settings-loader, // Note: We can't use machine-loader because it relies on settings-loader,
// which relies on this // which relies on this
function getMachines () { function getMachines () {
return db.$any('select device_id from devices') return db.any('select device_id from devices')
} }
function fetchMachines () { function fetchMachines () {

View file

@ -22,7 +22,7 @@ function fetchConfig () {
const sql = `select data from user_config where type=$1 and schema_version=$2 const sql = `select data from user_config where type=$1 and schema_version=$2
order by id desc limit 1` order by id desc limit 1`
return db.$oneOrNone(sql, ['config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.oneOrNone(sql, ['config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row ? row.data.config : []) .then(row => row ? row.data.config : [])
} }

View file

@ -7,7 +7,7 @@ function generateOTP (name) {
const sql = 'insert into one_time_passes (token, name) values ($1, $2)' const sql = 'insert into one_time_passes (token, name) values ($1, $2)'
return db.$none(sql, [otp, name]) return db.none(sql, [otp, name])
.then(() => otp) .then(() => otp)
} }
@ -16,7 +16,7 @@ function validateOTP (otp) {
where token=$1 where token=$1
returning name, created < now() - interval '1 hour' as expired` returning name, created < now() - interval '1 hour' as expired`
return db.$one(sql, [otp]) return db.one(sql, [otp])
.then(r => ({success: !r.expired, expired: r.expired, name: r.name})) .then(r => ({success: !r.expired, expired: r.expired, name: r.name}))
.catch(() => ({success: false, expired: false})) .catch(() => ({success: false, expired: false}))
} }
@ -29,7 +29,7 @@ function register (otp) {
const token = crypto.randomBytes(32).toString('hex') const token = crypto.randomBytes(32).toString('hex')
const sql = 'insert into user_tokens (token, name) values ($1, $2)' const sql = 'insert into user_tokens (token, name) values ($1, $2)'
return db.$none(sql, [token, r.name]) return db.none(sql, [token, r.name])
.then(() => ({success: true, token: token})) .then(() => ({success: true, token: token}))
}) })
.catch(() => ({success: false, expired: false})) .catch(() => ({success: false, expired: false}))
@ -38,7 +38,7 @@ function register (otp) {
function authenticate (token) { function authenticate (token) {
const sql = 'select token from user_tokens where token=$1' const sql = 'select token from user_tokens where token=$1'
return db.$one(sql, [token]).then(() => true).catch(() => false) return db.one(sql, [token]).then(() => true).catch(() => false)
} }
module.exports = { module.exports = {

View file

@ -25,7 +25,7 @@ function totem (hostname, name) {
const buf = Buffer.concat([caHash, token, Buffer.from(hostname)]) const buf = Buffer.concat([caHash, token, Buffer.from(hostname)])
const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)' const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)'
return db.$none(sql, [hexToken, caHexToken, name]) return db.none(sql, [hexToken, caHexToken, name])
.then(() => bsAlpha.encode(buf)) .then(() => bsAlpha.encode(buf))
}) })
} }

View file

@ -20,7 +20,7 @@ function machinesLastPing () {
from machine_events from machine_events
group by device_id` group by device_id`
return Promise.all([machineLoader.getMachineNames(), db.$any(sql)]) return Promise.all([machineLoader.getMachineNames(), db.any(sql)])
.then(([machines, events]) => { .then(([machines, events]) => {
if (machines.length === 0) return 'No paired machines' if (machines.length === 0) return 'No paired machines'
@ -52,7 +52,7 @@ function status () {
order by created desc order by created desc
limit 1` limit 1`
return Promise.all([checkWasConfigured(), db.$oneOrNone(sql, ['ping']), machinesLastPing()]) return Promise.all([checkWasConfigured(), db.oneOrNone(sql, ['ping']), machinesLastPing()])
.then(([wasConfigured, statusRow, machineStatus]) => { .then(([wasConfigured, statusRow, machineStatus]) => {
const age = statusRow && moment.duration(statusRow.age, 'seconds') const age = statusRow && moment.duration(statusRow.age, 'seconds')
const up = statusRow ? statusRow.age < CONSIDERED_UP_SECS : false const up = statusRow ? statusRow.age < CONSIDERED_UP_SECS : false

View file

@ -70,7 +70,7 @@ function loadConfig (versionId) {
where id=$1 and type=$2 and schema_version=$3 where id=$1 and type=$2 and schema_version=$3
and valid` and valid`
return db.$one(sql, [versionId, 'config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.one(sql, [versionId, 'config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row.data.config) .then(row => row.data.config)
.then(configValidate.validate) .then(configValidate.validate)
.catch(err => { .catch(err => {
@ -92,7 +92,7 @@ function loadLatestConfig (filterSchemaVersion = true) {
order by id desc order by id desc
limit 1` limit 1`
return db.$one(sql, ['config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.one(sql, ['config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row.data.config) .then(row => row.data.config)
.then(configValidate.validate) .then(configValidate.validate)
.catch(err => { .catch(err => {
@ -113,7 +113,7 @@ function loadRecentConfig () {
order by id desc order by id desc
limit 1` limit 1`
return db.$one(sql, ['config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.one(sql, ['config', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row.data.config) .then(row => row.data.config)
} }
@ -121,7 +121,7 @@ function loadAccounts (filterSchemaVersion = true) {
const toFields = fieldArr => _.fromPairs(_.map(r => [r.code, r.value], fieldArr)) const toFields = fieldArr => _.fromPairs(_.map(r => [r.code, r.value], fieldArr))
const toPairs = r => [r.code, toFields(r.fields)] const toPairs = r => [r.code, toFields(r.fields)]
return db.$oneOrNone(`select data from user_config where type=$1 ${filterSchemaVersion ? 'and schema_version=$2' : ''}`, ['accounts', configValidate.SETTINGS_LOADER_SCHEMA_VERSION]) return db.oneOrNone(`select data from user_config where type=$1 ${filterSchemaVersion ? 'and schema_version=$2' : ''}`, ['accounts', configValidate.SETTINGS_LOADER_SCHEMA_VERSION])
.then(function (data) { .then(function (data) {
if (!data) return {} if (!data) return {}
return _.fromPairs(_.map(toPairs, data.data.accounts)) return _.fromPairs(_.map(toPairs, data.data.accounts))
@ -136,8 +136,8 @@ function save (config) {
const sql = 'insert into user_config (type, data, valid) values ($1, $2, $3)' const sql = 'insert into user_config (type, data, valid) values ($1, $2, $3)'
return configValidate.validate(config) return configValidate.validate(config)
.then(() => db.$none(sql, ['config', {config}, true])) .then(() => db.none(sql, ['config', {config}, true]))
.catch(() => db.$none(sql, ['config', {config}, false])) .catch(() => db.none(sql, ['config', {config}, false]))
} }
function configAddField (scope, fieldCode, fieldType, fieldClass, value) { function configAddField (scope, fieldCode, fieldType, fieldClass, value) {

View file

@ -37,7 +37,7 @@ function batch () {
from cash_out_txs from cash_out_txs
order by created desc limit $1` order by created desc limit $1`
return Promise.all([db.$any(cashInSql, [cashInTx.PENDING_INTERVAL, NUM_RESULTS]), db.$any(cashOutSql, [NUM_RESULTS, REDEEMABLE_AGE])]) return Promise.all([db.any(cashInSql, [cashInTx.PENDING_INTERVAL, NUM_RESULTS]), db.any(cashOutSql, [NUM_RESULTS, REDEEMABLE_AGE])])
.then(packager) .then(packager)
} }
@ -57,8 +57,8 @@ function single (txId) {
where id=$1` where id=$1`
return Promise.all([ return Promise.all([
db.$oneOrNone(cashInSql, [cashInTx.PENDING_INTERVAL, txId]), db.oneOrNone(cashInSql, [cashInTx.PENDING_INTERVAL, txId]),
db.$oneOrNone(cashOutSql, [txId, REDEEMABLE_AGE]) db.oneOrNone(cashOutSql, [txId, REDEEMABLE_AGE])
]) ])
.then(packager) .then(packager)
.then(_.head) .then(_.head)

View file

@ -7,7 +7,7 @@ function createAuthToken (userID, type) {
const token = crypto.randomBytes(32).toString('hex') const token = crypto.randomBytes(32).toString('hex')
const sql = `INSERT INTO auth_tokens (token, type, user_id) VALUES ($1, $2, $3) ON CONFLICT (user_id, type) DO UPDATE SET token=$1, expire=now() + interval '${constants.AUTH_TOKEN_EXPIRATION_TIME}' RETURNING *` const sql = `INSERT INTO auth_tokens (token, type, user_id) VALUES ($1, $2, $3) ON CONFLICT (user_id, type) DO UPDATE SET token=$1, expire=now() + interval '${constants.AUTH_TOKEN_EXPIRATION_TIME}' RETURNING *`
return db.$one(sql, [token, type, userID]) return db.one(sql, [token, type, userID])
} }
module.exports = { module.exports = {

View file

@ -3,7 +3,7 @@ const notifierQueries = require('./notifier/queries')
// Get all blacklist rows from the DB "blacklist" table that were manually inserted by the operator // Get all blacklist rows from the DB "blacklist" table that were manually inserted by the operator
const getBlacklist = () => { const getBlacklist = () => {
return db.$any(`SELECT * FROM blacklist`).then(res => return db.any(`SELECT * FROM blacklist`).then(res =>
res.map(item => ({ res.map(item => ({
cryptoCode: item.crypto_code, cryptoCode: item.crypto_code,
address: item.address address: item.address
@ -15,12 +15,12 @@ const getBlacklist = () => {
const deleteFromBlacklist = (cryptoCode, address) => { const deleteFromBlacklist = (cryptoCode, address) => {
const sql = `DELETE FROM blacklist WHERE crypto_code = $1 AND address = $2` const sql = `DELETE FROM blacklist WHERE crypto_code = $1 AND address = $2`
notifierQueries.clearBlacklistNotification(cryptoCode, address) notifierQueries.clearBlacklistNotification(cryptoCode, address)
return db.$none(sql, [cryptoCode, address]) return db.none(sql, [cryptoCode, address])
} }
const insertIntoBlacklist = (cryptoCode, address) => { const insertIntoBlacklist = (cryptoCode, address) => {
return db return db
.$none( .none(
'INSERT INTO blacklist (crypto_code, address) VALUES ($1, $2);', 'INSERT INTO blacklist (crypto_code, address) VALUES ($1, $2);',
[cryptoCode, address] [cryptoCode, address]
) )
@ -28,7 +28,7 @@ const insertIntoBlacklist = (cryptoCode, address) => {
function blocked (address, cryptoCode) { function blocked (address, cryptoCode) {
const sql = `SELECT * FROM blacklist WHERE address = $1 AND crypto_code = $2` const sql = `SELECT * FROM blacklist WHERE address = $1 AND crypto_code = $2`
return db.$any(sql, [address, cryptoCode]) return db.any(sql, [address, cryptoCode])
} }
function addToUsedAddresses (address, cryptoCode) { function addToUsedAddresses (address, cryptoCode) {
@ -36,7 +36,7 @@ function addToUsedAddresses (address, cryptoCode) {
if (cryptoCode === 'ETH') return Promise.resolve() if (cryptoCode === 'ETH') return Promise.resolve()
const sql = `INSERT INTO blacklist (crypto_code, address) VALUES ($1, $2)` const sql = `INSERT INTO blacklist (crypto_code, address) VALUES ($1, $2)`
return db.$oneOrNone(sql, [cryptoCode, address]) return db.oneOrNone(sql, [cryptoCode, address])
} }
module.exports = { module.exports = {

View file

@ -16,11 +16,11 @@ function atomic (machineTx, pi) {
const sql = 'select * from cash_in_txs where id=$1' const sql = 'select * from cash_in_txs where id=$1'
const sql2 = 'select * from bills where cash_in_txs_id=$1' const sql2 = 'select * from bills where cash_in_txs_id=$1'
return t.$oneOrNone(sql, [machineTx.id]) return t.oneOrNone(sql, [machineTx.id])
.then(row => { .then(row => {
if (row && row.tx_version >= machineTx.txVersion) throw new E.StaleTxError('Stale tx') if (row && row.tx_version >= machineTx.txVersion) throw new E.StaleTxError('Stale tx')
return t.$any(sql2, [machineTx.id]) return t.any(sql2, [machineTx.id])
.then(billRows => { .then(billRows => {
const dbTx = cashInLow.toObj(row) const dbTx = cashInLow.toObj(row)
@ -47,9 +47,9 @@ function insertNewBills (t, billRows, machineTx) {
const sql2 = `update devices set cashbox = cashbox + $2 const sql2 = `update devices set cashbox = cashbox + $2
where device_id = $1` where device_id = $1`
return t.$none(sql2, [deviceID, dbBills.length]) return t.none(sql2, [deviceID, dbBills.length])
.then(() => { .then(() => {
return t.$none(sql) return t.none(sql)
}) })
.then(() => bills) .then(() => bills)
} }

View file

@ -61,7 +61,7 @@ function upsert (t, dbTx, preProcessedTx) {
function insert (t, tx) { function insert (t, tx) {
const dbTx = massage(tx) const dbTx = massage(tx)
const sql = pgp.helpers.insert(dbTx, null, 'cash_in_txs') + ' returning *' const sql = pgp.helpers.insert(dbTx, null, 'cash_in_txs') + ' returning *'
return t.$one(sql) return t.one(sql)
.then(toObj) .then(toObj)
} }
@ -72,7 +72,7 @@ function update (t, tx, changes) {
const sql = pgp.helpers.update(dbChanges, null, 'cash_in_txs') + const sql = pgp.helpers.update(dbChanges, null, 'cash_in_txs') +
pgp.as.format(' where id=$1', [tx.id]) + ' returning *' pgp.as.format(' where id=$1', [tx.id]) + ' returning *'
return t.$one(sql) return t.one(sql)
.then(toObj) .then(toObj)
} }

View file

@ -69,7 +69,7 @@ function logAction (rec, tx) {
const sql = pgp.helpers.insert(action, null, 'cash_in_actions') const sql = pgp.helpers.insert(action, null, 'cash_in_actions')
return db.$none(sql) return db.none(sql)
.then(_.constant(rec)) .then(_.constant(rec))
} }
@ -77,7 +77,7 @@ function logActionById (action, _rec, txId) {
const rec = _.assign(_rec, { action, tx_id: txId }) const rec = _.assign(_rec, { action, tx_id: txId })
const sql = pgp.helpers.insert(rec, null, 'cash_in_actions') const sql = pgp.helpers.insert(rec, null, 'cash_in_actions')
return db.$none(sql) return db.none(sql)
} }
function checkForBlacklisted (tx) { function checkForBlacklisted (tx) {
@ -165,7 +165,7 @@ function monitorPending (settings) {
.catch(logger.error) .catch(logger.error)
} }
return db.$any(sql, [PENDING_INTERVAL, MAX_PENDING]) return db.any(sql, [PENDING_INTERVAL, MAX_PENDING])
.then(rows => pEachSeries(rows, row => processPending(row))) .then(rows => pEachSeries(rows, row => processPending(row)))
.catch(logger.error) .catch(logger.error)
} }
@ -182,7 +182,7 @@ function cancel (txId) {
return pgp.helpers.update(updateRec, null, 'cash_in_txs') + return pgp.helpers.update(updateRec, null, 'cash_in_txs') +
pgp.as.format(' where id=$1', [txId]) pgp.as.format(' where id=$1', [txId])
}) })
.then(sql => db.$result(sql, false)) .then(sql => db.result(sql, false))
.then(res => { .then(res => {
if (res.rowCount !== 1) throw new Error('No such tx-id') if (res.rowCount !== 1) throw new Error('No such tx-id')
}) })

View file

@ -14,14 +14,14 @@ function logActionById (t, action, _rec, txId) {
const rec = _.assign(_rec, {action, tx_id: txId, redeem: false}) const rec = _.assign(_rec, {action, tx_id: txId, redeem: false})
const sql = pgp.helpers.insert(rec, null, 'cash_out_actions') const sql = pgp.helpers.insert(rec, null, 'cash_out_actions')
return t.$none(sql) return t.none(sql)
} }
function logAction (t, action, _rec, tx) { function logAction (t, action, _rec, tx) {
const rec = _.assign(_rec, {action, tx_id: tx.id, redeem: !!tx.redeem, device_id: tx.deviceId}) const rec = _.assign(_rec, {action, tx_id: tx.id, redeem: !!tx.redeem, device_id: tx.deviceId})
const sql = pgp.helpers.insert(rec, null, 'cash_out_actions') const sql = pgp.helpers.insert(rec, null, 'cash_out_actions')
return t.$none(sql) return t.none(sql)
.then(_.constant(tx)) .then(_.constant(tx))
} }

View file

@ -20,7 +20,7 @@ function atomic (tx, pi, fromClient) {
const mode = new TransactionMode({ tiLevel: isolationLevel.serializable }) const mode = new TransactionMode({ tiLevel: isolationLevel.serializable })
function transaction (t) { function transaction (t) {
const sql = 'select * from cash_out_txs where id=$1' const sql = 'select * from cash_out_txs where id=$1'
return t.$oneOrNone(sql, [tx.id]) return t.oneOrNone(sql, [tx.id])
.then(toObj) .then(toObj)
.then(oldTx => { .then(oldTx => {
const isStale = fromClient && oldTx && (oldTx.txVersion >= tx.txVersion) const isStale = fromClient && oldTx && (oldTx.txVersion >= tx.txVersion)
@ -99,7 +99,7 @@ function preProcess (t, oldTx, newTx, pi) {
function nextHd (t, isHd, tx) { function nextHd (t, isHd, tx) {
if (!isHd) return Promise.resolve(tx) if (!isHd) return Promise.resolve(tx)
return t.$one("select nextval('hd_indices_seq') as hd_index") return t.one("select nextval('hd_indices_seq') as hd_index")
.then(row => _.set('hdIndex', row.hd_index, tx)) .then(row => _.set('hdIndex', row.hd_index, tx))
} }
@ -118,7 +118,7 @@ function updateCassettes (t, tx) {
tx.deviceId tx.deviceId
] ]
return t.$one(sql, values) return t.one(sql, values)
.then(r => socket.emit(_.assign(r, {op: 'cassetteUpdate', deviceId: tx.deviceId}))) .then(r => socket.emit(_.assign(r, {op: 'cassetteUpdate', deviceId: tx.deviceId})))
} }

View file

@ -111,6 +111,6 @@ function redeemableTxs (deviceId) {
and provisioned_1 is not null and provisioned_1 is not null
and (extract(epoch from (now() - greatest(created, confirmed_at))) * 1000) < $4` and (extract(epoch from (now() - greatest(created, confirmed_at))) * 1000) < $4`
return db.$any(sql, [deviceId, true, false, REDEEMABLE_AGE]) return db.any(sql, [deviceId, true, false, REDEEMABLE_AGE])
.then(_.map(toObj)) .then(_.map(toObj))
} }

View file

@ -26,7 +26,7 @@ function insert (t, tx) {
const dbTx = toDb(tx) const dbTx = toDb(tx)
const sql = pgp.helpers.insert(dbTx, null, 'cash_out_txs') + ' returning *' const sql = pgp.helpers.insert(dbTx, null, 'cash_out_txs') + ' returning *'
return t.$one(sql) return t.one(sql)
.then(toObj) .then(toObj)
} }
@ -39,7 +39,7 @@ function update (t, tx, changes) {
const newTx = _.merge(tx, changes) const newTx = _.merge(tx, changes)
return t.$none(sql) return t.none(sql)
.then(() => newTx) .then(() => newTx)
} }

View file

@ -103,7 +103,7 @@ function fetchOpenTxs (statuses, fromAge, toAge, applyFilter, coinFilter) {
const coinClause = _.map(pgp.as.text, coinFilter).join(',') const coinClause = _.map(pgp.as.text, coinFilter).join(',')
const statusClause = _.map(pgp.as.text, statuses).join(',') const statusClause = _.map(pgp.as.text, statuses).join(',')
return db.$any(sql, [fromAge, toAge, coinClause, statusClause]) return db.any(sql, [fromAge, toAge, coinClause, statusClause])
.then(rows => rows.map(toObj)) .then(rows => rows.map(toObj))
} }
@ -151,7 +151,7 @@ function monitorUnnotified (settings) {
and (redeem=$4 or ((extract(epoch from (now() - created))) * 1000)>$5)` and (redeem=$4 or ((extract(epoch from (now() - created))) * 1000)>$5)`
const notify = tx => plugins(settings, tx.deviceId).notifyConfirmation(tx) const notify = tx => plugins(settings, tx.deviceId).notifyConfirmation(tx)
return db.$any(sql, [MAX_NOTIFY_AGE, false, false, true, MIN_NOTIFY_AGE]) return db.any(sql, [MAX_NOTIFY_AGE, false, false, true, MIN_NOTIFY_AGE])
.then(rows => _.map(toObj, rows)) .then(rows => _.map(toObj, rows))
.then(txs => Promise.all(txs.map(notify))) .then(txs => Promise.all(txs.map(notify)))
.catch(logger.error) .catch(logger.error)
@ -169,7 +169,7 @@ function cancel (txId) {
return pgp.helpers.update(updateRec, null, 'cash_out_txs') + return pgp.helpers.update(updateRec, null, 'cash_out_txs') +
pgp.as.format(' where id=$1', [txId]) pgp.as.format(' where id=$1', [txId])
}) })
.then(sql => db.$result(sql, false)) .then(sql => db.result(sql, false))
.then(res => { .then(res => {
if (res.rowCount !== 1) throw new Error('No such tx-id') if (res.rowCount !== 1) throw new Error('No such tx-id')
}) })

View file

@ -108,7 +108,7 @@ function getMachines (rates, settings) {
where display=TRUE and where display=TRUE and
paired=TRUE paired=TRUE
order by created` order by created`
return db.$any(sql, [STALE_INTERVAL]) return db.any(sql, [STALE_INTERVAL])
.then(_.map(_.partial(mapMachine, [rates, settings]))) .then(_.map(_.partial(mapMachine, [rates, settings])))
} }

View file

@ -260,6 +260,6 @@ test('Verify axios request schema', async () => {
) )
) )
db.$any.mockResolvedValue(dbResponse) db.any.mockResolvedValue(dbResponse)
await car.update(rates, settings) await car.update(rates, settings)
}) })

View file

@ -11,7 +11,7 @@ function logSanctionsMatch (deviceId, customer, sanctionsId, alias) {
values values
($1, $2, $3, $4, $5, $6)` ($1, $2, $3, $4, $5, $6)`
return db.$none(sql, [uuid.v4(), deviceId, sanctionsId, alias.id, alias.fullName, customer.id]) return db.none(sql, [uuid.v4(), deviceId, sanctionsId, alias.id, alias.fullName, customer.id])
} }
function logSanctionsMatches (deviceId, customer, results) { function logSanctionsMatches (deviceId, customer, results) {

View file

@ -20,7 +20,7 @@ function add (complianceOverride) {
override_by, override_by,
verification) verification)
values ($1, $2, $3, now(), $4, $5) returning *` values ($1, $2, $3, now(), $4, $5) returning *`
return db.$one(sql, [ return db.one(sql, [
uuid.v4(), uuid.v4(),
complianceOverride.customerId, complianceOverride.customerId,
complianceOverride.complianceType, complianceOverride.complianceType,

View file

@ -34,7 +34,7 @@ const operatorDataDir = _.get('operatorDataDir', options)
*/ */
function add (customer) { function add (customer) {
const sql = 'insert into customers (id, phone, phone_at) values ($1, $2, now()) returning *' const sql = 'insert into customers (id, phone, phone_at) values ($1, $2, now()) returning *'
return db.$one(sql, [uuid.v4(), customer.phone]) return db.one(sql, [uuid.v4(), customer.phone])
.then(populateOverrideUsernames) .then(populateOverrideUsernames)
.then(computeStatus) .then(computeStatus)
.then(populateDailyVolume) .then(populateDailyVolume)
@ -54,7 +54,7 @@ function add (customer) {
*/ */
function get (phone) { function get (phone) {
const sql = 'select * from customers where phone=$1' const sql = 'select * from customers where phone=$1'
return db.$oneOrNone(sql, [phone]) return db.oneOrNone(sql, [phone])
.then(populateDailyVolume) .then(populateDailyVolume)
.then(camelize) .then(camelize)
} }
@ -80,7 +80,7 @@ function update (id, data, userToken, txId) {
const sql = Pgp.helpers.update(updateData, _.keys(updateData), 'customers') + const sql = Pgp.helpers.update(updateData, _.keys(updateData), 'customers') +
' where id=$1 returning *' ' where id=$1 returning *'
return db.$one(sql, [id]) return db.one(sql, [id])
.then(addComplianceOverrides(id, updateData, userToken)) .then(addComplianceOverrides(id, updateData, userToken))
.then(populateOverrideUsernames) .then(populateOverrideUsernames)
.then(computeStatus) .then(computeStatus)
@ -120,7 +120,7 @@ async function updateCustomer (id, data, userToken) {
' where id=$1' ' where id=$1'
invalidateCustomerNotifications(id, formattedData) invalidateCustomerNotifications(id, formattedData)
await db.$none(sql, [id]) await db.none(sql, [id])
return getCustomerById(id) return getCustomerById(id)
} }
@ -145,7 +145,7 @@ const invalidateCustomerNotifications = (id, data) => {
*/ */
function getById (id, userToken) { function getById (id, userToken) {
const sql = 'select * from customers where id=$1' const sql = 'select * from customers where id=$1'
return db.$oneOrNone(sql, [id]) return db.oneOrNone(sql, [id])
.then(populateOverrideUsernames) .then(populateOverrideUsernames)
.then(computeStatus) .then(computeStatus)
.then(populateDailyVolume) .then(populateDailyVolume)
@ -174,10 +174,10 @@ function getDailyVolume (id, txId) {
function getDailyVolumeQueries (id) { function getDailyVolumeQueries (id) {
return [ return [
db.$one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_in_txs db.one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_in_txs
where customer_id=$1 where customer_id=$1
and created > now() - interval '1 day'`, [id]), and created > now() - interval '1 day'`, [id]),
db.$one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_out_txs db.one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_out_txs
where customer_id=$1 where customer_id=$1
and created > now() - interval '1 day'`, [id]) and created > now() - interval '1 day'`, [id])
] ]
@ -185,11 +185,11 @@ function getDailyVolumeQueries (id) {
function getDailyVolumeMinusCurrentTxQueries (id, txId) { function getDailyVolumeMinusCurrentTxQueries (id, txId) {
return [ return [
db.$one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_in_txs db.one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_in_txs
where customer_id=$1 where customer_id=$1
and id!=$2 and id!=$2
and created > now() - interval '1 day'`, [id, txId]), and created > now() - interval '1 day'`, [id, txId]),
db.$one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_out_txs db.one(`select coalesce(sum(fiat), 0) as total, max(created) as maxdate from cash_out_txs
where customer_id=$1 where customer_id=$1
and id!=$2 and id!=$2
and created > now() - interval '1 day'`, [id, txId]) and created > now() - interval '1 day'`, [id, txId])
@ -432,7 +432,7 @@ function batch () {
const sql = `select * from customers const sql = `select * from customers
where id != $1 where id != $1
order by created desc limit $2` order by created desc limit $2`
return db.$any(sql, [ anonymous.uuid, NUM_RESULTS ]) return db.any(sql, [ anonymous.uuid, NUM_RESULTS ])
.then(customers => Promise.all(_.map(customer => { .then(customers => Promise.all(_.map(customer => {
return populateOverrideUsernames(customer) return populateOverrideUsernames(customer)
.then(computeStatus) .then(computeStatus)
@ -475,7 +475,7 @@ function getCustomersList () {
where c.id != $1 where c.id != $1
) as cl where rn = 1 ) as cl where rn = 1
limit $2` limit $2`
return db.$any(sql, [ anonymous.uuid, NUM_RESULTS ]) return db.any(sql, [ anonymous.uuid, NUM_RESULTS ])
.then(customers => Promise.all(_.map(customer => { .then(customers => Promise.all(_.map(customer => {
return populateOverrideUsernames(customer) return populateOverrideUsernames(customer)
.then(camelize) .then(camelize)
@ -513,7 +513,7 @@ function getCustomerById (id) {
from cash_out_txs where confirmed_at is not null) t on c.id = t.customer_id from cash_out_txs where confirmed_at is not null) t on c.id = t.customer_id
where c.id = $1 where c.id = $1
) as cl where rn = 1` ) as cl where rn = 1`
return db.$oneOrNone(sql, [id]) return db.oneOrNone(sql, [id])
.then(populateOverrideUsernames) .then(populateOverrideUsernames)
.then(camelize) .then(camelize)
} }

View file

@ -10,11 +10,11 @@ DbMigrateStore.prototype.save = function (set, fn) {
lastRun: set.lastRun, lastRun: set.lastRun,
migrations: set.migrations migrations: set.migrations
}) })
db.$none(upsert, [insertData]).then(fn).catch(err => console.log(err)) db.none(upsert, [insertData]).then(fn).catch(err => console.log(err))
} }
DbMigrateStore.prototype.load = function (fn) { DbMigrateStore.prototype.load = function (fn) {
db.$one('select data from migrations').then(({ data }) => { db.one('select data from migrations').then(({ data }) => {
fn(null, data) fn(null, data)
}) })
} }

View file

@ -93,7 +93,7 @@ eventBus.subscribe('log', args => {
// because this module is imported before ALS is set up on app.js // because this module is imported before ALS is set up on app.js
const store = defaultStore() const store = defaultStore()
asyncLocalStorage.run(store, () => { asyncLocalStorage.run(store, () => {
db.$one(sql, [uuid.v4(), '', msgToSave, level, meta]) db.one(sql, [uuid.v4(), '', msgToSave, level, meta])
.then(_.mapKeys(_.camelCase)) .then(_.mapKeys(_.camelCase))
}) })
}) })

View file

@ -22,7 +22,7 @@ function getLastSeen (deviceId) {
const sql = `select id, timestamp, serial from logs const sql = `select id, timestamp, serial from logs
where device_id=$1 where device_id=$1
order by timestamp desc, serial desc limit 1` order by timestamp desc, serial desc limit 1`
return db.$oneOrNone(sql, [deviceId]) return db.oneOrNone(sql, [deviceId])
.then(log => log ? {timestamp: log.timestamp, serial: log.serial, id: log.id} : null) .then(log => log ? {timestamp: log.timestamp, serial: log.serial, id: log.id} : null)
} }
@ -56,14 +56,14 @@ function update (deviceId, logLines) {
}, logLines) }, logLines)
const sql = pgp.helpers.insert(logs, cs) + 'on conflict do nothing' const sql = pgp.helpers.insert(logs, cs) + 'on conflict do nothing'
return db.$none(sql) return db.none(sql)
} }
function clearOldLogs () { function clearOldLogs () {
const sql = `delete from logs const sql = `delete from logs
where timestamp < now() - interval '3 days'` where timestamp < now() - interval '3 days'`
return db.$none(sql) return db.none(sql)
} }
function getUnlimitedMachineLogs (deviceId, until = new Date().toISOString()) { function getUnlimitedMachineLogs (deviceId, until = new Date().toISOString()) {
@ -75,7 +75,7 @@ function getUnlimitedMachineLogs (deviceId, until = new Date().toISOString()) {
and timestamp > (timestamp $2 - interval '2 days') and timestamp > (timestamp $2 - interval '2 days')
order by timestamp desc, serial desc` order by timestamp desc, serial desc`
return Promise.all([db.$any(sql, [ deviceId, until ]), getMachineName(deviceId)]) return Promise.all([db.any(sql, [ deviceId, until ]), getMachineName(deviceId)])
.then(([logs, machineName]) => ({ .then(([logs, machineName]) => ({
logs: _.map(_.mapKeys(_.camelCase), logs), logs: _.map(_.mapKeys(_.camelCase), logs),
currentMachine: {deviceId, name: machineName} currentMachine: {deviceId, name: machineName}
@ -90,7 +90,7 @@ function getMachineLogs (deviceId, until = new Date().toISOString(), limit = nul
limit $3 limit $3
offset $4` offset $4`
return Promise.all([db.$any(sql, [ deviceId, until, limit, offset ]), getMachineName(deviceId)]) return Promise.all([db.any(sql, [ deviceId, until, limit, offset ]), getMachineName(deviceId)])
.then(([logs, machineName]) => ({ .then(([logs, machineName]) => ({
logs: _.map(_.mapKeys(_.camelCase), logs), logs: _.map(_.mapKeys(_.camelCase), logs),
currentMachine: {deviceId, name: machineName} currentMachine: {deviceId, name: machineName}
@ -106,7 +106,7 @@ function simpleGetMachineLogs (deviceId, from = new Date(0).toISOString(), until
limit $4 limit $4
offset $5` offset $5`
return db.$any(sql, [ deviceId, from, until, limit, offset ]) return db.any(sql, [ deviceId, from, until, limit, offset ])
.then(_.map(_.mapKeys(_.camelCase))) .then(_.map(_.mapKeys(_.camelCase)))
} }

View file

@ -11,7 +11,7 @@ const notifierUtils = require('./notifier/utils')
const notifierQueries = require('./notifier/queries') const notifierQueries = require('./notifier/queries')
function getMachines () { function getMachines () {
return db.$any('SELECT * FROM devices WHERE display=TRUE ORDER BY created') return db.any('SELECT * FROM devices WHERE display=TRUE ORDER BY created')
.then(rr => rr.map(r => ({ .then(rr => rr.map(r => ({
deviceId: r.device_id, deviceId: r.device_id,
cashbox: r.cashbox, cashbox: r.cashbox,
@ -83,34 +83,34 @@ function getMachineNames (config) {
*/ */
function getMachineName (machineId) { function getMachineName (machineId) {
const sql = 'SELECT * FROM devices WHERE device_id=$1' const sql = 'SELECT * FROM devices WHERE device_id=$1'
return db.$oneOrNone(sql, [machineId]) return db.oneOrNone(sql, [machineId])
.then(it => it.name) .then(it => it.name)
} }
function getMachine (machineId) { function getMachine (machineId) {
const sql = 'SELECT * FROM devices WHERE device_id=$1' const sql = 'SELECT * FROM devices WHERE device_id=$1'
return db.$oneOrNone(sql, [machineId]).then(res => _.mapKeys(_.camelCase)(res)) return db.oneOrNone(sql, [machineId]).then(res => _.mapKeys(_.camelCase)(res))
} }
function renameMachine (rec) { function renameMachine (rec) {
const sql = 'UPDATE devices SET name=$1 WHERE device_id=$2' const sql = 'UPDATE devices SET name=$1 WHERE device_id=$2'
return db.$none(sql, [rec.newName, rec.deviceId]) return db.none(sql, [rec.newName, rec.deviceId])
} }
function resetCashOutBills (rec) { function resetCashOutBills (rec) {
const detailB = notifierUtils.buildDetail({ deviceId: rec.deviceId }) const detailB = notifierUtils.buildDetail({ deviceId: rec.deviceId })
const sql = `UPDATE devices SET cassette1=$1, cassette2=$2 WHERE device_id=$3;` const sql = `UPDATE devices SET cassette1=$1, cassette2=$2 WHERE device_id=$3;`
return db.$none(sql, [rec.cassettes[0], rec.cassettes[1], rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance')) return db.none(sql, [rec.cassettes[0], rec.cassettes[1], rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance'))
} }
function emptyCashInBills (rec) { function emptyCashInBills (rec) {
const sql = 'UPDATE devices SET cashbox=0 WHERE device_id=$1' const sql = 'UPDATE devices SET cashbox=0 WHERE device_id=$1'
return db.$none(sql, [rec.deviceId]) return db.none(sql, [rec.deviceId])
} }
function setCassetteBills (rec) { function setCassetteBills (rec) {
const sql = 'update devices set cashbox=$1, cassette1=$2, cassette2=$3 where device_id=$4' const sql = 'update devices set cashbox=$1, cassette1=$2, cassette2=$3 where device_id=$4'
return db.$none(sql, [rec.cashbox, rec.cassettes[0], rec.cassettes[1], rec.deviceId]) return db.none(sql, [rec.cashbox, rec.cassettes[0], rec.cassettes[1], rec.deviceId])
} }
function unpair (rec) { function unpair (rec) {

View file

@ -1,4 +1,4 @@
const { asyncLocalStorage, defaultStore } = require('./async-storage') const { asyncLocalStorage, defaultStore } = require('../async-storage')
const computeSchema = (req, res, next) => { const computeSchema = (req, res, next) => {
const store = defaultStore() const store = defaultStore()

View file

@ -2,8 +2,8 @@ const db = require('../../db')
function validateUser (username, password) { function validateUser (username, password) {
return db.tx(t => { return db.tx(t => {
const q1 = t.$one('SELECT * FROM users WHERE username=$1 AND password=$2', [username, password]) const q1 = t.one('SELECT * FROM users WHERE username=$1 AND password=$2', [username, password])
const q2 = t.$none('UPDATE users SET last_accessed = now() WHERE username=$1', [username]) const q2 = t.none('UPDATE users SET last_accessed = now() WHERE username=$1', [username])
return t.batch([q1, q2]) return t.batch([q1, q2])
.then(([user]) => user) .then(([user]) => user)

View file

@ -25,7 +25,7 @@ function totem (name) {
const buf = Buffer.concat([caHash, token, Buffer.from(options.hostname)]) const buf = Buffer.concat([caHash, token, Buffer.from(options.hostname)])
const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)' const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)'
return db.$none(sql, [hexToken, caHexToken, name]) return db.none(sql, [hexToken, caHexToken, name])
.then(() => bsAlpha.encode(buf)) .then(() => bsAlpha.encode(buf))
}) })
} }

View file

@ -10,7 +10,7 @@ function getServerLogs (from = new Date(0).toISOString(), until = new Date().toI
limit $3 limit $3
offset $4` offset $4`
return db.$any(sql, [ from, until, limit, offset ]) return db.any(sql, [ from, until, limit, offset ])
.then(_.map(_.mapKeys(_.camelCase))) .then(_.map(_.mapKeys(_.camelCase)))
} }

View file

@ -93,8 +93,8 @@ function batch (
ORDER BY created DESC limit $4 offset $5` ORDER BY created DESC limit $4 offset $5`
return Promise.all([ return Promise.all([
db.$any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]), db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]),
db.$any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]) db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status])
]) ])
.then(packager) .then(packager)
} }
@ -136,8 +136,8 @@ function getCustomerTransactionsBatch (ids) {
WHERE c.id IN ($1^) WHERE c.id IN ($1^)
ORDER BY created DESC limit $2` ORDER BY created DESC limit $2`
return Promise.all([ return Promise.all([
db.$any(cashInSql, [_.map(pgp.as.text, ids).join(','), cashInTx.PENDING_INTERVAL, NUM_RESULTS]), db.any(cashInSql, [_.map(pgp.as.text, ids).join(','), cashInTx.PENDING_INTERVAL, NUM_RESULTS]),
db.$any(cashOutSql, [_.map(pgp.as.text, ids).join(','), NUM_RESULTS, REDEEMABLE_AGE]) db.any(cashOutSql, [_.map(pgp.as.text, ids).join(','), NUM_RESULTS, REDEEMABLE_AGE])
]) ])
.then(packager).then(transactions => { .then(packager).then(transactions => {
const transactionMap = _.groupBy('customerId', transactions) const transactionMap = _.groupBy('customerId', transactions)
@ -180,8 +180,8 @@ function single (txId) {
WHERE id=$1` WHERE id=$1`
return Promise.all([ return Promise.all([
db.$oneOrNone(cashInSql, [cashInTx.PENDING_INTERVAL, txId]), db.oneOrNone(cashInSql, [cashInTx.PENDING_INTERVAL, txId]),
db.$oneOrNone(cashOutSql, [txId, REDEEMABLE_AGE]) db.oneOrNone(cashOutSql, [txId, REDEEMABLE_AGE])
]) ])
.then(packager) .then(packager)
.then(_.head) .then(_.head)

View file

@ -25,11 +25,11 @@ function saveAccounts (accounts) {
return loadAccounts() return loadAccounts()
.then(currentAccounts => { .then(currentAccounts => {
const newAccounts = _.merge(currentAccounts, accounts) const newAccounts = _.merge(currentAccounts, accounts)
return db.$none(accountsSql, ['accounts', { accounts: newAccounts }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION]) return db.none(accountsSql, ['accounts', { accounts: newAccounts }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION])
}) })
} }
function resetAccounts (schemaVersion) { function resetAccounts (schemaVersion) {
return db.$none( return db.none(
accountsSql, accountsSql,
[ [
'accounts', 'accounts',
@ -49,7 +49,7 @@ function loadAccounts (schemaVersion) {
order by id desc order by id desc
limit 1` limit 1`
return db.$oneOrNone(sql, ['accounts', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION]) return db.oneOrNone(sql, ['accounts', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
.then(_.compose(_.defaultTo({}), _.get('data.accounts'))) .then(_.compose(_.defaultTo({}), _.get('data.accounts')))
} }
@ -70,12 +70,12 @@ function saveConfig (config) {
return loadLatestConfigOrNone() return loadLatestConfigOrNone()
.then(currentConfig => { .then(currentConfig => {
const newConfig = _.assign(currentConfig, config) const newConfig = _.assign(currentConfig, config)
return db.$none(configSql, ['config', { config: newConfig }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION]) return db.none(configSql, ['config', { config: newConfig }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION])
}) })
} }
function resetConfig (schemaVersion) { function resetConfig (schemaVersion) {
return db.$none( return db.none(
configSql, configSql,
[ [
'config', 'config',
@ -103,7 +103,7 @@ function loadLatestConfig () {
order by id desc order by id desc
limit 1` limit 1`
return db.$one(sql, ['config', NEW_SETTINGS_LOADER_SCHEMA_VERSION]) return db.one(sql, ['config', NEW_SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row ? row.data.config : {}) .then(row => row ? row.data.config : {})
.catch(err => { .catch(err => {
throw err throw err
@ -118,7 +118,7 @@ function loadLatestConfigOrNone (schemaVersion) {
order by id desc order by id desc
limit 1` limit 1`
return db.$oneOrNone(sql, ['config', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION]) return db.oneOrNone(sql, ['config', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row ? row.data.config : {}) .then(row => row ? row.data.config : {})
} }
@ -130,7 +130,7 @@ function loadConfig (versionId) {
and schema_version=$3 and schema_version=$3
and valid` and valid`
return db.$one(sql, [versionId, 'config', NEW_SETTINGS_LOADER_SCHEMA_VERSION]) return db.one(sql, [versionId, 'config', NEW_SETTINGS_LOADER_SCHEMA_VERSION])
.then(row => row.data.config) .then(row => row.data.config)
.catch(err => { .catch(err => {
if (err.name === 'QueryResultError') { if (err.name === 'QueryResultError') {

View file

@ -7,7 +7,6 @@ const db = require('../db')
// types of notifications able to be inserted into db: // types of notifications able to be inserted into db:
/* /*
transaction - for normal transactions
highValueTransaction - for transactions of value higher than threshold highValueTransaction - for transactions of value higher than threshold
fiatBalance - when the number of notes in cash cassettes falls below threshold fiatBalance - when the number of notes in cash cassettes falls below threshold
cryptoBalance - when ammount of crypto balance in fiat falls below or above low/high threshold cryptoBalance - when ammount of crypto balance in fiat falls below or above low/high threshold
@ -17,65 +16,65 @@ error - notifications related to errors
function getMachineName (machineId) { function getMachineName (machineId) {
const sql = 'SELECT * FROM devices WHERE device_id=$1' const sql = 'SELECT * FROM devices WHERE device_id=$1'
return db.$oneOrNone(sql, [machineId]) return db.oneOrNone(sql, [machineId])
.then(it => it.name).catch(console.error) .then(it => it.name).catch(console.error)
} }
const addNotification = (type, message, detail) => { const addNotification = (type, message, detail) => {
const sql = `INSERT INTO notifications (id, type, message, detail) VALUES ($1, $2, $3, $4)` const sql = `INSERT INTO notifications (id, type, message, detail) VALUES ($1, $2, $3, $4)`
return db.$oneOrNone(sql, [uuidv4(), type, message, detail]).catch(console.error) return db.oneOrNone(sql, [uuidv4(), type, message, detail]).catch(console.error)
} }
const getAllValidNotifications = (type) => { const getAllValidNotifications = (type) => {
const sql = `SELECT * FROM notifications WHERE type = $1 AND valid = 't'` const sql = `SELECT * FROM notifications WHERE type = $1 AND valid = 't'`
return db.$any(sql, [type]).catch(console.error) return db.any(sql, [type]).catch(console.error)
} }
const invalidateNotification = (detail, type) => { const invalidateNotification = (detail, type) => {
detail = _.omitBy(_.isEmpty, detail) detail = _.omitBy(_.isEmpty, detail)
const sql = `UPDATE notifications SET valid = 'f', read = 't' WHERE valid = 't' AND type = $1 AND detail::jsonb @> $2::jsonb` const sql = `UPDATE notifications SET valid = 'f', read = 't' WHERE valid = 't' AND type = $1 AND detail::jsonb @> $2::jsonb`
return db.$none(sql, [type, detail]).catch(console.error).catch(console.error) return db.none(sql, [type, detail]).catch(console.error).catch(console.error)
} }
const batchInvalidate = (ids) => { const batchInvalidate = (ids) => {
const formattedIds = _.map(pgp.as.text, ids).join(',') const formattedIds = _.map(pgp.as.text, ids).join(',')
const sql = `UPDATE notifications SET valid = 'f', read = 't' WHERE id IN ($1^)` const sql = `UPDATE notifications SET valid = 'f', read = 't' WHERE id IN ($1^)`
return db.$none(sql, [formattedIds]).catch(console.error) return db.none(sql, [formattedIds]).catch(console.error)
} }
const clearBlacklistNotification = (cryptoCode, cryptoAddress) => { const clearBlacklistNotification = (cryptoCode, cryptoAddress) => {
const sql = `UPDATE notifications SET valid = 'f', read = 't' WHERE type = 'compliance' AND detail->>'cryptoCode' = $1 AND detail->>'cryptoAddress' = $2 AND (detail->>'code' = 'BLOCKED' OR detail->>'code' = 'REUSED')` const sql = `UPDATE notifications SET valid = 'f', read = 't' WHERE type = 'compliance' AND detail->>'cryptoCode' = $1 AND detail->>'cryptoAddress' = $2 AND (detail->>'code' = 'BLOCKED' OR detail->>'code' = 'REUSED')`
return db.$none(sql, [cryptoCode, cryptoAddress]).catch(console.error) return db.none(sql, [cryptoCode, cryptoAddress]).catch(console.error)
} }
const getValidNotifications = (type, detail) => { const getValidNotifications = (type, detail) => {
const sql = `SELECT * FROM notifications WHERE type = $1 AND valid = 't' AND detail @> $2` const sql = `SELECT * FROM notifications WHERE type = $1 AND valid = 't' AND detail @> $2`
return db.$any(sql, [type, detail]).catch(console.error) return db.any(sql, [type, detail]).catch(console.error)
} }
const getNotifications = () => { const getNotifications = () => {
const sql = `SELECT * FROM notifications ORDER BY created DESC` const sql = `SELECT * FROM notifications ORDER BY created DESC`
return db.$any(sql).catch(console.error) return db.any(sql).catch(console.error)
} }
const setRead = (id, read) => { const setRead = (id, read) => {
const sql = `UPDATE notifications SET read = $1 WHERE id = $2` const sql = `UPDATE notifications SET read = $1 WHERE id = $2`
return db.$none(sql, [read, id]).catch(console.error) return db.none(sql, [read, id]).catch(console.error)
} }
const markAllAsRead = () => { const markAllAsRead = () => {
const sql = `UPDATE notifications SET read = 't'` const sql = `UPDATE notifications SET read = 't'`
return db.$none(sql).catch(console.error) return db.none(sql).catch(console.error)
} }
const hasUnreadNotifications = () => { const hasUnreadNotifications = () => {
const sql = `SELECT EXISTS (SELECT 1 FROM notifications WHERE read = 'f' LIMIT 1)` const sql = `SELECT EXISTS (SELECT 1 FROM notifications WHERE read = 'f' LIMIT 1)`
return db.$oneOrNone(sql).then(res => res.exists).catch(console.error) return db.oneOrNone(sql).then(res => res.exists).catch(console.error)
} }
const getAlerts = () => { const getAlerts = () => {
const types = ['fiatBalance', 'cryptoBalance', 'error'] const types = ['fiatBalance', 'cryptoBalance', 'error']
const sql = `SELECT * FROM notifications WHERE valid = 't' AND type IN ($1:list) ORDER BY created DESC` const sql = `SELECT * FROM notifications WHERE valid = 't' AND type IN ($1:list) ORDER BY created DESC`
return db.$any(sql, [types]).catch(console.error) return db.any(sql, [types]).catch(console.error)
} }
module.exports = { module.exports = {

View file

@ -9,7 +9,7 @@ function pullToken (token) {
const sql = `delete from pairing_tokens const sql = `delete from pairing_tokens
where token=$1 where token=$1
returning name, created < now() - interval '1 hour' as expired` returning name, created < now() - interval '1 hour' as expired`
return db.$one(sql, [token]) return db.one(sql, [token])
} }
function unpair (deviceId) { function unpair (deviceId) {
@ -17,7 +17,7 @@ function unpair (deviceId) {
const deleteMachinePings = 'delete from machine_pings where device_id=$1' const deleteMachinePings = 'delete from machine_pings where device_id=$1'
// TODO new-admin: We should remove all configs related to that device. This can get tricky. // TODO new-admin: We should remove all configs related to that device. This can get tricky.
return Promise.all([db.$none(sql, [deviceId]), db.$none(deleteMachinePings, [deviceId])]) return Promise.all([db.none(sql, [deviceId]), db.none(deleteMachinePings, [deviceId])])
} }
function pair (token, deviceId, machineModel) { function pair (token, deviceId, machineModel) {
@ -29,7 +29,7 @@ function pair (token, deviceId, machineModel) {
on conflict (device_id) on conflict (device_id)
do update set paired=TRUE, display=TRUE` do update set paired=TRUE, display=TRUE`
return db.$none(insertSql, [deviceId, r.name]) return db.none(insertSql, [deviceId, r.name])
.then(() => true) .then(() => true)
}) })
.catch(err => { .catch(err => {
@ -51,7 +51,7 @@ function authorizeCaDownload (caToken) {
function isPaired (deviceId) { function isPaired (deviceId) {
const sql = 'select device_id, name from devices where device_id=$1 and paired=TRUE' const sql = 'select device_id, name from devices where device_id=$1 and paired=TRUE'
return db.$oneOrNone(sql, [deviceId]) return db.oneOrNone(sql, [deviceId])
.then(row => row && row.device_id === deviceId ? row.name : false) .then(row => row && row.device_id === deviceId ? row.name : false)
} }

View file

@ -192,7 +192,7 @@ function plugins (settings, deviceId) {
order by id desc order by id desc
limit 1` limit 1`
return db.$one(sql, ['config']) return db.one(sql, ['config'])
.then(row => row.id) .then(row => row.id)
} }
@ -281,9 +281,9 @@ function plugins (settings, deviceId) {
} }
return Promise.all([ return Promise.all([
db.$none(`insert into machine_pings(device_id, device_time) values($1, $2) db.none(`insert into machine_pings(device_id, device_time) values($1, $2)
ON CONFLICT (device_id) DO UPDATE SET device_time = $2, updated = now()`, [deviceId, deviceTime]), ON CONFLICT (device_id) DO UPDATE SET device_time = $2, updated = now()`, [deviceId, deviceTime]),
db.$none(pgp.helpers.update(devices, null, 'devices') + 'WHERE device_id = ${deviceId}', { db.none(pgp.helpers.update(devices, null, 'devices') + 'WHERE device_id = ${deviceId}', {
deviceId deviceId
}) })
]) ])
@ -364,7 +364,7 @@ function plugins (settings, deviceId) {
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]
return db.$none(sql, values) return db.none(sql, values)
}) })
} }
@ -379,7 +379,7 @@ function plugins (settings, deviceId) {
} }
function pong () { function pong () {
return db.$none(`UPDATE server_events SET created=now() WHERE event_type=$1; return db.none(`UPDATE server_events SET created=now() WHERE event_type=$1;
INSERT INTO server_events (event_type) SELECT $1 INSERT INTO server_events (event_type) SELECT $1
WHERE NOT EXISTS (SELECT 1 FROM server_events WHERE event_type=$1);`, ['ping']) WHERE NOT EXISTS (SELECT 1 FROM server_events WHERE event_type=$1);`, ['ping'])
.catch(logger.error) .catch(logger.error)
@ -583,8 +583,8 @@ function plugins (settings, deviceId) {
) )
const tradeEntry = massage(_tradeEntry, error) const tradeEntry = massage(_tradeEntry, error)
const sql = pgp.helpers.insert(tradeEntry, null, 'trades') + 'RETURNING *' const sql = pgp.helpers.insert(tradeEntry, null, 'trades') + 'RETURNING *'
db.$tx(t => { db.tx(t => {
return t.$oneOrNone(sql) return t.oneOrNone(sql)
.then(newTrade => recordTradeAndTx(newTrade.id, _tradeEntry, t)) .then(newTrade => recordTradeAndTx(newTrade.id, _tradeEntry, t))
}) })
} }
@ -735,7 +735,7 @@ function plugins (settings, deviceId) {
const sql = `update cash_out_txs set swept='t' const sql = `update cash_out_txs set swept='t'
where id=$1` where id=$1`
return db.$none(sql, row.id) return db.none(sql, row.id)
} }
}) })
.catch(err => logger.error('[%s] Sweep error: %s', cryptoCode, err.message)) .catch(err => logger.error('[%s] Sweep error: %s', cryptoCode, err.message))
@ -745,7 +745,7 @@ function plugins (settings, deviceId) {
const sql = `select id, crypto_code, hd_index from cash_out_txs const sql = `select id, crypto_code, hd_index from cash_out_txs
where hd_index is not null and not swept and status in ('confirmed', 'instant')` where hd_index is not null and not swept and status in ('confirmed', 'instant')`
return db.$any(sql) return db.any(sql)
.then(rows => Promise.all(rows.map(sweepHdRow))) .then(rows => Promise.all(rows.map(sweepHdRow)))
.catch(err => logger.error(err)) .catch(err => logger.error(err))
} }

View file

@ -22,14 +22,14 @@ exports.recordDeviceEvent = function recordDeviceEvent (deviceId, event) {
const values = [deviceId, event.eventType, event.note, const values = [deviceId, event.eventType, event.note,
event.deviceTime] event.deviceTime]
return db.$none(sql, values) return db.none(sql, values)
} }
exports.cassetteCounts = function cassetteCounts (deviceId) { exports.cassetteCounts = function cassetteCounts (deviceId) {
const sql = 'SELECT cassette1, cassette2 FROM devices ' + const sql = 'SELECT cassette1, cassette2 FROM devices ' +
'WHERE device_id=$1' 'WHERE device_id=$1'
return db.$one(sql, [deviceId]) return db.one(sql, [deviceId])
.then(row => { .then(row => {
const counts = [row.cassette1, row.cassette2] const counts = [row.cassette1, row.cassette2]
return {counts} return {counts}
@ -46,14 +46,14 @@ exports.machineEvent = function machineEvent (rec) {
const deleteSql = `delete from machine_events const deleteSql = `delete from machine_events
where created < now() - interval '1 days'` where created < now() - interval '1 days'`
return db.$none(sql, values) return db.none(sql, values)
.then(() => db.$none(deleteSql)) .then(() => db.none(deleteSql))
} }
exports.machineEventsByIdBatch = function machineEventsByIdBatch (machineIds) { exports.machineEventsByIdBatch = function machineEventsByIdBatch (machineIds) {
const formattedIds = _.map(pgp.as.text, machineIds).join(',') const formattedIds = _.map(pgp.as.text, machineIds).join(',')
const sql = `SELECT *, (EXTRACT(EPOCH FROM (now() - created))) * 1000 AS age FROM machine_events WHERE device_id IN ($1^) ORDER BY age ASC LIMIT 1` const sql = `SELECT *, (EXTRACT(EPOCH FROM (now() - created))) * 1000 AS age FROM machine_events WHERE device_id IN ($1^) ORDER BY age ASC LIMIT 1`
return db.$any(sql, [formattedIds]).then(res => { return db.any(sql, [formattedIds]).then(res => {
const events = _.map(_.mapKeys(_.camelCase))(res) const events = _.map(_.mapKeys(_.camelCase))(res)
const eventMap = _.groupBy('deviceId', events) const eventMap = _.groupBy('deviceId', events)
return machineIds.map(id => _.prop([0], eventMap[id])) return machineIds.map(id => _.prop([0], eventMap[id]))
@ -63,5 +63,5 @@ exports.machineEventsByIdBatch = function machineEventsByIdBatch (machineIds) {
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'
return db.$any(sql, []) return db.any(sql, [])
} }

View file

@ -3,27 +3,27 @@ const uuid = require('uuid')
function getAvailablePromoCodes () { function getAvailablePromoCodes () {
const sql = `SELECT * FROM coupons WHERE soft_deleted=false` const sql = `SELECT * FROM coupons WHERE soft_deleted=false`
return db.$any(sql) return db.any(sql)
} }
function getPromoCode (code) { function getPromoCode (code) {
const sql = `SELECT * FROM coupons WHERE code=$1 AND soft_deleted=false` const sql = `SELECT * FROM coupons WHERE code=$1 AND soft_deleted=false`
return db.$oneOrNone(sql, [code]) return db.oneOrNone(sql, [code])
} }
function createPromoCode (code, discount) { function createPromoCode (code, discount) {
const sql = `INSERT INTO coupons (id, code, discount) VALUES ($1, $2, $3) RETURNING *` const sql = `INSERT INTO coupons (id, code, discount) VALUES ($1, $2, $3) RETURNING *`
return db.$one(sql, [uuid.v4(), code, discount]) return db.one(sql, [uuid.v4(), code, discount])
} }
function deletePromoCode (id) { function deletePromoCode (id) {
const sql = `UPDATE coupons SET soft_deleted=true WHERE id=$1` const sql = `UPDATE coupons SET soft_deleted=true WHERE id=$1`
return db.$none(sql, [id]) return db.none(sql, [id])
} }
function getNumberOfAvailablePromoCodes () { function getNumberOfAvailablePromoCodes () {
const sql = `SELECT COUNT(id) FROM coupons WHERE soft_deleted=false` const sql = `SELECT COUNT(id) FROM coupons WHERE soft_deleted=false`
return db.$one(sql).then(res => res.count) return db.one(sql).then(res => res.count)
} }
module.exports = { getAvailablePromoCodes, getPromoCode, createPromoCode, deletePromoCode, getNumberOfAvailablePromoCodes } module.exports = { getAvailablePromoCodes, getPromoCode, createPromoCode, deletePromoCode, getNumberOfAvailablePromoCodes }

View file

@ -52,7 +52,7 @@ function fetchPhoneTx (phone) {
const values = [phone, false, TRANSACTION_EXPIRATION] const values = [phone, false, TRANSACTION_EXPIRATION]
return db.$any(sql, values) return db.any(sql, values)
.then(_.map(toCashOutTx)) .then(_.map(toCashOutTx))
.then(txs => { .then(txs => {
const seenTxs = _.some(it => it.status !== 'notSeen', txs) const seenTxs = _.some(it => it.status !== 'notSeen', txs)
@ -76,7 +76,7 @@ function fetchPhoneTx (phone) {
function fetchStatusTx (txId, status) { function fetchStatusTx (txId, status) {
const sql = 'select * from cash_out_txs where id=$1' const sql = 'select * from cash_out_txs where id=$1'
return db.$oneOrNone(sql, [txId]) return db.oneOrNone(sql, [txId])
.then(toCashOutTx) .then(toCashOutTx)
.then(tx => { .then(tx => {
if (!tx) throw httpError('No transaction', 404) if (!tx) throw httpError('No transaction', 404)
@ -86,7 +86,7 @@ function fetchStatusTx (txId, status) {
} }
function updateDeviceConfigVersion (versionId) { function updateDeviceConfigVersion (versionId) {
return db.$none('update devices set user_config_id=$1', [versionId]) return db.none('update devices set user_config_id=$1', [versionId])
} }
module.exports = { module.exports = {

View file

@ -5,12 +5,13 @@ const helmet = require('helmet')
const morgan = require('morgan') const morgan = require('morgan')
const nocache = require('nocache') const nocache = require('nocache')
const logger = require('./logger')
const options = require('./options')
const authorize = require('./middlewares/authorize') const authorize = require('./middlewares/authorize')
const errorHandler = require('./middlewares/errorHandler') const errorHandler = require('./middlewares/errorHandler')
const filterOldRequests = require('./middlewares/filterOldRequests') const filterOldRequests = require('./middlewares/filterOldRequests')
const computeSchema = require('./compute-schema') const computeSchema = require('./middlewares/compute-schema')
const logger = require('./logger')
const options = require('./options')
const findOperatorId = require('./middlewares/operatorId') const findOperatorId = require('./middlewares/operatorId')
const populateDeviceId = require('./middlewares/populateDeviceId') const populateDeviceId = require('./middlewares/populateDeviceId')
const populateSettings = require('./middlewares/populateSettings') const populateSettings = require('./middlewares/populateSettings')

View file

@ -2,7 +2,7 @@ const db = require('./db')
function getSessions () { function getSessions () {
const sql = `SELECT * FROM user_sessions ORDER BY sess -> 'user' ->> 'username'` const sql = `SELECT * FROM user_sessions ORDER BY sess -> 'user' ->> 'username'`
return db.$any(sql) return db.any(sql)
} }
function getLastSessionPerUser () { function getLastSessionPerUser () {
@ -16,27 +16,27 @@ function getLastSessionPerUser () {
SELECT DISTINCT ON (username) SELECT DISTINCT ON (username)
username, role username, role
FROM users) b ON a.username = b.username` FROM users) b ON a.username = b.username`
return db.$any(sql) return db.any(sql)
} }
function getSessionsByUsername (username) { function getSessionsByUsername (username) {
const sql = `SELECT * FROM user_sessions WHERE sess -> 'user' ->> 'username'=$1` const sql = `SELECT * FROM user_sessions WHERE sess -> 'user' ->> 'username'=$1`
return db.$any(sql, [username]) return db.any(sql, [username])
} }
function getSessionById (sessionID) { function getSessionById (sessionID) {
const sql = `SELECT * FROM user_sessions WHERE sid=$1` const sql = `SELECT * FROM user_sessions WHERE sid=$1`
return db.$any(sql, [sessionID]) return db.any(sql, [sessionID])
} }
function deleteSessionsByUsername (username) { function deleteSessionsByUsername (username) {
const sql = `DELETE FROM user_sessions WHERE sess -> 'user' ->> 'username'=$1` const sql = `DELETE FROM user_sessions WHERE sess -> 'user' ->> 'username'=$1`
return db.$none(sql, [username]) return db.none(sql, [username])
} }
function deleteSessionById (sessionID) { function deleteSessionById (sessionID) {
const sql = `DELETE FROM user_sessions WHERE sid=$1` const sql = `DELETE FROM user_sessions WHERE sid=$1`
return db.$none(sql, [sessionID]) return db.none(sql, [sessionID])
} }
module.exports = { getSessions, getLastSessionPerUser, getSessionsByUsername, getSessionById, deleteSessionsByUsername, deleteSessionById } module.exports = { getSessions, getLastSessionPerUser, getSessionsByUsername, getSessionById, deleteSessionsByUsername, deleteSessionById }

View file

@ -1,13 +0,0 @@
const db = require('./db')
function getTokenList () {
const sql = `select * from user_tokens`
return db.$any(sql)
}
function revokeToken (token) {
const sql = `delete from user_tokens where token = $1`
return db.$none(sql, [token])
}
module.exports = { getTokenList, revokeToken }

View file

@ -78,7 +78,7 @@ function customerHistory (customerId, thresholdDays) {
ORDER BY created;` ORDER BY created;`
const days = _.isNil(thresholdDays) ? 0 : thresholdDays const days = _.isNil(thresholdDays) ? 0 : thresholdDays
return db.$any(sql, [customerId, `${days} days`]) return db.any(sql, [customerId, `${days} days`])
} }
module.exports = { post, cancel, customerHistory } module.exports = { post, cancel, customerHistory }

View file

@ -19,7 +19,7 @@ const db = require('./db')
*/ */
function get (token) { function get (token) {
const sql = 'SELECT * FROM user_tokens WHERE token=$1' const sql = 'SELECT * FROM user_tokens WHERE token=$1'
return db.$oneOrNone(sql, [token]) return db.oneOrNone(sql, [token])
} }
/** /**
@ -35,45 +35,45 @@ function get (token) {
function getByIds (ids) { function getByIds (ids) {
const sql = `SELECT * FROM users WHERE id IN ($1^)` const sql = `SELECT * FROM users WHERE id IN ($1^)`
const idList = _.map(pgp.as.text, ids).join(',') const idList = _.map(pgp.as.text, ids).join(',')
return db.$any(sql, [idList]) return db.any(sql, [idList])
} }
function getUserById (id) { function getUserById (id) {
const sql = `SELECT * FROM users WHERE id=$1` const sql = `SELECT * FROM users WHERE id=$1`
return db.$oneOrNone(sql, [id]) return db.oneOrNone(sql, [id])
} }
function getUserByUsername (username) { function getUserByUsername (username) {
const sql = `SELECT * FROM users WHERE username=$1` const sql = `SELECT * FROM users WHERE username=$1`
return db.$oneOrNone(sql, [username]) return db.oneOrNone(sql, [username])
} }
function getUsers () { function getUsers () {
const sql = `SELECT id, username, role, enabled, last_accessed, last_accessed_from, last_accessed_address FROM users ORDER BY username` const sql = `SELECT id, username, role, enabled, last_accessed, last_accessed_from, last_accessed_address FROM users ORDER BY username`
return db.$any(sql) return db.any(sql)
} }
function verifyAndUpdateUser (id, ua, ip) { function verifyAndUpdateUser (id, ua, ip) {
const sql = `SELECT id, username, role, enabled FROM users WHERE id=$1 limit 1` const sql = `SELECT id, username, role, enabled FROM users WHERE id=$1 limit 1`
return db.$oneOrNone(sql, [id]) return db.oneOrNone(sql, [id])
.then(user => { .then(user => {
if (!user) return null if (!user) return null
const sql2 = `UPDATE users SET last_accessed=now(), last_accessed_from=$1, last_accessed_address=$2 WHERE id=$3 RETURNING id, role, enabled` const sql2 = `UPDATE users SET last_accessed=now(), last_accessed_from=$1, last_accessed_address=$2 WHERE id=$3 RETURNING id, role, enabled`
return db.$one(sql2, [ua, ip, id]) return db.one(sql2, [ua, ip, id])
}) })
.then(user => user) .then(user => user)
} }
function saveTemp2FASecret (id, secret) { function saveTemp2FASecret (id, secret) {
const sql = 'UPDATE users SET temp_twofa_code=$1 WHERE id=$2' const sql = 'UPDATE users SET temp_twofa_code=$1 WHERE id=$2'
return db.$none(sql, [secret, id]) return db.none(sql, [secret, id])
} }
function save2FASecret (id, secret) { function save2FASecret (id, secret) {
return db.tx(t => { return db.tx(t => {
const q1 = t.$none('UPDATE users SET twofa_code=$1, temp_twofa_code=NULL WHERE id=$2', [secret, id]) const q1 = t.none('UPDATE users SET twofa_code=$1, temp_twofa_code=NULL WHERE id=$2', [secret, id])
const q2 = t.$none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id]) const q2 = t.none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id])
return t.batch([q1, q2]) return t.batch([q1, q2])
}) })
} }
@ -82,7 +82,7 @@ function validateAuthToken (token, type) {
const sql = `SELECT user_id, now() < expire AS success FROM auth_tokens const sql = `SELECT user_id, now() < expire AS success FROM auth_tokens
WHERE token=$1 AND type=$2` WHERE token=$1 AND type=$2`
return db.$one(sql, [token, type]) return db.one(sql, [token, type])
.then(res => ({ userID: res.user_id, success: res.success })) .then(res => ({ userID: res.user_id, success: res.success }))
} }
@ -90,9 +90,9 @@ function reset2FASecret (token, id, secret) {
return validateAuthToken(token, 'reset_twofa').then(res => { return validateAuthToken(token, 'reset_twofa').then(res => {
if (!res.success) throw new Error('Failed to verify 2FA reset token') if (!res.success) throw new Error('Failed to verify 2FA reset token')
return db.tx(t => { return db.tx(t => {
const q1 = t.$none('UPDATE users SET twofa_code=$1, temp_twofa_code=NULL WHERE id=$2', [secret, id]) const q1 = t.none('UPDATE users SET twofa_code=$1, temp_twofa_code=NULL WHERE id=$2', [secret, id])
const q2 = t.$none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id]) const q2 = t.none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id])
const q3 = t.$none(`DELETE FROM auth_tokens WHERE token=$1 and type='reset_twofa'`, [token]) const q3 = t.none(`DELETE FROM auth_tokens WHERE token=$1 and type='reset_twofa'`, [token])
return t.batch([q1, q2, q3]) return t.batch([q1, q2, q3])
}) })
}) })
@ -103,9 +103,9 @@ function updatePassword (token, id, password) {
if (!res.success) throw new Error('Failed to verify password reset token') if (!res.success) throw new Error('Failed to verify password reset token')
return argon2.hash(password).then(function (hash) { return argon2.hash(password).then(function (hash) {
return db.tx(t => { return db.tx(t => {
const q1 = t.$none(`UPDATE users SET password=$1 WHERE id=$2`, [hash, id]) const q1 = t.none(`UPDATE users SET password=$1 WHERE id=$2`, [hash, id])
const q2 = t.$none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id]) const q2 = t.none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id])
const q3 = t.$none(`DELETE FROM auth_tokens WHERE token=$1 and type='reset_password'`, [token]) const q3 = t.none(`DELETE FROM auth_tokens WHERE token=$1 and type='reset_password'`, [token])
return t.batch([q1, q2, q3]) return t.batch([q1, q2, q3])
}) })
}) })
@ -117,13 +117,13 @@ function createUserRegistrationToken (username, role) {
const sql = `INSERT INTO user_register_tokens (token, username, role) VALUES ($1, $2, $3) ON CONFLICT (username) const sql = `INSERT INTO user_register_tokens (token, username, role) VALUES ($1, $2, $3) ON CONFLICT (username)
DO UPDATE SET token=$1, expire=now() + interval '${constants.REGISTRATION_TOKEN_EXPIRATION_TIME}' RETURNING *` DO UPDATE SET token=$1, expire=now() + interval '${constants.REGISTRATION_TOKEN_EXPIRATION_TIME}' RETURNING *`
return db.$one(sql, [token, username, role]) return db.one(sql, [token, username, role])
} }
function validateUserRegistrationToken (token) { function validateUserRegistrationToken (token) {
const sql = `SELECT username, role, now() < expire AS success FROM user_register_tokens WHERE token=$1` const sql = `SELECT username, role, now() < expire AS success FROM user_register_tokens WHERE token=$1`
return db.$one(sql, [token]) return db.one(sql, [token])
.then(res => ({ username: res.username, role: res.role, success: res.success })) .then(res => ({ username: res.username, role: res.role, success: res.success }))
} }
@ -132,8 +132,8 @@ function register (token, username, password, role) {
if (!res.success) throw new Error('Failed to verify registration token') if (!res.success) throw new Error('Failed to verify registration token')
return argon2.hash(password).then(hash => { return argon2.hash(password).then(hash => {
return db.tx(t => { return db.tx(t => {
const q1 = t.$none(`INSERT INTO users (id, username, password, role) VALUES ($1, $2, $3, $4)`, [uuid.v4(), username, hash, role]) const q1 = t.none(`INSERT INTO users (id, username, password, role) VALUES ($1, $2, $3, $4)`, [uuid.v4(), username, hash, role])
const q2 = t.$none(`DELETE FROM user_register_tokens WHERE token=$1`, [token]) const q2 = t.none(`DELETE FROM user_register_tokens WHERE token=$1`, [token])
return t.batch([q1, q2]) return t.batch([q1, q2])
}) })
}) })
@ -142,18 +142,18 @@ function register (token, username, password, role) {
function changeUserRole (id, newRole) { function changeUserRole (id, newRole) {
const sql = `UPDATE users SET role=$1 WHERE id=$2` const sql = `UPDATE users SET role=$1 WHERE id=$2`
return db.$none(sql, [newRole, id]) return db.none(sql, [newRole, id])
} }
function enableUser (id) { function enableUser (id) {
const sql = `UPDATE users SET enabled=true WHERE id=$1` const sql = `UPDATE users SET enabled=true WHERE id=$1`
return db.$none(sql, [id]) return db.none(sql, [id])
} }
function disableUser (id) { function disableUser (id) {
return db.tx(t => { return db.tx(t => {
const q1 = t.$none(`UPDATE users SET enabled=false WHERE id=$1`, [id]) const q1 = t.none(`UPDATE users SET enabled=false WHERE id=$1`, [id])
const q2 = t.$none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id]) const q2 = t.none(`DELETE FROM user_sessions WHERE sess -> 'user' ->> 'id'=$1`, [id])
return t.batch([q1, q2]) return t.batch([q1, q2])
}) })
} }

View file

@ -6,7 +6,7 @@ module.exports = { multi }
function multi (sqls, cb) { function multi (sqls, cb) {
const doQuery = s => { const doQuery = s => {
return () => { return () => {
return db.$none(s) return db.none(s)
.catch(err => { .catch(err => {
console.log(err.stack) console.log(err.stack)
throw err throw err

53
package-lock.json generated
View file

@ -5281,6 +5281,11 @@
} }
} }
}, },
"assert-options": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz",
"integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ=="
},
"assert-plus": { "assert-plus": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
@ -6957,9 +6962,9 @@
"integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo="
}, },
"buffer-writer": { "buffer-writer": {
"version": "1.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
"integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
}, },
"buffer-xor": { "buffer-xor": {
"version": "1.0.3", "version": "1.0.3",
@ -14890,11 +14895,6 @@
"tmpl": "1.0.x" "tmpl": "1.0.x"
} }
}, },
"manakin": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/manakin/-/manakin-0.5.2.tgz",
"integrity": "sha512-pfDSB7QYoVg0Io4KMV9hhPoXpj6p0uBscgtyUSKCOFZe8bqgbpStfgnKIbF/ulnr6U3ICu4OqdyxAqBgOhZwBQ=="
},
"map-age-cleaner": { "map-age-cleaner": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
@ -16500,9 +16500,9 @@
} }
}, },
"packet-reader": { "packet-reader": {
"version": "0.3.1", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
"integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
}, },
"pandemonium": { "pandemonium": {
"version": "1.5.0", "version": "1.5.0",
@ -16690,20 +16690,21 @@
}, },
"dependencies": { "dependencies": {
"pg-types": { "pg-types": {
"version": "1.12.1", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"requires": { "requires": {
"postgres-array": "~1.0.0", "pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0", "postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.0", "postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0" "postgres-interval": "^1.1.0"
} }
}, },
"semver": { "postgres-array": {
"version": "4.3.2", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
} }
} }
}, },
@ -16718,9 +16719,9 @@
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
}, },
"pg-minify": { "pg-minify": {
"version": "0.5.5", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-0.5.5.tgz", "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz",
"integrity": "sha512-7Pf9h6nV1RFqED1hkRosePqvpPwNUUtW06TT4+lHwzesxa5gffxkShTjYH6JXV5sSSfh5+2yHOTTWEkCyCQ0Eg==" "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg=="
}, },
"pg-native": { "pg-native": {
"version": "3.0.0", "version": "3.0.0",
@ -19402,9 +19403,9 @@
"dev": true "dev": true
}, },
"spex": { "spex": {
"version": "2.0.2", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/spex/-/spex-2.0.2.tgz", "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz",
"integrity": "sha512-LU6TS3qTEpRth+FnNs/fIWEmridYN7JmaN2k1Jk31XVC4ex7+wYxiHMnKguRxS7oKjbOFl4H6seeWNDFFgkVRg==" "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg=="
}, },
"split": { "split": {
"version": "1.0.1", "version": "1.0.1",

View file

@ -7,7 +7,7 @@ function pp (o) {
} }
function dbFetchConfig () { function dbFetchConfig () {
return db.$oneOrNone( return db.oneOrNone(
'select data from user_config where type=$1 order by id desc limit 1', 'select data from user_config where type=$1 order by id desc limit 1',
['config'] ['config']
) )