Added NEX DataStore upload service

This commit is contained in:
Jonathan Barrow
2021-09-07 21:57:43 -04:00
parent b5905b207c
commit 52b8ae1285
5 changed files with 104 additions and 0 deletions

View File

@@ -23,8 +23,12 @@
"aws-sdk": "^2.978.0",
"bcrypt": "^5.0.0",
"colors": "^1.4.0",
"dicer": "^0.2.5",
"express": "^4.17.1",
"express-form-data": "^2.0.17",
"express-rate-limit": "^5.3.0",
"express-subdomain": "^1.0.5",
"formidable": "^1.2.2",
"fs-extra": "^8.1.0",
"got": "^11.8.2",
"image-pixels": "^2.2.2",
@@ -34,6 +38,7 @@
"mongoose": "^5.8.3",
"mongoose-unique-validator": "^2.0.3",
"morgan": "^1.9.1",
"multer": "^1.4.3",
"nodemailer": "^6.4.2",
"tga": "^1.0.4",
"xmlbuilder": "^13.0.2",

View File

@@ -13,6 +13,7 @@ const app = express();
const accountWiiU = require('./services/wiiu');
//const account3DS = require('./services/3ds');
const datastore = require('./services/datastore');
// START APPLICATION
app.set('etag', false);
@@ -30,6 +31,7 @@ app.use(xmlparser);
// import the servers into one
app.use(accountWiiU);
//app.use(account3DS);
app.use(datastore);
// 404 handler
logger.info('Creating 404 status handler');

View File

@@ -0,0 +1,20 @@
const express = require('express');
const subdomain = require('express-subdomain');
const logger = require('../../../logger');
const routes = require('./routes');
// Router to handle the subdomain
const datastore = express.Router();
// Setup routes
logger.info('[CDN] Applying imported routes');
datastore.use(routes.UPLOAD);
// Main router for endpoints
const router = express.Router();
// Create subdomains
logger.info('[CDN] Creating \'datastore\' subdomain');
router.use(subdomain('datastore', datastore));
module.exports = router;

View File

@@ -0,0 +1,3 @@
module.exports = {
UPLOAD: require('./upload.js'),
};

View File

@@ -0,0 +1,74 @@
const crypto = require('crypto');
const router = require('express').Router();
const Dicer = require('dicer');
const fs = require('fs');
const util = require('../../../util');
const signatureSecret = fs.readFileSync(`${__dirname}/../../../../certs/nex/datastore/secret.key`);
function multipartParser(request, response, next) {
const RE_BOUNDARY = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i;
const RE_FILE_NAME = /name="(.*)"/;
const boundary = RE_BOUNDARY.exec(request.header('content-type'));
const dicer = new Dicer({ boundary: boundary[1] || boundary[2] });
const files = {};
dicer.on('part', part => {
let fileBuffer = Buffer.alloc(0);
let fileName = '';
part.on('header', header => {
fileName = RE_FILE_NAME.exec(header['content-disposition'][0])[1];
});
part.on('data', data => {
fileBuffer = Buffer.concat([fileBuffer, data]);
});
part.on('end', () => {
files[fileName] = fileBuffer;
});
});
dicer.on('finish', function () {
request.files = files;
return next();
});
request.pipe(dicer);
}
router.post('/upload', multipartParser, async (request, response) => {
const {
bucket, // Space name
key, // path
file, // the file content
acl, // S3 ACL
pid, // uploading user PID
date, // upload time
signature, // data signature
} = request.files;
// Signatures only good for 1 minute
const minute = 1000 * 60;
const minuteAgo = Date.now() - minute;
if (Number(date) < Math.floor(minuteAgo / 1000)) {
return response.sendStatus(400);
}
const data = pid.toString() + bucket.toString() + key.toString() + date.toString();
const hmac = crypto.createHmac('sha256', signatureSecret).update(data).digest('hex');
console.log(hmac, signature.toString());
if (hmac !== signature.toString()) {
return response.sendStatus(400);
}
await util.uploadCDNAsset(bucket.toString(), key.toString(), file, acl.toString());
response.sendStatus(200);
});
module.exports = router;