Functional Weave
Code in Rust

auth.validate-password-change@1.0.0

impl/typescript.ts

1,566 bytes · the TypeScript implementation · view raw

import { checkPassword } from "./auth_password_policy_check_password.ts";
import { type PasswordPolicy } from "./auth_password_policy_types.ts";
import { type PasswordChangeCheck } from "./auth_validate_password_change_types.ts";

/**
 * A change-password form checked in one call: the current password must be
 * given and correct, the new one must meet the policy and differ from it.
 */
export function validatePasswordChange(
  currentPassword: string,
  newPassword: string,
  currentPasswordMatches: boolean,
  email: string,
  name: string,
  policy: PasswordPolicy,
): PasswordChangeCheck {
  // A non-string (a malformed JSON body) is an empty field, not an exception.
  const current = typeof currentPassword === "string" ? currentPassword : "";
  const next = typeof newPassword === "string" ? newPassword : "";
  const fields: Record<string, string> = {};

  if (current === "") fields.currentPassword = "Enter your current password.";
  else if (currentPasswordMatches !== true) fields.currentPassword = "That is not your current password.";

  // Checked even when empty, so a nonsensical policy always throws.
  const check = checkPassword(next, email, name, policy);
  if (next === "") {
    fields.newPassword = "Enter a new password.";
  } else {
    const messages = check.failures.map((f) => f.message);
    if (next === current) messages.push("Choose a password that is different from your current one.");
    if (messages.length > 0) fields.newPassword = messages.join(" ");
  }

  return { valid: Object.keys(fields).length === 0, fields };
}