快速身份验证。类型 'Document' 上不存在属性'comparePassword'



我是express和node.js的新手。我正在尝试构建一个没有前端的身份验证系统。我用的是打字本、护照、本地护照和猫鼬。我得到以下错误:

TSError: ⨯ Unable to compile TypeScript:
auth.ts:20:37 - error TS2339: Property 'comparePassword' does not exist on type 'Document'.
20       const passwordOK = await user.comparePassword(password);
~~~~~~~~~~~~~~~
auth.ts:32:19 - error TS2339: Property '_id' does not exist on type 'Model<Document, {}>'.
32   done(null, user._id);
~~~

这是我的代码授权。ts

import { Request, Response, NextFunction } from "express";
import passport from "passport";
import mongoose, { Document } from "mongoose";
const LocalStrategy = require("passport-local").Strategy;
//const UserModel = require("./src/models/crmModel");
import { UserSchema } from "./src/models/crmModel";
const User = mongoose.model("User", UserSchema);
passport.use(
new LocalStrategy({ usernameField: "email" }, async function (
username: string,
password: string,
done: Function
) {
try {
const user = await User.findOne({ email: username }).exec();
if (!user) {
return done(null, false, { message: "Invalid username or password" });
}
const passwordOK = await user.comparePassword(password);
if (!passwordOK) {
return done(null, false, { message: "Invalid username or password" });
}
return done(null, user);
} catch (err) {
return done(err);
}
})
);
passport.serializeUser(function (user, done) {
done(null, user._id);
});
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id).exec();
return done(null, user);
} catch (err) {
return done(err);
}
});
module.exports = {
initialize: passport.initialize(),
session: passport.session(),
setUser: (req: Request, res: Response, next: NextFunction) => {
res.locals.user = req.user;
return next();
},
};

这是我的crmModel.ts代码

import mongoose from "mongoose";
import * as EmailValidator from "email-validator";
import { NextFunction } from "express";
import { Document } from "mongoose";
const bcrypt = require("bcrypt");
const SALT_ROUNDS = 12;
interface props extends Document {
username: string;
email: string;
password: string;
}
export const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
trim: true,
index: { unique: true },
minlength: 3,
},
email: {
type: String,
required: true,
trim: true,
lowercase: true,
index: { unique: true },
validate: {
validator: EmailValidator.validate,
message: (props) => `${props.value} is not valid email address!`,
},
},
password: {
type: String,
required: true,
trim: true,
index: { unique: true },
minlength: 8,
},
},
{
timestamps: true,
}
).pre<props>("save", async function (next) {
const user = this;
if (!user.isModified("password")) return next();
try {
const hash = await bcrypt.hash(user.password, SALT_ROUNDS);
user.password = hash;
return next();
} catch (err) {
return next(err);
}
});
UserSchema.methods.comparePassword = async function comparePassword(
candidate: string
) {
return bcrypt.compare(candidate, this.password);
};

我想是导入有问题(我使用它的方式(。当我使用如图所示的require(在代码中注释(时,我没有得到这些错误,但我得到了以下错误:

findOne is not a function

你能给我指路吗?

TypeScript无法从模式定义中获取类型,因此必须手动描述它们。修改crmModel文件:

import { Document, Model } from "mongoose";
export interface UserDocument extends Document {
username: string;
email: string;
password: string;
comparePassword(candidate: string): Promise<boolean> // or whatever it returns
}
export interface UserModel extends Model<UserDocument> {}
const UserSchema = new mongoose.Schema<UserDocument>({
// ...
}).pre<UserDocument>('save', async function(/* ... */) { 
// ...
})
UserSchema.methods.comparePassword = async function(/* */) { /* ... */}
const User = mongoose.model<UserDocument, UserModel>('User', UserSchema)
export default User

注意,我在crmModel文件中移动了模型声明,您可以稍后将其导入任何位置,模型应该创建一次。此外,您还可以在UserDocument中添加任何其他需要的方法,并在UserModel中添加静态方法

虽然我刚刚意识到,我不确定为什么它说findOne is not a function,因为它应该在任何模型上定义,但我希望添加接口将解决问题

最新更新