feat(challenges): add banned words & slur blocker to challenges

This commit is contained in:
CuriousMagpie
2023-11-02 16:22:31 -04:00
parent 40d6b60ee3
commit 0f742d219f
2 changed files with 65 additions and 2 deletions

View File

@@ -2,6 +2,11 @@ import _ from 'lodash';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import { authWithHeaders, authWithSession } from '../../middlewares/auth'; import { authWithHeaders, authWithSession } from '../../middlewares/auth';
import { model as Challenge } from '../../models/challenge'; import { model as Challenge } from '../../models/challenge';
import bannedWords from '../../libs/bannedWords';
import bannedSlurs from '../../libs/bannedSlurs';
import { getUserInfo } from '../../libs/email';
import { getMatchesByWordArray } from '../../libs/stringUtils';
import * as slack from '../../libs/slack';
import { import {
model as Group, model as Group,
basicFields as basicGroupFields, basicFields as basicGroupFields,
@@ -12,6 +17,7 @@ import {
nameFields, nameFields,
} from '../../models/user'; } from '../../models/user';
import { import {
BadRequest,
NotFound, NotFound,
NotAuthorized, NotAuthorized,
} from '../../libs/errors'; } from '../../libs/errors';
@@ -36,6 +42,16 @@ const { MAX_SUMMARY_SIZE_FOR_CHALLENGES } = common.constants;
const api = {}; const api = {};
function textContainsBannedWord (message) {
const bannedWordsMatched = getMatchesByWordArray(message, bannedWords);
return bannedWordsMatched.length > 0;
}
function textContainsBannedSlur (message) {
const bannedSlursMatched = getMatchesByWordArray(message, bannedSlurs);
return bannedSlursMatched.length > 0;
}
/** /**
* @apiDefine ChallengeLeader Challenge Leader * @apiDefine ChallengeLeader Challenge Leader
* The leader of the challenge can use this route. * The leader of the challenge can use this route.
@@ -230,6 +246,53 @@ api.createChallenge = {
headers: req.headers, headers: req.headers,
}); });
// check challenge for slurs
if (group.privacy === 'public'
&& textContainsBannedSlur(req.workingChallenge.name
|| req.workingChallenge.shortName
|| req.workingChallenge.summary
|| req.workingChallenge.description)) {
const { message } = req.body;
user.flags.chatRevoked = true;
await user.save();
// email mods
const authorEmail = getUserInfo(user, ['email']).email;
// send Slack message
slack.sendSlurNotification({
authorEmail,
author: user,
group,
message,
});
throw new BadRequest(res.t('bannedSlurUsed'));
}
// prevent banned words being posted, except in private challenges
if (group.privacy === 'public'
&& textContainsBannedWord(req.workingChallenge.name
|| req.workingChallenge.shortName
|| req.workingChallenge.summary
|| req.workingChallenge.description)) {
const { message } = req.body;
await user.save();
// email mods
const authorEmail = getUserInfo(user, ['email']).email;
// send Slack message
slack.sendSlurNotification({
authorEmail,
author: user,
group,
message,
});
throw new BadRequest(res.t('bannedWordUsed'));
}
res.respond(201, response); res.respond(201, response);
}, },
}; };

View File

@@ -30,8 +30,8 @@ export function nameContainsNewline (username) {
} }
function usernameIsForbidden (username) { function usernameIsForbidden (username) {
const forbidddenWordsMatched = getMatchesByWordArray(username, forbiddenUsernames); const forbiddenWordsMatched = getMatchesByWordArray(username, forbiddenUsernames);
return forbidddenWordsMatched.length > 0; return forbiddenWordsMatched.length > 0;
} }
const invalidCharsRegex = new RegExp('[^a-z0-9_-]', 'i'); const invalidCharsRegex = new RegExp('[^a-z0-9_-]', 'i');