- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import bcrypt from 'bcrypt';
|
|
import crypto from 'crypto';
|
|
|
|
const SALT_ROUNDS = 12;
|
|
|
|
export async function hashPassword(password: string): Promise<string> {
|
|
if (password.length < 8) {
|
|
throw new Error('Пароль должен содержать минимум 8 символов');
|
|
}
|
|
|
|
const hasUpperCase = /[A-Z]/.test(password);
|
|
const hasLowerCase = /[a-z]/.test(password);
|
|
const hasNumbers = /\d/.test(password);
|
|
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password);
|
|
|
|
if (!hasUpperCase || !hasLowerCase || !hasNumbers || !hasSpecialChar) {
|
|
throw new Error('Пароль должен содержать заглавные и строчные буквы, цифры и специальные символы');
|
|
}
|
|
|
|
return await bcrypt.hash(password, SALT_ROUNDS);
|
|
}
|
|
|
|
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
|
|
return await bcrypt.compare(password, hash);
|
|
}
|
|
|
|
export function generateTempPassword(): string {
|
|
const lower = 'abcdefghijklmnopqrstuvwxyz';
|
|
const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
const digits = '0123456789';
|
|
const special = '!@#$%^&*';
|
|
const charset = lower + upper + digits + special;
|
|
|
|
const pick = (set: string) => set[crypto.randomInt(set.length)];
|
|
|
|
const chars: string[] = [
|
|
pick(lower),
|
|
pick(upper),
|
|
pick(digits),
|
|
pick(special),
|
|
...Array.from({ length: 8 }, () => pick(charset)),
|
|
];
|
|
|
|
// Shuffle using Fisher-Yates with crypto.randomInt
|
|
for (let i = chars.length - 1; i > 0; i--) {
|
|
const j = crypto.randomInt(i + 1);
|
|
[chars[i], chars[j]] = [chars[j], chars[i]];
|
|
}
|
|
|
|
return chars.join('');
|
|
}
|