Files
EMS-ESP32/interface/src/validators/security.ts
2025-10-28 22:19:43 +01:00

67 lines
1.9 KiB
TypeScript

import Schema from 'async-validator';
import type { InternalRuleItem } from 'async-validator';
import type { UserType } from 'types';
const USERNAME_PATTERN = /^[a-zA-Z0-9_\\.]{1,24}$/;
const JWT_SECRET_MAX_LENGTH = 64;
const PASSWORD_MAX_LENGTH = 64;
export const SECURITY_SETTINGS_VALIDATOR = new Schema({
jwt_secret: [
{ required: true, message: 'JWT secret is required' },
{
type: 'string',
min: 1,
max: JWT_SECRET_MAX_LENGTH,
message: `JWT secret must be between 1 and ${JWT_SECRET_MAX_LENGTH} characters`
}
]
});
/**
* Creates a validator to ensure username uniqueness
* @param users - Array of existing users to check against
* @returns Validator rule for unique username
*/
export const createUniqueUsernameValidator = (users: UserType[]) => ({
validator(
_rule: InternalRuleItem,
username: string,
callback: (error?: string) => void
) {
if (username && users.some((u) => u.username === username)) {
callback('Username already in use');
} else {
callback();
}
}
});
/**
* Creates a validator schema for user creation/editing
* @param users - Array of existing users for uniqueness check
* @param creating - Whether this is for creating a new user (enables uniqueness check)
* @returns Schema validator for user data
*/
export const createUserValidator = (users: UserType[], creating: boolean) =>
new Schema({
username: [
{ required: true, message: 'Username is required' },
{
type: 'string',
pattern: USERNAME_PATTERN,
message: "Must be 1-24 characters: alphanumeric, '_' or '.'"
},
...(creating ? [createUniqueUsernameValidator(users)] : [])
],
password: [
{ required: true, message: 'Please provide a password' },
{
type: 'string',
min: 1,
max: PASSWORD_MAX_LENGTH,
message: `Password must be 1-${PASSWORD_MAX_LENGTH} characters`
}
]
});