Friday, May 10, 2024
 Popular · Latest · Hot · Upcoming
163
rated 0 times [  166] [ 3]  / answers: 1 / hits: 59705  / 5 Years ago, mon, march 4, 2019, 12:00:00

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?


More From » node.js

 Answers
11

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 interceptors 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.


[#52492] Wednesday, February 27, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kaitlynnb

Total Points: 402
Total Questions: 96
Total Answers: 109

Location: Trinidad and Tobago
Member since Fri, May 8, 2020
4 Years ago
kaitlynnb questions
;