diff --git a/lib/customers.js b/lib/customers.js index 4f01ea7b..029a2fd1 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -216,7 +216,7 @@ function enhanceEditedFields (fields, userToken) { */ function deleteEditedData (id, data) { - // NOT IMPLEMENTING THIS FEATURE FOR NOW + // NOT IMPLEMENTING THIS FEATURE FOR THE CURRENT VERSION // const defaults = [ // 'front_camera', // 'id_card_data', @@ -235,6 +235,53 @@ function deleteEditedData (id, data) { return getCustomerById(id) } +/** + * Replace customer's compliance photos + * + * @name save + * @function + * + * @param {string} id Customer's id + * @param {File} photo New photo data + * @param {string} photoType Photo's compliance type + * + * @returns {object} path New photo path + * + */ +function replacePhoto (id, photo, photoType) { + const baseDir = photoType === 'frontCamera' ? frontCameraBaseDir : idPhotoCardBasedir + const { createReadStream } = photo + const stream = createReadStream() + + // 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()' +} + const invalidateCustomerNotifications = (id, data) => { if (data.authorized_override !== 'verified') return Promise.resolve() diff --git a/lib/new-admin/graphql/resolvers/customer.resolver.js b/lib/new-admin/graphql/resolvers/customer.resolver.js index 4173c128..5bfd42e4 100644 --- a/lib/new-admin/graphql/resolvers/customer.resolver.js +++ b/lib/new-admin/graphql/resolvers/customer.resolver.js @@ -3,7 +3,6 @@ const customers = require('../../../customers') const filters = require('../../filters') const resolvers = { - // Upload: GraphQLUpload, Customer: { isAnonymous: parent => (parent.customerId === anonymous.uuid) @@ -22,9 +21,15 @@ const resolvers = { addCustomField: (...[, { customerId, label, value }]) => customers.addCustomField(customerId, label, value), saveCustomField: (...[, { customerId, fieldId, newValue }]) => customers.saveCustomField(customerId, fieldId, newValue), removeCustomField: (...[, [ { customerId, fieldId } ]]) => customers.removeCustomField(customerId, fieldId), - editCustomer: (root, { customerId, customerEdit }, context) => { + editCustomer: async (root, { customerId, customerEdit }, context) => { const token = !!context.req.cookies.lid && context.req.session.user.id - return customers.edit(customerId, customerEdit, token) + const editedData = await customerEdit + return customers.edit(customerId, editedData, token) + }, + replacePhoto: async (root, { customerId, photoType, newPhoto }, context) => { + const photo = await newPhoto + return customers.replacePhoto(customerId, photoType, photo) + .then(() => customers.getCustomerById(customerId)) }, deleteEditedData: (root, { customerId, customerEdit }) => { return customers.deleteEditedData(customerId, customerEdit) diff --git a/lib/new-admin/graphql/types/customer.type.js b/lib/new-admin/graphql/types/customer.type.js index 151c1527..f6d56d4d 100644 --- a/lib/new-admin/graphql/types/customer.type.js +++ b/lib/new-admin/graphql/types/customer.type.js @@ -12,7 +12,8 @@ const typeDef = gql` authorizedOverride: String daysSuspended: Int isSuspended: Boolean - frontCamera: Upload + newPhoto: Upload + photoType: String frontCameraPath: String frontCameraAt: Date frontCameraOverride: String @@ -68,7 +69,6 @@ const typeDef = gql` } input CustomerEdit { - frontCamera: Upload idCardData: JSONObject idCardPhoto: Upload usSsn: String @@ -87,6 +87,7 @@ const typeDef = gql` removeCustomField(customerId: ID!, fieldId: ID!): CustomerCustomField @auth editCustomer(customerId: ID!, customerEdit: CustomerEdit): Customer @auth deleteEditedData(customerId: ID!, customerEdit: CustomerEdit): Customer @auth + replacePhoto(customerId: ID!, photoType: String, newPhoto: Upload): Customer @auth } ` diff --git a/new-lamassu-admin/src/pages/Customers/CustomerData.js b/new-lamassu-admin/src/pages/Customers/CustomerData.js index ed116708..9785afa3 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerData.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerData.js @@ -60,6 +60,7 @@ const Photo = ({ show, src }) => { const CustomerData = ({ customer, updateCustomer, + replacePhoto, editCustomer, deleteEditedData }) => { @@ -230,7 +231,11 @@ const CustomerData = ({ authorize: () => updateCustomer({ frontCameraOverride: OVERRIDE_AUTHORIZED }), reject: () => updateCustomer({ frontCameraOverride: OVERRIDE_REJECTED }), - save: values => editCustomer({ frontCamera: values.frontCamera }), + save: values => + replacePhoto({ + newPhoto: values.frontCamera, + photoType: 'frontCamera' + }), deleteEditedData: () => deleteEditedData({ frontCamera: null }), children: customer.frontCameraPath ? ( updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED }), reject: () => updateCustomer({ idCardPhotoOverride: OVERRIDE_REJECTED }), - save: values => editCustomer({ idCardPhoto: values.idCardPhoto }), + save: values => + replacePhoto({ + newPhoto: values.idCardPhoto, + photoType: 'idCardPhoto' + }), deleteEditedData: () => deleteEditedData({ idCardPhoto: null }), children: customer.idCardPhotoPath ? ( { } ) + const [replaceCustomerPhoto] = useMutation(REPLACE_CUSTOMER_PHOTO, { + onCompleted: () => getCustomer() + }) + const [editCustomerData] = useMutation(EDIT_CUSTOMER, { onCompleted: () => getCustomer() }) @@ -176,6 +196,15 @@ const CustomerProfile = memo(() => { } }) + const replacePhoto = it => + replaceCustomerPhoto({ + variables: { + customerId, + newPhoto: it.newPhoto, + photoType: it.photoType + } + }) + const editCustomer = it => editCustomerData({ variables: { @@ -343,6 +372,7 @@ const CustomerProfile = memo(() => { diff --git a/new-lamassu-admin/src/pages/Customers/components/EditableCard.js b/new-lamassu-admin/src/pages/Customers/components/EditableCard.js index 5b1c45e5..936fd076 100644 --- a/new-lamassu-admin/src/pages/Customers/components/EditableCard.js +++ b/new-lamassu-admin/src/pages/Customers/components/EditableCard.js @@ -243,6 +243,7 @@ const EditableCard = ({ setInput(fileInput)} onChange={event => {