Squashed commit of the following:

commit 83bcd07e20
Author: SabreCat <sabrecat@gmail.com>
Date:   Fri Dec 22 17:24:45 2023 -0600

    fix(profile): revert state on error

commit 6aa6278727
Author: SabreCat <sabrecat@gmail.com>
Date:   Fri Dec 22 14:37:28 2023 -0600

    fix(test): no longer care about swears in profile

commit 0882c77038
Author: SabreCat <sabe@habitica.com>
Date:   Fri Dec 22 14:15:42 2023 -0600

    fix(lint): remove unused functions

commit 9b275ef72d
Author: SabreCat <sabe@habitica.com>
Date:   Fri Dec 22 14:09:11 2023 -0600

    fix(profiles): restore reporting functionality
    Also remove unused and/or unrelated code and clean up comments

commit f4ed8c1461
Merge: da16aa9c75 f8ba191eea
Author: SabreCat <sabe@habitica.com>
Date:   Fri Dec 22 12:11:00 2023 -0600

    Merge branch 'release' into slur-swear-blocker

commit da16aa9c75
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Thu Dec 21 13:20:28 2023 -0500

    feat(s/s blocker): challenge updates to slack

commit 51bed61c4c
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Dec 19 15:36:59 2023 -0500

    feat(s/s blocker): work on challenges

commit 139cbcb21c
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Wed Dec 13 13:20:45 2023 -0500

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

commit 805b287721
Author: SabreCat <sabe@habitica.com>
Date:   Tue Dec 12 16:35:54 2023 -0600

    fix(profiles): improve profanity check logic

commit 02ef7e8822
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Dec 12 17:22:29 2023 -0500

    feat(slur blocker): arghhhhhh

commit 949dee9b1e
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Dec 12 13:57:29 2023 -0500

    feat(slur blocker): more refactoring

commit bf953998f4
Merge: d21aa687b7 f572aa442e
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Mon Dec 11 15:20:06 2023 -0500

    Merge branch 'release' into slur-swear-blocker

commit d21aa687b7
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Thu Dec 7 18:00:29 2023 -0500

    feat(slur blocker): refactoring code

commit f2db90c494
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Wed Dec 6 12:12:55 2023 -0500

    feat(slur/swear blocker): work on Profiles

commit 8f9822ffe8
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Mon Dec 4 17:25:17 2023 -0500

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

commit bdb2e06e5e
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Fri Dec 1 16:11:27 2023 -0500

    feat(slur/swear): working on it

commit 7277b5cad5
Merge: 24d14277ab 941f1f976c
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Fri Dec 1 15:04:46 2023 -0500

    Merge branch 'profile-slur-swear-blocker' into slur-swear-blocker

commit 941f1f976c
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Thu Nov 30 14:34:30 2023 -0500

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

commit 0863017efc
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Nov 28 16:21:21 2023 -0500

    feat(profiles): slur/swear blocker

commit e9937d864f
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Mon Nov 27 15:24:37 2023 -0500

    feat(profiles): slur/swear blocker

commit 24d14277ab
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Mon Nov 27 14:12:46 2023 -0500

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

commit 1251f5b6a7
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Nov 14 16:28:29 2023 -0500

    feat(challenges): swear and slur blocker

commit a771045ca7
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Nov 14 15:46:16 2023 -0500

    feat(challenges): even more slur blocker

commit e5e91aa78a
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Tue Nov 14 14:31:25 2023 -0500

    feat(challenges): more slur blocker

commit 50e824e4e3
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Mon Nov 13 15:12:14 2023 -0500

    feat(challenges): slur blocker

commit 315ea24ef4
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Fri Nov 3 12:31:12 2023 -0400

    feat(challenges): slur blocker work

commit 0f742d219f
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Thu Nov 2 16:22:31 2023 -0400

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

commit 40d6b60ee3
Author: CuriousMagpie <eilatan@gmail.com>
Date:   Mon Oct 23 13:00:46 2023 -0400

    update packages on local/origin repo
This commit is contained in:
Sabe Jones
2024-01-10 15:14:11 -06:00
parent 7a2c7c5b30
commit b7def686e9
9 changed files with 119 additions and 180 deletions

View File

