Created
February 6, 2019 14:23
-
-
Save Apollinaire/37bac78ea3cc9b8c01ef05e5079c0f8a to your computer and use it in GitHub Desktop.
AWS-SDK update for vulcan-files-s3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import S3 from 'aws-sdk/clients/s3'; | |
import curryUploadToS3 from './curryUploadToS3'; | |
import curryDeleteFromS3 from './curryDeleteFromS3'; | |
import serveFilesFromS3 from './serveFilesFromS3'; | |
/** | |
* Creates an S3 storage provider, as needed by {@link createFSCollection}. | |
* | |
* @param {{key: String, secret: String, region: String, bucket: String}} config | |
* @param {String} cfdomain | |
* @return {{S3Client: Object, upload: curriedUploadToS3, delete: curriedDeleteFromS3, serve: serveFilesFromS3}} | |
*/ | |
export default function createS3StorageProvider(config, cfdomain) { | |
const S3Client = new S3({ | |
secretAccessKey: config.secret, | |
accessKeyId: config.key, | |
region: config.region, | |
// sslEnabled: true, // optional | |
httpOptions: { | |
timeout: 6000, | |
agent: false | |
} | |
}); | |
return { | |
S3Client, | |
upload: curryUploadToS3(S3Client, cfdomain, config.region, config.bucket), | |
delete: curryDeleteFromS3(S3Client, config.region, config.bucket), | |
serve: serveFilesFromS3, | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import has from 'lodash/has'; | |
let bound; | |
if (Meteor.isServer) { | |
bound = Meteor.bindEnvironment(callback => (callback())); | |
} | |
/** | |
* curryDeleteFromS3 - curries a function that deletes a file from AWS S3 with | |
* from an S3 client | |
* | |
* @param {object} S3Client A Knox S3 client or any client with similar API. | |
* | |
* @return {function} returns curriedDeleteFromS3 | |
*/ | |
export default function curryDeleteFromS3(S3Client, bucket) { | |
/** | |
* curriedDeleteFromS3 - Deletes a file from S3 and updates the doc's versions | |
* that contains that file. | |
* | |
* @param {FilesCollection} FilesCollection Collection that needs to be updated | |
* once the files is deleted from S3 | |
* @param {string} docId The id of the doc that needs to be updated | |
* once the file is deleted | |
* @param {object} versionReference The information of the version that wants | |
* to be deleted. The refernce of the file in S3 needs to be in `versionReference.meta.pipePath` | |
* | |
* @return {promise} returns a promise - resolve returns the same version reference | |
* - reject returns the error that caused it. | |
*/ | |
return function curriedDeleteFromS3(FilesCollection, docId, versionReference) { | |
return new Promise((resolve, reject) => { | |
if (has(versionReference, 'meta.pipePath')) { | |
// using aws-sdk but never really tested that since I can't fire a delete from the FScollection | |
S3Client.deleteObject({Key: versionReference.meta.pipePath, Bucket: bucket}, (deleteFromS3Error) => { | |
bound(() => { | |
if (deleteFromS3Error) { | |
reject(deleteFromS3Error); | |
} else { | |
FilesCollection.collection.update({ _id: docId }, { | |
$unset: { [`versions.${versionReference.version}`]: '' }, | |
}, (collectionUpadteError) => { | |
if (collectionUpadteError) { | |
reject(collectionUpadteError); | |
} | |
// TODO remove console.log and add it to a log collection | |
console.log( | |
`${versionReference.name || | |
`${docId}-${versionReference.version}`}: deleted from S3` | |
); | |
resolve(versionReference); | |
}); | |
} | |
}); | |
}); | |
} else { | |
// console.warn(`This ${versionReference.name} has no linked file in S3`); | |
resolve(versionReference); | |
} | |
}); | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import snakeCase from 'lodash/snakeCase'; | |
import { Meteor } from 'meteor/meteor'; | |
import { Random } from 'meteor/random'; | |
import fs from 'fs'; | |
let bound; | |
if (Meteor.isServer) { | |
bound = Meteor.bindEnvironment(callback => callback()); | |
} | |
/** | |
* curryUploadToS3 - it curries the curriedUploadToS3 with an S3Client and a | |
* CloudFront domain | |
* | |
* @param {Object} S3Client A Knox S3 client | |
* @param {String} cfdomain A CloudFront domain linked to the S3 client | |
* | |
* @return {function} returns curriedUploadToS3 | |
*/ | |
export default function curryUploadToS3(S3Client, cfdomain, region, bucket) { | |
/** | |
* curriedUploadToS3 - Uploads a file to S3 and updates the collection with | |
* the new metadata. It also unlinks the original file from the internal FS. | |
* | |
* @param {FileCollection} FilesCollection The FilesCollection from where the | |
* reference docs belongs to. It is used to update the doc with the new metadata | |
* @param {string} docId The id from the reference doc that needs to be updated | |
* @param {object} versionRef The information of the version that will be | |
* uploaded to S3. It need to contain the path of the file version that needs to be uploaded. | |
* | |
* @return {promise} returns a promise - resolve: returns the same versionRef | |
* as the input - reject: returns the error that cause it | |
*/ | |
return function curriedUploadToS3(FilesCollection, docId, versionRef) { | |
return new Promise((resolve, reject) => { | |
const { version } = versionRef; | |
const url = cfdomain ? cfdomain : `https://s3.${region}.amazonaws.com/${bucket}` | |
// console.log(versionRef); | |
// 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 = `${snakeCase(FilesCollection.collectionName)}/${version}/${Random.id()}-${version}.${versionRef.extension}`; | |
const fileStream = fs.createReadStream(versionRef.path); | |
fileStream.on('error', function(err) { | |
console.log('File Error', err); | |
}); | |
// Here we upoload the file | |
S3Client.putObject({Bucket: 'liveforgooddev', Key: filePath, Body: fileStream, ContentType: versionRef.type }, (S3error, res) => { | |
bound(() => { | |
if (S3error) { | |
reject(S3error); // Reject | |
} else { | |
// If no error, update the mongo document | |
const upd = { | |
$set: { | |
[`versions.${version}.uploadedTo3rdParty`]: true, | |
[`versions.${version}.meta.pipeFrom`]: `${url}/${filePath}`, | |
[`versions.${version}.meta.pipePath`]: filePath, | |
}, | |
}; | |
// Here we perform the document update | |
FilesCollection.collection.update( | |
{ | |
_id: docId, | |
}, | |
upd, | |
collectionError => { | |
if (collectionError) { | |
reject(collectionError); | |
} else { | |
// Unlink original files from FS after successful upload to AWS:S3 | |
FilesCollection.unlink(FilesCollection.collection.findOne(docId), version); | |
// TODO remove console.log and add it to a log collection | |
console.log(`${versionRef.name || `${docId}-${version}`}: uploaded`); | |
resolve(versionRef); | |
} | |
} | |
); | |
} | |
}); | |
}); | |
}); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment