Front facing camera (#289)

* Front facing camera

* Adding in configuration and update script
This commit is contained in:
Rafael Taranto 2019-07-05 17:17:59 +01:00 committed by Josh Harvey
parent 90de4fe24d
commit 00c4187081
10 changed files with 142 additions and 8 deletions

View file

@ -0,0 +1,12 @@
#!/usr/bin/env node
'use strict'
const fs = require('fs')
const options = require('../lib/options-loader')()
if (!options.opts.frontCameraDir) {
options.opts.frontCameraDir = '/opt/lamassu-server/frontcamera'
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
}

View file

@ -71,6 +71,9 @@ lamassu-migrate-config >> ${LOG_FILE} 2>&1
decho "update to mnemonic" decho "update to mnemonic"
lamassu-update-to-mnemonic --prod >> ${LOG_FILE} 2>&1 lamassu-update-to-mnemonic --prod >> ${LOG_FILE} 2>&1
decho "update configure frontcamera"
lamassu-configure-frontcamera >> ${LOG_FILE} 2>&1
decho "update ofac sources" decho "update ofac sources"
lamassu-ofac-update-sources >> ${LOG_FILE} 2>&1 lamassu-ofac-update-sources >> ${LOG_FILE} 2>&1

View file

@ -178,6 +178,19 @@ customerView customer =
, alt "N/A" , alt "N/A"
] [] ] []
] ]
, h2 [] [ text "Front Facing Camera Photo" ]
, case customer.frontCameraPath of
Nothing ->
text "N/A"
Just frontCameraPath ->
div []
[ img
[ src ("/front-camera-photo/" ++ frontCameraPath)
, height 200
, alt "N/A"
] []
]
] ]

View file

@ -13,5 +13,6 @@
"strike": { "strike": {
"baseUrl": "https://api.strike.acinq.co/api/" "baseUrl": "https://api.strike.acinq.co/api/"
}, },
"idPhotoCardDir": "/opt/lamassu-server/idphotocard" "idPhotoCardDir": "/opt/lamassu-server/idphotocard",
"frontCameraDir": "/opt/lamassu-server/frontcamera"
} }

View file

@ -18,6 +18,7 @@ BACKUP_DIR=/var/backups/postgresql
BLOCKCHAIN_DIR=/mnt/blockchains BLOCKCHAIN_DIR=/mnt/blockchains
OFAC_DATA_DIR=/var/lamassu/ofac OFAC_DATA_DIR=/var/lamassu/ofac
ID_PHOTO_CARD_DIR=/opt/lamassu-server/idphotocard ID_PHOTO_CARD_DIR=/opt/lamassu-server/idphotocard
FRONTCAMERA_DIR=/opt/lamassu-server/frontcamera
# Look into http://unix.stackexchange.com/questions/140734/configure-localtime-dpkg-reconfigure-tzdata # Look into http://unix.stackexchange.com/questions/140734/configure-localtime-dpkg-reconfigure-tzdata
@ -181,6 +182,7 @@ cat <<EOF > $CONFIG_DIR/lamassu.json
"blockchainDir": "$BLOCKCHAIN_DIR", "blockchainDir": "$BLOCKCHAIN_DIR",
"ofacDataDir": "$OFAC_DATA_DIR", "ofacDataDir": "$OFAC_DATA_DIR",
"idPhotoCardDir": "$ID_PHOTO_CARD_DIR", "idPhotoCardDir": "$ID_PHOTO_CARD_DIR",
"frontCameraDir": "$FRONTCAMERA_DIR",
"strike": { "strike": {
"baseUrl": "https://api.strike.acinq.co/api/" "baseUrl": "https://api.strike.acinq.co/api/"
}, },

View file

