Merge pull request #1829 from RafaelTaranto/chore/remove-deprecated-compat-code
LAM-1394 feat: reject requests from incompatible machines
This commit is contained in:
commit
708cebe5b3
9 changed files with 44 additions and 279 deletions
|
|
@ -40,11 +40,7 @@ function insertNewBills (t, billRows, machineTx) {
|
|||
const bills = pullNewBills(billRows, machineTx)
|
||||
if (_.isEmpty(bills)) return Promise.resolve([])
|
||||
|
||||
const _dbBills = _.map(cashInLow.massage, bills)
|
||||
// BACKWARDS_COMPATIBILITY 8.1
|
||||
// bills before 8.6 don't have destination_unit
|
||||
const dbBills = _.map(_.defaults({ destination_unit: 'cashbox'}))(_dbBills)
|
||||
|
||||
const dbBills = _.map(cashInLow.massage, bills)
|
||||
const billsByDestination = _.countBy(_.get(['destination_unit']) ,dbBills)
|
||||
|
||||
const columns = ['id', 'fiat', 'fiat_code', 'crypto_code', 'cash_in_fee', 'cash_in_txs_id', 'device_time', 'destination_unit']
|
||||
|
|
|
|||
|
|
@ -59,10 +59,7 @@ function matchOfac (deviceId, customer) {
|
|||
})
|
||||
}
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 7.5
|
||||
// machines before 7.5 need to test sanctionsActive here
|
||||
function validateOfac (deviceId, sanctionsActive, customer) {
|
||||
if (!sanctionsActive) return Promise.resolve(true)
|
||||
function validateOfac (deviceId, customer) {
|
||||
if (customer.sanctionsOverride === 'blocked') return Promise.resolve(false)
|
||||
if (customer.sanctionsOverride === 'verified') return Promise.resolve(true)
|
||||
|
||||
|
|
@ -70,8 +67,8 @@ function validateOfac (deviceId, sanctionsActive, customer) {
|
|||
.then(didMatch => !didMatch)
|
||||
}
|
||||
|
||||
function validationPatch (deviceId, sanctionsActive, customer) {
|
||||
return validateOfac(deviceId, sanctionsActive, customer)
|
||||
function validationPatch (deviceId, customer) {
|
||||
return validateOfac(deviceId, customer)
|
||||
.then(sanctions =>
|
||||
_.isNil(customer.sanctions) || customer.sanctions !== sanctions ?
|
||||
{ sanctions } :
|
||||
|
|
|
|||
31
lib/middlewares/rejectIncompatbleMachines.js
Normal file
31
lib/middlewares/rejectIncompatbleMachines.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
const semver = require('semver')
|
||||
const version = require('../../package.json').version
|
||||
const logger = require('../logger')
|
||||
|
||||
const rejectIncompatibleMachines = function (req, res, next) {
|
||||
const machineVersion = req.query.version
|
||||
const deviceId = req.deviceId
|
||||
|
||||
if (!machineVersion) return next()
|
||||
|
||||
const serverMajor = semver.major(version)
|
||||
const machineMajor = semver.major(machineVersion)
|
||||
|
||||
if (serverMajor - machineMajor > 1) {
|
||||
logger.error(`Machine version too old: ${machineVersion} deviceId: ${deviceId}`)
|
||||
return res.status(400).json({
|
||||
error: 'Machine version too old'
|
||||
})
|
||||
}
|
||||
|
||||
if (serverMajor < machineMajor) {
|
||||
logger.error(`Machine version too new: ${machineVersion} deviceId: ${deviceId}`)
|
||||
return res.status(400).json({
|
||||
error: 'Machine version too new'
|
||||
})
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
module.exports = rejectIncompatibleMachines
|
||||
|
|
@ -22,8 +22,7 @@ const logsRoutes = require('./routes/logsRoutes')
|
|||
const pairingRoutes = require('./routes/pairingRoutes')
|
||||
const diagnosticsRoutes = require('./routes/diagnosticsRoutes')
|
||||
const performanceRoutes = require('./routes/performanceRoutes')
|
||||
const phoneCodeRoutes = require('./routes/phoneCodeRoutes')
|
||||
const pollingRoutes = require('./routes/pollingRoutes')
|
||||
const rejectIncompatibleMachines = require('./middlewares/rejectIncompatbleMachines')
|
||||
const stateRoutes = require('./routes/stateRoutes')
|
||||
const termsAndConditionsRoutes = require('./routes/termsAndConditionsRoutes')
|
||||
const { router: txRoutes } = require('./routes/txRoutes')
|
||||
|
|
@ -82,7 +81,6 @@ const loadRoutes = async () => {
|
|||
|
||||
// other app routes
|
||||
app.use('/graphql', recordPing)
|
||||
app.use('/poll', pollingRoutes)
|
||||
app.use('/terms_conditions', termsAndConditionsRoutes)
|
||||
app.use('/state', stateRoutes)
|
||||
app.use('/cashbox', cashboxRoutes)
|
||||
|
|
@ -95,10 +93,6 @@ const loadRoutes = async () => {
|
|||
app.use('/verify_transaction', verifyTxRoutes)
|
||||
app.use('/verify_promo_code', verifyPromoCodeRoutes)
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 9.0
|
||||
// machines before 9.0 still use the phone_code route
|
||||
app.use('/phone_code', phoneCodeRoutes)
|
||||
|
||||
app.use('/customer', customerRoutes)
|
||||
|
||||
app.use('/tx', txRoutes)
|
||||
|
|
@ -108,6 +102,9 @@ const loadRoutes = async () => {
|
|||
|
||||
app.use('/probe', probeRoutes)
|
||||
|
||||
// Not all requests have the machine version on the url
|
||||
// rejecting poll is enough to render the machine "stuck"
|
||||
app.use(rejectIncompatibleMachines)
|
||||
await graphQLServer.start()
|
||||
app.use('/graphql',
|
||||
express.json(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const semver = require('semver')
|
||||
const _ = require('lodash/fp')
|
||||
const { zonedTimeToUtc, utcToZonedTime } = require('date-fns-tz/fp')
|
||||
const { add, intervalToDuration } = require('date-fns/fp')
|
||||
|
|
@ -79,11 +78,7 @@ const createPendingManualComplianceNotifs = (settings, customer, deviceId) => {
|
|||
|
||||
function updateCustomer (req, res, next) {
|
||||
const id = req.params.id
|
||||
const machineVersion = req.query.version
|
||||
const txId = req.query.txId
|
||||
const patch = req.body
|
||||
const triggers = configManager.getTriggers(req.settings.config)
|
||||
const compatTriggers = complianceTriggers.getBackwardsCompatibleTriggers(triggers)
|
||||
const deviceId = req.deviceId
|
||||
const settings = req.settings
|
||||
|
||||
|
|
@ -96,15 +91,8 @@ function updateCustomer (req, res, next) {
|
|||
.catch(next)
|
||||
}
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 7.5
|
||||
// machines before 7.5 expect customer with sanctions result
|
||||
const isOlderMachineVersion = !machineVersion || semver.lt(machineVersion, '7.5.0-beta.0')
|
||||
customers.getById(id)
|
||||
.then(customer =>
|
||||
!customer ? Promise.reject(httpError('Not Found', 404)) :
|
||||
!isOlderMachineVersion ? {} :
|
||||
compliance.validationPatch(deviceId, !!compatTriggers.sanctions, _.merge(customer, patch))
|
||||
)
|
||||
.then(customer => !customer ? Promise.reject(httpError('Not Found', 404)) : {})
|
||||
.then(_.merge(patch))
|
||||
.then(newPatch => customers.updatePhotoCard(id, newPatch))
|
||||
.then(newPatch => customers.updateFrontCamera(id, newPatch))
|
||||
|
|
@ -135,7 +123,7 @@ function triggerSanctions (req, res, next) {
|
|||
customers.getById(id)
|
||||
.then(customer => {
|
||||
if (!customer) { throw httpError('Not Found', 404) }
|
||||
return compliance.validationPatch(req.deviceId, true, customer)
|
||||
return compliance.validationPatch(req.deviceId, customer)
|
||||
.then(patch => customers.update(id, patch))
|
||||
})
|
||||
.then(customer => respond(req, res, { customer }))
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const semver = require('semver')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const compliance = require('../compliance')
|
||||
const complianceTriggers = require('../compliance-triggers')
|
||||
const configManager = require('../new-config-manager')
|
||||
const { get, add, getById, update } = require('../customers')
|
||||
const httpError = require('../route-helpers').httpError
|
||||
const plugins = require('../plugins')
|
||||
const Tx = require('../tx')
|
||||
const respond = require('../respond')
|
||||
const loyalty = require('../loyalty')
|
||||
|
||||
function addOrUpdateCustomer (req) {
|
||||
const customerData = req.body
|
||||
const machineVersion = req.query.version
|
||||
const triggers = configManager.getTriggers(req.settings.config)
|
||||
const compatTriggers = complianceTriggers.getBackwardsCompatibleTriggers(triggers)
|
||||
const maxDaysThreshold = complianceTriggers.maxDaysThreshold(triggers)
|
||||
|
||||
return get(customerData.phone)
|
||||
.then(customer => {
|
||||
if (customer) return customer
|
||||
|
||||
return add(req.body)
|
||||
})
|
||||
.then(customer => getById(customer.id))
|
||||
.then(customer => {
|
||||
// BACKWARDS_COMPATIBILITY 7.5
|
||||
// machines before 7.5 expect customer with sanctions result
|
||||
const isOlderMachineVersion = !machineVersion || semver.lt(machineVersion, '7.5.0-beta.0')
|
||||
const shouldRunOfacCompat = !compatTriggers.sanctions && isOlderMachineVersion
|
||||
if (!shouldRunOfacCompat) return customer
|
||||
|
||||
return compliance.validationPatch(req.deviceId, !!compatTriggers.sanctions, customer)
|
||||
.then(patch => {
|
||||
if (_.isEmpty(patch)) return customer
|
||||
return update(customer.id, patch)
|
||||
})
|
||||
})
|
||||
.then(customer => {
|
||||
return Tx.customerHistory(customer.id, maxDaysThreshold)
|
||||
.then(result => {
|
||||
customer.txHistory = result
|
||||
return customer
|
||||
})
|
||||
})
|
||||
.then(customer => {
|
||||
return loyalty.getCustomerActiveIndividualDiscount(customer.id)
|
||||
.then(discount => ({ ...customer, discount }))
|
||||
})
|
||||
}
|
||||
|
||||
function getCustomerWithPhoneCode (req, res, next) {
|
||||
const pi = plugins(req.settings, req.deviceId)
|
||||
const phone = req.body.phone
|
||||
|
||||
return pi.getPhoneCode(phone)
|
||||
.then(code => {
|
||||
return addOrUpdateCustomer(req)
|
||||
.then(customer => respond(req, res, { code, customer }))
|
||||
})
|
||||
.catch(err => {
|
||||
if (err.name === 'BadNumberError') throw httpError('Bad number', 401)
|
||||
throw err
|
||||
})
|
||||
.catch(next)
|
||||
}
|
||||
|
||||
router.post('/', getCustomerWithPhoneCode)
|
||||
|
||||
module.exports = router
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
const express = require('express')
|
||||
const nmd = require('nano-markdown')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
const complianceTriggers = require('../compliance-triggers')
|
||||
const configManager = require('../new-config-manager')
|
||||
const plugins = require('../plugins')
|
||||
const semver = require('semver')
|
||||
const state = require('../middlewares/state')
|
||||
const version = require('../../package.json').version
|
||||
const { batchGetCustomInfoRequest, getCustomInfoRequests } = require('../new-admin/services/customInfoRequests')
|
||||
|
||||
const urlsToPing = [
|
||||
`us.archive.ubuntu.com`,
|
||||
`uk.archive.ubuntu.com`,
|
||||
`za.archive.ubuntu.com`,
|
||||
`cn.archive.ubuntu.com`
|
||||
]
|
||||
|
||||
const speedtestFiles = [
|
||||
{
|
||||
url: 'https://github.com/lamassu/speed-test-assets/raw/main/python-defaults_2.7.18-3.tar.gz',
|
||||
size: 44668
|
||||
}
|
||||
]
|
||||
|
||||
function checkHasLightning (settings) {
|
||||
return configManager.getWalletSettings('BTC', settings.config).layer2 !== 'no-layer2'
|
||||
}
|
||||
|
||||
const createTerms = terms => (terms.active && terms.text) ? ({
|
||||
active: terms.active,
|
||||
title: terms.title,
|
||||
text: nmd(terms.text),
|
||||
accept: terms.acceptButtonText,
|
||||
cancel: terms.cancelButtonText
|
||||
}) : null
|
||||
|
||||
const buildTriggers = (allTriggers) => {
|
||||
const normalTriggers = []
|
||||
const customTriggers = _.filter(o => {
|
||||
if (_.isEmpty(o.customInfoRequestId) || _.isNil(o.customInfoRequestId)) normalTriggers.push(o)
|
||||
return !_.isNil(o.customInfoRequestId) && !_.isEmpty(o.customInfoRequestId)
|
||||
}, allTriggers)
|
||||
|
||||
return _.flow([_.map(_.get('customInfoRequestId')), batchGetCustomInfoRequest])(customTriggers)
|
||||
.then(res => {
|
||||
res.forEach((details, index) => {
|
||||
// make sure we aren't attaching the details to the wrong trigger
|
||||
if (customTriggers[index].customInfoRequestId !== details.id) return
|
||||
customTriggers[index] = { ...customTriggers[index], customInfoRequest: details }
|
||||
})
|
||||
return [...normalTriggers, ...customTriggers]
|
||||
})
|
||||
}
|
||||
|
||||
function poll (req, res, next) {
|
||||
const machineVersion = req.query.version
|
||||
const machineModel = req.query.model
|
||||
const deviceId = req.deviceId
|
||||
const deviceTime = req.deviceTime
|
||||
const pid = req.query.pid
|
||||
const settings = req.settings
|
||||
const operatorId = res.locals.operatorId
|
||||
const localeConfig = configManager.getLocale(deviceId, settings.config)
|
||||
const zeroConfLimits = _.reduce((acc, cryptoCode) => {
|
||||
acc[cryptoCode] = configManager.getWalletSettings(cryptoCode, settings.config).zeroConfLimit
|
||||
return acc
|
||||
}, {}, localeConfig.cryptoCurrencies)
|
||||
const pi = plugins(settings, deviceId)
|
||||
const hasLightning = checkHasLightning(settings)
|
||||
|
||||
const operatorInfo = configManager.getOperatorInfo(settings.config)
|
||||
const machineInfo = { deviceId: req.deviceId, deviceName: req.deviceName }
|
||||
const cashOutConfig = configManager.getCashOut(deviceId, settings.config)
|
||||
const receipt = configManager.getReceipt(settings.config)
|
||||
const terms = configManager.getTermsConditions(settings.config)
|
||||
const enablePaperWalletOnly = configManager.getCompliance(settings.config).enablePaperWalletOnly
|
||||
|
||||
state.pids = _.update(operatorId, _.set(deviceId, { pid, ts: Date.now() }), state.pids)
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 8.1
|
||||
// Machines after 8.1 only need the server version from the initial polling request.
|
||||
if (semver.gte(machineVersion, '8.1.0-beta.0'))
|
||||
return res.json({ version })
|
||||
|
||||
return Promise.all([
|
||||
pi.recordPing(deviceTime, machineVersion, machineModel),
|
||||
pi.pollQueries(),
|
||||
buildTriggers(configManager.getTriggers(settings.config)),
|
||||
configManager.getTriggersAutomation(getCustomInfoRequests(true), settings.config, true),
|
||||
])
|
||||
.then(([_pingRes, results, triggers, triggersAutomation]) => {
|
||||
const reboot = pid && state.reboots?.[operatorId]?.[deviceId] === pid
|
||||
const shutdown = pid && state.shutdowns?.[operatorId]?.[deviceId] === pid
|
||||
const restartServices = pid && state.restartServicesMap?.[operatorId]?.[deviceId] === pid
|
||||
const emptyUnit = pid && state.emptyUnit?.[operatorId]?.[deviceId] === pid
|
||||
const refillUnit = pid && state.refillUnit?.[operatorId]?.[deviceId] === pid
|
||||
const langs = localeConfig.languages
|
||||
|
||||
const locale = {
|
||||
fiatCode: localeConfig.fiatCurrency,
|
||||
localeInfo: {
|
||||
primaryLocale: langs[0],
|
||||
primaryLocales: langs,
|
||||
country: localeConfig.country
|
||||
}
|
||||
}
|
||||
|
||||
const response = {
|
||||
error: null,
|
||||
locale,
|
||||
version,
|
||||
receiptPrintingActive: receipt.active,
|
||||
automaticReceiptPrint: receipt.automaticPrint,
|
||||
smsReceiptActive: receipt.sms,
|
||||
enablePaperWalletOnly,
|
||||
twoWayMode: cashOutConfig.active,
|
||||
zeroConfLimits,
|
||||
reboot,
|
||||
shutdown,
|
||||
restartServices,
|
||||
emptyUnit,
|
||||
refillUnit,
|
||||
hasLightning,
|
||||
receipt,
|
||||
operatorInfo,
|
||||
machineInfo,
|
||||
triggers,
|
||||
triggersAutomation,
|
||||
speedtestFiles,
|
||||
urlsToPing
|
||||
}
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 7.6
|
||||
// Machines before 7.6 expect a single zeroConfLimit value per machine.
|
||||
if (!semver.gte(machineVersion, '7.6.0-beta.0'))
|
||||
response.zeroConfLimit = _.min(_.values(zeroConfLimits))
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 7.5
|
||||
// machines before 7.5 expect old compliance
|
||||
if (!machineVersion || semver.lt(machineVersion, '7.5.0-beta.0')) {
|
||||
const compatTriggers = complianceTriggers.getBackwardsCompatibleTriggers(triggers)
|
||||
response.smsVerificationActive = !!compatTriggers.sms
|
||||
response.smsVerificationThreshold = compatTriggers.sms
|
||||
response.idCardDataVerificationActive = !!compatTriggers.idCardData
|
||||
response.idCardDataVerificationThreshold = compatTriggers.idCardData
|
||||
response.idCardPhotoVerificationActive = !!compatTriggers.idCardPhoto
|
||||
response.idCardPhotoVerificationThreshold = compatTriggers.idCardPhoto
|
||||
response.sanctionsVerificationActive = !!compatTriggers.sanctions
|
||||
response.sanctionsVerificationThreshold = compatTriggers.sanctions
|
||||
response.frontCameraVerificationActive = !!compatTriggers.facephoto
|
||||
response.frontCameraVerificationThreshold = compatTriggers.facephoto
|
||||
}
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 7.4.9
|
||||
// machines before 7.4.9 expect t&c on poll
|
||||
if (!machineVersion || semver.lt(machineVersion, '7.4.9')) {
|
||||
response.terms = createTerms(terms)
|
||||
}
|
||||
|
||||
return res.json(_.assign(response, results))
|
||||
})
|
||||
.catch(next)
|
||||
}
|
||||
|
||||
router.get('/', poll)
|
||||
|
||||
module.exports = router
|
||||
3
package-lock.json
generated
3
package-lock.json
generated
|
|
@ -86,7 +86,7 @@
|
|||
"promise-sequential": "^1.1.1",
|
||||
"queue-promise": "^2.2.1",
|
||||
"request-promise": "^4.2.6",
|
||||
"semver": "^7.1.3",
|
||||
"semver": "^7.7.1",
|
||||
"serve-static": "^1.12.4",
|
||||
"talisman": "^0.20.0",
|
||||
"telnyx": "^1.25.5",
|
||||
|
|
@ -18226,6 +18226,7 @@
|
|||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@
|
|||
"promise-sequential": "^1.1.1",
|
||||
"queue-promise": "^2.2.1",
|
||||
"request-promise": "^4.2.6",
|
||||
"semver": "^7.1.3",
|
||||
"semver": "^7.7.1",
|
||||
"serve-static": "^1.12.4",
|
||||
"talisman": "^0.20.0",
|
||||
"telnyx": "^1.25.5",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue