Debbuging AWS S3 integration
import {FilesCollection} from 'meteor/ostrio:files';
import {Meteor} from 'meteor/meteor';
import {Random} from 'meteor/random';
import _ from 'lodash';
export const MAX_ALLOWED_SIZE_MB = 2;
export const MAX_ALLOWED_SIZE_KB = MAX_ALLOWED_SIZE_MB * 1024;
export const MAX_ALLOWED_SIZE_B = MAX_ALLOWED_SIZE_KB * 1024;
export const ALLOWED_FILE_TYPES = ['png', 'jpg', 'jpeg'];
export const ALLOWED_FILE_TYPES_REGEXP = new RegExp(ALLOWED_FILE_TYPES.join('|'), 'i');
let knox, bound, client, Request, cfdomain;
if (Meteor.isServer) {
// Fix CloudFront certificate issue Read:
// https://github.com/chilts/awssum/issues/164
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
knox = Npm.require('knox');
Request = Npm.require('request');
bound = Meteor.bindEnvironment(function (callback) {
return callback();
});
// TODO add it from settings
cfdomain = 'https://XXXXXX.cloudfront.net' //
client = knox.createClient({key: 'YYYYYYYY', secret: 'ZZZZZZZZZZ', bucket: 'my-app-test', region: 'eu-central-1'});
}
console.log(knox, cfdomain, client);
const ProductImages = new FilesCollection({
debug: true,
throttle: false,
storagePath: 'assets/app/uploads/productImages',
collectionName: 'product_images',
allowClientCode: false, // Disallow remove files from Client
onBeforeUpload(file) {
if (file.size > MAX_ALLOWED_SIZE_B) {
return 'exceed-max-allowed-size';
}
if (!ALLOWED_FILE_TYPES_REGEXP.test(file.extension)) {
return 'invalid-file-type';
}
return true;
},
onAfterUpload: function (fileRef) {
// In onAfterUpload callback we will move file to AWS:S3
const self = this;
_.each(fileRef.versions, function (vRef, version) {
// We use Random.id() instead of real file's _id to secure files from reverse
// engineering As after viewing this code it will be easy to get access to
// unlisted and protected files
const filePath = "files/" + (Random.id()) + "-" + version + "." + fileRef.extension;
console.log(filePath);
client.putFile(vRef.path, filePath, function (error, res) {
bound(function () {
let upd;
if (error) {
console.error(error);
} else {
upd = {
$set: {}
};
upd['$set']["versions." + version + ".meta.pipeFrom"] = cfdomain + '/' + filePath;
upd['$set']["versions." + version + ".meta.pipePath"] = filePath;
self.collection.update({
_id: fileRef._id
}, upd, function (error) {
if (error) {
console.error(error);
} else {
console.log('Success');
// Unlink original files from FS after successful upload to AWS:S3
self.unlink(self.collection.findOne(fileRef._id), version);
}
});
}
});
});
});
},
interceptDownload: function (http, fileRef, version) {
let path,
ref,
ref1,
ref2;
path = (ref = fileRef.versions) != null
? (ref1 = ref[version]) != null
? (ref2 = ref1.meta) != null
? ref2.pipeFrom
: void 0
: void 0
: void 0;
if (path) {
// If file is moved to S3 We will pipe request to S3 So, original link will stay
// always secure
Request({
url: path,
headers: _.pick(http.request.headers, 'range', 'accept-language', 'accept', 'cache-control', 'pragma', 'connection', 'upgrade-insecure-requests', 'user-agent')
}).pipe(http.response);
return true;
} else {
// While file is not yet uploaded to S3 We will serve file from FS
return false;
}
}
});
if (Meteor.isServer) {
// Intercept File's collection remove method to remove file from S3
const _origRemove = ProductImages.remove;
ProductImages.remove = function (search) {
const cursor = this.collection.find(search);
cursor.forEach(function (fileRef) {
_.each(fileRef.versions, function (vRef) {
let ref;
if (vRef != null
? (ref = vRef.meta) != null
? ref.pipePath
: void 0
: void 0) {
client.deleteFile(vRef.meta.pipePath, function (error) {
bound(function () {
if (error) {
console.error(error);
}
});
});
}
});
});
// Call original method
_origRemove.call(this, search);
};
}
export default ProductImages;
I20161110-20:03:03.573(1)? [FilesCollection] [find({"meta":{"sessionId":"P9FeBQXF6dpQheBEv"}}, undefined)]
I20161110-20:06:27.578(1)? [FilesCollection] [File Start Method] IMG_3189.PNG - AFGLPexSm5ihbC9EA
I20161110-20:06:27.580(1)? [FilesCollection] [Upload] [Start Method] Got #-1/1 chunks, dst: IMG_3189.PNG
I20161110-20:06:28.117(1)? [FilesCollection] [Upload] [DDP] Got #1/1 chunks, dst: IMG_3189.PNG
I20161110-20:06:28.128(1)? [FilesCollection] [Upload] [DDP] Got #-1/1 chunks, dst: IMG_3189.PNG
I20161110-20:06:28.130(1)? [FilesCollection] [Upload] [finish(ing)Upload] -> assets/app/uploads/productImages/AFGLPexSm5ihbC9EA.PNG
I20161110-20:06:28.158(1)? [FilesCollection] [Upload] [finish(ed)Upload] -> assets/app/uploads/productImages/AFGLPexSm5ihbC9EA.PNG
I20161110-20:06:28.159(1)? files/4Q4NdzA7C8bWT7Qkh-original.PNG
I20161110-20:06:28.221(1)? [FilesCollection] [_preCollectionCursor.observeChanges] [removed]: AFGLPexSm5ihbC9EA
I20161110-20:06:28.948(1)? Success
I20161110-20:06:28.956(1)? [FilesCollection] [unlink(AFGLPexSm5ihbC9EA, original)]