jaredhanson / passport

Simple, unobtrusive authentication for Node.js.
https://www.passportjs.org?utm_source=github&utm_medium=referral&utm_campaign=passport&utm_content=about
MIT License
22.92k stars 1.24k forks source link

Property 'serializeUser' does not exist on type 'UserModel'.ts(2339) #894

Open learner00000 opened 2 years ago

learner00000 commented 2 years ago

This is my models/users.ts file:

import mongoose from 'mongoose';
const Schema = mongoose.Schema;
import passportLocalMongoose from 'passport-local-mongoose';

export interface digitalWalletDocument extends mongoose.Document{
    currencyName: string;
    value: number;

}

const digitalWalletSchema = new Schema<digitalWalletDocument>({
    currencyName : {
        type : String
    },
    value : {
        type : Number
    }
});

export interface UserDocument extends mongoose.Document{
    username :  String;
    firstName : String;
    lastName : String;
    email : String;
    telNumber : Number;
    nationalCode : Number;
    admin : Boolean;
    image :  String;
    wallet : Number;
    rate : Number;
    shabaCode :Number;
    cardNumber : Number;
    birthDay : String;
    status : String;
    address : String;
    documnetPath : String;
    description : String;
    purchased : String;
    digitalWallet : digitalWalletDocument;
}

export const userSchema = new Schema<UserDocument>({
    username : {
        type : String,
        sparse : true ,
        unique : true
    },
    firstName : {
        type: String
    },
    lastName : {
        type : String
    },
    email : {
        type : String,
        unique : true
    },
    telNumber : {
        type : Number
    },
    nationalCode : {
        type : Number,
        sparse : true,
        unique : true
    },
    admin : {
        type:Boolean,
        default : false
    },
    image : {
        type : String
    },
    wallet: {
        type : Number,
        default : 0
    },
    rate : {
        type : Number,
        default : 0
    },
    shabaCode : {
        type : Number
    },
    cardNumber : {
        type : Number
    },
    birthDay : {
        type : String
    },
    status : {
        type : String
    },
    address : {
        type : String
    },
    documnetPath : {
        type : String
    },
    description : {
        type: String
    },
    purchased : [String],
    digitalWallet : [digitalWalletSchema]
}, {timestamps : true});

export interface UserModel extends mongoose.Model<UserDocument> {};

userSchema.plugin(passportLocalMongoose,{usernameField : 'email'});

export default mongoose.model<UserDocument,UserModel>('User' , userSchema);

And the following is the authentication.ts file that uses the user.ts file:

import express, {Request, Response, NextFunction} from 'express';
import mongoose from 'mongoose';
import passport from 'passport';
import passportLocal from 'passport-local';
const LocalStrategy = passportLocal.Strategy;
import passportJWT from 'passport-jwt';
const passportJWTStrategy = passportJWT.Strategy;
const ExtractJWT = passportJWT.ExtractJwt;
import JWT from 'jsonwebtoken';
import User from './models/users';
import config from './config';

export const local = passport.use(new LocalStrategy( User.authenticate()));

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

exports.getToken = (user: any) => {
    return JWT.sign(user, config.secretKey,{ expiresIn : "2d"});
};

const opt = {
    secretOrKey : config.secretKey,
    jwtFromRequest : ExtractJWT.fromAuthHeaderAsBearerToken()
};

export const jwtAuth = passport.use(new passportJWTStrategy(opt , (payload ,done) => {

    User.findOne({_id : payload._id},(err: any , user: typeof User ) => {
        if(err){
            return done(err,false);
        }
        else if(user){
            return done(null , user);
        }
        else{
            return done(null, false);
        }
    });
}));

export const verifyUser = passport.authenticate('jwt', {session : false});

export function verifyAdmin(req: Request, res: Response, next: NextFunction) {
    if(req.user.admin){
        return next();
    }
    else{
        let err = new Error('Only Admin can access to this web page or resources!');
        err.status = 403;
        return next(err);
    }
}

I get the following error messages:

Property 'authenticate' does not exist on type 'UserModel'.ts(2339)
Property 'serializeUser' does not exist on type 'UserModel'.ts(2339)
Property 'deserializeUser' does not exist on type 'UserModel'.ts(2339)

The sources of errors are these lines:

export const local = passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

I don't know what is the problem and how can I fix it? I tried to search on the internet and find the similar questions and do what the similar questions' answers suggest but none of them worked for me!

MouSoeng commented 2 years ago

You should be reference to the test of passport-local-mongoose. In the index.test-d.ts, the UserModel should be extends from PassportLocalModel, and the Schema should recognize as PassportLocalSchema. Link to passport-local-mongoose test file for your reference: https://github.com/saintedlama/passport-local-mongoose/blob/main/test/types/index.test-d.ts