From afc78d512e26fcf85e9b0c44beed6f9614e109aa Mon Sep 17 00:00:00 2001 From: Fabio Cigliano Date: Wed, 15 Aug 2018 19:27:55 +0200 Subject: [PATCH] handle idCardPhoto image upload --- lamassu-default.json | 3 +- lib/customers.js | 65 +++++++++++++++++++++++++++++++++++++++++++- lib/routes.js | 3 +- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/lamassu-default.json b/lamassu-default.json index 203d3b6d..f8400b72 100644 --- a/lamassu-default.json +++ b/lamassu-default.json @@ -12,5 +12,6 @@ }, "strike": { "baseUrl": "https://api.strike.acinq.co/api/" - } + }, + "idPhotoCardDir": "/opt/lamassu-server/idphotocard" } diff --git a/lib/customers.js b/lib/customers.js index 5ae0c013..089e7e16 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -1,14 +1,22 @@ const uuid = require('uuid') const Pgp = require('pg-promise')() const _ = require('lodash/fp') +const crypto = require('crypto') +const makeDir = require('make-dir') +const path = require('path') +const fs = require('fs') +const util = require('util') const db = require('./db') const BN = require('./bn') const anonymous = require('../lib/constants').anonymousCustomer const complianceOverrides = require('./compliance_overrides') const users = require('./users') +const options = require('./options') +const writeFile = util.promisify(fs.writeFile) const NUM_RESULTS = 20 +const idPhotoCardBasedir = _.get('idPhotoCardDir', options) /** * Add new customer @@ -332,4 +340,59 @@ function batch () { }, customers))) } -module.exports = {add, get, batch, getById, update} +/** + * @param {String} id customer id + * @param {Object} patch customer update record + * @returns {Promise} new patch to be applied + */ +function updatePhotoCard (id, patch) { + return Promise.resolve(patch) + .then(patch => { + // Base64 encoded image /9j/4AAQSkZJRgABAQAAAQ.. + let imageData = _.get('idCardPhotoData', patch) + + if (_.isEmpty(imageData)) { + return patch + } + + // remove idCardPhotoData from the update record + const newPatch = _.omit('idCardPhotoData', patch) + + // decode the base64 string to binary data + imageData = Buffer.from(imageData, 'base64') + + // workout the image hash + // i.e. 240e85ff2e4bb931f235985dd0134e459239496d2b5af6c5665168d38ef89b50 + const hash = crypto + .createHash('sha256') + .update(imageData) + .digest('hex') + + // workout the image folder + // i.e. 24/0e/85 + const rpath = _.join(path.sep, _.map(_.wrap(_.join, ''), _.take(3, _.chunk(2, _.split('', hash))))) + + // i.e. ..//idphotocard/24/0e/85 + const dirname = path.join(idPhotoCardBasedir, rpath) + + // create the directory tree if needed + _.attempt(() => makeDir.sync(dirname)) + + // i.e. ..//idphotocard/24/0e/85/240e85ff2e4bb931f235985dd01....jpg + const filename = path.join(dirname, hash + '.jpg') + + // update db record patch + // i.e. { + // "idCardPhotoPath": "24/0e/85/240e85ff2e4bb931f235985dd01....jpg", + // "idCardPhotoAt": "now()" + // } + newPatch.idCardPhotoPath = path.join(rpath, hash + '.jpg') + newPatch.idCardPhotoAt = 'now()' + + // write image file + return writeFile(filename, imageData) + .then(() => newPatch) + }) +} + +module.exports = {add, get, batch, getById, update, updatePhotoCard} diff --git a/lib/routes.js b/lib/routes.js index 63dee14d..074de437 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -216,6 +216,7 @@ function updateCustomer (req, res, next) { const mergedCustomer = _.merge(customer, patch) return compliance.validationPatch(req.deviceId, config, mergedCustomer) .then(_.merge(patch)) + .then(newPatch => customers.updatePhotoCard(id, newPatch)) .then(newPatch => customers.update(id, newPatch)) }) .then(customer => respond(req, res, {customer})) @@ -328,7 +329,7 @@ const app = express() const localApp = express() app.use(helmet({noCache: true})) -app.use(bodyParser.json()) +app.use(bodyParser.json({limit: '2mb'})) app.use(morgan('dev', {skip, stream: logger.stream})) // These two have their own authorization