diff --git a/src/api/topics.js b/src/api/topics.js index cee48c87bf6e..bda48d59daae 100644 --- a/src/api/topics.js +++ b/src/api/topics.js @@ -4,6 +4,8 @@ const user = require('../user'); const topics = require('../topics'); const posts = require('../posts'); const meta = require('../meta'); +const events = require('../events'); +const privileges = require('../privileges'); const controllerHelpers = require('../controllers/helpers'); const socketHelpers = require('../socket.io/helpers'); @@ -75,3 +77,84 @@ topicsAPI.reply = async function (caller, data) { return postObj[0]; }; + +topicsAPI.delete = async function (caller, data) { + await doTopicAction('delete', 'event:topic_deleted', caller, { + tids: [data.tid], + }); +}; + +topicsAPI.restore = async function (caller, data) { + await doTopicAction('restore', 'event:topic_restored', caller, { + tids: [data.tid], + }); +}; + +topicsAPI.purge = async function (caller, data) { + await doTopicAction('purge', 'event:topic_purged', caller, { + tids: [data.tid], + }); +}; + +topicsAPI.pin = async function (caller, data) { + await doTopicAction('pin', 'event:topic_pinned', caller, { + tids: [data.tid], + }); +}; + +topicsAPI.unpin = async function (caller, data) { + await doTopicAction('unpin', 'event:topic_unpinned', caller, { + tids: [data.tid], + }); +}; + +topicsAPI.lock = async function (caller, data) { + await doTopicAction('lock', 'event:topic_locked', caller, { + tids: [data.tid], + }); +}; + +topicsAPI.unlock = async function (caller, data) { + await doTopicAction('unlock', 'event:topic_unlocked', caller, { + tids: [data.tid], + }); +}; + +async function doTopicAction(action, event, caller, { tids }) { + if (!Array.isArray(tids)) { + throw new Error('[[error:invalid-tid]]'); + } + + const exists = (await Promise.all(tids.map(async tid => await topics.exists(tid)))).every(Boolean); + if (!exists) { + throw new Error('[[error:no-topic]]'); + } + + if (typeof topics.tools[action] !== 'function') { + return; + } + + const uids = await user.getUidsFromSet('users:online', 0, -1); + + await Promise.all(tids.map(async function (tid) { + const title = await topics.getTopicField(tid, 'title'); + const data = await topics.tools[action](tid, caller.uid); + const notifyUids = await privileges.categories.filterUids('topics:read', data.cid, uids); + socketHelpers.emitToUids(event, data, notifyUids); + await logTopicAction(action, caller, tid, title); + })); +} + +async function logTopicAction(action, req, tid, title) { + var actionsToLog = ['delete', 'restore', 'purge']; + if (!actionsToLog.includes(action)) { + return; + } + await events.log({ + type: 'topic-' + action, + uid: req.uid, + ip: req.ip, + tid: tid, + title: String(title), + }); +} diff --git a/src/controllers/write/topics.js b/src/controllers/write/topics.js index 543fe3fd58b8..ff35ca62c268 100644 --- a/src/controllers/write/topics.js +++ b/src/controllers/write/topics.js @@ -2,12 +2,8 @@ const api = require('../../api'); const topics = require('../../topics'); -const user = require('../../user'); -const events = require('../../events'); -const privileges = require('../../privileges'); const helpers = require('../helpers'); -const socketHelpers = require('../../socket.io/helpers'); const Topics = module.exports; @@ -26,51 +22,37 @@ Topics.reply = async (req, res) => { }; Topics.delete = async (req, res) => { - await doTopicAction('delete', 'event:topic_deleted', req, { - tids: [req.params.tid], - }); + await api.topics.delete(req, req.params); helpers.formatApiResponse(200, res); }; Topics.restore = async (req, res) => { - await doTopicAction('restore', 'event:topic_restored', req, { - tids: [req.params.tid], - }); + await api.topics.restore(req, req.params); helpers.formatApiResponse(200, res); }; Topics.purge = async (req, res) => { - await doTopicAction('purge', 'event:topic_purged', req, { - tids: [req.params.tid], - }); + await api.topics.purge(req, req.params); helpers.formatApiResponse(200, res); }; Topics.pin = async (req, res) => { - await doTopicAction('pin', 'event:topic_pinned', req, { - tids: [req.params.tid], - }); + await api.topics.pin(req, req.params); helpers.formatApiResponse(200, res); }; Topics.unpin = async (req, res) => { - await doTopicAction('unpin', 'event:topic_unpinned', req, { - tids: [req.params.tid], - }); + await api.topics.unpin(req, req.params); helpers.formatApiResponse(200, res); }; Topics.lock = async (req, res) => { - await doTopicAction('lock', 'event:topic_locked', req, { - tids: [req.params.tid], - }); + await api.topics.lock(req, req.params); helpers.formatApiResponse(200, res); }; Topics.unlock = async (req, res) => { - await doTopicAction('unlock', 'event:topic_unlocked', req, { - tids: [req.params.tid], - }); + await api.topics.unlock(req, req.params); helpers.formatApiResponse(200, res); }; @@ -98,37 +80,3 @@ Topics.deleteTags = async (req, res) => { await topics.deleteTopicTags(req.params.tid); helpers.formatApiResponse(200, res); }; - -async function doTopicAction(action, event, socket, { tids }) { - if (!Array.isArray(tids)) { - throw new Error('[[error:invalid-tid]]'); - } - - if (typeof topics.tools[action] !== 'function') { - return; - } - - const uids = await user.getUidsFromSet('users:online', 0, -1); - - await Promise.all(tids.map(async function (tid) { - const title = await topics.getTopicField(tid, 'title'); - const data = await topics.tools[action](tid, socket.uid); - const notifyUids = await privileges.categories.filterUids('topics:read', data.cid, uids); - socketHelpers.emitToUids(event, data, notifyUids); - await logTopicAction(action, socket, tid, title); - })); -} - -async function logTopicAction(action, req, tid, title) { - var actionsToLog = ['delete', 'restore', 'purge']; - if (!actionsToLog.includes(action)) { - return; - } - await events.log({ - type: 'topic-' + action, - uid: req.uid, - ip: req.ip, - tid: tid, - title: String(title), - }); -} diff --git a/src/routes/write/topics.js b/src/routes/write/topics.js index 17637e066c32..b46de2f36518 100644 --- a/src/routes/write/topics.js +++ b/src/routes/write/topics.js @@ -12,16 +12,16 @@ module.exports = function () { setupApiRoute(router, 'post', '/', [...middlewares, middleware.checkRequired.bind(null, ['cid', 'title', 'content'])], controllers.write.topics.create); setupApiRoute(router, 'post', '/:tid', [...middlewares, middleware.checkRequired.bind(null, ['content']), middleware.assert.topic], controllers.write.topics.reply); - setupApiRoute(router, 'delete', '/:tid', [...middlewares, middleware.assert.topic], controllers.write.topics.purge); + setupApiRoute(router, 'delete', '/:tid', [...middlewares], controllers.write.topics.purge); - setupApiRoute(router, 'put', '/:tid/state', [...middlewares, middleware.assert.topic], controllers.write.topics.restore); - setupApiRoute(router, 'delete', '/:tid/state', [...middlewares, middleware.assert.topic], controllers.write.topics.delete); + setupApiRoute(router, 'put', '/:tid/state', [...middlewares], controllers.write.topics.restore); + setupApiRoute(router, 'delete', '/:tid/state', [...middlewares], controllers.write.topics.delete); - setupApiRoute(router, 'put', '/:tid/pin', [...middlewares, middleware.assert.topic], controllers.write.topics.pin); - setupApiRoute(router, 'delete', '/:tid/pin', [...middlewares, middleware.assert.topic], controllers.write.topics.unpin); + setupApiRoute(router, 'put', '/:tid/pin', [...middlewares], controllers.write.topics.pin); + setupApiRoute(router, 'delete', '/:tid/pin', [...middlewares], controllers.write.topics.unpin); - setupApiRoute(router, 'put', '/:tid/lock', [...middlewares, middleware.assert.topic], controllers.write.topics.lock); - setupApiRoute(router, 'delete', '/:tid/lock', [...middlewares, middleware.assert.topic], controllers.write.topics.unlock); + setupApiRoute(router, 'put', '/:tid/lock', [...middlewares], controllers.write.topics.lock); + setupApiRoute(router, 'delete', '/:tid/lock', [...middlewares], controllers.write.topics.unlock); setupApiRoute(router, 'put', '/:tid/follow', [...middlewares, middleware.assert.topic], controllers.write.topics.follow); setupApiRoute(router, 'delete', '/:tid/follow', [...middlewares, middleware.assert.topic], controllers.write.topics.unfollow); diff --git a/src/socket.io/topics/tools.js b/src/socket.io/topics/tools.js index 3e7a3a2e0950..f4181a5d45c0 100644 --- a/src/socket.io/topics/tools.js +++ b/src/socket.io/topics/tools.js @@ -1,11 +1,9 @@ 'use strict'; -const user = require('../../user'); +const api = require('../../api'); const topics = require('../../topics'); -const events = require('../../events'); const privileges = require('../../privileges'); const plugins = require('../../plugins'); -const socketHelpers = require('../helpers'); const sockets = require('..'); module.exports = function (SocketTopics) { @@ -36,77 +34,39 @@ module.exports = function (SocketTopics) { SocketTopics.delete = async function (socket, data) { sockets.warnDeprecated(socket, 'DELETE /api/v3/topics/state'); - await SocketTopics.doTopicAction('delete', 'event:topic_deleted', socket, data); + await api.topics.delete(socket, data); }; SocketTopics.restore = async function (socket, data) { sockets.warnDeprecated(socket, 'PUT /api/v3/topics/state'); - await SocketTopics.doTopicAction('restore', 'event:topic_restored', socket, data); + await api.topics.restore(socket, data); }; SocketTopics.purge = async function (socket, data) { sockets.warnDeprecated(socket, 'DELETE /api/v3/topics'); - await SocketTopics.doTopicAction('purge', 'event:topic_purged', socket, data); + await api.topics.purge(socket, data); }; SocketTopics.lock = async function (socket, data) { sockets.warnDeprecated(socket, 'PUT /api/v3/topics/lock'); - await SocketTopics.doTopicAction('lock', 'event:topic_locked', socket, data); + await api.topics.lock(socket, data); }; SocketTopics.unlock = async function (socket, data) { sockets.warnDeprecated(socket, 'DELETE /api/v3/topics/lock'); - await SocketTopics.doTopicAction('unlock', 'event:topic_unlocked', socket, data); + await api.topics.unlock(socket, data); }; SocketTopics.pin = async function (socket, data) { sockets.warnDeprecated(socket, 'PUT /api/v3/topics/pin'); - await SocketTopics.doTopicAction('pin', 'event:topic_pinned', socket, data); + await api.topics.pin(socket, data); }; SocketTopics.unpin = async function (socket, data) { sockets.warnDeprecated(socket, 'DELETE /api/v3/topics/pin'); - await SocketTopics.doTopicAction('unpin', 'event:topic_unpinned', socket, data); + await api.topics.unpin(socket, data); }; - SocketTopics.doTopicAction = async function (action, event, socket, data) { - if (!socket.uid) { - throw new Error('[[error:no-privileges]]'); - } - - if (!data || !Array.isArray(data.tids)) { - throw new Error('[[error:invalid-tid]]'); - } - - if (typeof topics.tools[action] !== 'function') { - return; - } - - const uids = await user.getUidsFromSet('users:online', 0, -1); - - await Promise.all(data.tids.map(async function (tid) { - const title = await topics.getTopicField(tid, 'title'); - const data = await topics.tools[action](tid, socket.uid); - const notifyUids = await privileges.categories.filterUids('topics:read', data.cid, uids); - socketHelpers.emitToUids(event, data, notifyUids); - await logTopicAction(action, socket, tid, title); - })); - }; - - async function logTopicAction(action, socket, tid, title) { - var actionsToLog = ['delete', 'restore', 'purge']; - if (!actionsToLog.includes(action)) { - return; - } - await events.log({ - type: 'topic-' + action, - uid: socket.uid, - ip: socket.ip, - tid: tid, - title: String(title), - }); - } - SocketTopics.orderPinnedTopics = async function (socket, data) { if (!Array.isArray(data)) { throw new Error('[[error:invalid-data]]');