adminTempPassword.js 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import crypto from "node:crypto";
  2. import { PASSWORD_POLICY, validateNewPassword } from "@/lib/auth/passwordPolicy";
  3. const LETTERS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
  4. const DIGITS = "23456789";
  5. const SPECIALS = "!@#$%&*_-";
  6. const CHARSET = `${LETTERS}${DIGITS}${SPECIALS}`;
  7. const DEFAULT_TEMP_PASSWORD_LENGTH = Math.max(PASSWORD_POLICY.minLength, 12);
  8. const MAX_GENERATION_ATTEMPTS = 20;
  9. function randomChar(chars) {
  10. const i = crypto.randomInt(0, chars.length);
  11. return chars[i];
  12. }
  13. function shuffle(input) {
  14. const chars = String(input).split("");
  15. for (let i = chars.length - 1; i > 0; i -= 1) {
  16. const j = crypto.randomInt(0, i + 1);
  17. [chars[i], chars[j]] = [chars[j], chars[i]];
  18. }
  19. return chars.join("");
  20. }
  21. function normalizeLength(length) {
  22. if (!Number.isInteger(length)) return DEFAULT_TEMP_PASSWORD_LENGTH;
  23. return Math.max(PASSWORD_POLICY.minLength, length);
  24. }
  25. export function generateAdminTemporaryPassword({ length } = {}) {
  26. const targetLength = normalizeLength(length);
  27. for (let attempt = 0; attempt < MAX_GENERATION_ATTEMPTS; attempt += 1) {
  28. const base = [randomChar(LETTERS), randomChar(DIGITS)];
  29. while (base.length < targetLength) {
  30. base.push(randomChar(CHARSET));
  31. }
  32. const candidate = shuffle(base.join(""));
  33. if (validateNewPassword({ newPassword: candidate }).ok) {
  34. return candidate;
  35. }
  36. }
  37. throw new Error("Unable to generate temporary password");
  38. }