Slur swear blocker challenges redux (#15089)

* update packages on local/origin repo

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

* feat(challenges): slur blocker work

* feat(challenges): slur blocker

* feat(challenges): more slur blocker

* feat(challenges): even more slur blocker

* feat(challenges): swear and slur blocker

* feat(challenges): update behavior based on public/private groups

* feat(profiles): slur/swear blocker

* feat(profiles): slur/swear blocker

* feat(profiles/PMs): slur/swear blocker upgrade

* feat(slur/swear): working on it

* feat(profiles/challenges): work on profile block & slack report

* feat(slur/swear blocker): work on Profiles

* feat(slur blocker): refactoring code

* feat(slur blocker): more refactoring

* feat(slur blocker): arghhhhhh

* fix(profiles): improve profanity check logic

* fix(slack): update Slack notification to include authorEmail and remove undefined

* feat(s/s blocker): work on challenges

* feat(s/s blocker): challenge update

* feat(s/s blocker): slack notifs refinements

* feat(s/s blocker): refine slack notifs & disallow use of challenges POST API route if user is chatRevoked:true in db

* update package.json and package-lock.json

* attempt to disable create challenge button for muted users

* another attempt to disable create challenge

* block muted users from creating challenges

* CSS button fun

* fix CSS button

* refactor(css): move button style to global
Also, disable Clone button if user is chat revoked

* fix(lint): remove unused fn

* fix(challenges): handle null slur check

* fix(groups): throw notFound earlier

* fix(challenges): CSS and logic updates

* fix(lint): remove whitespace

* fix(challenges): don't disable create buttons

* fix(slack): restore broken profile flag fields

* chore(cleanup): remove comments and whitespace

* chore(cleanup): one more white space

---------

Co-authored-by: SabreCat <sabe@habitica.com>
This commit is contained in:
Natalie
2024-01-16 15:22:03 -05:00
committed by GitHub
parent 8b2e13b5fd
commit 4cbc3d7664
14 changed files with 166 additions and 86 deletions

View File

@@ -2,6 +2,11 @@ import _ from 'lodash';
import cloneDeep from 'lodash/cloneDeep';
import { authWithHeaders, authWithSession } from '../../middlewares/auth';
import { model as Challenge } from '../../models/challenge';
import bannedWords from '../../libs/bannedWords';
import bannedSlurs from '../../libs/bannedSlurs';
import { getMatchesByWordArray } from '../../libs/stringUtils';
import * as slack from '../../libs/slack';
import { getUserInfo } from '../../libs/email';
import {
model as Group,
basicFields as basicGroupFields,
@@ -12,6 +17,7 @@ import {
nameFields,
} from '../../models/user';
import {
BadRequest,
NotFound,
NotAuthorized,
} from '../../libs/errors';
@@ -39,6 +45,22 @@ const { MAX_SUMMARY_SIZE_FOR_CHALLENGES } = common.constants;
const api = {};
function textContainsBannedWord (message) {
if (!message) {
return false;
}
const bannedWordsMatched = getMatchesByWordArray(message, bannedWords);
return bannedWordsMatched.length > 0;
}
function textContainsBannedSlur (message) {
if (!message) {
return false;
}
const bannedSlursMatched = getMatchesByWordArray(message, bannedSlurs);
return bannedSlursMatched.length > 0;
}
/**
* @apiDefine ChallengeLeader Challenge Leader
* The leader of the challenge can use this route.
@@ -212,7 +234,50 @@ api.createChallenge = {
const validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
const { savedChal, group } = await createChallenge(user, req, res);
const group = await Group.getGroup({
user, groupId: req.body.group, fields: basicGroupFields, optionalMembership: true,
});
if (!group) {
throw new NotFound(res.t('groupNotFound'));
}
// check public challenges for banned words & chat revocation
if (group.privacy === 'public') {
const textToCheck = `${req.body.name} ${req.body.shortName} ${req.body.summary} ${req.body.description}`;
if (textContainsBannedSlur(textToCheck)) {
const authorEmail = getUserInfo(user, ['email']).email;
const problemContent = `Challenge Name: ${req.body.name}\n
Challenge Tag: ${req.body.shortName}\n
Challenge Summary: ${req.body.summary}\n
Challenge Description: ${req.body.description}`;
slack.sendChallengeSlurNotification({
authorEmail,
author: user,
displayName: user.profile.name,
username: user.auth.local.username,
uuid: user.id,
language: user.preferences.language,
problemContent,
});
user.flags.chatRevoked = true;
await user.save();
throw new BadRequest(res.t('challengeBannedSlurs'));
}
if (textContainsBannedWord(textToCheck)) {
throw new BadRequest(res.t('challengeBannedWords'));
}
if (user.flags.chatRevoked) {
throw new BadRequest(res.t('cannotMakeChallenge'));
}
}
const { savedChal } = await createChallenge(user, req, res);
await user.save();
const response = savedChal.toJSON();
response.leader = { // the leader is the authenticated user