feat: closes #12154, add exempt groups

for new user restrictions
This commit is contained in:
Barış Soner Uşaklı
2023-11-07 12:36:40 -05:00
parent 119c3362ff
commit fdff165e2b
11 changed files with 63 additions and 23 deletions

View File

@@ -23,10 +23,11 @@
"chatMessageDelay": 2000,
"newbieChatMessageDelay": 120000,
"notificationSendDelay": 60,
"newbiePostDelayThreshold": 3,
"newbieReputationThreshold": 3,
"postQueue": 0,
"postQueueReputationThreshold": 0,
"groupsExemptFromPostQueue": ["administrators", "Global Moderators"],
"groupsExemptFromNewUserRestrictions": ["administrators", "Global Moderators"],
"groupsExemptFromMaintenanceMode": ["administrators", "Global Moderators"],
"minimumPostLength": 8,
"maximumPostLength": 32767,

View File

@@ -87,5 +87,6 @@
"restrictions.seconds-between-new": "Seconds between posts for new users",
"restrictions.seconds-before-new": "Seconds before a new user can make their first post",
"restrictions.seconds-edit-after-new": "Number of seconds a post remains editable for new users (set to 0 to disable)",
"restrictions.milliseconds-between-messages": "Time between chat messages for new users (ms)"
"restrictions.milliseconds-between-messages": "Time between chat messages for new users (ms)",
"restrictions.groups-exempt-from-new-user-restrictions": "Select groups that should be exempt from the new user restrictions"
}

View File

@@ -13,6 +13,10 @@ get:
properties:
title:
type: string
groupsExemptFromNewUserRestrictions:
type: array
items:
$ref: ../../../components/schemas/GroupObject.yaml#/GroupDataObject
notificationSettings:
type: array
items:

View File

@@ -20,7 +20,7 @@ async function rateLimitExceeded(caller, field) {
user.isPrivileged(caller.uid),
user.getUserField(caller.uid, 'reputation'),
]);
const newbie = !isPrivileged && meta.config.newbiePostDelayThreshold > reputation;
const newbie = !isPrivileged && meta.config.newbieReputationThreshold > reputation;
const delay = newbie ? meta.config.newbieChatMessageDelay : meta.config.chatMessageDelay;
session[field] = session[field] || 0;

View File

