From 2b1fdc56a119e397f221430335822009b31e4c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Thu, 18 Jan 2024 17:07:52 -0500 Subject: [PATCH] feat: limit post/user flags per day closes #12274 --- install/data/defaults.json | 2 ++ .../en-GB/admin/settings/reputation.json | 7 ++++++- public/language/en-GB/error.json | 2 ++ src/flags.js | 16 +++++++++++++- src/views/admin/settings/reputation.tpl | 21 +++++++++++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/install/data/defaults.json b/install/data/defaults.json index 47a3e8d4a2..7b12002dc4 100644 --- a/install/data/defaults.json +++ b/install/data/defaults.json @@ -99,6 +99,8 @@ "min:rep:aboutme": 0, "min:rep:signature": 0, "flags:limitPerTarget": 0, + "flags:postFlagsPerDay": 10, + "flags:userFlagsPerDay": 10, "flags:autoFlagOnDownvoteThreshold": 0, "flags:actionOnResolve": "rescind", "flags:actionOnReject": "rescind", diff --git a/public/language/en-GB/admin/settings/reputation.json b/public/language/en-GB/admin/settings/reputation.json index 53801c6662..e4fff22620 100644 --- a/public/language/en-GB/admin/settings/reputation.json +++ b/public/language/en-GB/admin/settings/reputation.json @@ -23,7 +23,12 @@ "flags.limit-per-target": "Maximum number of times something can be flagged", "flags.limit-per-target-placeholder": "Default: 0", "flags.limit-per-target-help": "When a post or user is flagged multiple times, each additional flag is considered a "report" and added to the original flag. Set this option to a number other than zero to limit the number of reports an item can receive.", - "flags.auto-flag-on-downvote-threshold": "Number of downvotes to auto flag posts (Set to 0 to disable, default: 0)", + "flags.limit-post-flags-per-day": "Maximum number of times a user can flag posts in a day", + "flags.limit-post-flags-per-day-help": "Set to 0 to disable, (default: 10)", + "flags.limit-user-flags-per-day": "Maximum number of times a user can flag users in a day", + "flags.limit-user-flags-per-day-help": "Set to 0 to disable, (default: 10)", + "flags.auto-flag-on-downvote-threshold": "Number of downvotes to auto flag posts", + "flags.auto-flag-on-downvote-threshold-help": "Set to 0 to disable, (default: 0)", "flags.auto-resolve-on-ban": "Automatically resolve all of a user's tickets when they are banned", "flags.action-on-resolve": "Do the following when a flag is resolved", "flags.action-on-reject": "Do the following when a flag is rejected", diff --git a/public/language/en-GB/error.json b/public/language/en-GB/error.json index 75a8328aa1..47500b65a2 100644 --- a/public/language/en-GB/error.json +++ b/public/language/en-GB/error.json @@ -211,6 +211,8 @@ "user-already-flagged": "You have already flagged this user", "post-flagged-too-many-times": "This post has been flagged by others already", "user-flagged-too-many-times": "This user has been flagged by others already", + "too-many-post-flags-per-day": "You can only flag %1 post(s) per day", + "too-many-user-flags-per-day": "You can only flag %1 user(s) per day", "cant-flag-privileged": "You are not allowed to flag the profiles or content of privileged users (moderators/global moderators/admins)", "cant-locate-flag-report": "Cannot locate flag report", "self-vote": "You cannot vote on your own post", diff --git a/src/flags.js b/src/flags.js index 7ec1c504c1..833bb7edd8 100644 --- a/src/flags.js +++ b/src/flags.js @@ -629,8 +629,22 @@ Flags.canFlag = async function (type, id, uid, skipLimitCheck = false) { throw new Error(`[[error:${type}-flagged-too-many-times]]`); } } + const oneday = 24 * 60 * 60 * 1000; + const now = Date.now(); + const [flagIds, canRead, isPrivileged] = await Promise.all([ + db.getSortedSetRangeByScore(`flags:byReporter:${uid}`, 0, -1, now - oneday, '+inf'), + privileges.posts.can('topics:read', id, uid), + user.isPrivileged(uid), + ]); + const allowedFlagsPerDay = meta.config[`flags:${type}FlagsPerDay`]; + if (!isPrivileged && allowedFlagsPerDay > 0) { + const flagData = await db.getObjects(flagIds.map(id => `flag:${id}`)); + const flagsOfType = flagData.filter(f => f && f.type === type); + if (allowedFlagsPerDay > 0 && flagsOfType.length > allowedFlagsPerDay) { + throw new Error(`[[error:too-many-${type}-flags-per-day, ${allowedFlagsPerDay}]]`); + } + } - const canRead = await privileges.posts.can('topics:read', id, uid); switch (type) { case 'user': return true; diff --git a/src/views/admin/settings/reputation.tpl b/src/views/admin/settings/reputation.tpl index c747f22189..1786596c30 100644 --- a/src/views/admin/settings/reputation.tpl +++ b/src/views/admin/settings/reputation.tpl @@ -94,9 +94,30 @@ [[admin/settings/reputation:flags.limit-per-target-help]]

+ +
+ + +

+ [[admin/settings/reputation:flags.limit-post-flags-per-day-help]] +

+
+ +
+ + +

+ [[admin/settings/reputation:flags.limit-user-flags-per-day-help]] +

+
+ +
+

+ [[admin/settings/reputation:flags.auto-flag-on-downvote-threshold-help]] +