Source: aws.js

/**
 * @fileOverview Authentication API Controller
 * @class aws
 * @author Calvin Ho
 */
// Set S3 endpoint to DigitalOcean Spaces
const aws = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');

const bucket = 'restvo';
const endpoint = 's3.us-west-000.backblazeb2.com';

var credentials = new aws.SharedIniFileCredentials({profile: 'restvo'});
aws.config.credentials = credentials;
const spacesEndpoint = new aws.Endpoint(endpoint);
const us_west_000 = new aws.S3({
    endpoint: spacesEndpoint
});
const Media = require('../models/media');

/**
 * @method upload
 * @desc uploads s3 file
 * @memberof aws
 * @author Calvin Ho
 * @param {any} req.type type of file
 * @param {any} req.size size of file
 * @param {any} req._id file ID
 * @param {any} req.ext extension of file
 * @param {any} req.location location of file
 * @param {any} req.upload actual file data
 * @returns {json} JSON object with url of s3 file
 */
exports.upload = async (req, res, next) => {
    try {
        upload(req, res, async (err) => {
            if (err) {
                return next({topic: 'System Error', title: 'Aws Upload Failed.', err: err});
            }
            let url = 'https://d2z4pehxidbzz4.cloudfront.net/' + req.body.location.replace(/ /g,"_");
            console.log('File uploaded successfully', url);
            res.json(url);
            // after file upload, log media info
            const filename = req.body.location.substring(req.body.location.lastIndexOf('/') + 1).toLowerCase();
            const ext = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
            let source = {
                type: ['mp4','ogg','webm'].indexOf(ext) > -1 ? 'video' : ['jpg','jpeg','gif','png'].indexOf(ext) > -1 ? 'image' : 'document',
                sources: [{
                    src: url,
                    type: ['mp4','ogg','webm'].indexOf(ext) > -1 ? 'video/' + ext : ext === 'mov' ? 'video/mp4' : ext,
                    size: req.body.size || 0
                }],
                existence: true,
                status: 'uploaded',
                uploadedAt: new Date(),
                author: req.user._id
            };
            if (req.body.type === 'community' && req.body._id) {
                source.church = req.body._id;
            }
            let media = await Media.create(source);
            console.log("Logged media info", media, 'file size', req.body.size);
        })
    } catch (err) {
        next({topic: 'System Error', title: 'Aws upload failed.', err: err});
    }
};

const upload = multer({
    limits: {
        fieldSize: 50 * 1024 * 1024,
    },
    storage: multerS3({
        s3: us_west_000,
        bucket: bucket,
        acl: 'public-read',
        key: function (req, file, cb) {
            cb(null, req.body.location.replace(/ /g,"_"));
        }
    })
}).single('upload');

/** 
 * @method remove
 * @desc removes s3 file
 * @memberof aws
 * @author Calvin Ho 
 * @param {any} req.url url of file to remove
 * @returns {string} String saying "File removal success"
 */
exports.remove = async (req, res, next) => {
    try {
        //console.log("body", req.body);
        if (req.body.type && req.body._id && req.body.file) { // obsolete in 1.3.28+. us_west_000 only
            let params = {
                Bucket: bucket,
                Delete: { // required
                    Objects: [ // required
                        { Key: req.body.type + '/' + req.body._id + '/'  + req.body.file }
                    ]
                }
            };
            us_west_000.deleteObjects(params, function(err, data) {
                if (err) {
                    console.log(err, err.stack);
                    return res.json("Cannot remove long urls"); // cannot remove 1.3.28+ long urls so ignore the error
                } // an error occurred
                console.log(data);           // successful response
                res.json("File removal success");
            });
        } else if (req.body.url) { // 1.3.28+, allowing for backblaze us_west_000 and other data centers
            let file_location = req.body.url.substring(req.body.url.indexOf('.com/') + 5); //.toLowerCase() might not be needed
            let url_bucket = req.body.url.substring(req.body.url.indexOf('://') + 3, req.body.url.indexOf('.'));
            let url_endpoint = req.body.url.substring(req.body.url.indexOf('.') + 1, req.body.url.indexOf('.com/') + 4);
            console.log("remove", url_bucket, url_endpoint, file_location);
            if (url_endpoint) {
                // just mark for deletion. do not delete
                let media = await Media.findOneAndUpdate({ "sources.src": req.body.url },
                    { $set: { status: 'marked for deletion' }});
                console.log("Logged media info", media);
                res.json("File removal success");
                /*let params = {
                    Bucket: url_bucket,
                    Delete: { // required
                        Objects: [ // required
                            { Key: file_location }
                        ]
                    }
                };
                // if url_endpoint === 's3.us-west-000.backblazeb2.com'
                us_west_000.deleteObjects(params, async (err, data) => {
                    if (err) {
                        // should be able to remove all urls. so throw error
                        return next({topic: 'System Error', title: 'Remove from Aws failed.', err: err});
                    }
                    let media = await Media.findOneAndUpdate({ "sources.src": req.body.url },
                    { $set: { existence: true, deletedAt: new Date() }});
                    res.json("File removal success");
                });*/
            } else {
                return res.json("Aws remove - cannot find endpoint"); // cannot proceed without providing endpoint
            }
        } else {
            return res.json("Aws remove - no url provided"); // cannot proceed without providing url
        }
    } catch (err) {
        next({topic: 'System Error', title: 'Remove from Aws failed.', err: err});
    }
};