@@ -46,7 +46,10 @@ settingsController.email = async (req, res) => {
};
settingsController.user = async (req, res) => {
const notificationTypes = await notifications.getAllNotificationTypes();
const [notificationTypes, groupData] = await Promise.all([
notifications.getAllNotificationTypes(),
groups.getNonPrivilegeGroups('groups:createtime', 0, -1),
]);
const notificationSettings = notificationTypes.map(type => ({
name: type,
label: `[[notifications:${type.replace(/_/g, '-')}]]`,
@@ -54,6 +57,7 @@ settingsController.user = async (req, res) => {
res.render('admin/settings/user', {
title: '[[admin/menu:settings/user]]',
notificationSettings: notificationSettings,
groupsExemptFromNewUserRestrictions: groupData,
});
};

View File

@@ -274,17 +274,19 @@ module.exports = function (Groups) {
}
async function updateConfig(oldName, newName) {
if (meta.config.groupsExemptFromPostQueue.includes(oldName)) {
meta.config.groupsExemptFromPostQueue.splice(
meta.config.groupsExemptFromPostQueue.indexOf(oldName), 1, newName
);
await meta.configs.set('groupsExemptFromPostQueue', meta.config.groupsExemptFromPostQueue);
}
if (meta.config.groupsExemptFromMaintenanceMode.includes(oldName)) {
meta.config.groupsExemptFromMaintenanceMode.splice(
meta.config.groupsExemptFromMaintenanceMode.indexOf(oldName), 1, newName
);
await meta.configs.set('groupsExemptFromMaintenanceMode', meta.config.groupsExemptFromMaintenanceMode);
const configKeys = [
'groupsExemptFromPostQueue',
'groupsExemptFromNewUserRestrictions',
'groupsExemptFromMaintenanceMode',
];
for (const key of configKeys) {
if (meta.config[key] && meta.config[key].includes(oldName)) {
meta.config[key].splice(
meta.config[key].indexOf(oldName), 1, newName
);
await meta.configs.set(key, meta.config[key]);
}
}
}

View File

@@ -139,7 +139,7 @@ privsPosts.canEdit = async function (pid, uid) {
if (
!results.isMod &&
meta.config.newbiePostEditDuration > 0 &&
meta.config.newbiePostDelayThreshold > results.userData.reputation &&
meta.config.newbieReputationThreshold > results.userData.reputation &&
Date.now() - results.postData.timestamp > meta.config.newbiePostEditDuration * 1000
) {
return { flag: false, message: `[[error:post-edit-duration-expired, ${meta.config.newbiePostEditDuration}]]` };

View File

@@ -0,0 +1,15 @@
/* eslint-disable no-await-in-loop */
'use strict';
const db = require('../../database');
module.exports = {
name: 'Rename newbiePostDelayThreshold to newbieReputationThreshold',
timestamp: Date.UTC(2023, 10, 7),
method: async function () {
const current = await db.getObjectField('config', 'newbiePostDelayThreshold');
await db.setObjectField('config', 'newbieReputationThreshold', current);
await db.deleteObjectField('config', 'newbiePostDelayThreshold');
},
};

View File

@@ -3,6 +3,7 @@
const db = require('../database');
const meta = require('../meta');
const privileges = require('../privileges');
const groups = require('../groups');
module.exports = function (User) {
User.isReadyToPost = async function (uid, cid) {
@@ -31,9 +32,10 @@ module.exports = function (User) {
if (parseInt(uid, 10) === 0) {
return;
}
const [userData, isAdminOrMod] = await Promise.all([
const [userData, isAdminOrMod, isMemberOfExempt] = await Promise.all([
User.getUserFields(uid, ['uid', 'mutedUntil', 'joindate', 'email', 'reputation'].concat([field])),
privileges.categories.isAdminOrMod(cid, uid),
groups.isMemberOfAny(uid, meta.config.groupsExemptFromNewUserRestrictions),
]);
if (!userData.uid) {
@@ -54,14 +56,15 @@ module.exports = function (User) {
const lasttime = userData[field] || 0;
if (
!isMemberOfExempt &&
meta.config.newbiePostDelay > 0 &&
meta.config.newbiePostDelayThreshold > userData.reputation &&
meta.config.newbieReputationThreshold > userData.reputation &&
now - lasttime < meta.config.newbiePostDelay * 1000
) {
if (meta.config.newbiewPostDelay % 60 === 0) {
throw new Error(`[[error:too-many-posts-newbie-minutes, ${Math.floor(meta.config.newbiePostDelay / 60)}, ${meta.config.newbiePostDelayThreshold}]]`);
throw new Error(`[[error:too-many-posts-newbie-minutes, ${Math.floor(meta.config.newbiePostDelay / 60)}, ${meta.config.newbieReputationThreshold}]]`);
} else {
throw new Error(`[[error:too-many-posts-newbie, ${meta.config.newbiePostDelay}, ${meta.config.newbiePostDelayThreshold}]]`);
throw new Error(`[[error:too-many-posts-newbie, ${meta.config.newbiePostDelay}, ${meta.config.newbieReputationThreshold}]]`);
}
} else if (now - lasttime < meta.config.postDelay * 1000) {
throw new Error(`[[error:too-many-posts, ${meta.config.postDelay}]]`);

View File

@@ -218,8 +218,8 @@
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/user:restrictions-new]]</h5>
<div class="mb-3">
<label class="form-label" for="newbiePostDelayThreshold">[[admin/settings/user:restrictions.rep-threshold]]</label>
<input id="newbiePostDelayThreshold" type="text" class="form-control" value="3" data-field="newbiePostDelayThreshold">
<label class="form-label" for="newbieReputationThreshold">[[admin/settings/user:restrictions.rep-threshold]]</label>
<input id="newbieReputationThreshold" type="text" class="form-control" value="3" data-field="newbieReputationThreshold">
</div>
<div class="mb-3">
@@ -241,6 +241,16 @@
<label class="form-label" for="newbieChatMessageDelay">[[admin/settings/user:restrictions.milliseconds-between-messages]]</label>
<input id="newbieChatMessageDelay" type="text" class="form-control" data-field="newbieChatMessageDelay">
</div>
<div class="mb-3">
<label class="form-label" for="groupsExemptFromNewUserRestrictions">[[admin/settings/user:restrictions.groups-exempt-from-new-user-restrictions]]</label>
<select id="groupsExemptFromNewUserRestrictions" class="form-select" multiple data-field="groupsExemptFromNewUserRestrictions">
{{{ each groupsExemptFromNewUserRestrictions }}}
<option value="{groupsExemptFromNewUserRestrictions.displayName}">{groupsExemptFromNewUserRestrictions.displayName}</option>
{{{ end }}}
</select>
</div>
</div>
<hr/>

View File

@@ -317,7 +317,7 @@ describe('User', () => {
it('should error when a new user posts if the last post time is 10 < 30 seconds', (done) => {
meta.config.newbiePostDelay = 30;
meta.config.newbiePostDelayThreshold = 3;
meta.config.newbieReputationThreshold = 3;
User.setUserField(testUid, 'lastposttime', +new Date() - (20 * 1000), () => {
Topics.post({