Improved UI and compliance with api endpoint restrictions

This commit is contained in:
Sven laptop
2026-07-24 23:51:26 +02:00
parent c891f53197
commit beb8bb287e
17 changed files with 1464 additions and 335 deletions
+62 -23
View File
@@ -61,20 +61,36 @@ function isDisposableEmail(email) {
);
}
export function validateRegistration({ name, username, email, password }) {
const trimmedName = name.trim();
const trimmedUsername = username.trim();
const normalizedEmail = email.trim().toLowerCase();
function hasControlCharacter(value) {
return [...value].some((character) => {
const code = character.charCodeAt(0);
return code <= 0x1f || code === 0x7f;
});
}
function validateName(name) {
const trimmedName = name.trim();
if (hasControlCharacter(name)) {
return "Input contains unsupported control characters.";
}
if (trimmedName.length < 1 || trimmedName.length > 100) {
return "Name must be between 1 and 100 characters.";
}
return null;
}
if (trimmedUsername.length < 1 || trimmedUsername.length > 50 || /\s/.test(trimmedUsername)) {
function validateUsername(username) {
const trimmedUsername = username.trim();
if (hasControlCharacter(username) || trimmedUsername.length < 1 || trimmedUsername.length > 50 || /\s/.test(trimmedUsername)) {
return "Username must be between 1 and 50 characters and cannot contain whitespace.";
}
return null;
}
function validateEmail(email, { checkDisposable = false } = {}) {
const normalizedEmail = email.trim().toLowerCase();
if (
hasControlCharacter(email) ||
normalizedEmail.length < 1 ||
normalizedEmail.length > 254 ||
/\s/.test(normalizedEmail) ||
@@ -82,8 +98,14 @@ export function validateRegistration({ name, username, email, password }) {
) {
return "Enter a valid email address without whitespace.";
}
if (checkDisposable && isDisposableEmail(normalizedEmail)) {
return "Disposable or temporary email addresses are not allowed.";
}
return null;
}
if (password.length < 1 || password.length > 128) {
function validatePassword(password, username, email) {
if (hasControlCharacter(password) || password.length < 1 || password.length > 128) {
return "Password must be between 1 and 128 characters.";
}
@@ -96,9 +118,14 @@ export function validateRegistration({ name, username, email, password }) {
}
const passwordForComparison = password.toLowerCase();
const { localPart } = getEmailParts(normalizedEmail);
const trimmedUsername = username.trim();
const normalizedEmail = email.trim().toLowerCase();
const localPart = EMAIL_PATTERN.test(normalizedEmail) ? getEmailParts(normalizedEmail).localPart : "";
if (passwordForComparison.includes(trimmedUsername.toLowerCase()) || passwordForComparison.includes(localPart.toLowerCase())) {
if (
(trimmedUsername && passwordForComparison.includes(trimmedUsername.toLowerCase())) ||
(localPart && passwordForComparison.includes(localPart.toLowerCase()))
) {
return "Password cannot contain your username or email address.";
}
@@ -110,27 +137,42 @@ export function validateRegistration({ name, username, email, password }) {
return "Password cannot contain repeated or sequential character patterns.";
}
if (isDisposableEmail(normalizedEmail)) {
return "Disposable or temporary email addresses are not allowed.";
}
return null;
}
export function validateLogin({ email, password }) {
const normalizedEmail = email.trim().toLowerCase();
if (normalizedEmail.length < 1 || normalizedEmail.length > 254 || /\s/.test(normalizedEmail) || !EMAIL_PATTERN.test(normalizedEmail)) {
return "Enter a valid email address without whitespace.";
}
export function getRegistrationFieldErrors(form) {
return {
name: validateName(form.name),
username: validateUsername(form.username),
email: validateEmail(form.email, { checkDisposable: true }),
password: validatePassword(form.password, form.username, form.email),
};
}
function validateLoginPassword(password) {
if (password.length < 1 || password.length > 128) {
return "Password must be between 1 and 128 characters.";
}
return null;
}
export function getLoginFieldErrors(form) {
return {
email: validateEmail(form.email),
password: validateLoginPassword(form.password),
};
}
export function validateRegistration(form) {
const errors = getRegistrationFieldErrors(form);
return errors.name || errors.username || errors.email || errors.password || null;
}
export function validateLogin({ email, password }) {
const errors = getLoginFieldErrors({ email, password });
return errors.email || errors.password || null;
}
export function normalizeRegistrationData({ name, username, email, password }) {
return {
name: name.trim(),
@@ -148,8 +190,5 @@ export function normalizeLoginData({ email, password }) {
}
export function isControlCharacterPresent(value) {
return [...value].some((character) => {
const code = character.charCodeAt(0);
return code <= 0x1f || code === 0x7f;
});
return hasControlCharacter(value);
}