5

Here is the addUser method inside users.service.ts -

// post a single user
async addUser(createUserDTO: CreateUserDTO): Promise<User> {
    const newUser = await this.userModel(createUserDTO);
    return newUser.save();
}

Here is the POST controller method inside users.controller.ts -

// add a user
@Post('/create')
async addUser(@Res() res, @Body() createUserDTO: CreateUserDTO) {
    const user = await this.usersService.addUser(createUserDTO);
    return res.status(HttpStatus.OK).json({
        message: "User has been created successfully",
        user
    })
}

I've tried using mongo collection findOne method and got user details if it's already present in mongo but not able understand how to throw exception when exist and when not exist add it in mongodb in nest js style -

const user = await this.userModel.findOne({ userName: createUserDTO.userName });

I would appreciate the help :)

N.B: Totally newbie in nest js

Sayan
  • 481
  • 5
  • 12

5 Answers5

3

You can modify your user.service.ts file so that it might contain a separate method to check if the user exists.

async doesUserExists(createUserDTO: CreateUserDTO): any {
    const user = await this.userModel.findOne({ userName: createUserDTO.userName });
    if(user.length != 0){
        return true;
    }
    return false;
}

In your user.controller file, You can call the user exists function in user service to check and then proceed accordingly

// add a user
@Post('/create')
async addUser(@Res() res, @Body() createUserDTO: CreateUserDTO) {
    if(await this.userService.doesUserExists()){
        return res.status(HttpStatus.OK).json({
            message: "User already exists"
        })
    }
    const user = await this.usersService.addUser(createUserDTO);
    return res.status(HttpStatus.OK).json({
        message: "User has been created successfully",
        user
    })
}
Sasuke Uchiha
  • 421
  • 6
  • 17
  • @Sasuka: Is it not possible on the same method(i.e. addUser())? To check user exist or not do we must need a separate method(i.e. doesUserExists())? – Sayan Aug 29 '19 at 12:58
  • 1
    @SayanSamanta You are right, you could do that if you add in a property while defining your model schema, such as ```// Create a schema var userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true}, password: String });``` This will then throw you an error when you try to again save a user with email ```duplicate key error``` – Sasuke Uchiha Aug 29 '19 at 13:03
  • @Susuka: Got you, now I'm facing another issue - DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead. Don't know how to set mongoose.set('useCreateIndex', true) in nest js way – Sayan Aug 29 '19 at 13:22
  • 1
    @SayanSamanta You could use ```mongoose.connect(uri, { useCreateIndex: true });``` instead of ```mongoose.set('useCreateIndex', true)```. If you wanna know more about this warning you can visit this link https://mongoosejs.com/docs/deprecations.html – Sasuke Uchiha Aug 29 '19 at 13:26
  • @susuka: Although It's little different in nest js way - MongooseModule.forRoot('mongodb://localhost/db-new', { useNewUrlParser: true, useCreateIndex: true }), but got your point. – Sayan Aug 29 '19 at 13:33
  • @susuka: After changed directly on mongo schema(unique: true) not throwing an exception but after drop the DB and restarting the server start, throwing an exception #ref - https://stackoverflow.com/questions/5535610/mongoose-unique-index-not-working, BTW - thanks for the help :) – Sayan Aug 29 '19 at 13:47
3

You have two ways to do this:

1.- On the same service function

service:

private async addUser(createUserDTO: CreateUserDTO) {
    if ((await this.userModel.findOne({ username: createUserDTO.username }))){
      throw new ConflictException('User already exist');
    }
    const user = new this.userModel(createUserDTO);
    return await user.save();
}

controller:

// add a user

@Post('/create')
async addUser(@Body() createUserDTO: CreateUserDTO) {
    return await this.usersService.addUser(createUserDTO);
}

Dont worry about the exception throwed, nestjs will give a HTTP 409 error to the client.

2.- Using a guard (elegant solution, see: https://docs.nestjs.com/guards)

@Injectable()
export class UserExistGuard implements CanActivate {
  constructor(@InjectModel('User') private readonly userModel: Model<User>) {
  }

  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    const user = context.switchToHttp().getRequest().body;
    return !!(await this.userModel.findOne({ username: user.username }));
  }
}

and in the controller

@UseGuards(UserExistGuard)
@Post('/create')
async addUser(@Body() createUserDTO: CreateUserDTO) {
    return await this.usersService.addUser(createUserDTO);
}

Note: I have not tested the code.

Nestor Perez
  • 827
  • 11
  • 17
1

Here is my solution :

users.service.ts:

Have to return a Promise of type any(to be in safe position) otherwise nest will complain as it is a async function.

  async isUserExists(createUserDto: CreateUserDto): Promise<any> {
    const { email } = createUserDto;
    const user = await this.userModel.findOne({ email });
    if (user) return true;
    else return false;
  }

users.controller.ts:

@Post("/create")
  async createUser(@Res() res, @Body() createUserDto: CreateUserDto) {
    if (await this.usersService.isUserExists(createUserDto)) {
      return res.status(HttpStatus.OK).json({
        message: "User already registered",
      });
    }

    const user = await this.usersService.insertUser(createUserDto);
    return res.status(HttpStatus.OK).json({
      message: "User has been created successfully",
      user,
    });
  }
Mahadi Hassan
  • 906
  • 10
  • 10
0

Your user service should look like this:

async addUser(data: CreateUserDto): Promise<any> {
  const exists = await this.userModel.findOne({ email });
  if(exists) throw new ConflictException('User already exists!');

  const user = await this.userModel.create(data);
  return user;
}

Your user controller should look like this:

@Post()
async createNewUser(@Body() data: CreateUserDto): Promise<any> {
  return await this.userService.addUser(data);
}
Sachin Yadav
  • 128
  • 3
  • 12
0

user.service.ts

async create(createUser: CreateUserDto) {
   const exists = await this.usersModel.exists({ username: createUser.username });
   if (exists) throw new ConflictException('User already exist');

   const newUser = await this.userModel(createUser);
   return newUser.save();
  }

user.controller.ts

@Post()
async create(@Body() createUser: CreateUserDto) {
    return await this.usersService.create(createUser);
}

Response if user exists :

{
    "statusCode": 409,
    "message": "User already exist",
    "error": "Conflict"
}