@ -38,6 +38,7 @@ const supportServer = require('./admin-support')
const NEVER = new Date(Date.now() + 100 * T.years) const NEVER = new Date(Date.now() + 100 * T.years)
const REAUTHENTICATE_INTERVAL = T.minute const REAUTHENTICATE_INTERVAL = T.minute
const idPhotoCardBasedir = _.get('idPhotoCardDir', options) const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
const frontCameraBasedir = _.get('frontCameraDir', options)
const devMode = argv.dev const devMode = argv.dev
@ -255,7 +256,12 @@ if (!fs.existsSync(idPhotoCardBasedir)) {
makeDir.sync(idPhotoCardBasedir) makeDir.sync(idPhotoCardBasedir)
} }
if (!fs.existsSync(frontCameraBasedir)) {
makeDir.sync(frontCameraBasedir)
}
app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, {index: false})) app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, {index: false}))
app.use('/front-camera-photo', serveStatic(frontCameraBasedir, {index: false}))
function register (req, res, next) { function register (req, res, next) {
const otp = req.query.otp const otp = req.query.otp

View file

@ -8,7 +8,6 @@ const fs = require('fs')
const util = require('util') const util = require('util')
const moment = require('moment') const moment = require('moment')
const db = require('./db') const db = require('./db')
const BN = require('./bn') const BN = require('./bn')
const anonymous = require('../lib/constants').anonymousCustomer const anonymous = require('../lib/constants').anonymousCustomer
@ -19,6 +18,7 @@ const writeFile = util.promisify(fs.writeFile)
const NUM_RESULTS = 1000 const NUM_RESULTS = 1000
const idPhotoCardBasedir = _.get('idPhotoCardDir', options) const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
const frontCameraBaseDir = _.get('frontCameraDir', options)
/** /**
* Add new customer * Add new customer
@ -432,4 +432,54 @@ function updatePhotoCard (id, patch) {
}) })
} }
module.exports = {add, get, batch, getById, update, updatePhotoCard} function updateFrontCamera (id, patch) {
return Promise.resolve(patch)
.then(patch => {
// Base64 encoded image /9j/4AAQSkZJRgABAQAAAQ..
const imageData = _.get('frontCameraData', patch)
if (_.isEmpty(imageData)) {
return patch
}
// remove idCardPhotoData from the update record
const newPatch = _.omit('frontCameraData', patch)
// 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. ../<lamassu-server-home>/idphotocard/24/0e/85
const dirname = path.join(frontCameraBaseDir, rpath)
// create the directory tree if needed
_.attempt(() => makeDir.sync(dirname))
// i.e. ../<lamassu-server-home>/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.frontCameraPath = path.join(rpath, hash + '.jpg')
newPatch.frontCameraAt = 'now()'
// write image file
return writeFile(filename, decodedImageData)
.then(() => newPatch)
})
}
module.exports = { add, get, batch, getById, update, updatePhotoCard, updateFrontCamera }

View file

@ -233,6 +233,7 @@ function updateCustomer (req, res, next) {
return compliance.validationPatch(req.deviceId, config, mergedCustomer) return compliance.validationPatch(req.deviceId, config, mergedCustomer)
.then(_.merge(patch)) .then(_.merge(patch))
.then(newPatch => customers.updatePhotoCard(id, newPatch)) .then(newPatch => customers.updatePhotoCard(id, newPatch))
.then(newPatch => customers.updateFrontCamera(id, newPatch))
.then(newPatch => customers.update(id, newPatch, null, txId)) .then(newPatch => customers.update(id, newPatch, null, txId))
}) })
.then(customer => respond(req, res, { customer })) .then(customer => respond(req, res, { customer }))

View file

@ -84,6 +84,7 @@
"lamassu-ofac-update": "./bin/lamassu-ofac-update", "lamassu-ofac-update": "./bin/lamassu-ofac-update",
"lamassu-send-coins": "./bin/lamassu-send-coins", "lamassu-send-coins": "./bin/lamassu-send-coins",
"lamassu-update-to-mnemonic": "./bin/lamassu-update-to-mnemonic", "lamassu-update-to-mnemonic": "./bin/lamassu-update-to-mnemonic",
"lamassu-configure-frontcamera": "./bin/lamassu-configure-frontcamera",
"lamassu-ofac-update-sources": "./bin/lamassu-ofac-update-sources", "lamassu-ofac-update-sources": "./bin/lamassu-ofac-update-sources",
"lamassu-devices": "./bin/lamassu-devices", "lamassu-devices": "./bin/lamassu-devices",
"lamassu-operator": "./bin/lamassu-operator", "lamassu-operator": "./bin/lamassu-operator",

View file

@ -35981,7 +35981,52 @@ var _user$project$Customer_View$customerView = function (customer) {
}); });
} }
}(), }(),
_1: {ctor: '[]'} _1: {
ctor: '::',
_0: A2(
_elm_lang$html$Html$h2,
{ctor: '[]'},
{
ctor: '::',
_0: _elm_lang$html$Html$text('Front Facing Camera Photo'),
_1: {ctor: '[]'}
}),
_1: {
ctor: '::',
_0: function () {
var _p3 = customer.frontCameraPath;
if (_p3.ctor === 'Nothing') {
return _elm_lang$html$Html$text('N/A');
} else {
return A2(
_elm_lang$html$Html$div,
{ctor: '[]'},
{
ctor: '::',
_0: A2(
_elm_lang$html$Html$img,
{
ctor: '::',
_0: _elm_lang$html$Html_Attributes$src(
A2(_elm_lang$core$Basics_ops['++'], '/front-camera-photo/', _p3._0)),
_1: {
ctor: '::',
_0: _elm_lang$html$Html_Attributes$height(200),
_1: {
ctor: '::',
_0: _elm_lang$html$Html_Attributes$alt('N/A'),
_1: {ctor: '[]'}
}
}
},
{ctor: '[]'}),
_1: {ctor: '[]'}
});
}
}(),
_1: {ctor: '[]'}
}
}
} }
} }
} }
@ -35990,8 +36035,8 @@ var _user$project$Customer_View$customerView = function (customer) {
}); });
}; };
var _user$project$Customer_View$view = function (model) { var _user$project$Customer_View$view = function (model) {
var _p3 = model; var _p4 = model;
switch (_p3.ctor) { switch (_p4.ctor) {
case 'NotAsked': case 'NotAsked':
return A2( return A2(
_elm_lang$html$Html$div, _elm_lang$html$Html$div,
@ -36013,7 +36058,7 @@ var _user$project$Customer_View$view = function (model) {
{ {
ctor: '::', ctor: '::',
_0: _elm_lang$html$Html$text( _0: _elm_lang$html$Html$text(
_elm_lang$core$Basics$toString(_p3._0)), _elm_lang$core$Basics$toString(_p4._0)),
_1: {ctor: '[]'} _1: {ctor: '[]'}
}); });
default: default:
@ -36022,7 +36067,7 @@ var _user$project$Customer_View$view = function (model) {
{ctor: '[]'}, {ctor: '[]'},
{ {
ctor: '::', ctor: '::',
_0: _user$project$Customer_View$customerView(_p3._0), _0: _user$project$Customer_View$customerView(_p4._0),
_1: {ctor: '[]'} _1: {ctor: '[]'}
}); });
} }