diff --git a/src/controllers/write/topics.js b/src/controllers/write/topics.js index 77f8f130af..2277849683 100644 --- a/src/controllers/write/topics.js +++ b/src/controllers/write/topics.js @@ -95,18 +95,9 @@ Topics.getThumbs = async (req, res) => { }; Topics.addThumb = async (req, res) => { - // req.params.tid could be either a tid (pushing a new thumb to an existing topic) or a post UUID (a new topic being composed) - const id = req.params.tid; - const isUUID = validator.isUUID(id); - - // Sanity-check the tid if it's strictly not a uuid - if (!isUUID && (isNaN(parseInt(id, 10)) || !await topics.exists(req.params.tid))) { - return helpers.formatApiResponse(404, res, new Error('[[error:no-topic]]')); - } - - // While drafts are not protected, tids are - if (!isUUID && !await privileges.topics.canEdit(req.params.tid, req.user.uid)) { - return helpers.formatApiResponse(403, res, new Error('[[error:no-privileges]]')); + await checkThumbPrivileges(req, res); + if (res.headersSent) { + return; } /** @@ -122,15 +113,31 @@ Topics.addThumb = async (req, res) => { // Add uploaded files to topic zset await Promise.all(files.map(async (fileObj) => { - await topics.thumbs.associate(id, fileObj.path); + await topics.thumbs.associate(req.params.tid, fileObj.path); })); }; Topics.deleteThumb = async (req, res) => { - if (!await privileges.topics.canEdit(req.params.tid, req.user.uid)) { - return helpers.formatApiResponse(403, res, new Error('[[error:no-privileges]]')); + await checkThumbPrivileges(req, res); + if (res.headersSent) { + return; } await topics.thumbs.delete(req.params.tid, req.body.path); helpers.formatApiResponse(200, res, await topics.thumbs.get(req.params.tid)); }; + +async function checkThumbPrivileges(req, res) { + // req.params.tid could be either a tid (pushing a new thumb to an existing topic) or a post UUID (a new topic being composed) + const isUUID = validator.isUUID(req.params.tid); + + // Sanity-check the tid if it's strictly not a uuid + if (!isUUID && (isNaN(parseInt(req.params.tid, 10)) || !await topics.exists(req.params.tid))) { + return helpers.formatApiResponse(404, res, new Error('[[error:no-topic]]')); + } + + // While drafts are not protected, tids are + if (!isUUID && !await privileges.topics.canEdit(req.params.tid, req.user.uid)) { + return helpers.formatApiResponse(403, res, new Error('[[error:no-privileges]]')); + } +} diff --git a/src/routes/write/topics.js b/src/routes/write/topics.js index f72f8bef24..aa290c52c8 100644 --- a/src/routes/write/topics.js +++ b/src/routes/write/topics.js @@ -36,7 +36,7 @@ module.exports = function () { setupApiRoute(router, 'get', '/:tid/thumbs', [], controllers.write.topics.getThumbs); setupApiRoute(router, 'post', '/:tid/thumbs', [multipartMiddleware, middleware.validateFiles, ...middlewares], controllers.write.topics.addThumb); - setupApiRoute(router, 'delete', '/:tid/thumbs', [...middlewares, middleware.assert.topic, middleware.assert.path], controllers.write.topics.deleteThumb); + setupApiRoute(router, 'delete', '/:tid/thumbs', [...middlewares, middleware.assert.path], controllers.write.topics.deleteThumb); return router; }; diff --git a/src/topics/thumbs.js b/src/topics/thumbs.js index af06b1ace8..5303a2d319 100644 --- a/src/topics/thumbs.js +++ b/src/topics/thumbs.js @@ -53,9 +53,10 @@ Thumbs.commit = async function (uuid, tid) { await db.delete(set); }; -Thumbs.delete = async function (tid, relativePath) { +Thumbs.delete = async function (id, relativePath) { // TODO: tests - const set = `topic:${tid}:thumbs`; + const isDraft = validator.isUUID(String(id)); + const set = `${isDraft ? 'draft' : 'topic'}:${id}:thumbs`; const absolutePath = path.join(nconf.get('upload_path'), relativePath); const [associated, existsOnDisk] = await Promise.all([ db.isSortedSetMember(set, relativePath),