File

lib/common/user/abstract-user-subscriber.ts

Description

Abstract class for user entity subscribers to handle specific events.

Index

Properties
  • Protected Abstract Readonly type
Methods

Properties

Protected Abstract Readonly type
Type : Type<T>

Methods

Protected Async hashPassword
hashPassword(password: string)

Hashes a password using bcrypt.

Parameters :
Name Type Optional Description
password string No
  • The password to hash.
Returns : unknown

The hashed password.

Protected Async hashPasswordIfNeeded
hashPasswordIfNeeded(event: InsertEvent | UpdateEvent)

Hashes the user password if it has changed.

Parameters :
Name Type Optional Description
event InsertEvent<T> | UpdateEvent<T> No
  • The insert or update event.
Returns : any
Protected Async validateLogin
validateLogin(login: string)

Validates the login format.

Parameters :
Name Type Optional Description
login string No
  • The login string to validate.
Returns : any
import { BadRequestException } from "@nestjs/common";
import { InsertEvent } from "typeorm/subscriber/event/InsertEvent";
import { UpdateEvent } from "typeorm";
import * as bcrypt from "bcrypt";
import { Type } from "@nestjs/common/interfaces/type.interface";
import { UserEntity } from "./entity/user.entity";

/**
 * Abstract class for user entity subscribers to handle specific events.
 */
export abstract class AbstractUserSubscriber<T extends UserEntity> {
  protected abstract readonly type: Type<T>;

  /**
   * Validates the login format.
   * @param login - The login string to validate.
   * @throws BadRequestException if the login format is invalid.
   */
  protected async validateLogin(login: string) {
    const loginRegex = /^[A-Za-z0-9_]+$/;
    if (!loginRegex.test(login)) {
      throw new BadRequestException(
        "Login must contain only Latin letters, numbers, and underscores.",
      );
    }
  }

  /**
   * Hashes the user password if it has changed.
   * @param event - The insert or update event.
   */
  protected async hashPasswordIfNeeded(event: InsertEvent<T> | UpdateEvent<T>) {
    const { entity: user, manager } = event;
    if (typeof user.password === "number") {
      user.password = user.password.toString();
    }
    if (!user.password?.length) {
      delete user.password;
      return;
    }
    const foundUser: T = await manager.findOne(this.type, {
      where: { id: user.id },
    });
    if (foundUser) {
      if (await bcrypt.compare(user.password, foundUser.password)) {
        user.password = foundUser.password;
      } else {
        user.password = await this.hashPassword(user.password);
      }
    } else {
      user.password = await this.hashPassword(user.password);
    }
  }

  /**
   * Hashes a password using bcrypt.
   * @param password - The password to hash.
   * @returns The hashed password.
   */
  protected async hashPassword(password: string) {
    return await bcrypt.hash(password, 10);
  }
}

results matching ""

    No results matching ""