diff --git a/src/api/helpers.js b/src/api/helpers.js index 47c1426735..13aab1b07c 100644 --- a/src/api/helpers.js +++ b/src/api/helpers.js @@ -1,6 +1,11 @@ 'use strict'; const url = require('url'); +const user = require('../user'); +const topics = require('../topics'); +const privileges = require('../privileges'); +const socketHelpers = require('../socket.io/helpers'); +const events = require('../events'); // creates a slimmed down version of the request object exports.buildReqObject = (req, payload) => { @@ -28,3 +33,43 @@ exports.buildReqObject = (req, payload) => { headers: headers, }; }; + + +exports.doTopicAction = async function (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/api/topics.js b/src/api/topics.js index d2aee0d85e..3b1f8d0ee4 100644 --- a/src/api/topics.js +++ b/src/api/topics.js @@ -4,10 +4,10 @@ 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 apiHelpers = require('./helpers'); +const doTopicAction = apiHelpers.doTopicAction; + const socketHelpers = require('../socket.io/helpers'); const topicsAPI = module.exports; @@ -80,43 +80,43 @@ topicsAPI.reply = async function (caller, data) { topicsAPI.delete = async function (caller, data) { await doTopicAction('delete', 'event:topic_deleted', caller, { - tids: [data.tid], + tids: data.tids, }); }; topicsAPI.restore = async function (caller, data) { await doTopicAction('restore', 'event:topic_restored', caller, { - tids: [data.tid], + tids: data.tids, }); }; topicsAPI.purge = async function (caller, data) { await doTopicAction('purge', 'event:topic_purged', caller, { - tids: [data.tid], + tids: data.tids, }); }; topicsAPI.pin = async function (caller, data) { await doTopicAction('pin', 'event:topic_pinned', caller, { - tids: [data.tid], + tids: data.tids, }); }; topicsAPI.unpin = async function (caller, data) { await doTopicAction('unpin', 'event:topic_unpinned', caller, { - tids: [data.tid], + tids: data.tids, }); }; topicsAPI.lock = async function (caller, data) { await doTopicAction('lock', 'event:topic_locked', caller, { - tids: [data.tid], + tids: data.tids, }); }; topicsAPI.unlock = async function (caller, data) { await doTopicAction('unlock', 'event:topic_unlocked', caller, { - tids: [data.tid], + tids: data.tids, }); }; @@ -131,42 +131,3 @@ topicsAPI.ignore = async function (caller, data) { topicsAPI.unfollow = async function (caller, data) { await topics.unfollow(data.tid, caller.uid); }; - -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/posts.js b/src/controllers/write/posts.js index ce04402d2d..eaf9033922 100644 --- a/src/controllers/write/posts.js +++ b/src/controllers/write/posts.js @@ -13,8 +13,8 @@ const utils = require('../../utils'); const helpers = require('../helpers'); const sockets = require('../../socket.io'); +const apiHelpers = require('../../api/helpers'); const socketPostHelpers = require('../../socket.io/posts/helpers'); // eehhh... -const socketTopics = require('../../socket.io/topics'); // eehhh... const Posts = module.exports; @@ -111,7 +111,7 @@ Posts.purge = async (req, res) => { }); if (isMainAndLast) { - await socketTopics.doTopicAction('purge', 'event:topic_purged', { + await apiHelpers.doTopicAction('purge', 'event:topic_purged', { ip: req.ip, uid: req.user.uid, }, { tids: [postData.tid], cid: topicData.cid }); @@ -199,12 +199,12 @@ async function isMainAndLastPost(pid) { async function deleteOrRestoreTopicOf(command, pid, req) { const topic = await posts.getTopicFields(pid, ['tid', 'cid', 'deleted']); if (command === 'delete' && !topic.deleted) { - await socketTopics.doTopicAction('delete', 'event:topic_deleted', { + await apiHelpers.doTopicAction('delete', 'event:topic_deleted', { uid: req.user.uid, ip: req.ip, }, { tids: [topic.tid], cid: topic.cid }); } else if (command === 'restore' && topic.deleted) { - await socketTopics.doTopicAction('restore', 'event:topic_restored', { + await apiHelpers.doTopicAction('restore', 'event:topic_restored', { uid: req.user.uid, ip: req.ip, }, { tids: [topic.tid], cid: topic.cid }); diff --git a/src/controllers/write/topics.js b/src/controllers/write/topics.js index 9e56bd74df..7e44b4184f 100644 --- a/src/controllers/write/topics.js +++ b/src/controllers/write/topics.js @@ -22,37 +22,37 @@ Topics.reply = async (req, res) => { }; Topics.delete = async (req, res) => { - await api.topics.delete(req, req.params); + await api.topics.delete(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; Topics.restore = async (req, res) => { - await api.topics.restore(req, req.params); + await api.topics.restore(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; Topics.purge = async (req, res) => { - await api.topics.purge(req, req.params); + await api.topics.purge(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; Topics.pin = async (req, res) => { - await api.topics.pin(req, req.params); + await api.topics.pin(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; Topics.unpin = async (req, res) => { - await api.topics.unpin(req, req.params); + await api.topics.unpin(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; Topics.lock = async (req, res) => { - await api.topics.lock(req, req.params); + await api.topics.lock(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; Topics.unlock = async (req, res) => { - await api.topics.unlock(req, req.params); + await api.topics.unlock(req, { tids: [req.params.tid] }); helpers.formatApiResponse(200, res); }; diff --git a/src/socket.io/posts/tools.js b/src/socket.io/posts/tools.js index 492385481c..8e4df14a6e 100644 --- a/src/socket.io/posts/tools.js +++ b/src/socket.io/posts/tools.js @@ -5,7 +5,7 @@ const topics = require('../../topics'); const flags = require('../../flags'); const events = require('../../events'); const websockets = require('../index'); -const socketTopics = require('../topics'); +const apiHelpers = require('../../api/helpers'); const privileges = require('../../privileges'); const plugins = require('../../plugins'); const social = require('../../social'); @@ -158,16 +158,16 @@ module.exports = function (SocketPosts) { }); if (isMainAndLast) { - await socketTopics.doTopicAction('purge', 'event:topic_purged', socket, { tids: [postData.tid], cid: topicData.cid }); + await apiHelpers.doTopicAction('purge', 'event:topic_purged', socket, { tids: [postData.tid], cid: topicData.cid }); } }; async function deleteOrRestoreTopicOf(command, pid, socket) { const topic = await posts.getTopicFields(pid, ['tid', 'cid', 'deleted']); if (command === 'delete' && !topic.deleted) { - await socketTopics.doTopicAction('delete', 'event:topic_deleted', socket, { tids: [topic.tid], cid: topic.cid }); + await apiHelpers.doTopicAction('delete', 'event:topic_deleted', socket, { tids: [topic.tid], cid: topic.cid }); } else if (command === 'restore' && topic.deleted) { - await socketTopics.doTopicAction('restore', 'event:topic_restored', socket, { tids: [topic.tid], cid: topic.cid }); + await apiHelpers.doTopicAction('restore', 'event:topic_restored', socket, { tids: [topic.tid], cid: topic.cid }); } }