diff --git a/frontend/src/ts/auth.tsx b/frontend/src/ts/auth.tsx index 5647b94bec9a..b75d6e8cf2c0 100644 --- a/frontend/src/ts/auth.tsx +++ b/frontend/src/ts/auth.tsx @@ -1,4 +1,4 @@ -import { PasswordSchema } from "@monkeytype/schemas/users"; +import { NewPasswordSchema, PasswordSchema } from "@monkeytype/schemas/users"; import { tryCatch } from "@monkeytype/util/trycatch"; import { FirebaseError } from "firebase/app"; import { @@ -578,8 +578,19 @@ export function isUsingAuthenticationReactive(authMethod: AuthMethod): boolean { return authenticationMemos[authMethod]?.()?.isInUse ?? false; } -export function getPasswordSchema(): ZodString { - return isDevEnvironment() ? z.string().min(6) : PasswordSchema; +/** + * Returns the Zod schema for password validation. + * + * Set `isNew: true` for registration/creation flows (strict rules). + * Omit it for re-authentication flows (lenient: just non-empty). + * + * @param options - Set `isNew: true` for password creation/registration. + * @returns A Zod string schema. + */ +export function getPasswordSchema(options?: { isNew: boolean }): ZodString { + if (!options?.isNew) return PasswordSchema; + if (isDevEnvironment()) return z.string().min(6); + return NewPasswordSchema; } export function isUsingPasswordAuthentication(): boolean { diff --git a/frontend/src/ts/components/modals/account-settings/AddPasswordAuthModal.tsx b/frontend/src/ts/components/modals/account-settings/AddPasswordAuthModal.tsx index f30813912285..b790f37a9bfa 100644 --- a/frontend/src/ts/components/modals/account-settings/AddPasswordAuthModal.tsx +++ b/frontend/src/ts/components/modals/account-settings/AddPasswordAuthModal.tsx @@ -11,8 +11,8 @@ export function showAddPasswordAuthModal(): void { schema: z.object({ email: UserEmailSchema, emailConfirm: UserEmailSchema, - password: getPasswordSchema(), - passConfirm: getPasswordSchema(), + password: getPasswordSchema({ isNew: true }), + passConfirm: getPasswordSchema({ isNew: true }), }), inputs: { email: { diff --git a/frontend/src/ts/components/modals/account-settings/UpdatePasswordModal.tsx b/frontend/src/ts/components/modals/account-settings/UpdatePasswordModal.tsx index 4344575551ac..371fe34bb3b8 100644 --- a/frontend/src/ts/components/modals/account-settings/UpdatePasswordModal.tsx +++ b/frontend/src/ts/components/modals/account-settings/UpdatePasswordModal.tsx @@ -20,9 +20,9 @@ export function showUpdatePasswordModal(): void { showSimpleModal({ title: "Update password", schema: z.object({ - previousPass: z.string().min(1, "Current password is required"), - newPassword: getPasswordSchema(), - newPassConfirm: getPasswordSchema(), + previousPass: getPasswordSchema(), + newPassword: getPasswordSchema({ isNew: true }), + newPassConfirm: getPasswordSchema({ isNew: true }), }), inputs: { previousPass: { diff --git a/frontend/src/ts/components/pages/login/Register.tsx b/frontend/src/ts/components/pages/login/Register.tsx index 617a57d06bdc..e643300a85a2 100644 --- a/frontend/src/ts/components/pages/login/Register.tsx +++ b/frontend/src/ts/components/pages/login/Register.tsx @@ -213,7 +213,7 @@ export function Register(): JSXElement { ( ; -export const PasswordSchema = z +// stricter schema used while password creation +export const NewPasswordSchema = z .string() .min(8, { message: "must be at least 8 characters" }) .max(64, { message: "must be at most 64 characters" }) @@ -374,6 +375,10 @@ export const PasswordSchema = z .regex(/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/, { message: "must contain at least one special character", }); +export type NewPassword = z.infer; + +// lenient schema for existing passwords +export const PasswordSchema = z.string().min(1, "Required"); export type Password = z.infer; export const FriendSchema = UserSchema.pick({