Source

lib/client/PasswordClient.ts

import { PasswordState } from "../state/users/PasswordState";
import { PasscodeState } from "../state/users/PasscodeState";
import {
  InvalidPasswordError,
  TechnicalError,
  TooManyRequestsError,
  UnauthorizedError,
} from "../Errors";
import { Client } from "./Client";
import { HttpClientOptions } from "./HttpClient";

/**
 * A class to handle passwords.
 *
 * @constructor
 * @category SDK
 * @subcategory Clients
 * @extends {Client}
 */
class PasswordClient extends Client {
  passwordState: PasswordState;
  passcodeState: PasscodeState;

  // eslint-disable-next-line require-jsdoc
  constructor(api: string, options: HttpClientOptions) {
    super(api, options);
    /**
     *  @public
     *  @type {PasswordState}
     */
    this.passwordState = new PasswordState(options.cookieName);
    /**
     *  @public
     *  @type {PasscodeState}
     */
    this.passcodeState = new PasscodeState(options.cookieName);
  }

  /**
   * Logs in a user with a password.
   *
   * @param {string} userID - The UUID of the user.
   * @param {string} password - The password.
   * @return {Promise<void>}
   * @throws {InvalidPasswordError}
   * @throws {RequestTimeoutError}
   * @throws {TechnicalError}
   * @throws {TooManyRequestsError}
   * @see https://docs.hanko.io/api/public#tag/Password/operation/passwordLogin
   */
  async login(userID: string, password: string): Promise<void> {
    const response = await this.client.post("/password/login", {
      user_id: userID,
      password,
    });

    if (response.status === 401) {
      throw new InvalidPasswordError();
    } else if (response.status === 429) {
      const retryAfter = response.parseNumericHeader("Retry-After");
      this.passwordState.read().setRetryAfter(userID, retryAfter).write();
      throw new TooManyRequestsError(retryAfter);
    } else if (!response.ok) {
      throw new TechnicalError();
    }

    this.client.processResponseHeadersOnLogin(userID, response);
    return;
  }

  /**
   * Updates a password.
   *
   * @param {string} userID - The UUID of the user.
   * @param {string} password - The new password.
   * @return {Promise<void>}
   * @throws {RequestTimeoutError}
   * @throws {UnauthorizedError}
   * @throws {TechnicalError}
   * @see https://docs.hanko.io/api/public#tag/Password/operation/password
   */
  async update(userID: string, password: string): Promise<void> {
    const response = await this.client.put("/password", {
      user_id: userID,
      password,
    });

    if (response.status === 401) {
      this.client.dispatcher.dispatchSessionExpiredEvent();
      throw new UnauthorizedError();
    } else if (!response.ok) {
      throw new TechnicalError();
    }

    return;
  }

  /**
   * Returns the number of seconds the rate limiting is active for.
   *
   * @param {string} userID - The UUID of the user.
   * @return {number}
   */
  getRetryAfter(userID: string) {
    return this.passwordState.read().getRetryAfter(userID);
  }
}

export { PasswordClient };