I use nestjs with passport with jwt strategy. And I want to get a current user on some of my requests. Currently i have a decorator that looks like this:
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const user = ctx.switchToHttp().getRequest().user;
if (!user) {
return null;
}
return data ? user[data] : user; // extract a specific property only if specified or get a user object
},
);
It works as intended when i use it on a route with an AuthGuard:
@Get('test')
@UseGuards(AuthGuard())
testRoute(@CurrentUser() user: User) {
console.log('Current User: ', user);
return { user };
}
But how do i make it work (get current user) on non-guarded routes? I need users to be able to post their comments regardless of if they are authorized or not, however, when they are logged in, i need to get their name.
Basicaly, I need a way to propagate req.user on every(or at least on some of not AuthGuard'ed request), it is realy straight forward to do in express by applying passport middleware, but im not sure how to do it with @nestjs/passport.
[EDIT] Thanks to vpdiongzon for pointing me in the right direction, I chose to make a guard based on his answer, that just populates req.user with either user or null:
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class ApplyUser extends AuthGuard('jwt') {
handleRequest(err: any, user: any) {
if (user) return user;
return null;
}
}
And now I could just use it on any unprotected route that needs to get the current user
@Get('me')
@UseGuards(ApplyUser)
me(@CurrentUser() user: User) {
return { user };
}