Reputation: 505
I am using Nestjs and Mongoose. I need to fetch a user profile but ignore the password from Mongodb.
My user schema looks like this
@Schema()
export class User extends Document {
@Prop({ required: true, unique: true })
email: string;
@Prop({required: true})
password: string;
}
When the user logs in, I need to fetch the user with the password so that I can authenticate the user. Here is the findOne method in UsersService. It uses User
the schema as the type
async findOne(filter: FilterQuery<User>): Promise<User> {
return this.userModel.findOne(filter).exec();
}
However, in my authentication method, after the user is authenticated, I need to return the user without the password.
async validateUser(email: string, password: string): Promise<User | null> {
const user = await this.usersService.findOne({ email });
if (user && await compare(password, user.password)) {
const {password: ignore, ...result} = user.toObject();
return result;
}
return null;
}
This works, but user.toObject()
returns type any
which will ignore the type check. I still would like validateUser
method to make sure I return a promise of User
or null
Is there a type safe way to do so? Thank you very much in advance!
Upvotes: 1
Views: 1904
Reputation: 6432
In order to transform your plain JavaScript object returned by toObject
into a typed object, you might want to use class-transformer
library (the library is recommended by Nest.js
for validation purposes).
Step 1.
First install class-validator
:
$ npm i --save class-transformer
Step 2.
Once installed, assuming User
class has the following properties:
class User {
public id: any;
public email: string;
public password: number;
}
Create antoher class named UserWithoutPassward
and import Exclude
import { Exclude } from "class-transformer";
class UserWithoutPassword extends User {
@Exclude()
public password: number
}
We use Exclude
annotation to let class-transformer
know we would like to exclude password
.
Step 3.
import the plainToClass
function:
import { plainToClass } from "class-transformer";
And back to your code:
async validateUser(email: string, password: string): Promise<UserWithoutPassword | null> {
const user = await this.usersService.findOne({ email });
if (user && await compare(password, user.password))
{
return plainToClass(UserWithoutPassword, user.toObject());
}
return null;
}
plainToClass
method transforms a plain javascript object to instance of specific class, accepting the following parameters:
Further reference about the library
Hope it helps.
Upvotes: 2