问题
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