Howto get req.user in services in Nest JS

十年热恋 提交于 2020-05-26 12:16:13

问题


In a controller, I add the user object with a guard, inject some service and call that service to get some response. I have removed a lot of code for brevity.

@Controller()
@UseGuards(AuthGuard())
export class UserController() {
   constructor(private readonly userService: UsersService) {
   }

   @Get(':id')
   async findOne(@Param('id') id) {
      return await this.userService.findOne(id);
   }
}

Since I have the AuthGuard, I now know the user is logged in before entering :id route.

In the service I would do something like

@Injectable()
export class UsersService {
   async findOne(id: number): Promise<User> {
      return await this.usersRepository.findOne({where: {id: id}});
   }
}

But of course we want to have some checks that the logged in user has access to the user it is querying. The question is now how do I get the current logged in user. I can send it as a parameter from the controller, but since a lot of the backend would need security checked on the current user, I'm not sure that is a good idea.

@Get(':id)
async findOne(@Param('id') id, @Req() req: any) {
   return await this.userService.findOne(id, req.user);
}

Ideally, which doesn't work, I would be able to get it in the UserService:

async findOne(id: number, @Req req: any): Promise<User> {
   if (id === req.user.id || req.user.roles.contains('ADMIN')) {
      return await this.userRepository.findOne({where: {id: id}});
   }
}

Or perhaps through injection in the UserService constructor

constructor(@Inject(REQUEST_OBJECT) private readonly req: any) {}

So, is there a better way to send the user object through the backend than always sending the request object in each function call?


回答1:


Update March 2019

Since version v6, you can now inject the request object into a request-scoped provider:

import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable({ scope: Scope.REQUEST })
export class UsersService {
  constructor(@Inject(REQUEST) private readonly request: Request) {}
}

Outdated answer

It's not possible to inject the user (or request) directly into the service. Nest.js does not yet support request-scoped providers. This might change with version 6. Until then, a service does not know anything about a request.

Logged in user

You can create a custom decorator @User. Using a decorator is preferable over injecting the request object because then a lot of nest's advantages get lost (like inceptors and exception filters).

export const User = createParamDecorator((data, req) => {
  return req.user;
});

And then use it like this:

@UseGuards(AuthGuard()) 
@Get(':id)
async findOne(@Param('id') id, @User() user) {
   return await this.userService.findOne(id, user);
}

Roles

You can create a RolesGuard that makes sure the logged in user has the required roles. For details, see this answer.



来源:https://stackoverflow.com/questions/54979729/howto-get-req-user-in-services-in-nest-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!