Skip to main content

Custom decorator

info
  • Ở đợt trước, ta đã sử dụng Reflector.createDecorator()SetMetadata() tạo một decorator để đính kèm metatdata. Xem chi tiết tại đây
  • Ở bài này, ta sẽ tìm hiểu cách tạo 1 decorator. Khác với đợt trước, decorator lần này có thể truy cập vào các thuộc tính của request thông qua ExecutionContext

Tạo decorator

Ví dụ 1

  • Ở ví dụ dưới đây, ta sẽ tạo decorator @User để truy cập thông tin user ở trong request:
user.decorator.ts
import { createParamDecorator, ExecutionContext } from "@nestjs/common";

export const User = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
}
);
info
  • Ở bên trên, phương thức createParamDecorator() nhận vào 2 tham số là: data (tham số truyền vào khi gọi decorator), tham số thứ hai là ExecutionContext để có thể truy cập vào request object.
  • Và giờ ta có thể lấy user thông qua decorator @User như sau:
@Get()
async findOne(@User() user: UserEntity) {
console.log(user);
}

Ví dụ 2

  • Ở dưới đây, ta tạo decorator nhận vào 1 tham số là key của object cần lấy ra, nếu không truyền key vào, trả về toàn bộ object:
user.decorator.ts
import { createParamDecorator, ExecutionContext } from "@nestjs/common";

export const User = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;

return data ? user?.[data] : user;
}
);
@Get()
async findOne(@User('firstName') firstName: string) {
console.log(`Hello ${firstName}`);
}

Combine decorator

  • Ta có thể tạo một decorator trong đó gộp nhiều decorator khác lại với nhau thông qua applyDecorators() như sau:
auth.decorator.ts
import { applyDecorators } from "@nestjs/common";

export function Auth(...roles: Role[]) {
return applyDecorators(
SetMetadata("roles", roles),
UseGuards(AuthGuard, RolesGuard),
ApiBearerAuth(),
ApiUnauthorizedResponse({ description: "Unauthorized" })
);
}