mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 12:49:00 +00:00
54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
|
|
import { z } from "zod";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The single password rule for every surface that sets a password. It mirrors the
|
||
|
|
* server's Identity options: the character classes are ASCII, matching how the
|
||
|
|
* server classifies uppercase letters, digits and non-alphanumeric characters.
|
||
|
|
*/
|
||
|
|
export const PASSWORD_MIN_LENGTH = 6;
|
||
|
|
|
||
|
|
export type PasswordRuleId = "length" | "uppercase" | "number" | "special";
|
||
|
|
|
||
|
|
export type PasswordRule = {
|
||
|
|
id: PasswordRuleId;
|
||
|
|
label: string;
|
||
|
|
test: (password: string) => boolean;
|
||
|
|
};
|
||
|
|
|
||
|
|
export type PasswordRuleResult = {
|
||
|
|
id: PasswordRuleId;
|
||
|
|
label: string;
|
||
|
|
met: boolean;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const PASSWORD_RULES: readonly PasswordRule[] = [
|
||
|
|
{
|
||
|
|
id: "length",
|
||
|
|
label: `At least ${PASSWORD_MIN_LENGTH} characters`,
|
||
|
|
test: (password) => password.length >= PASSWORD_MIN_LENGTH,
|
||
|
|
},
|
||
|
|
{ id: "uppercase", label: "One uppercase letter", test: (password) => /[A-Z]/.test(password) },
|
||
|
|
{ id: "number", label: "One number", test: (password) => /[0-9]/.test(password) },
|
||
|
|
{
|
||
|
|
id: "special",
|
||
|
|
label: "One special character",
|
||
|
|
test: (password) => /[^A-Za-z0-9]/.test(password),
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
export const PASSWORD_REQUIREMENTS_MESSAGE = "Password must meet every requirement below";
|
||
|
|
|
||
|
|
export const PASSWORDS_DO_NOT_MATCH_MESSAGE = "Passwords don't match";
|
||
|
|
|
||
|
|
export function evaluatePasswordRules(password: string): PasswordRuleResult[] {
|
||
|
|
return PASSWORD_RULES.map(({ id, label, test }) => ({ id, label, met: test(password) }));
|
||
|
|
}
|
||
|
|
|
||
|
|
export function meetsPasswordPolicy(password: string): boolean {
|
||
|
|
return PASSWORD_RULES.every((rule) => rule.test(password));
|
||
|
|
}
|
||
|
|
|
||
|
|
export const passwordSchema = z.string().refine(meetsPasswordPolicy, {
|
||
|
|
message: PASSWORD_REQUIREMENTS_MESSAGE,
|
||
|
|
});
|