Skip to content
This repository has been archived by the owner on Dec 19, 2024. It is now read-only.

Commit

Permalink
v0.5.1
Browse files Browse the repository at this point in the history
Merge pull request #20 from tycrek/multer-2.0.0
  • Loading branch information
Josh Moore authored Jun 30, 2021
2 parents ad052f8 + c843f6d commit d816e25
Show file tree
Hide file tree
Showing 11 changed files with 483 additions and 236 deletions.
2 changes: 2 additions & 0 deletions MagicNumbers.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@
"CODE_BAD_REQUEST": 400,
"CODE_UNAUTHORIZED": 401,
"CODE_NOT_FOUND": 404,
"CODE_PAYLOAD_TOO_LARGE": 413,
"CODE_INTERNAL_SERVER_ERROR": 500,
"KILOBYTES": 1024
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
- ✔️ Usage metrics
- ✔️ Thumbnail support
- ✔️ Basic multi-user support
- ✔️ Configurable global upload limit (per-user coming soon!)
- ✔️ Local storage *or* block-storage support for [Amazon S3](https://aws.amazon.com/s3/) (including [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/))
- ✔️ Multiple access types
- **[ZWS](https://zws.im)**
Expand Down Expand Up @@ -89,6 +90,7 @@ In your Cloudflare DNS dashboard, make sure your domain/subdomain is set to **DN
- URL: `$json:.resource$`
- Thumbnail: `$json:.thumbnail$`
- Deletion URL: `$json:.delete$`
- Error message: `$response$`
- MagicCap users: **do not** include the `.` in the above (i.e. `$json:resource$`)
6. The file `sample_config.sxcu` can also be modified & imported to suit your needs

Expand Down
57 changes: 15 additions & 42 deletions ass.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ try {
}

// Load the config
const { host, port, useSsl, resourceIdSize, diskFilePath, gfyIdSize, resourceIdType, isProxied, s3enabled, saveAsOriginal } = require('./config.json');
const { host, port, maxUploadSize, useSsl, resourceIdSize, diskFilePath, gfyIdSize, resourceIdType, isProxied, s3enabled } = require('./config.json');

//#region Imports
const fs = require('fs-extra');
Expand All @@ -19,12 +19,10 @@ const fetch = require('node-fetch');
const marked = require('marked');
const { DateTime } = require('luxon');
const { WebhookClient, MessageEmbed } = require('discord.js');
const Thumbnail = require('./thumbnails');
const Vibrant = require('./vibrant');
const Hash = require('./hash');
const { uploadLocal, uploadS3, deleteS3 } = require('./storage');
const { path, saveData, log, verify, getTrueHttp, getTrueDomain, renameFile, generateToken, generateId, formatBytes, formatTimestamp, arrayEquals, getS3url, getDirectUrl, getSafeExt, getResourceColor, downloadTempS3, sanitize, replaceholder } = require('./utils');
const { CODE_NO_CONTENT, CODE_BAD_REQUEST, CODE_UNAUTHORIZED, CODE_NOT_FOUND } = require('./MagicNumbers.json');
const { doUpload, deleteS3, processUploaded } = require('./storage');
const { path, saveData, log, verify, getTrueHttp, getTrueDomain, generateToken, generateId, formatBytes,
formatTimestamp, arrayEquals, getS3url, getDirectUrl, getSafeExt, getResourceColor, replaceholder } = require('./utils');
const { CODE_NO_CONTENT, CODE_BAD_REQUEST, CODE_UNAUTHORIZED, CODE_NOT_FOUND, CODE_PAYLOAD_TOO_LARGE, CODE_INTERNAL_SERVER_ERROR } = require('./MagicNumbers.json');
//#endregion

//#region Variables, module setup
Expand Down Expand Up @@ -108,44 +106,14 @@ function startup() {

// Block unauthorized requests and attempt token sanitization
app.post('/', (req, res, next) => {
req.headers.authorization = req.headers.authorization || '';
req.token = req.headers.authorization.replace(/[^\da-z]/gi, ''); // Strip anything that isn't a digit or ASCII letter
!verify(req, users) ? res.sendStatus(CODE_UNAUTHORIZED) : next(); // skipcq: JS-0093
});

// Generate ID's to use for other functions
app.post('/', (req, _res, next) => (req.randomId = generateId('random', 32, null, null), next())); // skipcq: JS-0074, JS-0086, JS-0090
app.post('/', (req, _res, next) => (req.deleteId = generateId('random', 32, null, null), next())); // skipcq: JS-0074, JS-0086, JS-0090

// Upload file (local & S3) // skipcq: JS-0093
s3enabled
? app.post('/', (req, res, next) => uploadS3(req, res, (error) => ((error) && console.error(error), next()))) // skipcq: JS-0090
: app.post('/', uploadLocal, ({ next }) => next());

// Pre-response operations
app.post('/', (req, _res, next) => {
req.file.randomId = req.randomId;
req.file.deleteId = req.deleteId;

// Sanitize filename just in case Multer didn't catch it
req.file.originalname = sanitize(req.file.originalname);

// Download a temp copy to work with if using S3 storage
(s3enabled ? downloadTempS3(req.file) : new Promise((resolve) => resolve()))

// Generate the Thumbnail, Vibrant, and SHA1 hash
.then(() => Promise.all([Thumbnail(req.file), Vibrant(req.file), Hash(req.file)]))
// skipcq: JS-0086
.then(([thumbnail, vibrant, sha1]) => (
req.file.thumbnail = thumbnail,// skipcq: JS-0090
req.file.vibrant = vibrant,// skipcq: JS-0090
req.file.sha1 = sha1// skipcq: JS-0090
))

// Remove the temp file if using S3 storage, otherwise rename the local file
.then(() => (s3enabled ? fs.remove(path(diskFilePath, req.file.originalname)) : renameFile(req, saveAsOriginal ? req.file.originalname : req.file.sha1)))
.then(() => next())
.catch((err) => next(err));
});
// Upload file
app.post('/', doUpload, processUploaded, ({ next }) => next());
app.use('/', (err, _req, res, next) => err.code && err.code === 'LIMIT_FILE_SIZE' ? res.status(CODE_PAYLOAD_TOO_LARGE).send(`Max upload size: ${maxUploadSize}MB`) : next(err)); // skipcq: JS-0229

// Process uploaded file
app.post('/', (req, res) => {
Expand Down Expand Up @@ -275,7 +243,7 @@ function startup() {
}),
local: () => {
res.header('Accept-Ranges', 'bytes').header('Content-Length', fileData.size).type(fileData.mimetype);
fs.createReadStream(path(fileData.path)).pipe(res);
fs.createReadStream(fileData.path).pipe(res);
}
};

Expand Down Expand Up @@ -334,6 +302,11 @@ function startup() {
.catch(console.error);
});

app.use(([err, , res,]) => {
console.error(err);
res.sendStatus(CODE_INTERNAL_SERVER_ERROR);
});

// Host the server
app.listen(port, host, () => log(`Server started on [${host}:${port}]\nAuthorized users: ${Object.keys(users).length}\nAvailable files: ${Object.keys(data).length}`));
}
Expand Down
9 changes: 6 additions & 3 deletions hash.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
const fs = require('fs-extra');
const crypto = require('crypto');
const toArray = require('stream-to-array')
const { path } = require('./utils');
const { s3enabled, diskFilePath } = require('./config.json');

/**
* Generates a SHA1 hash for the provided file
* @param {*} file The file to hash
* @returns The SHA1 hash
*/
module.exports = (file) =>
new Promise((resolve, reject) =>
toArray((fs.createReadStream(s3enabled ? path(diskFilePath, file.originalname) : path(file.path))))
toArray((fs.createReadStream(file.path)))
.then((parts) => Buffer.concat(parts.map((part) => (Buffer.isBuffer(part) ? part : Buffer.from(part)))))
.then((buf) => crypto.createHash('sha1').update(buf).digest('hex')) // skipcq: JS-D003
.then(resolve)
Expand Down
Loading

0 comments on commit d816e25

Please sign in to comment.