Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to 'protect' a property and exclude it from select statements

Tags:

typeorm

I'd like to protect certain properties on the data-layer level. For example I'd like to protect the password hash I store in the database for a user, so that it doesn't show up in arbitrary select-statements.

This way only when it's explicitly requested in a select property, property2 statement.

like image 459
Highmastdon Avatar asked May 01 '17 21:05

Highmastdon


2 Answers

I think a more accurate answer would be to set select: false on column options:

@Column({ select: false })
password: string;

And explicitly select the column like this:

const user = await getRepository(User)
    .createQueryBuilder()
    .addSelect('password')
    .getOne()
like image 122
nomadoda Avatar answered Nov 09 '22 05:11

nomadoda


TypeORM goes well with routing-controllers so you should use it, behind the scenes it uses class-transformer to serialize and deserialize your data. So you can use the @Exclude decorator from that library to prevent certain properties being sent down to the clients.

It also uses the class-validator library to validate the data when specifying it as the type in the controller functions. These are powerful toys. Here is a small example of how you can leverage both:

import { Entity, Column, PrimaryGeneratedColumn, Index, OneToMany } from "typeorm";
import { Exclude, Expose } from "class-transformer";
import { IsNotEmpty, IsEmail, MinLength, MaxLength, Min, Max, IsNumber, IsString } from "class-validator";

@Entity()
export class User extends BaseEntity {

  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  @IsNotEmpty()
  @IsEmail()
  @Index({ unique: true })
  email: string;

  @Exclude()
  @Column()
  passwordHash: string;

  @Column()
  @IsNotEmpty()
  @IsString()
  firstName: string;

  @Column()
  @IsNotEmpty()
  @IsString()
  lastName: string;

  @Column({ type: 'integer', default: Gender.NotSpecified })
  @IsNumber()
  @Min(1)
  @Max(3)
  gender: Gender;


  @Expose()
  get admin() {
    return this.role == Role.Admin;
  }

  @Expose()
  get stylist() {
    return this.role == Role.Stylist;
  }
}

If you use an another server-side library you can still take advantage of class-transformer and class-validator. You just need to call the validate function manually in your routes, for example for restify you can write:

import {validate } from "class-validator";
import {plainToClass} from "class-transformer";
// ... more code

server.post('/hello', function create(req, res, next) {
   let bodyJSON = parseBodyTheWayYouWant(req.body);
   let post = plainToClass(bodyJSON);
   validate(post)
   return next();
});
like image 9
NoNameProvided Avatar answered Nov 09 '22 03:11

NoNameProvided