const UserError = require('vn-loopback/util/user-error'); const fs = require('fs-extra'); module.exports = Self => { Self.remoteMethodCtx('updateFile', { description: 'updates a file properties or file', accessType: 'WRITE', accepts: [{ arg: 'id', type: 'Number', description: 'The document id', http: {source: 'path'} }, { arg: 'warehouseId', type: 'Number', description: 'The warehouse id' }, { arg: 'companyId', type: 'Number', description: 'The company id' }, { arg: 'dmsTypeId', type: 'Number', description: 'The dms type id' }, { arg: 'reference', type: 'String' }, { arg: 'description', type: 'String' }, { arg: 'hasFile', type: 'Boolean', description: 'True if has an attached file' }], returns: { type: 'Object', root: true }, http: { path: `/:id/updateFile`, verb: 'POST' } }); Self.updateFile = async(ctx, id, warehouseId, companyId, dmsTypeId, reference, description, hasFile, options) => { const storageConnector = Self.app.dataSources.storage.connector; const models = Self.app.models; const fileOptions = {}; let tx; let myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); if (!myOptions.transaction) { tx = await Self.beginTransaction({}); myOptions.transaction = tx; } try { const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dmsTypeId); if (!hasWriteRole) throw new UserError(`You don't have enough privileges`); // Upload file to temporary path const tempContainer = await getContainer('temp'); let files = []; try { const uploaded = await models.Container.upload(tempContainer.name, ctx.req, ctx.result, fileOptions); files = Object.values(uploaded.files).map(file => { return file[0]; }); } catch (err) { if (err.message != 'No file content uploaded') throw e; } const updatedDmsList = []; for (const file of files) { const updatedDms = await updateDms(id, dmsTypeId, companyId, warehouseId, reference, description, hasFile, file, myOptions); const pathHash = storageConnector.getPathHash(updatedDms.id); const container = await getContainer(pathHash); const originPath = `${tempContainer.client.root}/${tempContainer.name}/${file.name}`; const destinationPath = `${container.client.root}/${pathHash}/${updatedDms.file}`; fs.rename(originPath, destinationPath); updatedDmsList.push(updatedDms); } if (tx) await tx.commit(); return updatedDmsList; } catch (e) { if (tx) await tx.rollback(); throw e; } }; async function updateDms(id, dmsTypeId, companyId, warehouseId, reference, description, hasFile, file, myOptions) { const storageConnector = Self.app.dataSources.storage.connector; const dms = await Self.findById(id, null, myOptions); const updatedDms = await dms.updateAttributes({ dmsTypeFk: dmsTypeId, companyFk: companyId, warehouseFk: warehouseId, reference: reference, description: description, contentType: file.type, hasFile: hasFile }, myOptions); let fileName = file.name; const oldExtension = storageConnector.getFileExtension(dms.file); const newExtension = storageConnector.getFileExtension(fileName); try { if (oldExtension != newExtension) { const pathHash = storageConnector.getPathHash(updatedDms.id); await Self.app.models.Container.removeFile(pathHash, dms.file); } } catch (err) {} fileName = `${updatedDms.id}.${newExtension}`; return updatedDms.updateAttribute('file', fileName, myOptions); } /** * Returns a container instance * If doesn't exists creates a new one * * @param {String} name Container name * @return {Object} Container instance */ async function getContainer(name) { const models = Self.app.models; let container; try { container = await models.Container.getContainer(name); } catch (err) { if (err.code === 'ENOENT') { container = await models.Container.createContainer({ name: name }); } else throw err; } return container; } };