From 979f24b173592cd62cc6456b1ba48be7496965d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 21 Aug 2023 14:00:36 -0400 Subject: [PATCH] feat: #6021 add min:rep-post-links (#11938) new reputation limit to post links if post queue is enabled and user doesn't have enough reputation to post links, queue their posts if post queue is NOT enabled and user doesn't have enough reputation to post links show error check content on topic post, topic reply, post edit --- install/data/defaults.json | 1 + .../en-GB/admin/settings/reputation.json | 1 + public/language/en-GB/error.json | 1 + src/api/posts.js | 2 ++ src/posts/queue.js | 25 ++++++++++++++++++- src/topics/create.js | 6 +++++ src/views/admin/settings/reputation.tpl | 4 +++ 7 files changed, 39 insertions(+), 1 deletion(-) diff --git a/install/data/defaults.json b/install/data/defaults.json index 12acc55fd6..e32f98fd27 100644 --- a/install/data/defaults.json +++ b/install/data/defaults.json @@ -89,6 +89,7 @@ "min:rep:chat": 0, "min:rep:downvote": 0, "min:rep:upvote": 0, + "min:rep:post-links": 0, "min:rep:flag": 0, "min:rep:profile-picture": 0, "min:rep:cover-picture": 0, diff --git a/public/language/en-GB/admin/settings/reputation.json b/public/language/en-GB/admin/settings/reputation.json index 293aa5b440..53801c6662 100644 --- a/public/language/en-GB/admin/settings/reputation.json +++ b/public/language/en-GB/admin/settings/reputation.json @@ -11,6 +11,7 @@ "downvotes-per-day": "Downvotes per day (set to 0 for unlimited downvotes)", "downvotes-per-user-per-day": "Downvotes per user per day (set to 0 for unlimited downvotes)", "min-rep-chat": "Minimum reputation to send chat messages", + "min-rep-post-links": "Minimum reputation to post links", "min-rep-flag": "Minimum reputation to flag posts", "min-rep-website": "Minimum reputation to add \"Website\" to user profile", "min-rep-aboutme": "Minimum reputation to add \"About me\" to user profile", diff --git a/public/language/en-GB/error.json b/public/language/en-GB/error.json index a374787ea6..af0b72e990 100644 --- a/public/language/en-GB/error.json +++ b/public/language/en-GB/error.json @@ -199,6 +199,7 @@ "not-enough-reputation-to-chat": "You need %1 reputation to chat", "not-enough-reputation-to-upvote": "You need %1 reputation to upvote", "not-enough-reputation-to-downvote": "You need %1 reputation to downvote", + "not-enough-reputation-to-post-links": "You need %1 reputation to post links", "not-enough-reputation-to-flag": "You need %1 reputation to flag this post", "not-enough-reputation-min-rep-website": "You need %1 reputation to add a website", "not-enough-reputation-min-rep-aboutme": "You need %1 reputation to add an about me", diff --git a/src/api/posts.js b/src/api/posts.js index cb2621ec81..8a8e53ec3a 100644 --- a/src/api/posts.js +++ b/src/api/posts.js @@ -99,6 +99,8 @@ postsAPI.edit = async function (caller, data) { throw new Error(`[[error:content-too-short, ${meta.config.minimumPostLength}]]`); } else if (contentLen > meta.config.maximumPostLength) { throw new Error(`[[error:content-too-long, ${meta.config.maximumPostLength}]]`); + } else if (!await posts.canUserPostContentWithLinks(caller.uid, data.content)) { + throw new Error(`[[error:not-enough-reputation-to-post-links, ${meta.config['min:rep:post-links']}]]`); } data.uid = caller.uid; diff --git a/src/posts/queue.js b/src/posts/queue.js index 2c485fb11e..565e21338b 100644 --- a/src/posts/queue.js +++ b/src/posts/queue.js @@ -85,6 +85,24 @@ module.exports = function (Posts) { postData.data.content = result.postData.content; } + Posts.canUserPostContentWithLinks = async function (uid, content) { + if (!content) { + return false; + } + const [reputation, isPrivileged] = await Promise.all([ + user.getUserField(uid, 'reputation'), + user.isPrivileged(uid), + ]); + + if (!isPrivileged && reputation < meta.config['min:rep:post-links']) { + const parsed = await plugins.hooks.fire('filter:parse.raw', String(content)); + if (parsed.match(/]*>([^<]+)<\/a>/g)) { + return false; + } + } + return true; + }; + Posts.shouldQueue = async function (uid, data) { const [userData, isMemberOfExempt, categoryQueueEnabled] = await Promise.all([ user.getUserFields(uid, ['uid', 'reputation', 'postcount']), @@ -94,7 +112,12 @@ module.exports = function (Posts) { const shouldQueue = meta.config.postQueue && categoryQueueEnabled && !isMemberOfExempt && - (!userData.uid || userData.reputation < meta.config.postQueueReputationThreshold || userData.postcount <= 0); + ( + !userData.uid || + userData.reputation < meta.config.postQueueReputationThreshold || + userData.postcount <= 0 || + !await Posts.canUserPostContentWithLinks(uid, data.content) + ); const result = await plugins.hooks.fire('filter:post.shouldQueue', { shouldQueue: !!shouldQueue, uid: uid, diff --git a/src/topics/create.js b/src/topics/create.js index f962b21ddf..44755ec7ee 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -98,6 +98,9 @@ module.exports = function (Topics) { data.tags = await Topics.filterTags(data.tags, data.cid); if (!data.fromQueue && !isAdmin) { Topics.checkContent(data.content); + if (!await posts.canUserPostContentWithLinks(uid, data.content)) { + throw new Error(`[[error:not-enough-reputation-to-post-links, ${meta.config['min:rep:post-links']}]]`); + } } if (!categoryExists) { @@ -177,6 +180,9 @@ module.exports = function (Topics) { if (!data.fromQueue && !isAdmin) { await user.isReadyToPost(uid, data.cid); Topics.checkContent(data.content); + if (!await posts.canUserPostContentWithLinks(uid, data.content)) { + throw new Error(`[[error:not-enough-reputation-to-post-links, ${meta.config['min:rep:post-links']}]]`); + } } // For replies to scheduled topics, don't have a timestamp older than topic's itself diff --git a/src/views/admin/settings/reputation.tpl b/src/views/admin/settings/reputation.tpl index 6f5796170e..c747f22189 100644 --- a/src/views/admin/settings/reputation.tpl +++ b/src/views/admin/settings/reputation.tpl @@ -53,6 +53,10 @@ +
+ + +