Stop using empty/whitespace as chat display names (#4553)
* fix(chat): fixes #4522 to stop people from setting invalid display names * fix(chat): also guard against non-ascii whitespace like non breaking space * Update web/utils/displayNameValidation.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: handle additional whitespace * Update web/utils/displayNameValidation.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Javascript formatting autofixes * fix: deduplicate running of validation * fix: fix error with useMemo * Update web/utils/displayNameValidation.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update web/utils/displayNameValidation.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Javascript formatting autofixes * fix: fix component rendering issue --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
co-authored by
Copilot
Owncast
parent
74bbe9666f
commit
8eb8bdc18b
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Validates a display name for chat usage.
|
||||
* @param name The proposed display name
|
||||
* @param currentName The user's current display name (to check if it's different)
|
||||
* @param characterLimit Maximum allowed character count
|
||||
* @returns Object with validation result and error message if invalid
|
||||
*/
|
||||
export interface DisplayNameValidationResult {
|
||||
isValid: boolean;
|
||||
errorMessage?: string;
|
||||
trimmedName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims Unicode whitespace characters, similar to Go's strings.TrimSpace()
|
||||
* This includes ASCII whitespace plus Unicode space characters and invisible characters
|
||||
*/
|
||||
// Unicode whitespace character class used for trimming (matches Go's strings.TrimSpace)
|
||||
const UNICODE_WHITESPACE_CLASS =
|
||||
'[\\s\\u00A0\\u1680\\u180E\\u2000-\\u200A\\u200B-\\u200D\\u2028\\u2029\\u202F\\u205F\\u3000\\uFEFF]';
|
||||
|
||||
export function trimUnicodeWhitespace(str: string): string {
|
||||
// Unicode whitespace regex that matches what Go's strings.TrimSpace() removes
|
||||
// This pattern matches all relevant Unicode whitespace at start/end of string
|
||||
const unicodeWhitespacePattern = new RegExp(
|
||||
`^${UNICODE_WHITESPACE_CLASS}+|${UNICODE_WHITESPACE_CLASS}+$`,
|
||||
'g',
|
||||
);
|
||||
return str.replace(unicodeWhitespacePattern, '');
|
||||
}
|
||||
|
||||
export function validateDisplayName(
|
||||
name: string | undefined,
|
||||
currentName: string,
|
||||
characterLimit: number = 30,
|
||||
): DisplayNameValidationResult {
|
||||
// Check if name is provided
|
||||
if (name === undefined) {
|
||||
return {
|
||||
isValid: false,
|
||||
errorMessage: 'Display name is required',
|
||||
};
|
||||
}
|
||||
|
||||
// Trim Unicode whitespace (similar to Go's strings.TrimSpace)
|
||||
const trimmedName = trimUnicodeWhitespace(name);
|
||||
|
||||
// Check if trimmed name is empty (was only whitespace or originally empty)
|
||||
if (trimmedName.length === 0) {
|
||||
return {
|
||||
isValid: false,
|
||||
errorMessage: 'Display name cannot be empty or contain only whitespace',
|
||||
};
|
||||
}
|
||||
|
||||
// Check if name is different from current
|
||||
if (trimmedName === currentName) {
|
||||
return {
|
||||
isValid: false,
|
||||
errorMessage: 'New name must be different from current name',
|
||||
};
|
||||
}
|
||||
|
||||
// Check character limit (using Unicode-aware length)
|
||||
const characterCount = Array.from(trimmedName).length;
|
||||
if (characterCount > characterLimit) {
|
||||
return {
|
||||
isValid: false,
|
||||
errorMessage: `Display name cannot exceed ${characterLimit} characters`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
trimmedName,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user