Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nestjs: Mongoose schema returns full document with spread operator instead of the required properties

I have created a separate service for the user that creates a simple user without any specification. Then i am using the create function from userService in AuthService for signup. In the userService, it returns the data as mongoose Schema. While in AuthService, i want to exclude password and some other details so i have created Dto for signupResponse. The problem here is that it is returning full document instead of the required properties here.

The code for userService.ts:

import {Model} from 'mongoose';
import {InjectModel} from '@nestjs/mongoose';
import {User, UserDocument} from './schemas/user.schema';

import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UserService {
  constructor(@InjectModel(User.name) private userRepository: Model<UserDocument>) {}

  async create(createUserDto: CreateUserDto): Promise<User> {
    const newUser = new this.userRepository(createUserDto);
    return await newUser.save();
  }
}

the authService.ts class:

import { CreateUserDto } from 'src/user/dto/create-user.dto';
import { UserService } from 'src/user/user.service';
import { SigninDto } from './dto/signin/signin.dto';
import {JwtService} from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import {signupResponseDto} from './dto/signup/signup-response.dto';

@Injectable()
export class AuthService {
  constructor(private readonly userService: UserService, private readonly jwtService: JwtService){}

  async signup(signupDto: CreateUserDto): Promise<signupResponseDto>
  {
    const {password, ...otherData} = signupDto;
    
    const hashedPassword = await this.createHash(password);

    const newSignupBody: CreateUserDto = {password: hashedPassword, ...otherData};
  
    const createUser = await this.userService.create(newSignupBody);

    const {username} = createUser;

    const token = this.createToken(username, createUser['_id']);

    const result:signupResponseDto = {_id: createUser['_id'], token, ...createUser};

    return result;
    
  }
}

The result of the api test is:

{
  "_id": "60b95077448c29067c1fb349",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1271738373jffghdfghiOjE2MjI4NDM4OTV9._HKhNMeobCm0G6B2r7aaiTDsk53Qmp36poLG4bmPmlY",
  "$__": {
    "strictMode": true,
    "inserting": true,
    "getters": {},
    "_id": "60b95077448c29067c1fb349",
    "wasPopulated": false,
    "activePaths": {
      "paths": {
        "email": "require",
        "username": "require",
        "password": "require"
      },
      "states": {
        "ignore": {},
        "default": {},
        "init": {},
        "modify": {},
        "require": {
          "email": true,
          "username": true,
          "password": true
        }
      },
      "stateNames": [
        "require",
        "modify",
        "init",
        "default",
        "ignore"
      ]
    },
    "pathsToScopes": {},
    "cachedRequired": {},
    "session": null,
    "$setCalled": {},
    "emitter": {
      "_events": {},
      "_eventsCount": 0,
      "_maxListeners": 0
    },
    "$options": {
      "defaults": true
    },
    "validating": null,
    "backup": {
      "activePaths": {
        "modify": {
          "password": true,
          "email": true,
          "username": true,
          "security_answer": true
        },
        "default": {
          "updated_at": true,
          "created_at": true,
          "_id": true
        }
      }
    },
    "savedState": {}
  },
  "isNew": false,
  "$locals": {},
  "$op": null,
  "_doc": {
    "updated_at": "2021-06-03T21:58:11.071Z",
    "created_at": "2021-06-03T21:58:11.071Z",
    "_id": "60b95077448c29067c1fb349",
    "password": "$2b$10$K2gq31/Bv4tythgdWx/ObigM9izspn7wd01BUKcJ2P8dORC2loW",
    "email": "[email protected]",
    "username": "test",
    "security_answer": "banana",
    "__v": 0
  }
}

SignupDto

export class signupResponseDto
{
    _id: string;
    username: string;
    email: string;
    token: string;
    created_at: Date
}
like image 420
Noobish Avatar asked Sep 06 '25 22:09

Noobish


1 Answers

Try return await newUser.save().toObject(); or if you will ever query records via find/findOne methods append .lean() after their call.

From Mongoose documentation:

Documents have a toObject method which converts the mongoose document into a plain JavaScript object.

or if you query anything checkout this page:

Documents returned from queries with the lean option enabled are plain javascript objects, not Mongoose Documents.

like image 65
Yehor Orlov Avatar answered Sep 09 '25 12:09

Yehor Orlov