mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 13:47:33 +01:00
Squashed commit of the following:
commit83bcd07e20Author: SabreCat <sabrecat@gmail.com> Date: Fri Dec 22 17:24:45 2023 -0600 fix(profile): revert state on error commit6aa6278727Author: SabreCat <sabrecat@gmail.com> Date: Fri Dec 22 14:37:28 2023 -0600 fix(test): no longer care about swears in profile commit0882c77038Author: SabreCat <sabe@habitica.com> Date: Fri Dec 22 14:15:42 2023 -0600 fix(lint): remove unused functions commit9b275ef72dAuthor: 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 commitf4ed8c1461Merge:da16aa9c75f8ba191eeaAuthor: SabreCat <sabe@habitica.com> Date: Fri Dec 22 12:11:00 2023 -0600 Merge branch 'release' into slur-swear-blocker commitda16aa9c75Author: CuriousMagpie <eilatan@gmail.com> Date: Thu Dec 21 13:20:28 2023 -0500 feat(s/s blocker): challenge updates to slack commit51bed61c4cAuthor: CuriousMagpie <eilatan@gmail.com> Date: Tue Dec 19 15:36:59 2023 -0500 feat(s/s blocker): work on challenges commit139cbcb21cAuthor: CuriousMagpie <eilatan@gmail.com> Date: Wed Dec 13 13:20:45 2023 -0500 fix(slack): update Slack notification to include authorEmail and remove undefined commit805b287721Author: SabreCat <sabe@habitica.com> Date: Tue Dec 12 16:35:54 2023 -0600 fix(profiles): improve profanity check logic commit02ef7e8822Author: CuriousMagpie <eilatan@gmail.com> Date: Tue Dec 12 17:22:29 2023 -0500 feat(slur blocker): arghhhhhh commit949dee9b1eAuthor: CuriousMagpie <eilatan@gmail.com> Date: Tue Dec 12 13:57:29 2023 -0500 feat(slur blocker): more refactoring commitbf953998f4Merge:d21aa687b7f572aa442eAuthor: CuriousMagpie <eilatan@gmail.com> Date: Mon Dec 11 15:20:06 2023 -0500 Merge branch 'release' into slur-swear-blocker commitd21aa687b7Author: CuriousMagpie <eilatan@gmail.com> Date: Thu Dec 7 18:00:29 2023 -0500 feat(slur blocker): refactoring code commitf2db90c494Author: CuriousMagpie <eilatan@gmail.com> Date: Wed Dec 6 12:12:55 2023 -0500 feat(slur/swear blocker): work on Profiles commit8f9822ffe8Author: CuriousMagpie <eilatan@gmail.com> Date: Mon Dec 4 17:25:17 2023 -0500 feat(profiles/challenges): work on profile block & slack report commitbdb2e06e5eAuthor: CuriousMagpie <eilatan@gmail.com> Date: Fri Dec 1 16:11:27 2023 -0500 feat(slur/swear): working on it commit7277b5cad5Merge:24d14277ab941f1f976cAuthor: CuriousMagpie <eilatan@gmail.com> Date: Fri Dec 1 15:04:46 2023 -0500 Merge branch 'profile-slur-swear-blocker' into slur-swear-blocker commit941f1f976cAuthor: CuriousMagpie <eilatan@gmail.com> Date: Thu Nov 30 14:34:30 2023 -0500 feat(profiles/PMs): slur/swear blocker upgrade commit0863017efcAuthor: CuriousMagpie <eilatan@gmail.com> Date: Tue Nov 28 16:21:21 2023 -0500 feat(profiles): slur/swear blocker commite9937d864fAuthor: CuriousMagpie <eilatan@gmail.com> Date: Mon Nov 27 15:24:37 2023 -0500 feat(profiles): slur/swear blocker commit24d14277abAuthor: CuriousMagpie <eilatan@gmail.com> Date: Mon Nov 27 14:12:46 2023 -0500 feat(challenges): update behavior based on public/private groups commit1251f5b6a7Author: CuriousMagpie <eilatan@gmail.com> Date: Tue Nov 14 16:28:29 2023 -0500 feat(challenges): swear and slur blocker commita771045ca7Author: CuriousMagpie <eilatan@gmail.com> Date: Tue Nov 14 15:46:16 2023 -0500 feat(challenges): even more slur blocker commite5e91aa78aAuthor: CuriousMagpie <eilatan@gmail.com> Date: Tue Nov 14 14:31:25 2023 -0500 feat(challenges): more slur blocker commit50e824e4e3Author: CuriousMagpie <eilatan@gmail.com> Date: Mon Nov 13 15:12:14 2023 -0500 feat(challenges): slur blocker commit315ea24ef4Author: CuriousMagpie <eilatan@gmail.com> Date: Fri Nov 3 12:31:12 2023 -0400 feat(challenges): slur blocker work commit0f742d219fAuthor: CuriousMagpie <eilatan@gmail.com> Date: Thu Nov 2 16:22:31 2023 -0400 feat(challenges): add banned words & slur blocker to challenges commit40d6b60ee3Author: CuriousMagpie <eilatan@gmail.com> Date: Mon Oct 23 13:00:46 2023 -0400 update packages on local/origin repo
This commit is contained in:
@@ -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({
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
|
||||
@@ -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 = !!(
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user