Nest.js/Mongoose:为啥我的预保存钩子无法触发?
Posted
技术标签:
【中文标题】Nest.js/Mongoose:为啥我的预保存钩子无法触发?【英文标题】:Nest.js/Mongoose: Why is my pre save hook failing to be triggered?Nest.js/Mongoose:为什么我的预保存钩子无法触发? 【发布时间】:2020-10-14 15:32:48 【问题描述】:我刚开始使用 Nest.js,到目前为止一切顺利。但是,我遇到了一个问题,即我的用户模式中的猫鼬预保存钩子没有被触发。这应该很简单,但无论出于何种原因,密码都以纯格式而不是散列形式保存。什么给了?
还有一个小问题 - 在使用 @Prop 装饰器时,如何定义引用另一个模式的字段? profile 字段应该是 mongoose.schema.types.objectid 在没有装饰器的情况下,它只是 profile: type: mongoose.Schema.Types.ObjectId, ref: 'Profile' 。
以下是相关的sn-ps。
用户架构
import Prop, Schema, SchemaFactory from '@nestjs/mongoose';
import Document from 'mongoose';
@Schema(
timestamps: true,
)
export class User extends Document
@Prop( required: true )
fullname: string;
@Prop( required: true, unique: true )
username: string;
@Prop( required: true, unique: true, lowercase: true )
email: string;
@Prop( required: true )
password: string;
@Prop( required: true, ref: 'Profile' )
profile: string
@Prop( required: true, enum: ['admin', 'basic' ])
role: string
export const UserSchema = SchemaFactory.createForClass(User);
用户模块
import Module from '@nestjs/common';
import MongooseModule from '@nestjs/mongoose';
import * as bcrypt from 'bcrypt';
import User, UserSchema from './user.model';
import UsersController from './users.controller';
import UsersService from './users.service';
@Module(
imports: [
MongooseModule.forFeatureAsync([
name: User.name,
useFactory: () =>
const schema = UserSchema;
schema.pre<User>('save', async function (next: Function)
const user = this;
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(user.password, salt);
user.password = hashedPassword;
next();
);
schema.methods.comparePasswords = async function (submittedPassword)
const user = this;
await bcrypt.compare(submittedPassword, user.password);
;
return schema;
,
,
]),
],
controllers: [UsersController],
providers: [UsersService],
)
export class UsersModule
用户服务
import Injectable, HttpException, HttpStatus from '@nestjs/common';
import InjectModel from '@nestjs/mongoose';
import Model from 'mongoose';
import JwtService from '@nestjs/jwt';
import UsersService from '../users/users.service';
import ProfilesService from '../profiles/profiles.service';
import User from '../users/user.model';
@Injectable()
export class AuthService
constructor(
@InjectModel(User.name) private readonly userModel: Model<User>,
private usersService: UsersService,
private profilesService: ProfilesService,
private jwtService: JwtService
)
async signup(signupData): Promise<any>
const foundUser = await this.userModel.findOne( email: signupData.email );
if (foundUser)
throw new HttpException(
'Email is already in use',
HttpStatus.BAD_REQUEST
);
const createdProfile = await this.profilesService.createProfile();
const createdUser = await this.userModel.create(
...signupData,
profile: createdProfile._id,
role: 'basic',
);
const createdUserCopy = ...createdUser.toObject() ;
delete createdUserCopy.password;
delete createdUserCopy.__v;
const payload =
username: createdUser.username,
sub: createdUser._id,
;
return
user: createdUserCopy,
token: this.jwtService.sign(payload),
;
【问题讨论】:
【参考方案1】:您不能将async
与next()
结合使用
schema.pre<User>('save', function (next)
const user = this;
console.log(user)
next();
);
应该工作
【讨论】:
【参考方案2】:我知道这个问题很久以前就被问过了,但是对于再次面临这个问题的人来说,这里是如何解决它。
useFactory: () =>
const schema = UserSchema;
schema.pre<User>('save', async function ()
const user = this;
const salt = await bcrypt.genSalt(10);
const hashPassword = await bcrypt.hash(user.password, salt);
user.salt = salt;
user.password = hashPassword;
);
return schema;
您可以使用返回承诺的函数,而不是手动调用 next()。特别是,您可以使用 async/await。
【讨论】:
以上是关于Nest.js/Mongoose:为啥我的预保存钩子无法触发?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 matlab 中使用带有 libsvm 的预计算内核