diff --git a/bin/cert-gen.sh b/bin/cert-gen.sh index b64c042f..d4b1bb9c 100755 --- a/bin/cert-gen.sh +++ b/bin/cert-gen.sh @@ -15,6 +15,7 @@ POSTGRES_PASS=postgres123 OFAC_DATA_DIR=$CONFIG_DIR/ofac IDPHOTOCARD_DIR=$CONFIG_DIR/idphotocard FRONTCAMERA_DIR=$CONFIG_DIR/frontcamera +IDCARDDATA_DIR=$CONFIG_DIR/idcarddata mkdir -p $CERT_DIR mkdir -p $CONFIG_DIR >> $LOG_FILE 2>&1 @@ -113,7 +114,8 @@ cat < $CONFIG_DIR/lamassu.json } ], "idPhotoCardDir": "$IDPHOTOCARD_DIR", - "frontCameraDir": "$FRONTCAMERA_DIR" + "frontCameraDir": "$FRONTCAMERA_DIR", + "idCardDataDir": "$IDCARDDATA_DIR" } EOF diff --git a/lamassu-default.json b/lamassu-default.json index 19943309..c036738d 100644 --- a/lamassu-default.json +++ b/lamassu-default.json @@ -14,5 +14,6 @@ "baseUrl": "https://api.strike.acinq.co/api/" }, "idPhotoCardDir": "/opt/lamassu-server/idphotocard", - "frontCameraDir": "/opt/lamassu-server/frontcamera" + "frontCameraDir": "/opt/lamassu-server/frontcamera", + "idCardDataDir": "/opt/lamassu-server/idcarddata" } diff --git a/lamassu-remote-install/install b/lamassu-remote-install/install index fce7536f..deec2dad 100755 --- a/lamassu-remote-install/install +++ b/lamassu-remote-install/install @@ -19,6 +19,7 @@ BLOCKCHAIN_DIR=/mnt/blockchains OFAC_DATA_DIR=/var/lamassu/ofac ID_PHOTO_CARD_DIR=/opt/lamassu-server/idphotocard FRONTCAMERA_DIR=/opt/lamassu-server/frontcamera +IDCARDDATA_DIR=/opt/lamassu-server/idcarddata # Look into http://unix.stackexchange.com/questions/140734/configure-localtime-dpkg-reconfigure-tzdata @@ -183,6 +184,7 @@ cat < $CONFIG_DIR/lamassu.json "ofacDataDir": "$OFAC_DATA_DIR", "idPhotoCardDir": "$ID_PHOTO_CARD_DIR", "frontCameraDir": "$FRONTCAMERA_DIR", + "idCardDataDir": "$IDCARDDATA_DIR" "strike": { "baseUrl": "https://api.strike.acinq.co/api/" }, diff --git a/lib/customers.js b/lib/customers.js index 6a47d4bc..4749c8a7 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -20,6 +20,7 @@ const notifierUtils = require('./notifier/utils') const NUM_RESULTS = 1000 const idPhotoCardBasedir = _.get('idPhotoCardDir', options) const frontCameraBaseDir = _.get('frontCameraDir', options) +const idCardDataDir = _.get('idCardDataDir', options) /** * Add new customer @@ -570,6 +571,77 @@ function updatePhotoCard (id, patch) { }) } +/** + * @param {String} imageData image encoded + * @param {String} directory directory path of id card data for a certain user + */ + +function updatePhoto (imageData, directory) { + return Promise.resolve(imageData) + .then(patch => { + if (_.isEmpty(imageData)) { + return patch + } + + const newPatch = { + idCardDataPath: '' + } + + // decode the base64 string to binary data + const decodedImageData = 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. ..//idcardphoto/customer_id/24/0e/85 + const dirname = path.join(directory, rpath) + + // create the directory tree if needed + _.attempt(() => makeDir.sync(dirname)) + + // i.e. ..//idcardphoto/customer_id/24/0e/85/240e85ff2e4bb931f235985dd01....jpg + const filename = path.join(dirname, hash + '.jpg') + + // + // i.e. { + // "idCardDataPath": "24/0e/85/240e85ff2e4bb931f235985dd01....jpg", + // "idCardDataAt": "now()" + // } + newPatch.idCardData = path.join(rpath) + newPatch.idCardDataAt = 'now()' + + // write image file + return writeFile(filename, decodedImageData) + .then(() => newPatch) + }) +} + +/** + * @param {String} id customer id + * @param {Object} patch customer latest id card photos + * @returns {Promise} new patch to be applied + */ +function updateIdCardData (patch, id) { + const directory = idCardDataDir + '/' + id + return Promise.resolve(patch) + .then(patch => { + const imagesData = _.get('photos', patch) + _.map(imageData => { + return updatePhoto(imageData, directory) + .then(newPatch => newPatch) + .catch(err => console.log('An error ocurred while saving the image ', err)) + }, imagesData) + }) +} + function updateFrontCamera (id, patch) { return Promise.resolve(patch) .then(patch => { @@ -620,4 +692,4 @@ function updateFrontCamera (id, patch) { }) } -module.exports = { add, get, batch, getCustomersList, getCustomerById, getById, update, updateCustomer, updatePhotoCard, updateFrontCamera } +module.exports = { add, get, batch, getCustomersList, getCustomerById, getById, update, updateCustomer, updatePhotoCard, updateFrontCamera, updateIdCardData } diff --git a/lib/routes/customerRoutes.js b/lib/routes/customerRoutes.js index c4745c6a..a8b62487 100644 --- a/lib/routes/customerRoutes.js +++ b/lib/routes/customerRoutes.js @@ -43,6 +43,19 @@ function updateCustomer (req, res, next) { .catch(next) } +function updateIdCardData (req, res, next) { + const id = req.params.id + const patch = req.body + customers.getById(id) + .then(customer => { + if (!customer) { throw httpError('Not Found', 404) } + return customers.updateIdCardData(patch, id) + .then(() => customer) + }) + .then(customer => respond(req, res, { customer })) + .catch(next) +} + function triggerSanctions (req, res, next) { const id = req.params.id @@ -90,5 +103,6 @@ router.patch('/:id', updateCustomer) router.patch('/:id/sanctions', triggerSanctions) router.patch('/:id/block', triggerBlock) router.patch('/:id/suspend', triggerSuspend) +router.patch('/:id/cardphotos', updateIdCardData) module.exports = router