UNPKG

nuxt-supabase-team-auth

Version:

Drop-in Nuxt 3 module for team-based authentication with Supabase

84 lines (83 loc) 3.6 kB
import { DEFAULT_PASSWORD_POLICY } from "../types/password-policy.js"; export function validatePassword(password, policy = {}) { const errors = []; const mergedPolicy = { ...DEFAULT_PASSWORD_POLICY, ...policy }; if (password.length < mergedPolicy.minLength) { errors.push(`Password must be at least ${mergedPolicy.minLength} characters`); } if (mergedPolicy.requireUppercase && !/[A-Z]/.test(password)) { errors.push("Password must contain at least one uppercase letter"); } if (mergedPolicy.requireLowercase && !/[a-z]/.test(password)) { errors.push("Password must contain at least one lowercase letter"); } if (mergedPolicy.requireNumbers && !/\d/.test(password)) { errors.push("Password must contain at least one number"); } if (mergedPolicy.requireSpecialChars) { const escapedChars = mergedPolicy.specialChars.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-"); const specialCharsRegex = new RegExp(`[${escapedChars}]`); if (!specialCharsRegex.test(password)) { errors.push("Password must contain at least one special character"); } } if (policy.customValidator) { const customResult = policy.customValidator(password); if (customResult !== true) { errors.push(typeof customResult === "string" ? customResult : "Password does not meet custom requirements"); } } return { isValid: errors.length === 0, errors }; } export function generatePasswordHelpText(policy = {}) { if (policy.helpText) { return policy.helpText; } const mergedPolicy = { ...DEFAULT_PASSWORD_POLICY, ...policy }; const requirements = []; requirements.push(`at least ${mergedPolicy.minLength} characters`); const charRequirements = []; if (mergedPolicy.requireUppercase) charRequirements.push("uppercase"); if (mergedPolicy.requireLowercase) charRequirements.push("lowercase"); if (mergedPolicy.requireNumbers) charRequirements.push("numbers"); if (mergedPolicy.requireSpecialChars) charRequirements.push("special characters"); if (charRequirements.length > 0) { requirements.push(charRequirements.join(", ")); } return `Must be ${requirements.join(" with ")}`; } export async function createPasswordSchema(policy = {}) { const v = await import("valibot"); const mergedPolicy = { ...DEFAULT_PASSWORD_POLICY, ...policy }; const pipes = [ v.string(), v.minLength(mergedPolicy.minLength, `Password must be at least ${mergedPolicy.minLength} characters`) ]; if (mergedPolicy.requireUppercase) { pipes.push(v.regex(/[A-Z]/, "Password must contain at least one uppercase letter")); } if (mergedPolicy.requireLowercase) { pipes.push(v.regex(/[a-z]/, "Password must contain at least one lowercase letter")); } if (mergedPolicy.requireNumbers) { pipes.push(v.regex(/\d/, "Password must contain at least one number")); } if (mergedPolicy.requireSpecialChars) { const escapedChars = mergedPolicy.specialChars.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-"); const specialCharsRegex = new RegExp(`[${escapedChars}]`); pipes.push(v.regex(specialCharsRegex, "Password must contain at least one special character")); } if (policy.customValidator) { pipes.push(v.custom((value) => { const result = policy.customValidator(value); return result === true; }, (value) => { const result = policy.customValidator(value); return typeof result === "string" ? result : "Password does not meet custom requirements"; })); } return v.pipe(...pipes); }