Nest: CurrentUser Decorator

Created on 1 Jul 2018  路  13Comments  路  Source: nestjs/nest

I'm submitting a...


[X] Feature request

Current behavior


Now I'm required to get my user by a service.

Expected behavior


I would be awesome to have it by a custom decorator like routing-controllers does: read here
It's a cleaner way to get the current user.

Would it be nice to have a feature like this, or something similar.

question 馃檶

Most helpful comment

here is a simple one

import { createParamDecorator, UnauthorizedException } from '@nestjs/common';

export interface CurrentUserOptions {
  required?: boolean;
}

export const CurrentUser: (options?: CurrentUserOptions) => ParameterDecorator = createParamDecorator((options: CurrentUserOptions = {}, req) => {
  const user = req.user;
  if (options.required && !user) {
    throw new UnauthorizedException();
  }
  return user;
});

All 13 comments

Hey to get the current user you can have a middleware that populate the current user on the request and then create a custom parameter decorator that can be use in the controller to get the user from the request.

@adrien2p is there some documentation on it? And does it load the current use on every request or only on the requests that use this custom decorator? Cause it would be efficient to load it only when it's needed to?

The middleware will apply on the route according to your configuration. And the decorator will be there just to pick it from the request. So if you don鈥檛 use the decorator it will not be picked. But the middleware will always be executed before accessing the route. That is depending on the implementation you are doing. There is a doc about custom decorator and about middleware. But what you are trying to do is more related to the implementation of your project i think

@adrien2p thanks for your feedback! I've build the decorator and it's working as expected the only problem is I don't know how to get my typeorm instance (User collection) inside the decorator?

If you want the active user, it mean than he is connected, put the authenticated user on the request through the middleware. And the you will be able to pick him from the request

@adrien2p yes I get that but for example inside a service I can inject a typeorm repository by doing this:

 @InjectRepository(User) private readonly userRepository: Repository<User>

My question is how to do this inside the decorator so I can query the database to get the user.

You can鈥檛 that is not the purpose of a decorator. You have to get the user else where before ^^

With a decorator you can work with metadata (metaprograming)

@adrien2p I don't know how to get it to work by doing (metaprogramming) but how I solved it is by extending my User Entity with the TypeORM BaseEntity class:

@Entity('users')
export class User extends BaseEntity {
...
}

What I can do now in the decorator is:

import { createParamDecorator } from '@nestjs/common';
import {User} from './user.entity';

export const CurrentUser = createParamDecorator(async (data, req) => {

    if (req.session.hasOwnProperty('userId') && !!req.session.userId) {
        return await User.findOne({id: req.session.userId})
    } else {
        return null;
    }
});

The BaseEntity class is getting the current connection context in some way, so that enabled my decorator to use the database connection and query it :).

Great :) good job

Just wanted to add: Nest gives flexibility to easily create any type of decorator. We haven't provided a built-in solution to don't suggest any auth strategy/database.

here is a simple one

import { createParamDecorator, UnauthorizedException } from '@nestjs/common';

export interface CurrentUserOptions {
  required?: boolean;
}

export const CurrentUser: (options?: CurrentUserOptions) => ParameterDecorator = createParamDecorator((options: CurrentUserOptions = {}, req) => {
  const user = req.user;
  if (options.required && !user) {
    throw new UnauthorizedException();
  }
  return user;
});

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings