mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-24 01:10:31 +01:00
refactor: flag sanity checks, +feat: flag limits
- Added new config flag:limitPerTarget, to disallow flags after an item has already been flagged x times (default 0, or infinite) - New zset flags:byTarget, score is the number of times a flag has been made against that item - "already-flagged" translation key removed, now "post-already-flagged" or "user-already-flagged" -- this fixed bug where flagging a user you've already flagged would tell you you've already flagged this post already. - Refactored Flags.canFlag to throw errors only, instead of returning boolean - Updated ACP form inputs for reputation settings page to be more bootstrappy - +1 upgrade script
This commit is contained in:
33
src/flags.js
33
src/flags.js
@@ -277,7 +277,7 @@ Flags.create = async function (type, id, uid, reason, timestamp) {
|
||||
timestamp = Date.now();
|
||||
doHistoryAppend = true;
|
||||
}
|
||||
const [flagExists, targetExists, canFlag, targetUid, targetCid] = await Promise.all([
|
||||
const [flagExists, targetExists,, targetUid, targetCid] = await Promise.all([
|
||||
// Sanity checks
|
||||
Flags.exists(type, id, uid),
|
||||
Flags.targetExists(type, id),
|
||||
@@ -287,12 +287,11 @@ Flags.create = async function (type, id, uid, reason, timestamp) {
|
||||
Flags.getTargetCid(type, id),
|
||||
]);
|
||||
if (flagExists) {
|
||||
throw new Error('[[error:already-flagged]]');
|
||||
throw new Error(`[[error:${type}-already-flagged]]`);
|
||||
} else if (!targetExists) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
} else if (!canFlag) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
|
||||
const flagId = await db.incrObjectField('global', 'nextFlagId');
|
||||
|
||||
await db.setObject('flag:' + flagId, {
|
||||
@@ -307,6 +306,7 @@ Flags.create = async function (type, id, uid, reason, timestamp) {
|
||||
await db.sortedSetAdd('flags:byReporter:' + uid, timestamp, flagId); // by reporter
|
||||
await db.sortedSetAdd('flags:byType:' + type, timestamp, flagId); // by flag type
|
||||
await db.sortedSetAdd('flags:hash', flagId, [type, id, uid].join(':')); // save zset for duplicate checking
|
||||
await db.sortedSetIncrBy('flags:byTarget', 1, [type, id].join(':')); // by flag target (score is count)
|
||||
await analytics.increment('flags'); // some fancy analytics
|
||||
|
||||
if (targetUid) {
|
||||
@@ -336,13 +336,28 @@ Flags.exists = async function (type, id, uid) {
|
||||
};
|
||||
|
||||
Flags.canFlag = async function (type, id, uid) {
|
||||
if (type === 'user') {
|
||||
return true;
|
||||
const limit = meta.config['flags:limitPerTarget'];
|
||||
if (limit > 0) {
|
||||
const score = await db.sortedSetScore('flags:byTarget', `${type}:${id}`);
|
||||
if (score >= limit) {
|
||||
throw new Error(`[[error:${type}-flagged-too-many-times]]`);
|
||||
}
|
||||
}
|
||||
if (type === 'post') {
|
||||
return await privileges.posts.can('topics:read', id, uid);
|
||||
|
||||
const canRead = await privileges.posts.can('topics:read', id, uid);
|
||||
switch (type) {
|
||||
case 'user':
|
||||
return true;
|
||||
|
||||
case 'post':
|
||||
if (!canRead) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
};
|
||||
|
||||
Flags.getTarget = async function (type, id, uid) {
|
||||
|
||||
Reference in New Issue
Block a user