diff --git a/backend/__tests__/dal/user.spec.ts b/backend/__tests__/dal/user.spec.ts index 779e69618..33697319d 100644 --- a/backend/__tests__/dal/user.spec.ts +++ b/backend/__tests__/dal/user.spec.ts @@ -207,7 +207,6 @@ describe("UserDal", () => { "", // empty " ".repeat(16), // too long ".testName", // cant begin with period - "miodec", // profanity "asdasdAS$", // invalid characters ]; diff --git a/backend/__tests__/utils/validation.spec.ts b/backend/__tests__/utils/validation.spec.ts index 7821dac1b..1f5106c44 100644 --- a/backend/__tests__/utils/validation.spec.ts +++ b/backend/__tests__/utils/validation.spec.ts @@ -88,14 +88,6 @@ describe("Validation", () => { it("isUsernameValid", () => { const testCases = [ - { - name: "Miodec", - expected: false, - }, - { - name: "fucker", - expected: false, - }, { name: "Bruce", expected: true, @@ -124,10 +116,6 @@ describe("Validation", () => { name: ".period", expected: false, }, - { - name: "fucking_profane", - expected: false, - }, ]; testCases.forEach((testCase) => { @@ -141,6 +129,14 @@ describe("Validation", () => { text: "https://www.fuckyou.com", expected: true, }, + { + text: "fucking_profane", + expected: true, + }, + { + text: "fucker", + expected: true, + }, { text: "Hello world!", expected: false, @@ -160,7 +156,7 @@ describe("Validation", () => { ]; testCases.forEach((testCase) => { - expect(Validation.containsProfanity(testCase.text)).toBe( + expect(Validation.containsProfanity(testCase.text, "substring")).toBe( testCase.expected ); }); diff --git a/backend/src/api/routes/users.ts b/backend/src/api/routes/users.ts index 4f813b5df..5faaacf72 100644 --- a/backend/src/api/routes/users.ts +++ b/backend/src/api/routes/users.ts @@ -69,7 +69,7 @@ const usernameValidation = joi .string() .required() .custom((value, helpers) => { - if (containsProfanity(value)) { + if (containsProfanity(value, "substring")) { return helpers.error("string.profanity"); } @@ -531,14 +531,15 @@ const profileDetailsBase = joi .string() .allow("") .custom((value, helpers) => { - if (containsProfanity(value)) { + if (containsProfanity(value, "word")) { return helpers.error("string.profanity"); } return value; }) .messages({ - "string.profanity": "Profanity detected. Please remove it.", + "string.profanity": + "Profanity detected. Please remove it. (if you believe this is a mistake, please contact us)", }); router.patch( diff --git a/backend/src/dal/user.ts b/backend/src/dal/user.ts index 688044fa8..d70d96453 100644 --- a/backend/src/dal/user.ts +++ b/backend/src/dal/user.ts @@ -1,5 +1,5 @@ import _ from "lodash"; -import { isUsernameValid } from "../utils/validation"; +import { containsProfanity, isUsernameValid } from "../utils/validation"; import { canFunboxGetPb, checkAndUpdatePb } from "../utils/pb"; import * as db from "../init/db"; import MonkeyError from "../utils/error"; @@ -113,6 +113,9 @@ export async function updateName( if (!isUsernameValid(name)) { throw new MonkeyError(400, "Invalid username"); } + if (containsProfanity(name, "substring")) { + throw new MonkeyError(400, "Username contains profanity"); + } if ( name?.toLowerCase() !== previousName?.toLowerCase() && diff --git a/backend/src/utils/validation.ts b/backend/src/utils/validation.ts index 6120130a0..26ee57e2a 100644 --- a/backend/src/utils/validation.ts +++ b/backend/src/utils/validation.ts @@ -1,7 +1,7 @@ import _ from "lodash"; import { replaceHomoglyphs } from "../constants/homoglyphs"; -import { profanities, regexProfanities } from "../constants/profanities"; -import { intersect, matchesAPattern, sanitizeString } from "./misc"; +import { profanities } from "../constants/profanities"; +import { intersect, sanitizeString } from "./misc"; import { default as FunboxList } from "../constants/funbox-list"; export function inRange(value: number, min: number, max: number): boolean { @@ -22,17 +22,13 @@ export function isUsernameValid(name: string): boolean { return false; } - const isProfanity = profanities.some((profanity) => - normalizedName.includes(profanity) - ); - if (isProfanity) { - return false; - } - return VALID_NAME_PATTERN.test(name); } -export function containsProfanity(text: string): boolean { +export function containsProfanity( + text: string, + mode: "word" | "substring" +): boolean { const normalizedText = text .toLowerCase() .split(/[.,"/#!?$%^&*;:{}=\-_`~()\s\n]+/g) @@ -40,9 +36,11 @@ export function containsProfanity(text: string): boolean { return replaceHomoglyphs(sanitizeString(str) ?? ""); }); - const hasProfanity = regexProfanities.some((profanity) => { + const hasProfanity = profanities.some((profanity) => { return normalizedText.some((word) => { - return matchesAPattern(word, profanity); + return mode === "word" + ? word.startsWith(profanity) + : word.includes(profanity); }); });