@@ -94,14 +94,6 @@ describe('PUT /user', () => {
message: t('bannedSlurUsedInProfile'),
});
await expect(user.put('/user', {
'profile.name': 'TESTPLACEHOLDERSWEARWORDHERE',
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('bannedWordUsedInProfile'),
});
await expect(user.put('/user', {
'profile.name': 'namecontainsnewline\n',
})).to.eventually.be.rejected.and.eql({

View File

@@ -1222,9 +1222,10 @@ export default {
const { nextRewardAt } = currentLoginDay;
return ((nextRewardAt - previousRewardDay));
},
save () {
async save () {
const values = {};
const edits = cloneDeep(this.editingProfile);
const oldProfile = cloneDeep(this.user.profile);
each(edits, (value, key) => {
// Using toString because we need to compare two arrays (websites)
@@ -1235,7 +1236,12 @@ export default {
}
});
this.$store.dispatch('user:set', values);
await this.$store.dispatch('user:set', values).catch(() => {
this.user.profile = oldProfile;
this.editingProfile.name = this.user.profile.name;
this.editingProfile.imageUrl = this.user.profile.imageUrl;
this.editingProfile.blurb = this.user.profile.blurb;
});
this.editing = false;
},

View File

@@ -17,9 +17,6 @@ import { removeFromArray } from '../../libs/collectionManipulators';
import { getUserInfo } from '../../libs/email';
import * as slack from '../../libs/slack';
import { chatReporterFactory } from '../../libs/chatReporting/chatReporterFactory';
import bannedWords from '../../libs/bannedWords';
import { getMatchesByWordArray } from '../../libs/stringUtils';
import bannedSlurs from '../../libs/bannedSlurs';
import apiError from '../../libs/apiError';
import highlightMentions from '../../libs/highlightMentions';
import { getAnalyticsServiceByEnvironment } from '../../libs/analyticsService';
@@ -50,11 +47,6 @@ const ACCOUNT_MIN_CHAT_AGE = Number(nconf.get('ACCOUNT_MIN_CHAT_AGE'));
const api = {};
function textContainsBannedSlur (message) {
const bannedSlursMatched = getMatchesByWordArray(message, bannedSlurs);
return bannedSlursMatched.length > 0;
}
/**
* @api {get} /api/v3/groups/:groupId/chat Get chat messages from a group
* @apiName GetChat
@@ -90,10 +82,6 @@ api.getChat = {
},
};
function getBannedWordsFromText (message) {
return getMatchesByWordArray(message, bannedWords);
}
/**
* @api {post} /api/v3/groups/:groupId/chat Post chat message to a group
* @apiName PostChat
@@ -137,39 +125,6 @@ api.postChat = {
throw new BadRequest(res.t('featureRetired'));
}
// Check message for banned slurs
if (group && group.privacy !== 'private' && textContainsBannedSlur(req.body.message)) {
const { message } = req.body;
user.flags.chatRevoked = true;
await user.save();
// Email the mods
const authorEmail = getUserInfo(user, ['email']).email;
// Slack the mods
slack.sendSlurNotification({
authorEmail,
author: user,
group,
message,
});
throw new BadRequest(res.t('bannedSlurUsed'));
}
if (group.privacy === 'public' && user.flags.chatRevoked) {
throw new NotAuthorized(res.t('chatPrivilegesRevoked'));
}
// prevent banned words being posted, except in private guilds/parties
// and in certain public guilds with specific topics
if (group.privacy === 'public' && !group.bannedWordsAllowed) {
const matchedBadWords = getBannedWordsFromText(req.body.message);
if (matchedBadWords.length > 0) {
throw new BadRequest(res.t('bannedWordUsed', { swearWordsUsed: matchedBadWords.join(', ') }));
}
}
const chatRes = await Group.toJSONCleanChat(group, user);
const lastClientMsg = req.query.previousMsg;
const chatUpdated = !!(

View File

@@ -15,7 +15,7 @@
// Email admin@habitica.com to discuss the change you want made.
//
// All updates to this file must be done through a direct commit to limit
// the words visibility in GitHub to protect our coders, socialites, and
// the words visibility in GitHub to protect our coders and
// wiki editors who look through PRs for information.
//
// When adding words that contain asterisks, put two backslashes before them.

View File

@@ -2,8 +2,7 @@
// CONTENT WARNING:
//
// This file contains slurs, swear words, religious oaths, and words related
// to addictive substance and adult topics.
// This file contains slurs, swear words, and religious oaths.
// Do not read this file if you do not want to be exposed to those words.
//
// The words are stored in an array called `bannedWords` which is then
@@ -18,7 +17,7 @@
// Email admin@habitica.com to discuss the change you want made.
//
// All updates to this file must be done through a direct commit to limit
// the words visibility in GitHub to protect our coders, socialites, and
// the words visibility in GitHub to protect our coders and
// wiki editors who look through PRs for information.
//
// When adding words that contain asterisks, put two backslashes before them.
@@ -85,13 +84,20 @@ const bannedWords = [
'damn',
'goddamn',
'damnit',
'dammit',
'damned',
'omfg',
'ass',
'arse',
'arsehole',
'asshole',
'badarse',
'badass',
'bastard',
'bastards',
'bitch',
'bitchy',
'bitches',
'bitching',
'b\\*tch',
'blowjob',
'bugger',
'buggery',
'buggering',
@@ -101,6 +107,57 @@ const bannedWords = [
'bullshitter',
'bullshiting',
'bullshitting',
'cocksucker',
'cocksucking',
'cunnilingus',
'dafuq',
'fag',
'fap',
'fapping',
'fellatio',
'fuck',
'fucks',
'fucking',
'fucked',
'fuckwit',
'fucker',
'fuckers',
'f\\*ck',
'fuckhead',
'fuckheads',
'goddamn',
'handjob',
'kickarse',
'kickass',
'lmao',
'lmfao',
'omfg',
'masturbate',
'masturbates',
'masturbating',
'masturbation',
'milf',
'motherfucker',
'motherfuckers',
'motherfucking',
'muthafucka',
'nigga',
'niggas',
'nofap',
'no fap',
'no-fap',
'no nut',
'no-nut',
'no-nut-november',
'nutting',
'nuttin',
'rape',
'raped',
'raping',
'r\\*pe',
'r\\*ped',
'r\\*ping',
'rimjob',
'shiz',
'shit',
'shite',
@@ -114,81 +171,12 @@ const bannedWords = [
'sh\\*t',
'sh\\*tty',
'sh\\*tting',
'fuck',
'fucks',
'fucking',
'fucked',
'fuckwit',
'fucker',
'fuckers',
'f\\*ck',
'fuckhead',
'fuckheads',
'motherfucker',
'motherfuckers',
'motherfucking',
'muthafucka',
'dafuq',
'wtf',
'stfu',
'ass',
'arse',
'asshole',
'badass',
'kickass',
'arsehole',
'badarse',
'kickarse',
'lmao',
'lmfao',
'bitch',
'bitchy',
'bitches',
'bitching',
'b\\*tch',
'fag',
'slut',
'sluts',
'nigga',
'niggas',
'bastard',
'bastards',
'rape',
'raped',
'raping',
'r\\*pe',
'r\\*ped',
'r\\*ping',
'blowjob',
'rimjob',
'handjob',
'cunnilingus',
'fellatio',
'sodomy',
'milf',
'cocksucker',
'cocksucking',
'fap',
'nofap',
'no fap',
'no-fap',
'fapping',
'no nut',
'no-nut',
'no-nut-november',
'nutting',
'nuttin',
'masturbate',
'masturbates',
'masturbating',
'masturbation',
'stfu',
'wtf',
'heroin',
'cocaine',
];
export default bannedWords;

View File

@@ -324,34 +324,21 @@ function sendShadowMutedPostNotification ({
.catch(err => logger.error(err, 'Error while sending flag data to Slack.'));
}
function sendSlurNotification ({
// slack slur notification for Profiles
function sendProfileSlurNotification ({
authorEmail,
author,
group,
message,
uuid,
language,
problemContent,
}) {
if (SKIP_FLAG_METHODS) {
return;
}
const text = `${author.profile.name} (${author._id}) tried to post a slur`;
const title = 'User Profile Report: Slur';
const titleLink = `${BASE_URL}/profile/${uuid}`;
let titleLink;
let title = `Slur in ${group.name}`;
if (group.id === TAVERN_ID) {
titleLink = `${BASE_URL}/groups/tavern`;
} else if (group.privacy === 'public') {
titleLink = `${BASE_URL}/groups/guild/${group.id}`;
} else {
title += ` - (${group.privacy} ${group.type})`;
}
const authorName = formatUser({
name: author.auth.local.username,
displayName: author.profile.name,
email: authorEmail,
uuid: author.id,
});
const text = `@${author} ${authorEmail} (${uuid}, ${language}) tried to post a slur in their Profile.`;
flagSlack
.send({
@@ -359,10 +346,10 @@ function sendSlurNotification ({
attachments: [{
fallback: 'Slur Message',
color: 'danger',
author_name: authorName,
author_email: authorEmail,
title,
title_link: titleLink,
text: message,
text: problemContent,
mrkdwn_in: [
'text',
],
@@ -378,6 +365,6 @@ export {
sendProfileFlagNotification,
sendSubscriptionNotification,
sendShadowMutedPostNotification,
sendSlurNotification,
sendProfileSlurNotification,
formatUser,
};

View File

@@ -1,4 +1,6 @@
import _ from 'lodash';
import * as slack from '../slack';
import { getUserInfo } from '../email';
import common from '../../../common';
import * as Tasks from '../../models/task';
import { model as Groups } from '../../models/group';
@@ -105,19 +107,6 @@ function checkPreferencePurchase (user, path, item) {
return _.get(user.purchased, itemPath);
}
async function checkNewInputForProfanity (user, res, newValue) {
const containsSlur = stringContainsProfanity(newValue, 'slur');
const containsBannedWord = stringContainsProfanity(newValue);
if (containsSlur || containsBannedWord) {
if (containsSlur) {
user.flags.chatRevoked = true;
await user.save();
throw new BadRequest(res.t('bannedSlurUsedInProfile'));
}
throw new BadRequest(res.t('bannedWordUsedInProfile'));
}
}
export async function update (req, res, { isV3 = false }) {
const { user } = res.locals;
@@ -134,17 +123,40 @@ export async function update (req, res, { isV3 = false }) {
});
}
let slurWasUsed = false;
let problemContent = '';
if (req.body['profile.name'] !== undefined) {
const newName = req.body['profile.name'];
if (newName === null) throw new BadRequest(res.t('invalidReqParams'));
if (newName.length > 30) throw new BadRequest(res.t('displaynameIssueLength'));
if (nameContainsNewline(newName)) throw new BadRequest(res.t('displaynameIssueNewline'));
await checkNewInputForProfanity(user, res, newName);
if (stringContainsProfanity(newName, 'slur')) {
slurWasUsed = true;
problemContent += `Profile Name: ${newName}\n\n`;
}
}
if (req.body['profile.blurb'] !== undefined) {
const newBlurb = req.body['profile.blurb'];
await checkNewInputForProfanity(user, res, newBlurb);
if (stringContainsProfanity(newBlurb, 'slur')) {
slurWasUsed = true;
problemContent += `Profile Blurb: ${newBlurb}`;
}
}
if (slurWasUsed) {
const authorEmail = getUserInfo(user, ['email']).email;
user.flags.chatRevoked = true;
await user.save();
slack.sendProfileSlurNotification({
authorEmail,
author: user.auth.local.username,
uuid: user.id,
language: user.preferences.language,
problemContent,
});
throw new BadRequest(res.t('bannedSlurUsedInProfile'));
}
let groupsToMirror;

View File

@@ -30,8 +30,8 @@ export function nameContainsNewline (username) {
}
function usernameIsForbidden (username) {
const forbidddenWordsMatched = getMatchesByWordArray(username, forbiddenUsernames);
return forbidddenWordsMatched.length > 0;
const forbiddenWordsMatched = getMatchesByWordArray(username, forbiddenUsernames);
return forbiddenWordsMatched.length > 0;
}
const invalidCharsRegex = new RegExp('[^a-z0-9_-]', 'i');
@@ -43,7 +43,6 @@ function usernameContainsInvalidCharacters (username) {
export function verifyDisplayName (displayName, res) {
const issues = [];
if (displayName.length < 1 || displayName.length > 30) issues.push(res.t('displaynameIssueLength'));
if (stringContainsProfanity(displayName)) issues.push(res.t('bannedWordUsedInProfile'));
if (stringContainsProfanity(displayName, 'slur')) issues.push(res.t('bannedSlurUsedInProfile'));
if (nameContainsNewline(displayName)) issues.push(res.t('displaynameIssueNewline'));