feat: rescind post flags

This commit is contained in:
Opliko
2024-04-14 00:07:55 +02:00
parent 7c4ae8eb82
commit 9ab1a2d129
6 changed files with 72 additions and 0 deletions

View File

@@ -87,8 +87,11 @@
"modal-submit": "Submit Report", "modal-submit": "Submit Report",
"modal-submit-success": "Content has been flagged for moderation.", "modal-submit-success": "Content has been flagged for moderation.",
"modal-confirm-rescind": "Rescind Report?",
"bulk-actions": "Bulk Actions", "bulk-actions": "Bulk Actions",
"bulk-resolve": "Resolve Flag(s)", "bulk-resolve": "Resolve Flag(s)",
"bulk-purge": "Purge Flag(s)",
"bulk-success": "%1 flags updated", "bulk-success": "%1 flags updated",
"flagged-timeago-readable": "Flagged <span class=\"timeago\" title=\"%1\"></span> (%2)", "flagged-timeago-readable": "Flagged <span class=\"timeago\" title=\"%1\"></span> (%2)",
"auto-flagged": "[Auto Flagged] Received %1 downvotes." "auto-flagged": "[Auto Flagged] Received %1 downvotes."

View File

@@ -147,6 +147,18 @@ define('forum/topic/postTools', [
}); });
}); });
postContainer.on('click', '[component="post/already-flagged"]', function () {
const pid = getData($(this), 'data-pid');
require(['flags'], function (flags) {
bootbox.confirm('[[flags:modal-confirm-rescind]]', function (confirm) {
if (!confirm) {
return;
}
flags.rescindByType('post', pid);
});
});
});
postContainer.on('click', '[component="post/flagUser"]', function () { postContainer.on('click', '[component="post/flagUser"]', function () {
const uid = getData($(this), 'data-uid'); const uid = getData($(this), 'data-uid');
require(['flags'], function (flags) { require(['flags'], function (flags) {

View File

@@ -62,6 +62,32 @@ define('flags', ['hooks', 'components', 'api', 'alerts'], function (hooks, compo
}).catch(alerts.error); }).catch(alerts.error);
}; };
Flag.rescindByType = function (type, id) {
api.del(`/flags/${type}/${id}/report`).then(() => {
alerts.success('[[flags:rescinded]]');
hooks.fire('action:flag.rescinded', { type: type, id: id });
if (type === 'post') {
const postEl = components.get('post', 'pid', id);
postEl.find('[component="post/flag"]').removeClass('hidden').parent().attr('hidden', null);
postEl.find('[component="post/already-flagged"]').addClass('hidden').parent().attr('hidden', '');
}
}).catch(alerts.error);
};
Flag.rescind = function (flagId) {
api.del(`/flags/${flagId}/report`).then(() => {
alerts.success('[[flags:rescinded]]');
hooks.fire('action:flag.rescinded', { flagId: flagId });
}).catch(alerts.error);
};
Flag.purge = function (flagId) {
api.del(`/flags/${flagId}`).then(() => {
alerts.success('[[flags:purged]]');
hooks.fire('action:flag.purged', { flagId: flagId });
}).catch(alerts.error);
};
function createFlag(type, id, reason) { function createFlag(type, id, reason) {
if (!type || !id || !reason) { if (!type || !id || !reason) {
return; return;

View File

@@ -59,6 +59,24 @@ flagsApi.rescind = async ({ uid }, { flagId }) => {
await flags.rescindReport(type, targetId, uid); await flags.rescindReport(type, targetId, uid);
}; };
flagsApi.rescindPost = async ({ uid }, { pid }) => {
const exists = await flags.exists('post', pid, uid);
if (!exists) {
throw new Error('[[error:no-flag]]');
}
await flags.rescindReport('post', pid, uid);
};
flagsApi.rescindUser = async ({ uid }, { uid: targetUid }) => {
const exists = await flags.exists('user', targetUid, uid);
if (!exists) {
throw new Error('[[error:no-flag]]');
}
await flags.rescindReport('user', targetUid, uid);
};
flagsApi.appendNote = async (caller, data) => { flagsApi.appendNote = async (caller, data) => {
const allowed = await user.isPrivileged(caller.uid); const allowed = await user.isPrivileged(caller.uid);
if (!allowed) { if (!allowed) {

View File

@@ -37,6 +37,16 @@ Flags.rescind = async (req, res) => {
helpers.formatApiResponse(200, res); helpers.formatApiResponse(200, res);
}; };
Flags.rescindPost = async (req, res) => {
await api.flags.rescindPost(req, { pid: req.params.pid });
helpers.formatApiResponse(200, res);
};
Flags.rescindUser = async (req, res) => {
await api.flags.rescindUser(req, { uid: req.params.uid });
helpers.formatApiResponse(200, res);
};
Flags.appendNote = async (req, res) => { Flags.appendNote = async (req, res) => {
const { note, datetime } = req.body; const { note, datetime } = req.body;
const payload = await api.flags.appendNote(req, { const payload = await api.flags.appendNote(req, {

View File

@@ -19,6 +19,9 @@ module.exports = function () {
setupApiRoute(router, 'delete', '/:flagId/report', middlewares, controllers.write.flags.rescind); setupApiRoute(router, 'delete', '/:flagId/report', middlewares, controllers.write.flags.rescind);
setupApiRoute(router, 'delete', '/post/:pid/report', middlewares, controllers.write.flags.rescindPost);
setupApiRoute(router, 'delete', '/user/:uid/report', middlewares, controllers.write.flags.rescindUser);
setupApiRoute(router, 'post', '/:flagId/notes', [...middlewares, middleware.assert.flag], controllers.write.flags.appendNote); setupApiRoute(router, 'post', '/:flagId/notes', [...middlewares, middleware.assert.flag], controllers.write.flags.appendNote);
setupApiRoute(router, 'delete', '/:flagId/notes/:datetime', [...middlewares, middleware.assert.flag], controllers.write.flags.deleteNote); setupApiRoute(router, 'delete', '/:flagId/notes/:datetime', [...middlewares, middleware.assert.flag], controllers.write.flags.deleteNote);