generator-policy.ts

2.2 KB · raw

1import type { PasswordPolicy } from "../shared/types";23export interface GeneratorState {4  currentLength: number;5  userHasAdjusted: boolean;6}78export interface PolicyResult {9  length: number;10  sliderMin: number;11  sliderMax: number;12  constraintNote: string;13}1415const DEFAULT_LENGTH = 64;16const DEFAULT_SLIDER_MIN = 8;17const DEFAULT_SLIDER_MAX = 256;1819export function initGeneratorState(): GeneratorState {20  return { currentLength: DEFAULT_LENGTH, userHasAdjusted: false };21}2223export function handleLengthChange(state: GeneratorState, length: number): GeneratorState {24  return { ...state, currentLength: length, userHasAdjusted: true };25}2627export function initFromPolicy(28  policy: PasswordPolicy | null,29  state: { currentLength: number; userHasAdjusted: boolean },30): PolicyResult {31  const sliderMin = policy?.minLength ? Math.max(1, policy.minLength) : DEFAULT_SLIDER_MIN;32  const sliderMax = policy?.maxLength ? Math.min(DEFAULT_SLIDER_MAX, policy.maxLength) : DEFAULT_SLIDER_MAX;3334  let length = state.currentLength;3536  if (policy) {37    if (policy.maxLength !== undefined && policy.minLength !== undefined) {38      // Both bounds: always clamp to valid range, regardless of userHasAdjusted39      length = Math.max(policy.minLength, Math.min(policy.maxLength, state.currentLength));40    } else if (policy.maxLength !== undefined) {41      if (!state.userHasAdjusted) {42        // Fresh open: offer the strongest password the site accepts43        length = policy.maxLength;44      } else if (state.currentLength > policy.maxLength) {45        // User above max: snap down46        length = policy.maxLength;47      }48    } else if (policy.minLength !== undefined && state.currentLength < policy.minLength) {49      // Below min: snap up50      length = policy.minLength;51    }52  }5354  let constraintNote = "";55  if (policy) {56    if (policy.maxLength !== undefined && length >= policy.maxLength) {57      constraintNote = `This site allows max ${policy.maxLength} characters`;58    } else if (policy.minLength !== undefined && length <= policy.minLength) {59      constraintNote = `This site requires at least ${policy.minLength} characters`;60    }61  }6263  return { length, sliderMin, sliderMax, constraintNote };64}