2016-07-15 23:05:18 +00:00
|
|
|
import uuid from 'node-uuid';
|
|
|
|
import policy from 's3-policy';
|
2020-02-25 22:14:50 +00:00
|
|
|
import s3 from '@auth0/s3';
|
2017-07-11 15:37:43 +00:00
|
|
|
import { getProjectsForUserId } from './project.controller';
|
|
|
|
import { findUserByUsername } from './user.controller';
|
2017-03-23 18:23:54 +00:00
|
|
|
|
|
|
|
const client = s3.createClient({
|
|
|
|
maxAsyncS3: 20,
|
|
|
|
s3RetryCount: 3,
|
|
|
|
s3RetryDelay: 1000,
|
2017-04-06 18:34:14 +00:00
|
|
|
multipartUploadThreshold: 20971520, // this is the default (20 MB)
|
|
|
|
multipartUploadSize: 15728640, // this is the default (15 MB)
|
2017-03-23 18:23:54 +00:00
|
|
|
s3Options: {
|
|
|
|
accessKeyId: `${process.env.AWS_ACCESS_KEY}`,
|
|
|
|
secretAccessKey: `${process.env.AWS_SECRET_KEY}`,
|
2017-04-13 18:39:03 +00:00
|
|
|
region: `${process.env.AWS_REGION}`
|
2017-03-23 18:23:54 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2017-12-13 19:56:24 +00:00
|
|
|
const s3Bucket = process.env.S3_BUCKET_URL_BASE ||
|
|
|
|
`https://s3-${process.env.AWS_REGION}.amazonaws.com/${process.env.S3_BUCKET}/`;
|
2016-07-15 23:05:18 +00:00
|
|
|
|
|
|
|
function getExtension(filename) {
|
|
|
|
const i = filename.lastIndexOf('.');
|
|
|
|
return (i < 0) ? '' : filename.substr(i);
|
|
|
|
}
|
|
|
|
|
2017-04-13 18:17:30 +00:00
|
|
|
export function getObjectKey(url) {
|
|
|
|
const urlArray = url.split('/');
|
|
|
|
let objectKey;
|
2020-07-16 21:00:50 +00:00
|
|
|
if (urlArray.length === 5) {
|
2017-04-13 18:17:30 +00:00
|
|
|
const key = urlArray.pop();
|
|
|
|
const userId = urlArray.pop();
|
2017-06-13 20:47:36 +00:00
|
|
|
objectKey = `${userId}/${key}`;
|
2017-04-13 18:17:30 +00:00
|
|
|
} else {
|
|
|
|
const key = urlArray.pop();
|
|
|
|
objectKey = key;
|
|
|
|
}
|
2017-06-13 20:47:36 +00:00
|
|
|
return objectKey;
|
2017-04-13 18:17:30 +00:00
|
|
|
}
|
|
|
|
|
2017-03-30 20:52:36 +00:00
|
|
|
export function deleteObjectsFromS3(keyList, callback) {
|
2017-04-06 18:34:14 +00:00
|
|
|
const keys = keyList.map((key) => { return { Key: key }; }); // eslint-disable-line
|
2017-03-30 20:52:36 +00:00
|
|
|
if (keyList.length > 0) {
|
2017-03-30 16:14:07 +00:00
|
|
|
const params = {
|
|
|
|
Bucket: `${process.env.S3_BUCKET}`,
|
|
|
|
Delete: {
|
2017-03-30 20:52:36 +00:00
|
|
|
Objects: keys,
|
2017-03-30 16:14:07 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
const del = client.deleteObjects(params);
|
2017-04-06 18:34:14 +00:00
|
|
|
del.on('end', () => {
|
|
|
|
if (callback) {
|
2017-03-30 16:14:07 +00:00
|
|
|
callback();
|
|
|
|
}
|
|
|
|
});
|
2017-04-06 18:34:14 +00:00
|
|
|
} else if (callback) {
|
|
|
|
callback();
|
2017-03-30 16:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-30 20:52:36 +00:00
|
|
|
export function deleteObjectFromS3(req, res) {
|
2020-03-03 23:52:39 +00:00
|
|
|
const { objectKey, userId } = req.params;
|
|
|
|
let fullObjectKey;
|
|
|
|
if (userId) {
|
|
|
|
fullObjectKey = `${userId}/${objectKey}`;
|
2019-09-25 21:54:46 +00:00
|
|
|
} else {
|
2020-03-03 23:52:39 +00:00
|
|
|
fullObjectKey = objectKey;
|
2019-09-25 21:54:46 +00:00
|
|
|
}
|
2020-03-03 23:52:39 +00:00
|
|
|
deleteObjectsFromS3([fullObjectKey], () => {
|
2017-04-06 18:34:14 +00:00
|
|
|
res.json({ success: true });
|
2017-03-30 20:52:36 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-07-15 23:05:18 +00:00
|
|
|
export function signS3(req, res) {
|
2019-09-26 19:06:43 +00:00
|
|
|
const limit = process.env.UPLOAD_LIMIT || 250000000;
|
|
|
|
if (req.user.totalSize > limit) {
|
2020-03-03 23:52:39 +00:00
|
|
|
res.status(403).send({ message: 'user has uploaded the maximum size of assets.' });
|
2019-09-26 19:06:43 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-01-11 20:50:36 +00:00
|
|
|
const fileExtension = getExtension(req.body.name);
|
|
|
|
const filename = uuid.v4() + fileExtension;
|
|
|
|
const acl = 'public-read';
|
|
|
|
const p = policy({
|
|
|
|
acl,
|
|
|
|
secret: process.env.AWS_SECRET_KEY,
|
|
|
|
length: 5000000, // in bytes?
|
|
|
|
bucket: process.env.S3_BUCKET,
|
|
|
|
key: filename,
|
|
|
|
expires: new Date(Date.now() + 60000),
|
|
|
|
});
|
|
|
|
const result = {
|
|
|
|
AWSAccessKeyId: process.env.AWS_ACCESS_KEY,
|
2017-04-06 18:34:14 +00:00
|
|
|
key: `${req.body.userId}/${filename}`,
|
2017-01-11 20:50:36 +00:00
|
|
|
policy: p.policy,
|
|
|
|
signature: p.signature
|
|
|
|
};
|
2020-03-03 23:52:39 +00:00
|
|
|
res.json(result);
|
2016-11-17 16:15:35 +00:00
|
|
|
}
|
2017-02-22 19:29:35 +00:00
|
|
|
|
2020-07-17 23:09:23 +00:00
|
|
|
export function copyObjectInS3(url, userId) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const objectKey = getObjectKey(url);
|
|
|
|
const fileExtension = getExtension(objectKey);
|
|
|
|
const newFilename = uuid.v4() + fileExtension;
|
|
|
|
const headParams = {
|
|
|
|
Bucket: `${process.env.S3_BUCKET}`,
|
|
|
|
Key: `${objectKey}`
|
|
|
|
};
|
|
|
|
client.s3.headObject(headParams, (headErr) => {
|
|
|
|
if (headErr) {
|
|
|
|
reject(new Error(`Object with key ${process.env.S3_BUCKET}/${objectKey} does not exist.`));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const params = {
|
|
|
|
Bucket: `${process.env.S3_BUCKET}`,
|
|
|
|
CopySource: `${process.env.S3_BUCKET}/${objectKey}`,
|
|
|
|
Key: `${userId}/${newFilename}`,
|
|
|
|
ACL: 'public-read'
|
|
|
|
};
|
|
|
|
const copy = client.copyObject(params);
|
|
|
|
copy.on('err', (err) => {
|
|
|
|
reject(err);
|
|
|
|
});
|
|
|
|
copy.on('end', (data) => {
|
|
|
|
resolve(`${s3Bucket}${userId}/${newFilename}`);
|
|
|
|
});
|
|
|
|
});
|
2017-05-14 01:38:48 +00:00
|
|
|
});
|
2020-07-17 23:09:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function copyObjectInS3RequestHandler(req, res) {
|
|
|
|
const { url } = req.body;
|
|
|
|
copyObjectInS3(url, req.user.id).then((newUrl) => {
|
|
|
|
res.json({ url: newUrl });
|
2017-03-23 18:23:54 +00:00
|
|
|
});
|
|
|
|
}
|
2017-07-11 15:37:43 +00:00
|
|
|
|
2020-07-16 18:25:02 +00:00
|
|
|
export function moveObjectToUserInS3(url, userId) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const objectKey = getObjectKey(url);
|
|
|
|
const fileExtension = getExtension(objectKey);
|
|
|
|
const newFilename = uuid.v4() + fileExtension;
|
2020-07-17 23:09:23 +00:00
|
|
|
const headParams = {
|
2020-07-16 18:25:02 +00:00
|
|
|
Bucket: `${process.env.S3_BUCKET}`,
|
2020-07-17 23:09:23 +00:00
|
|
|
Key: `${objectKey}`
|
2020-07-16 18:25:02 +00:00
|
|
|
};
|
2020-07-17 23:09:23 +00:00
|
|
|
client.s3.headObject(headParams, (headErr) => {
|
|
|
|
if (headErr) {
|
|
|
|
reject(new Error(`Object with key ${process.env.S3_BUCKET}/${objectKey} does not exist.`));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const params = {
|
|
|
|
Bucket: `${process.env.S3_BUCKET}`,
|
|
|
|
CopySource: `${process.env.S3_BUCKET}/${objectKey}`,
|
|
|
|
Key: `${userId}/${newFilename}`,
|
|
|
|
ACL: 'public-read'
|
|
|
|
};
|
|
|
|
const move = client.moveObject(params);
|
|
|
|
move.on('err', (err) => {
|
|
|
|
reject(err);
|
|
|
|
});
|
|
|
|
move.on('end', (data) => {
|
|
|
|
resolve(`${s3Bucket}${userId}/${newFilename}`);
|
|
|
|
});
|
2020-07-16 18:25:02 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-08 21:34:49 +00:00
|
|
|
export function listObjectsInS3ForUser(userId) {
|
|
|
|
let assets = [];
|
|
|
|
return new Promise((resolve) => {
|
2017-07-11 15:37:43 +00:00
|
|
|
const params = {
|
|
|
|
s3Params: {
|
|
|
|
Bucket: `${process.env.S3_BUCKET}`,
|
|
|
|
Prefix: `${userId}/`
|
|
|
|
}
|
|
|
|
};
|
2017-10-16 03:27:05 +00:00
|
|
|
client.listObjects(params)
|
2017-07-11 15:37:43 +00:00
|
|
|
.on('data', (data) => {
|
2017-10-16 03:27:05 +00:00
|
|
|
assets = assets.concat(data.Contents.map(object => ({ key: object.Key, size: object.Size })));
|
2017-07-11 15:37:43 +00:00
|
|
|
})
|
|
|
|
.on('end', () => {
|
2019-08-08 21:34:49 +00:00
|
|
|
resolve();
|
|
|
|
});
|
2020-03-03 23:52:39 +00:00
|
|
|
}).then(() => getProjectsForUserId(userId)).then((projects) => {
|
|
|
|
const projectAssets = [];
|
|
|
|
let totalSize = 0;
|
|
|
|
assets.forEach((asset) => {
|
|
|
|
const name = asset.key.split('/').pop();
|
|
|
|
const foundAsset = {
|
|
|
|
key: asset.key,
|
|
|
|
name,
|
|
|
|
size: asset.size,
|
|
|
|
url: `${process.env.S3_BUCKET_URL_BASE}${asset.key}`
|
|
|
|
};
|
|
|
|
totalSize += asset.size;
|
|
|
|
projects.some((project) => {
|
|
|
|
let found = false;
|
|
|
|
project.files.some((file) => {
|
|
|
|
if (!file.url) return false;
|
|
|
|
if (file.url.includes(asset.key)) {
|
|
|
|
found = true;
|
|
|
|
foundAsset.name = file.name;
|
|
|
|
foundAsset.sketchName = project.name;
|
|
|
|
foundAsset.sketchId = project.id;
|
|
|
|
foundAsset.url = file.url;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2017-07-11 15:37:43 +00:00
|
|
|
});
|
2020-03-03 23:52:39 +00:00
|
|
|
return found;
|
2017-07-11 15:37:43 +00:00
|
|
|
});
|
2020-03-03 23:52:39 +00:00
|
|
|
projectAssets.push(foundAsset);
|
2019-08-08 21:34:49 +00:00
|
|
|
});
|
2020-03-03 23:52:39 +00:00
|
|
|
return Promise.resolve({ assets: projectAssets, totalSize });
|
|
|
|
}).catch((err) => {
|
|
|
|
console.log('got an error');
|
|
|
|
console.log(err);
|
|
|
|
});
|
2019-08-08 21:34:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function listObjectsInS3ForUserRequestHandler(req, res) {
|
|
|
|
const { username } = req.user;
|
|
|
|
findUserByUsername(username, (user) => {
|
|
|
|
const userId = user.id;
|
|
|
|
listObjectsInS3ForUser(userId).then((objects) => {
|
|
|
|
res.json(objects);
|
|
|
|
});
|
2017-07-11 15:37:43 +00:00
|
|
|
});
|
|
|
|
}
|