From 579e1e754ab59a69925b5114641174aa70d18555 Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 1 Oct 2019 14:11:16 -0300 Subject: feature: uploader with chunks support --- src/api/routes/uploads/uploadPOST.js | 94 ++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/api/routes/uploads/uploadPOST.js (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js new file mode 100644 index 0000000..a461130 --- /dev/null +++ b/src/api/routes/uploads/uploadPOST.js @@ -0,0 +1,94 @@ +const Route = require('../../structures/Route'); +const path = require('path'); +const Util = require('../../utils/Util'); +const jetpack = require('fs-jetpack'); +const multer = require('multer'); +const upload = multer({ + storage: multer.memoryStorage(), + limits: { + fileSize: parseInt(process.env.MAX_SIZE, 10) * (1000 * 1000), + files: 1 + }, + fileFilter: (req, file, cb) => { + /* + if (options.blacklist.mimes.includes(file.mimetype)) { + return cb(new Error(`${file.mimetype} is a blacklisted filetype.`)); + } else if (options.blacklist.extensions.some(ext => path.extname(file.originalname).toLowerCase() === ext)) { + return cb(new Error(`${path.extname(file.originalname).toLowerCase()} is a blacklisted extension.`)); + } + */ + return cb(null, true); + } +}).array('files[]'); + +class uploadPOST extends Route { + constructor() { + super('/upload', 'post', { bypassAuth: true }); + } + + async run(req, res, db) { + const user = await Util.isAuthorized(req); + if (!user && process.env.PUBLIC_MODE == 'false') return res.status(401).json({ message: 'Not authorized to use this resource' }); + return upload(req, res, async err => { + if (err) console.error(err.message); + + const remappedKeys = this._remapKeys(req.body); + // const { uuid, chunkindex } = this._remapKeys(req.body); + let uploadedFile = {}; + for (const file of req.files) { + // console.log(file); + const ext = path.extname(file.originalname); + const hash = Util.generateFileHash(file.buffer); + const filename = Util.getUniqueFilename(file.originalname); + if (remappedKeys && remappedKeys.uuid) { + const chunkOutput = path.join(__dirname, + '..', + '..', + '..', + '..', + process.env.UPLOAD_FOLDER, + 'chunks', + remappedKeys.uuid, + `${remappedKeys.chunkindex.padStart(3, 0)}${ext || ''}`); + await jetpack.writeAsync(chunkOutput, file.buffer); + } else { + const output = path.join(__dirname, + '..', + '..', + '..', + '..', + process.env.UPLOAD_FOLDER, + filename); + await jetpack.writeAsync(output, file.buffer); + uploadedFile = { + name: filename, + hash, + size: file.buffer.length, + url: filename + }; + } + } + + if (!remappedKeys || !remappedKeys.uuid) Util.generateThumbnails(uploadedFile.name); + + return res.send(201, { + message: 'Sucessfully uploaded the file.', + ...uploadedFile + }); + }); + } + + _remapKeys(body) { + const keys = Object.keys(body); + if (keys.length) { + for (const key of keys) { + if (!/^dz/.test(key)) continue; + body[key.replace(/^dz/, '')] = body[key]; + delete body[key]; + } + return body; + } + } +} + +module.exports = uploadPOST; -- cgit v1.2.3 From c121bd42f38cc3bd47b68efd8cf70da158cbdf8d Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 12 Oct 2019 14:37:09 +0900 Subject: chore: upload fixes --- src/api/routes/uploads/uploadPOST.js | 70 +++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 5 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index a461130..06959f4 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -3,6 +3,7 @@ const path = require('path'); const Util = require('../../utils/Util'); const jetpack = require('fs-jetpack'); const multer = require('multer'); +const moment = require('moment'); const upload = multer({ storage: multer.memoryStorage(), limits: { @@ -29,14 +30,24 @@ class uploadPOST extends Route { async run(req, res, db) { const user = await Util.isAuthorized(req); if (!user && process.env.PUBLIC_MODE == 'false') return res.status(401).json({ message: 'Not authorized to use this resource' }); + return upload(req, res, async err => { if (err) console.error(err.message); - const remappedKeys = this._remapKeys(req.body); - // const { uuid, chunkindex } = this._remapKeys(req.body); + const albumId = req.body.albumid || req.headers.albumid; + if (albumId && !user) return res.status(401).json({ message: 'Only registered users can upload files to an album' }); + if (albumId && user) { + const album = await db.table('albums').where({ id: albumId, userId: user.id }).first(); + if (!album) return res.status(401).json({ message: 'Album doesn\'t exist or it doesn\'t belong to the user' }); + } + let uploadedFile = {}; + let originalFile; + let insertedId; + + const remappedKeys = this._remapKeys(req.body); for (const file of req.files) { - // console.log(file); + originalFile = file; const ext = path.extname(file.originalname); const hash = Util.generateFileHash(file.buffer); const filename = Util.getUniqueFilename(file.originalname); @@ -69,15 +80,64 @@ class uploadPOST extends Route { } } - if (!remappedKeys || !remappedKeys.uuid) Util.generateThumbnails(uploadedFile.name); + if (!remappedKeys || !remappedKeys.uuid) { + Util.generateThumbnails(uploadedFile.name); + insertedId = await this.saveFileToDatabase(req, res, user, db, uploadedFile, originalFile); + if (!insertedId) return res.status(500).json({ message: 'There was an error saving the file.' }); + uploadedFile.deleteUrl = `${process.env.DOMAIN}/api/file/${insertedId[0]}`; + } - return res.send(201, { + return res.status(201).send({ message: 'Sucessfully uploaded the file.', ...uploadedFile }); }); } + async saveFileToDatabase(req, res, user, db, file, originalFile) { + /* + Save the upload information to the database + */ + const now = moment.utc().toDate(); + let insertedId = null; + try { + /* + This is so fucking dumb + */ + if (process.env.DB_CLIENT === 'sqlite3') { + insertedId = await db.table('files').insert({ + userId: user ? user.id : null, + name: file.name, + original: originalFile.originalname, + type: originalFile.mimetype || '', + size: file.size, + hash: file.hash, + ip: req.ip, + createdAt: now, + editedAt: now + }); + } else { + insertedId = await db.table('files').insert({ + userId: user ? user.id : null, + name: file.name, + original: originalFile.originalname, + type: originalFile.mimetype || '', + size: file.size, + hash: file.hash, + ip: req.ip, + createdAt: now, + editedAt: now + }, 'id'); + } + return insertedId; + } catch (error) { + console.error('There was an error saving the file to the database'); + console.error(error); + return null; + // return res.status(500).json({ message: 'There was an error uploading the file.' }); + } + } + _remapKeys(body) { const keys = Object.keys(body); if (keys.length) { -- cgit v1.2.3 From e6eb13e5cd14cea7ed3d5f89af03d61d59311734 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 12 Oct 2019 17:52:49 +0900 Subject: feature: save uploaded files to album if specified --- src/api/routes/uploads/uploadPOST.js | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 06959f4..3411abc 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -31,19 +31,20 @@ class uploadPOST extends Route { const user = await Util.isAuthorized(req); if (!user && process.env.PUBLIC_MODE == 'false') return res.status(401).json({ message: 'Not authorized to use this resource' }); + const albumId = req.body.albumid || req.headers.albumid; + if (albumId && !user) return res.status(401).json({ message: 'Only registered users can upload files to an album' }); + if (albumId && user) { + const album = await db.table('albums').where({ id: albumId, userId: user.id }).first(); + if (!album) return res.status(401).json({ message: 'Album doesn\'t exist or it doesn\'t belong to the user' }); + } + return upload(req, res, async err => { if (err) console.error(err.message); - const albumId = req.body.albumid || req.headers.albumid; - if (albumId && !user) return res.status(401).json({ message: 'Only registered users can upload files to an album' }); - if (albumId && user) { - const album = await db.table('albums').where({ id: albumId, userId: user.id }).first(); - if (!album) return res.status(401).json({ message: 'Album doesn\'t exist or it doesn\'t belong to the user' }); - } - let uploadedFile = {}; let originalFile; let insertedId; + const now = moment.utc().toDate(); const remappedKeys = this._remapKeys(req.body); for (const file of req.files) { @@ -87,6 +88,19 @@ class uploadPOST extends Route { uploadedFile.deleteUrl = `${process.env.DOMAIN}/api/file/${insertedId[0]}`; } + /* + If the upload had an album specified we make sure to create the relation + and update the according timestamps.. + */ + if (albumId) { + try { + await db.table('albumsFiles').insert({ albumId, fileId: insertedId[0] }); + await db.table('albums').where('id', albumId).update('editedAt', now); + } catch (error) { + console.error(error); + } + } + return res.status(201).send({ message: 'Sucessfully uploaded the file.', ...uploadedFile -- cgit v1.2.3 From 2695d192ba253219f41dce259cc53070058cad91 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 12 Oct 2019 18:18:32 +0900 Subject: feature: prevent duplicated files - If the user uploads a file that already exists under their account, it will return the previous url - If an anonymous user uploads a file and already exists previously from another anon, return that url - Files are unique per account since they can be deleted, anonymous files can't --- src/api/routes/uploads/uploadPOST.js | 134 +++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 47 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 3411abc..d35b9fc 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -42,63 +42,66 @@ class uploadPOST extends Route { if (err) console.error(err.message); let uploadedFile = {}; - let originalFile; let insertedId; - const now = moment.utc().toDate(); const remappedKeys = this._remapKeys(req.body); - for (const file of req.files) { - originalFile = file; - const ext = path.extname(file.originalname); - const hash = Util.generateFileHash(file.buffer); - const filename = Util.getUniqueFilename(file.originalname); - if (remappedKeys && remappedKeys.uuid) { - const chunkOutput = path.join(__dirname, - '..', - '..', - '..', - '..', - process.env.UPLOAD_FOLDER, - 'chunks', - remappedKeys.uuid, - `${remappedKeys.chunkindex.padStart(3, 0)}${ext || ''}`); - await jetpack.writeAsync(chunkOutput, file.buffer); - } else { - const output = path.join(__dirname, - '..', - '..', - '..', - '..', - process.env.UPLOAD_FOLDER, - filename); - await jetpack.writeAsync(output, file.buffer); - uploadedFile = { - name: filename, - hash, - size: file.buffer.length, - url: filename - }; - } + const file = req.files[0]; + + const ext = path.extname(file.originalname); + const hash = Util.generateFileHash(file.buffer); + + const filename = Util.getUniqueFilename(file.originalname); + + /* + First let's get the hash of the file. This will be useful to check if the file + has already been upload by either the user or an anonymous user. + In case this is true, instead of uploading it again we retrieve the url + of the file that is already saved and thus don't store extra copies of the same file. + + For this we need to wait until we have a filename so that we can delete the uploaded file. + */ + const exists = await this.checkIfFileExists(db, user, hash); + if (exists) return this.fileExists(res, exists, filename); + + if (remappedKeys && remappedKeys.uuid) { + const chunkOutput = path.join(__dirname, + '..', + '..', + '..', + '..', + process.env.UPLOAD_FOLDER, + 'chunks', + remappedKeys.uuid, + `${remappedKeys.chunkindex.padStart(3, 0)}${ext || ''}`); + await jetpack.writeAsync(chunkOutput, file.buffer); + } else { + const output = path.join(__dirname, + '..', + '..', + '..', + '..', + process.env.UPLOAD_FOLDER, + filename); + await jetpack.writeAsync(output, file.buffer); + uploadedFile = { + name: filename, + hash, + size: file.buffer.length, + url: filename + }; } if (!remappedKeys || !remappedKeys.uuid) { Util.generateThumbnails(uploadedFile.name); - insertedId = await this.saveFileToDatabase(req, res, user, db, uploadedFile, originalFile); + insertedId = await this.saveFileToDatabase(req, res, user, db, uploadedFile, file); if (!insertedId) return res.status(500).json({ message: 'There was an error saving the file.' }); uploadedFile.deleteUrl = `${process.env.DOMAIN}/api/file/${insertedId[0]}`; - } - /* - If the upload had an album specified we make sure to create the relation - and update the according timestamps.. - */ - if (albumId) { - try { - await db.table('albumsFiles').insert({ albumId, fileId: insertedId[0] }); - await db.table('albums').where('id', albumId).update('editedAt', now); - } catch (error) { - console.error(error); - } + /* + If the upload had an album specified we make sure to create the relation + and update the according timestamps.. + */ + this.saveFileToAlbum(db, albumId, insertedId); } return res.status(201).send({ @@ -108,6 +111,43 @@ class uploadPOST extends Route { }); } + fileExists(res, exists, filename) { + res.json({ + message: 'Successfully uploaded the file.', + name: exists.name, + hash: exists.hash, + size: exists.size, + url: `${process.env.DOMAIN}/${exists.name}`, + deleteUrl: `${process.env.DOMAIN}/api/file/${exists.id}`, + repeated: true + }); + + return Util.deleteFile(filename); + } + + async checkIfFileExists(db, user, hash) { + const exists = await db.table('files') + .where(function() { // eslint-disable-line func-names + if (user) this.where('userId', user.id); + else this.whereNull('userId'); + }) + .where({ hash }) + .first(); + return exists; + } + + async saveFileToAlbum(db, albumId, insertedId) { + if (!albumId) return; + + const now = moment.utc().toDate(); + try { + await db.table('albumsFiles').insert({ albumId, fileId: insertedId[0] }); + await db.table('albums').where('id', albumId).update('editedAt', now); + } catch (error) { + console.error(error); + } + } + async saveFileToDatabase(req, res, user, db, file, originalFile) { /* Save the upload information to the database -- cgit v1.2.3 From b886fda0793b8a26de58cd462acf6676a0a8e7ed Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 11 May 2020 00:19:10 +0900 Subject: chore: cleanup and todo --- src/api/routes/uploads/uploadPOST.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index d35b9fc..d611175 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -11,6 +11,7 @@ const upload = multer({ files: 1 }, fileFilter: (req, file, cb) => { + // TODO: Enable blacklisting of files/extensions /* if (options.blacklist.mimes.includes(file.mimetype)) { return cb(new Error(`${file.mimetype} is a blacklisted filetype.`)); @@ -22,6 +23,20 @@ const upload = multer({ } }).array('files[]'); +/* + TODO: If source has transparency generate a png thumbnail, otherwise a jpg. + TODO: If source is a gif, generate a thumb of the first frame and play the gif on hover on the frontend. + TODO: If source is a video, generate a thumb of the first frame and save the video length to the file? + Another possible solution would be to play a gif on hover that grabs a few chunks like youtube. + + TODO: Think if its worth making a folder with the user uuid in uploads/ and upload the pictures there so + that this way at least not every single file will be in 1 directory + + - Addendum to this: Now that the default behaviour is to serve files with node, we can actually pull this off. Before this, having files in + subfolders meant messing with nginx and the paths, but now it should be fairly easy to re-arrange the folder structure with express.static + I see great value in this, open to suggestions. +*/ + class uploadPOST extends Route { constructor() { super('/upload', 'post', { bypassAuth: true }); -- cgit v1.2.3 From 496477ebda3f6c347a9944e22daae447d15ebc31 Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 11 May 2020 00:57:56 +0900 Subject: Feature: enable apiKey access to uploads and album fetching for the uploader/sharex/3rd party --- src/api/routes/uploads/uploadPOST.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index d611175..6c01dd3 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -39,7 +39,10 @@ const upload = multer({ class uploadPOST extends Route { constructor() { - super('/upload', 'post', { bypassAuth: true }); + super('/upload', 'post', { + bypassAuth: true, + canApiKey: true + }); } async run(req, res, db) { -- cgit v1.2.3 From ad852de51a0d2dd5d29c08838d5a430c58849e74 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 04:00:12 +0300 Subject: chore: linter the entire project using the new rules --- src/api/routes/uploads/uploadPOST.js | 44 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 6c01dd3..48fc592 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -1,17 +1,18 @@ -const Route = require('../../structures/Route'); const path = require('path'); -const Util = require('../../utils/Util'); const jetpack = require('fs-jetpack'); const multer = require('multer'); const moment = require('moment'); +const Util = require('../../utils/Util'); +const Route = require('../../structures/Route'); + const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: parseInt(process.env.MAX_SIZE, 10) * (1000 * 1000), - files: 1 + files: 1, }, - fileFilter: (req, file, cb) => { - // TODO: Enable blacklisting of files/extensions + fileFilter: (req, file, cb) => + // TODO: Enable blacklisting of files/extensions /* if (options.blacklist.mimes.includes(file.mimetype)) { return cb(new Error(`${file.mimetype} is a blacklisted filetype.`)); @@ -19,35 +20,34 @@ const upload = multer({ return cb(new Error(`${path.extname(file.originalname).toLowerCase()} is a blacklisted extension.`)); } */ - return cb(null, true); - } + cb(null, true) + , }).array('files[]'); /* TODO: If source has transparency generate a png thumbnail, otherwise a jpg. TODO: If source is a gif, generate a thumb of the first frame and play the gif on hover on the frontend. - TODO: If source is a video, generate a thumb of the first frame and save the video length to the file? - Another possible solution would be to play a gif on hover that grabs a few chunks like youtube. TODO: Think if its worth making a folder with the user uuid in uploads/ and upload the pictures there so that this way at least not every single file will be in 1 directory - - Addendum to this: Now that the default behaviour is to serve files with node, we can actually pull this off. Before this, having files in - subfolders meant messing with nginx and the paths, but now it should be fairly easy to re-arrange the folder structure with express.static - I see great value in this, open to suggestions. + XXX: Now that the default behaviour is to serve files with node, we can actually pull this off. + Before this, having files in subfolders meant messing with nginx and the paths, + but now it should be fairly easy to re-arrange the folder structure with express.static + I see great value in this, open to suggestions. */ class uploadPOST extends Route { constructor() { super('/upload', 'post', { bypassAuth: true, - canApiKey: true + canApiKey: true, }); } async run(req, res, db) { const user = await Util.isAuthorized(req); - if (!user && process.env.PUBLIC_MODE == 'false') return res.status(401).json({ message: 'Not authorized to use this resource' }); + if (!user && process.env.PUBLIC_MODE === 'false') return res.status(401).json({ message: 'Not authorized to use this resource' }); const albumId = req.body.albumid || req.headers.albumid; if (albumId && !user) return res.status(401).json({ message: 'Only registered users can upload files to an album' }); @@ -56,12 +56,13 @@ class uploadPOST extends Route { if (!album) return res.status(401).json({ message: 'Album doesn\'t exist or it doesn\'t belong to the user' }); } - return upload(req, res, async err => { + return upload(req, res, async (err) => { if (err) console.error(err.message); let uploadedFile = {}; let insertedId; + // eslint-disable-next-line no-underscore-dangle const remappedKeys = this._remapKeys(req.body); const file = req.files[0]; @@ -105,7 +106,7 @@ class uploadPOST extends Route { name: filename, hash, size: file.buffer.length, - url: filename + url: filename, }; } @@ -124,7 +125,7 @@ class uploadPOST extends Route { return res.status(201).send({ message: 'Sucessfully uploaded the file.', - ...uploadedFile + ...uploadedFile, }); }); } @@ -137,7 +138,7 @@ class uploadPOST extends Route { size: exists.size, url: `${process.env.DOMAIN}/${exists.name}`, deleteUrl: `${process.env.DOMAIN}/api/file/${exists.id}`, - repeated: true + repeated: true, }); return Util.deleteFile(filename); @@ -145,7 +146,7 @@ class uploadPOST extends Route { async checkIfFileExists(db, user, hash) { const exists = await db.table('files') - .where(function() { // eslint-disable-line func-names + .where(function () { // eslint-disable-line func-names if (user) this.where('userId', user.id); else this.whereNull('userId'); }) @@ -186,7 +187,7 @@ class uploadPOST extends Route { hash: file.hash, ip: req.ip, createdAt: now, - editedAt: now + editedAt: now, }); } else { insertedId = await db.table('files').insert({ @@ -198,7 +199,7 @@ class uploadPOST extends Route { hash: file.hash, ip: req.ip, createdAt: now, - editedAt: now + editedAt: now, }, 'id'); } return insertedId; @@ -220,6 +221,7 @@ class uploadPOST extends Route { } return body; } + return keys; } } -- cgit v1.2.3 From 6713eca9d4a4887dc8d7416dbdd8ec37de7bb2ed Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 19:22:25 +0300 Subject: chore: add unique integrity checks to the database for many-to-many tables --- src/api/routes/uploads/uploadPOST.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 48fc592..99f5ee5 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -84,10 +84,7 @@ class uploadPOST extends Route { if (remappedKeys && remappedKeys.uuid) { const chunkOutput = path.join(__dirname, - '..', - '..', - '..', - '..', + '../../../../', process.env.UPLOAD_FOLDER, 'chunks', remappedKeys.uuid, @@ -95,10 +92,7 @@ class uploadPOST extends Route { await jetpack.writeAsync(chunkOutput, file.buffer); } else { const output = path.join(__dirname, - '..', - '..', - '..', - '..', + '../../../../', process.env.UPLOAD_FOLDER, filename); await jetpack.writeAsync(output, file.buffer); -- cgit v1.2.3 From a057f26896d98e8a99819b5de62c79cccb2ec023 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 18 Jul 2020 03:23:59 +0900 Subject: Fix url retrieval of uploaded file --- src/api/routes/uploads/uploadPOST.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 6c01dd3..4b84da6 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -122,6 +122,7 @@ class uploadPOST extends Route { this.saveFileToAlbum(db, albumId, insertedId); } + uploadedFile = Util.constructFilePublicLink(uploadedFile); return res.status(201).send({ message: 'Sucessfully uploaded the file.', ...uploadedFile @@ -130,6 +131,7 @@ class uploadPOST extends Route { } fileExists(res, exists, filename) { + exists = Util.constructFilePublicLink(exists); res.json({ message: 'Successfully uploaded the file.', name: exists.name, -- cgit v1.2.3 From 90001c2df56d58e69fd199a518ae7f3e4ed327fc Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 24 Dec 2020 10:40:50 +0200 Subject: chore: remove trailing commas --- src/api/routes/uploads/uploadPOST.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 3e67293..567862a 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -9,7 +9,7 @@ const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: parseInt(process.env.MAX_SIZE, 10) * (1000 * 1000), - files: 1, + files: 1 }, fileFilter: (req, file, cb) => // TODO: Enable blacklisting of files/extensions @@ -21,7 +21,7 @@ const upload = multer({ } */ cb(null, true) - , + }).array('files[]'); /* @@ -41,7 +41,7 @@ class uploadPOST extends Route { constructor() { super('/upload', 'post', { bypassAuth: true, - canApiKey: true, + canApiKey: true }); } @@ -100,7 +100,7 @@ class uploadPOST extends Route { name: filename, hash, size: file.buffer.length, - url: filename, + url: filename }; } @@ -120,7 +120,7 @@ class uploadPOST extends Route { uploadedFile = Util.constructFilePublicLink(uploadedFile); return res.status(201).send({ message: 'Sucessfully uploaded the file.', - ...uploadedFile, + ...uploadedFile }); }); } @@ -134,7 +134,7 @@ class uploadPOST extends Route { size: exists.size, url: `${process.env.DOMAIN}/${exists.name}`, deleteUrl: `${process.env.DOMAIN}/api/file/${exists.id}`, - repeated: true, + repeated: true }); return Util.deleteFile(filename); @@ -183,7 +183,7 @@ class uploadPOST extends Route { hash: file.hash, ip: req.ip, createdAt: now, - editedAt: now, + editedAt: now }); } else { insertedId = await db.table('files').insert({ @@ -195,7 +195,7 @@ class uploadPOST extends Route { hash: file.hash, ip: req.ip, createdAt: now, - editedAt: now, + editedAt: now }, 'id'); } return insertedId; -- cgit v1.2.3 From fb2c27086f570fec60f4d52dcc9ca80e53186293 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 24 Dec 2020 23:45:16 +0900 Subject: Fix ESLint rules once and for all --- src/api/routes/uploads/uploadPOST.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 567862a..5458d48 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -56,7 +56,7 @@ class uploadPOST extends Route { if (!album) return res.status(401).json({ message: 'Album doesn\'t exist or it doesn\'t belong to the user' }); } - return upload(req, res, async (err) => { + return upload(req, res, async err => { if (err) console.error(err.message); let uploadedFile = {}; @@ -142,7 +142,7 @@ class uploadPOST extends Route { async checkIfFileExists(db, user, hash) { const exists = await db.table('files') - .where(function () { // eslint-disable-line func-names + .where(function() { // eslint-disable-line func-names if (user) this.where('userId', user.id); else this.whereNull('userId'); }) -- cgit v1.2.3 From e97fee48441717f3b508ac855339d0fb8210be53 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sun, 27 Dec 2020 04:27:56 +0900 Subject: Fixes chunked uploads not being saved to albums or thumbnails --- src/api/routes/uploads/uploadPOST.js | 61 ++---------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 5458d48..5d04da1 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -106,7 +106,7 @@ class uploadPOST extends Route { if (!remappedKeys || !remappedKeys.uuid) { Util.generateThumbnails(uploadedFile.name); - insertedId = await this.saveFileToDatabase(req, res, user, db, uploadedFile, file); + insertedId = await Util.saveFileToDatabase(req, res, user, db, uploadedFile, file); if (!insertedId) return res.status(500).json({ message: 'There was an error saving the file.' }); uploadedFile.deleteUrl = `${process.env.DOMAIN}/api/file/${insertedId[0]}`; @@ -114,7 +114,7 @@ class uploadPOST extends Route { If the upload had an album specified we make sure to create the relation and update the according timestamps.. */ - this.saveFileToAlbum(db, albumId, insertedId); + Util.saveFileToAlbum(db, albumId, insertedId); } uploadedFile = Util.constructFilePublicLink(uploadedFile); @@ -151,62 +151,6 @@ class uploadPOST extends Route { return exists; } - async saveFileToAlbum(db, albumId, insertedId) { - if (!albumId) return; - - const now = moment.utc().toDate(); - try { - await db.table('albumsFiles').insert({ albumId, fileId: insertedId[0] }); - await db.table('albums').where('id', albumId).update('editedAt', now); - } catch (error) { - console.error(error); - } - } - - async saveFileToDatabase(req, res, user, db, file, originalFile) { - /* - Save the upload information to the database - */ - const now = moment.utc().toDate(); - let insertedId = null; - try { - /* - This is so fucking dumb - */ - if (process.env.DB_CLIENT === 'sqlite3') { - insertedId = await db.table('files').insert({ - userId: user ? user.id : null, - name: file.name, - original: originalFile.originalname, - type: originalFile.mimetype || '', - size: file.size, - hash: file.hash, - ip: req.ip, - createdAt: now, - editedAt: now - }); - } else { - insertedId = await db.table('files').insert({ - userId: user ? user.id : null, - name: file.name, - original: originalFile.originalname, - type: originalFile.mimetype || '', - size: file.size, - hash: file.hash, - ip: req.ip, - createdAt: now, - editedAt: now - }, 'id'); - } - return insertedId; - } catch (error) { - console.error('There was an error saving the file to the database'); - console.error(error); - return null; - // return res.status(500).json({ message: 'There was an error uploading the file.' }); - } - } - _remapKeys(body) { const keys = Object.keys(body); if (keys.length) { @@ -217,7 +161,6 @@ class uploadPOST extends Route { } return body; } - return keys; } } -- cgit v1.2.3 From aa7d2453171b3a596a1be6676eaf39cc93fe178f Mon Sep 17 00:00:00 2001 From: Pitu Date: Sun, 27 Dec 2020 04:48:03 +0900 Subject: feat: Add hash checking for chunked uploads --- src/api/routes/uploads/uploadPOST.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'src/api/routes/uploads/uploadPOST.js') diff --git a/src/api/routes/uploads/uploadPOST.js b/src/api/routes/uploads/uploadPOST.js index 5d04da1..449999e 100644 --- a/src/api/routes/uploads/uploadPOST.js +++ b/src/api/routes/uploads/uploadPOST.js @@ -79,7 +79,7 @@ class uploadPOST extends Route { For this we need to wait until we have a filename so that we can delete the uploaded file. */ - const exists = await this.checkIfFileExists(db, user, hash); + const exists = await Util.checkIfFileExists(db, user, hash); if (exists) return this.fileExists(res, exists, filename); if (remappedKeys && remappedKeys.uuid) { @@ -140,17 +140,6 @@ class uploadPOST extends Route { return Util.deleteFile(filename); } - async checkIfFileExists(db, user, hash) { - const exists = await db.table('files') - .where(function() { // eslint-disable-line func-names - if (user) this.where('userId', user.id); - else this.whereNull('userId'); - }) - .where({ hash }) - .first(); - return exists; - } - _remapKeys(body) { const keys = Object.keys(body); if (keys.length) { -- cgit v1.2.3