feat(auth): make password length configurable via env (min 5–30, max 30–128)
CI / check (push) Successful in 29s
CI / tests-imaging-browsers (push) Successful in 1m46s
CI / tests-integration (push) Successful in 1m47s
CI / tests-unit (push) Successful in 1m49s
CI / tests-quality (push) Successful in 44s
CI / tests-ui (push) Successful in 4m38s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m38s
CI / check (push) Successful in 29s
CI / tests-imaging-browsers (push) Successful in 1m46s
CI / tests-integration (push) Successful in 1m47s
CI / tests-unit (push) Successful in 1m49s
CI / tests-quality (push) Successful in 44s
CI / tests-ui (push) Successful in 4m38s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m38s
Add PASSWORD_MIN_LENGTH / PASSWORD_MAX_LENGTH (validated in src/env.ts) and a
shared passwordPolicy helper. The policy drives the zod schemas in register,
password reset and the admin create-user dialog, plus the live requirement
checks and strength meter in the register form.
Locale messages now interpolate the configured minimum via {min} instead of
hard-coding 12.
This commit is contained in:
1 parent
aef0939ee9
commit
9cf1eb615c
36 files changed
+227
-143
No files matched your search
@@ -6,6 +6,7 @@ import { redirect } from "next/navigation";
|
||||
import { env } from "@/env";
|
||||
import { invalidateLoginCache } from "@/lib/auth/login-core";
|
||||
import { hashPassword } from "@/lib/auth/password";
|
||||
import { passwordPolicy } from "@/lib/auth/password-policy";
|
||||
import { revokeUserCredentials } from "@/lib/auth/session-revocation";
|
||||
import { db, PasswordReset, User } from "@/lib/db";
|
||||
import { logger } from "@/lib/logger";
|
||||
@@ -109,7 +110,11 @@ export async function resetPassword(formData: FormData): Promise<void> {
|
||||
}
|
||||
|
||||
let error: "password" | "invalid" | "failed" | null = null;
|
||||
if (password.length < 12) error = "password";
|
||||
if (
|
||||
password.length < passwordPolicy.minLength ||
|
||||
password.length > passwordPolicy.maxLength
|
||||
)
|
||||
error = "password";
|
||||
|
||||
if (!error) {
|
||||
try {
|
||||
|
||||
+10
-4
@@ -5,6 +5,7 @@ import { after } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { sendVerification } from "@/lib/auth/email-verification";
|
||||
import { hashPassword } from "@/lib/auth/password";
|
||||
import { passwordPolicy } from "@/lib/auth/password-policy";
|
||||
import { DEFAULT_AVATAR_FIGURE } from "@/lib/avatar-figure";
|
||||
import { invalidateKey } from "@/lib/cached-db";
|
||||
import { db, User } from "@/lib/db";
|
||||
@@ -83,6 +84,11 @@ function hasDisposableEmailDomain(email: string): boolean {
|
||||
return domain ? DISPOSABLE_EMAIL_DOMAINS.has(domain) : false;
|
||||
}
|
||||
|
||||
// Rendered into the schema below and mapped back to a locale-independent code
|
||||
// via `ZOD_MESSAGE_CODES`, so the length always reflects the configured policy.
|
||||
const PASSWORD_MIN_MESSAGE = `Password must be at least ${passwordPolicy.minLength} characters`;
|
||||
const PASSWORD_MAX_MESSAGE = "Password is too long";
|
||||
|
||||
const registerSchema = z
|
||||
.object({
|
||||
username: z
|
||||
@@ -105,8 +111,8 @@ const registerSchema = z
|
||||
),
|
||||
password: z
|
||||
.string()
|
||||
.min(12, "Password must be at least 12 characters") // Increased min length
|
||||
.max(128, "Password is too long") // Added max length
|
||||
.min(passwordPolicy.minLength, PASSWORD_MIN_MESSAGE)
|
||||
.max(passwordPolicy.maxLength, PASSWORD_MAX_MESSAGE)
|
||||
.regex(/[A-Z]/, "Password must contain at least one uppercase letter")
|
||||
.regex(/[a-z]/, "Password must contain at least one lowercase letter")
|
||||
.regex(/[0-9]/, "Password must contain at least one digit")
|
||||
@@ -160,8 +166,8 @@ const ZOD_MESSAGE_CODES: Record<string, RegisterErrorCode> = {
|
||||
"This username is reserved": "usernameReserved",
|
||||
"Enter a valid email address": "emailValid",
|
||||
"Temporary email domains are not allowed": "emailDisposable",
|
||||
"Password must be at least 12 characters": "passwordMinLength",
|
||||
"Password is too long": "passwordMaxLength",
|
||||
[PASSWORD_MIN_MESSAGE]: "passwordMinLength",
|
||||
[PASSWORD_MAX_MESSAGE]: "passwordMaxLength",
|
||||
"Password must contain at least one uppercase letter": "passwordUpper",
|
||||
"Password must contain at least one lowercase letter": "passwordLower",
|
||||
"Password must contain at least one digit": "passwordDigit",
|
||||
|
||||
Reference in new issue
Block a user