| 
									
										
										
										
											2018-02-08 12:01:06 +01:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Upload.js service | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @description: A set of functions similar to controller's actions to avoid code duplication. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  | const fs = require('fs'); | 
					
						
							| 
									
										
										
										
											2018-09-17 15:50:13 +08:00
										 |  |  | const crypto = require('crypto'); | 
					
						
							| 
									
										
										
										
											2018-04-30 18:00:01 +02:00
										 |  |  | const _ = require('lodash'); | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  | const toArray = require('stream-to-array'); | 
					
						
							|  |  |  | const uuid = require('uuid/v4'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 15:50:13 +08:00
										 |  |  | function niceHash(buffer) { | 
					
						
							|  |  |  |   return crypto | 
					
						
							|  |  |  |     .createHash('sha256') | 
					
						
							|  |  |  |     .update(buffer) | 
					
						
							|  |  |  |     .digest('base64') | 
					
						
							|  |  |  |     .replace(/=/g, '') | 
					
						
							|  |  |  |     .replace(/\//g, '-') | 
					
						
							|  |  |  |     .replace(/\+/, '_'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-08 12:01:06 +01:00
										 |  |  | module.exports = { | 
					
						
							| 
									
										
										
										
											2018-02-27 11:52:18 +01:00
										 |  |  |   bufferize: async files => { | 
					
						
							|  |  |  |     if (_.isEmpty(files) === 0) { | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |       throw 'Missing files.'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 17:18:33 +01:00
										 |  |  |     // files is always an array to map on
 | 
					
						
							| 
									
										
										
										
											2018-02-27 11:52:18 +01:00
										 |  |  |     files = _.isArray(files) ? files : [files]; | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 17:18:33 +01:00
										 |  |  |     // transform all files in buffer
 | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |     return Promise.all( | 
					
						
							|  |  |  |       files.map(async stream => { | 
					
						
							| 
									
										
										
										
											2018-09-17 15:50:13 +08:00
										 |  |  |         const parts = await toArray(fs.createReadStream(stream.path)); | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |         const buffers = parts.map( | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |           part => (_.isBuffer(part) ? part : Buffer.from(part)), | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 15:50:13 +08:00
										 |  |  |         const buffer = Buffer.concat(buffers); | 
					
						
							| 
									
										
										
										
											2018-08-02 20:09:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |         return { | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |           name: stream.name, | 
					
						
							| 
									
										
										
										
											2018-09-17 15:50:13 +08:00
										 |  |  |           sha256: niceHash(buffer), | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |           hash: uuid().replace(/-/g, ''), | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |           ext: | 
					
						
							|  |  |  |             stream.name.split('.').length > 1 | 
					
						
							|  |  |  |               ? `.${_.last(stream.name.split('.'))}` | 
					
						
							|  |  |  |               : '', | 
					
						
							| 
									
										
										
										
											2018-09-17 15:50:13 +08:00
										 |  |  |           buffer, | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |           mime: stream.type, | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |           size: (stream.size / 1000).toFixed(2), | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |         }; | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       }), | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |     ); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 17:10:25 +01:00
										 |  |  |   upload: async (files, config) => { | 
					
						
							| 
									
										
										
										
											2018-02-27 16:53:06 +01:00
										 |  |  |     // Get upload provider settings to configure the provider to use.
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |     const provider = _.find(strapi.plugins.upload.config.providers, { | 
					
						
							|  |  |  |       provider: config.provider, | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-03-06 15:49:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!provider) { | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       throw new Error( | 
					
						
							| 
									
										
										
										
											2018-10-19 09:26:09 +02:00
										 |  |  |         `The provider package isn't installed. Please run \`npm install strapi-provider-upload-${ | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |           config.provider | 
					
						
							|  |  |  |         }\``, | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2018-03-06 15:49:11 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 16:53:06 +01:00
										 |  |  |     const actions = provider.init(config); | 
					
						
							| 
									
										
										
										
											2018-02-20 17:10:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 16:53:06 +01:00
										 |  |  |     // Execute upload function of the provider for all files.
 | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |     return Promise.all( | 
					
						
							|  |  |  |       files.map(async file => { | 
					
						
							| 
									
										
										
										
											2018-02-20 17:10:25 +01:00
										 |  |  |         await actions.upload(file); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 16:53:06 +01:00
										 |  |  |         // Remove buffer to don't save it.
 | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |         delete file.buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-07 14:18:15 +01:00
										 |  |  |         file.provider = provider.provider; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 16:53:06 +01:00
										 |  |  |         return await strapi.plugins['upload'].services.upload.add(file); | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       }), | 
					
						
							| 
									
										
										
										
											2018-02-19 14:26:20 +01:00
										 |  |  |     ); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |   add: async values => { | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |     // Use Content Manager business logic to handle relation.
 | 
					
						
							|  |  |  |     if (strapi.plugins['content-manager']) { | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       return await strapi.plugins['content-manager'].services[ | 
					
						
							|  |  |  |         'contentmanager' | 
					
						
							|  |  |  |       ].add( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           model: 'file', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         values, | 
					
						
							|  |  |  |         'upload', | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return strapi.query('file', 'upload').create(values); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   edit: async (params, values) => { | 
					
						
							|  |  |  |     // Use Content Manager business logic to handle relation.
 | 
					
						
							|  |  |  |     if (strapi.plugins['content-manager']) { | 
					
						
							|  |  |  |       params.model = 'file'; | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       params.id = params._id || params.id; | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       return await strapi.plugins['content-manager'].services[ | 
					
						
							|  |  |  |         'contentmanager' | 
					
						
							|  |  |  |       ].edit(params, values, 'upload'); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return strapi.query('file', 'upload').update(_.assign(params, values)); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |   fetch: params => { | 
					
						
							|  |  |  |     return strapi | 
					
						
							|  |  |  |       .query('file', 'upload') | 
					
						
							|  |  |  |       .findOne(_.pick(params, ['_id', 'id'])); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |   fetchAll: params => { | 
					
						
							|  |  |  |     return strapi | 
					
						
							|  |  |  |       .query('file', 'upload') | 
					
						
							|  |  |  |       .find(strapi.utils.models.convertParams('file', params)); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-30 18:00:01 +02:00
										 |  |  |   count: async () => { | 
					
						
							| 
									
										
										
										
											2018-02-19 19:54:45 +01:00
										 |  |  |     return await strapi.query('file', 'upload').count(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 17:10:25 +01:00
										 |  |  |   remove: async (params, config) => { | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |     params.id = params._id || params.id; | 
					
						
							| 
									
										
										
										
											2018-07-20 15:09:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 15:57:34 +01:00
										 |  |  |     const file = await strapi.plugins['upload'].services.upload.fetch(params); | 
					
						
							| 
									
										
										
										
											2018-02-19 16:00:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 17:18:33 +01:00
										 |  |  |     // get upload provider settings to configure the provider to use
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |     const provider = _.cloneDeep( | 
					
						
							|  |  |  |       _.find(strapi.plugins.upload.config.providers, { | 
					
						
							|  |  |  |         provider: config.provider, | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2018-02-20 17:10:25 +01:00
										 |  |  |     _.assign(provider, config); | 
					
						
							| 
									
										
										
										
											2018-03-07 14:18:15 +01:00
										 |  |  |     const actions = provider.init(config); | 
					
						
							| 
									
										
										
										
											2018-02-20 17:10:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 17:18:33 +01:00
										 |  |  |     // execute delete function of the provider
 | 
					
						
							| 
									
										
										
										
											2018-03-07 14:18:15 +01:00
										 |  |  |     if (file.provider === provider.provider) { | 
					
						
							|  |  |  |       await actions.delete(file); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-19 16:00:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |     // Use Content Manager business logic to handle relation.
 | 
					
						
							|  |  |  |     if (strapi.plugins['content-manager']) { | 
					
						
							| 
									
										
										
										
											2018-02-19 16:00:37 +01:00
										 |  |  |       params.model = 'file'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       await strapi.plugins['content-manager'].services['contentmanager'].delete( | 
					
						
							|  |  |  |         params, | 
					
						
							|  |  |  |         { source: 'upload' }, | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2018-02-19 15:41:26 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return strapi.query('file', 'upload').delete(params); | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  |   }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |   uploadToEntity: async function(params, files, source) { | 
					
						
							| 
									
										
										
										
											2018-02-28 15:49:28 +01:00
										 |  |  |     // Retrieve provider settings from database.
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |     const config = await strapi | 
					
						
							|  |  |  |       .store({ | 
					
						
							|  |  |  |         environment: strapi.config.environment, | 
					
						
							|  |  |  |         type: 'plugin', | 
					
						
							|  |  |  |         name: 'upload', | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       .get({ key: 'provider' }); | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |     const model = | 
					
						
							|  |  |  |       source && source !== 'content-manager' | 
					
						
							|  |  |  |         ? strapi.plugins[source].models[params.model] | 
					
						
							|  |  |  |         : strapi.models[params.model]; | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 15:49:28 +01:00
										 |  |  |     // Asynchronous upload.
 | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  |     await Promise.all( | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |       Object.keys(files).map(async attribute => { | 
					
						
							|  |  |  |         // Bufferize files per attribute.
 | 
					
						
							|  |  |  |         const buffers = await this.bufferize(files[attribute]); | 
					
						
							|  |  |  |         const enhancedFiles = buffers.map(file => { | 
					
						
							|  |  |  |           const details = model.attributes[attribute]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // Add related information to be able to make
 | 
					
						
							|  |  |  |           // the relationships later.
 | 
					
						
							|  |  |  |           file[details.via] = [ | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  |               refId: params.id, | 
					
						
							|  |  |  |               ref: params.model, | 
					
						
							|  |  |  |               source, | 
					
						
							|  |  |  |               field: attribute, | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |             }, | 
					
						
							|  |  |  |           ]; | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |           return file; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |         // Make upload async.
 | 
					
						
							|  |  |  |         return this.upload(enhancedFiles, config); | 
					
						
							|  |  |  |       }), | 
					
						
							| 
									
										
										
										
											2018-02-28 12:33:32 +01:00
										 |  |  |     ); | 
					
						
							| 
									
										
										
										
											2018-09-10 16:05:00 +08:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2018-02-08 12:01:06 +01:00
										 |  |  | }; |