feat: core work for #9042, thumb deletion now accepts uuids

+ common data validation for thumb addition and deletion
v1.18.x
Julian Lam 4 years ago
parent 1f0c1cd229
commit b5d910f53b

@ -95,18 +95,9 @@ Topics.getThumbs = async (req, res) => {
}; };
Topics.addThumb = 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) await checkThumbPrivileges(req, res);
const id = req.params.tid; if (res.headersSent) {
const isUUID = validator.isUUID(id); return;
// 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]]'));
} }
/** /**
@ -122,15 +113,31 @@ Topics.addThumb = async (req, res) => {
// Add uploaded files to topic zset // Add uploaded files to topic zset
await Promise.all(files.map(async (fileObj) => { 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) => { Topics.deleteThumb = async (req, res) => {
if (!await privileges.topics.canEdit(req.params.tid, req.user.uid)) { await checkThumbPrivileges(req, res);
return helpers.formatApiResponse(403, res, new Error('[[error:no-privileges]]')); if (res.headersSent) {
return;
} }
await topics.thumbs.delete(req.params.tid, req.body.path); await topics.thumbs.delete(req.params.tid, req.body.path);
helpers.formatApiResponse(200, res, await topics.thumbs.get(req.params.tid)); 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]]'));
}
}

@ -36,7 +36,7 @@ module.exports = function () {
setupApiRoute(router, 'get', '/:tid/thumbs', [], controllers.write.topics.getThumbs); setupApiRoute(router, 'get', '/:tid/thumbs', [], controllers.write.topics.getThumbs);
setupApiRoute(router, 'post', '/:tid/thumbs', [multipartMiddleware, middleware.validateFiles, ...middlewares], controllers.write.topics.addThumb); 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; return router;
}; };

@ -53,9 +53,10 @@ Thumbs.commit = async function (uuid, tid) {
await db.delete(set); await db.delete(set);
}; };
Thumbs.delete = async function (tid, relativePath) { Thumbs.delete = async function (id, relativePath) {
// TODO: tests // 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 absolutePath = path.join(nconf.get('upload_path'), relativePath);
const [associated, existsOnDisk] = await Promise.all([ const [associated, existsOnDisk] = await Promise.all([
db.isSortedSetMember(set, relativePath), db.isSortedSetMember(set, relativePath),

Loading…
Cancel
Save