Oteto Blogのロゴ

【TypeORM】select: falseで非セキュアなカラムを除外する

@Entity("users")
export class User {
  @PrimaryGeneratedColumn('uuid')
  readonly id?: string;

  @Column({ type: 'varchar', unique: true })
  email: string;

  @Column({ type: 'varchar', name: 'hashed_password' })
  hashedPassword: string;
}

上記のようなEntityの場合、emailpasswordといった非セキュアなカラムをAPIのレスポンスに含めず秘匿にしたい場合がある。(別テーブルに切り出すという選択肢はここでは考慮しない)

await this.usersRepository.findOne({ where: { id: userId }, select: ['id'] });
// => { id: "xxx" }

TypeORMでは上記のようにselectオプションにそれ以外のカラムを指定することでそれが実現できる。

しかしfindする度に毎回それを指定するのは手間かつ冗長だし、何よりうっかり忘れることもあるので危険性がある。

解決法

@Entity("users")
export class User {
  @PrimaryGeneratedColumn('uuid')
  readonly id?: string;

  @Column({ type: 'varchar', unique: true })
  @Column({ type: 'varchar', unique: true, select: false })
  email: string;

  @Column({ type: 'varchar', name: 'hashed_password' })
  @Column({ type: 'varchar', name: 'hashed_password', select: false })
  hashedPassword: string;
}

特定のカラムにselect: falseを指定する。

await this.usersRepository.findOne({ where: { id: userId } });
// => { id: "xxx" }

こうすることでfindする度に毎回特定のカラムを除外する必要が無くなる。

await this.usersRepository.findOne({ where: { id: userId }, select: ['id', 'email', 'hashedPassword'] });
// => { id: "xxx", email: "xxx", hashedPassword: "xxx" }

逆にselect: falseとしたカラムを取得したい場合はselectオプションで明示的に含めればよい。