Sayan
Sayan

Reputation: 522

How to throw exception using nest js if user exist on mongo and else create the user?

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

Upvotes: 6

Views: 9119

Answers (5)

Honorable con
Honorable con

Reputation: 333

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"
}

Upvotes: 1

Sachin Yadav
Sachin Yadav

Reputation: 313

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);
}

Upvotes: 0

Mahadi Hassan
Mahadi Hassan

Reputation: 1016

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,
    });
  }

Upvotes: 1

Nestor Perez
Nestor Perez

Reputation: 877

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.

Upvotes: 4

Sasuke Uchiha
Sasuke Uchiha

Reputation: 491

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
    })
}

Upvotes: 3

Related Questions