From 864dc290110d8ee00c2e559479b0eb6a7357ede3 Mon Sep 17 00:00:00 2001 From: Dinesh Yadav Date: Fri, 16 Oct 2026 17:22:46 +0530 Subject: [PATCH] fix(api): anchor username validation regex - Anchor username validation RegExp with ^ and $ in EmbeddedChatApi.ts to prevent usernames with invalid characters from passing validation. - Add unit tests covering alphanumeric, space-to-dot replacement, symbols rejection, and empty username cases. Signed-off-by: Dinesh Yadav --- packages/api/src/EmbeddedChatApi.test.js | 51 ++++++++++++++++++++++++ packages/api/src/EmbeddedChatApi.ts | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 packages/api/src/EmbeddedChatApi.test.js diff --git a/packages/api/src/EmbeddedChatApi.test.js b/packages/api/src/EmbeddedChatApi.test.js new file mode 100644 index 000000000..aa1101749 --- /dev/null +++ b/packages/api/src/EmbeddedChatApi.test.js @@ -0,0 +1,51 @@ +import test, { describe } from "node:test"; +import assert from "node:assert/strict"; + +describe("EmbeddedChatApi updateUserUsername validation", () => { + const usernameRegExp = /^[0-9a-zA-Z-_.]+$/; + + const validateAndFormatUsername = (username) => { + const newUserName = username.replace(/\s/g, ".").toLowerCase(); + const isValid = usernameRegExp.test(newUserName); + return { newUserName, isValid }; + }; + + test("accepts valid alphanumeric username", () => { + const { newUserName, isValid } = validateAndFormatUsername("ValidUser456"); + assert.equal(newUserName, "validuser456"); + assert.equal(isValid, true); + }); + + test("normalizes spaces to dots and validates correctly", () => { + const { newUserName, isValid } = validateAndFormatUsername("John Doe"); + assert.equal(newUserName, "john.doe"); + assert.equal(isValid, true); + }); + + test("accepts allowed characters: hyphens, underscores, dots", () => { + const { newUserName, isValid } = + validateAndFormatUsername("john-doe_test.dev"); + assert.equal(newUserName, "john-doe_test.dev"); + assert.equal(isValid, true); + }); + + test("rejects usernames containing special symbols like @, !, #, $, %, etc.", () => { + assert.equal(validateAndFormatUsername("john@doe.com").isValid, false); + assert.equal(validateAndFormatUsername("user!name").isValid, false); + assert.equal(validateAndFormatUsername("user#tag").isValid, false); + assert.equal(validateAndFormatUsername("user$dollar").isValid, false); + assert.equal(validateAndFormatUsername("user%percent").isValid, false); + assert.equal(validateAndFormatUsername("user*star").isValid, false); + }); + + test('rejects usernames containing parentheses (e.g., "(Admin)")', () => { + const { newUserName, isValid } = + validateAndFormatUsername("John Doe (Admin)"); + assert.equal(newUserName, "john.doe.(admin)"); + assert.equal(isValid, false); + }); + + test("rejects empty usernames", () => { + assert.equal(validateAndFormatUsername("").isValid, false); + }); +}); diff --git a/packages/api/src/EmbeddedChatApi.ts b/packages/api/src/EmbeddedChatApi.ts index 6f2408414..5e897b15c 100644 --- a/packages/api/src/EmbeddedChatApi.ts +++ b/packages/api/src/EmbeddedChatApi.ts @@ -505,7 +505,7 @@ export default class EmbeddedChatApi { async updateUserUsername(userid: string, username: string) { const newUserName = username.replace(/\s/g, ".").toLowerCase(); - const usernameRegExp = /[0-9a-zA-Z-_.]+/; + const usernameRegExp = /^[0-9a-zA-Z-_.]+$/; if (usernameRegExp.test(newUserName)) { try {