UNPKG

rappopo-sob-marine

Version:

Rappopo Sob - Marine

151 lines (149 loc) 5.22 kB
const { _, createError, toUnixPath, fg, fs, mime } = require('rappopo-sob').Helper const context = require('rappopo-sob/lib/context') const path = require('path') module.exports = ({ sobr, sob }) => { return { settings: { webApi: { alias: { 'GET /:entity/:entityId': 'imageList', 'GET /:entity/:entityId/:file': 'imageGet', 'DELETE /:entity/:entityId/:file': 'imageRemove' } }, webRoot: { anonymous: ['imageStream'], alias: { 'GET /:entity/:entityId/:file': 'imageStream' } }, upload: { /* alias: { '/:entity/:id': 'uploadImage' } params: { busboyConfig: { limits: { files: 1 } } } */ } }, actions: { upload (ctx) { return new Promise((resolve, reject) => { const entity = ctx.meta.$multipart.entity || '' const entityId = ctx.meta.$multipart.entityId || '' Promise.resolve() .then(() => { this.checkParams(ctx, { entity, entityId }) const action = `marine${_.upperFirst(_.camelCase(entity))}.find` return ctx.broker.call(action, { query: { id: entityId }, limit: 1 }) }) .then(result => { if (result.length === 0) throw createError('Entity not found', 404, { id: 'notFound' }) return context.upload(ctx, { destDir: this.getDir(entity, entityId) }) }) .then(resolve) .catch(reject) }) }, imageStream (ctx) { return new Promise((resolve, reject) => { const { entity, entityId, file } = ctx.params Promise.resolve() .then(() => { this.checkParams(ctx, { entity, entityId, file }, true) return fg(this.getDir(entity, entityId) + '/' + file) }) .then(files => { if (files.length === 0) throw createError('File not found', 404) ctx.meta.$responseType = mime.lookup(path.basename(files[0])) const f = fs.createReadStream(files[0]) f.on('error', err => { throw err }) resolve(f) }) .catch(reject) }) }, imageGet (ctx) { return new Promise((resolve, reject) => { const { entity, entityId, file } = ctx.params Promise.resolve() .then(() => { this.checkParams(ctx, { entity, entityId, file }, true) return fg(this.getDir(entity, entityId) + '/' + file) }) .then(files => { if (files.length === 0) throw createError('File not found', 404) resolve(this.fileInfo(files[0])) }) .catch(reject) }) }, imageList (ctx) { return new Promise((resolve, reject) => { const { entity, entityId } = ctx.params Promise.resolve() .then(() => { this.checkParams(ctx, { entity, entityId }) return fg(this.getDir(entity, entityId) + '/*') }) .then(files => { const result = { page: 1, pageSize: files.length, total: files.length } result.rows = _.map(files, f => this.fileInfo(f)) resolve(result) }) .catch(reject) }) }, imageRemove (ctx) { return new Promise((resolve, reject) => { const { entity, entityId, file } = ctx.params Promise.resolve() .then(() => { this.checkParams(ctx, { entity, entityId, file }, true) return fg(this.getDir(entity, entityId) + '/' + file) }) .then(files => { if (files.length === 0) throw createError('File not found', 404) _.each(files, f => { try { fs.unlinkSync(files[0]) } catch (err) {} }) resolve({ msg: 'Image removed' }) }) .catch(reject) }) } }, methods: { getDir (entity, entityId) { return toUnixPath(path.join(this.broker.sobr.dataDir, 'upload', 'marineImage', entity, entityId)) }, checkParams (ctx, { entity, entityId, file }, withFile) { if (!ctx.meta.user) throw createError('Unauthenticated', 403) if (_.isEmpty(entity)) throw createError('Entity is required', 422, { entity: 'required' }) if (_.isEmpty(entityId)) throw createError('Entity ID is required', 422, { entityId: 'required' }) if (withFile && _.isEmpty(file)) throw createError('File is required', 422, { file: 'required' }) if (!['ship', 'organization', 'port'].includes(entity)) throw createError('Invalid entity', 422, { entity: 'invalid' }) }, fileInfo (file) { const stats = fs.statSync(file) return { id: path.basename(file), ts: stats.birthtime, size: stats.size } } } } }