|
|
|
@ -2,14 +2,32 @@ import { Meteor } from 'meteor/meteor'; |
|
|
|
|
import { FilesCollection } from 'meteor/ostrio:files'; |
|
|
|
|
import { createBucket } from './lib/grid/createBucket'; |
|
|
|
|
import fs from 'fs'; |
|
|
|
|
import FileType from 'file-type'; |
|
|
|
|
import path from 'path'; |
|
|
|
|
import { AttachmentStoreStrategyFilesystem, AttachmentStoreStrategyGridFs} from '/models/lib/attachmentStoreStrategy'; |
|
|
|
|
import FileStoreStrategyFactory, {moveToStorage, rename, STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS} from '/models/lib/fileStoreStrategy'; |
|
|
|
|
|
|
|
|
|
let attachmentUploadMimeTypes = []; |
|
|
|
|
let attachmentUploadSize = 0; |
|
|
|
|
let attachmentBucket; |
|
|
|
|
let storagePath; |
|
|
|
|
|
|
|
|
|
if (Meteor.isServer) { |
|
|
|
|
attachmentBucket = createBucket('attachments'); |
|
|
|
|
|
|
|
|
|
if (process.env.ATTACHMENTS_UPLOAD_MIME_TYPES) { |
|
|
|
|
attachmentUploadMimeTypes = process.env.ATTACHMENTS_UPLOAD_MIME_TYPES.split(','); |
|
|
|
|
attachmentUploadMimeTypes = attachmentUploadMimeTypes.map(value => value.trim()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (process.env.ATTACHMENTS_UPLOAD_MAX_SIZE) { |
|
|
|
|
attachmentUploadSize = parseInt(process.env.ATTACHMENTS_UPLOAD_MAX_SIZE); |
|
|
|
|
|
|
|
|
|
if (isNaN(attachmentUploadSize)) { |
|
|
|
|
attachmentUploadSize = 0 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
storagePath = path.join(process.env.WRITABLE_PATH, 'attachments'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -34,13 +52,39 @@ Attachments = new FilesCollection({ |
|
|
|
|
return ret; |
|
|
|
|
}, |
|
|
|
|
onAfterUpload(fileObj) { |
|
|
|
|
let storage = fileObj.meta.copyStorage || STORAGE_NAME_GRIDFS; |
|
|
|
|
let isValid = true; |
|
|
|
|
|
|
|
|
|
if (attachmentUploadMimeTypes.length) { |
|
|
|
|
const mimeTypeResult = Promise.await(FileType.fromFile(fileObj.path)); |
|
|
|
|
|
|
|
|
|
const mimeType = (mimeTypeResult ? mimeTypeResult.mime : fileObj.type); |
|
|
|
|
const baseMimeType = mimeType.split('/', 1)[0]; |
|
|
|
|
|
|
|
|
|
isValid = attachmentUploadMimeTypes.includes(mimeType) || attachmentUploadMimeTypes.includes(baseMimeType + '/*') || attachmentUploadMimeTypes.includes('*'); |
|
|
|
|
|
|
|
|
|
if (!isValid) { |
|
|
|
|
console.log("Validation of uploaded file failed: file " + fileObj.path + " - mimetype " + mimeType); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (attachmentUploadSize && fileObj.size > attachmentUploadSize) { |
|
|
|
|
console.log("Validation of uploaded file failed: file " + fileObj.path + " - size " + fileObj.size); |
|
|
|
|
isValid = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// current storage is the filesystem, update object and database
|
|
|
|
|
Object.keys(fileObj.versions).forEach(versionName => { |
|
|
|
|
fileObj.versions[versionName].storage = STORAGE_NAME_FILESYSTEM; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Attachments.update({ _id: fileObj._id }, { $set: { "versions" : fileObj.versions } }); |
|
|
|
|
moveToStorage(fileObj, storage, fileStoreStrategyFactory); |
|
|
|
|
|
|
|
|
|
if (isValid) { |
|
|
|
|
let storage = fileObj.meta.copyStorage || STORAGE_NAME_GRIDFS; |
|
|
|
|
moveToStorage(fileObj, storage, fileStoreStrategyFactory); |
|
|
|
|
} else { |
|
|
|
|
this.remove(fileObj._id); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
interceptDownload(http, fileObj, versionName) { |
|
|
|
|
const ret = fileStoreStrategyFactory.getFileStrategy(fileObj, versionName).interceptDownload(http, this.cacheControl); |
|
|
|
@ -57,10 +101,16 @@ Attachments = new FilesCollection({ |
|
|
|
|
// - if the board is public, everyone (even unconnected) can download it
|
|
|
|
|
// - if the board is private, only board members can download it
|
|
|
|
|
protected(fileObj) { |
|
|
|
|
// file may have been deleted already again after upload validation failed
|
|
|
|
|
if (!fileObj) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const board = Boards.findOne(fileObj.meta.boardId); |
|
|
|
|
if (board.isPublic()) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return board.hasMember(this.userId); |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|