I am using passport.js in conjunction with Sequelize version 6.3.3. The model file was scaffolded using the sequelize-cli and I have the following problems: I am unable to use either the instance methods or prototype methods that I have defined on my model classes. I keep getting the error "model.methodName is not a function".
Here is the code for my model: User.js
'use strict';
const { Model } = require('sequelize');
const bcrypt = require('bcryptjs');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
// define association here
}
testInstanceMethod() {
console.log('Test passed');
}
}
User.init(
{
email: {
type: DataTypes.STRING,
notNull: true,
unique: true,
validate: {
isEmail: {
args: true,
msg: 'Please enter a valid email',
},
},
},
password: {
type: DataTypes.STRING,
notNull: true,
validate: {
len: {
args: [8, 255],
msg: 'Password must be 8+ characters long',
},
},
},
},
{
sequelize,
modelName: 'User',
}
);
// Hash password before user is created
User.addHook('beforeCreate', async (user, options, next) => {
try {
// generate a salt
const salt = await bcrypt.genSalt(10);
// hash the password using the salt we generated above
const hashedPassword = await bcrypt.hash(user.password, salt);
// set user's password to the hashed password
user.password = hashedPassword;
} catch (error) {
console.log(error);
next(error);
}
});
User.prototype.isValidPassword = async (user, userInputtedPassword) => {
try {
return await bcrypt.compare(userInputtedPassword, user.password);
} catch (error) {
throw new Error(error);
}
};
return User;
};
passport.js
const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const db = require('../../models');
const LocalStrategy = require('passport-local');
/* ******************* */
// HANDLE JWT
/* ****************** */
// Passport jwt options object
let options = {};
// grab jwt from the header
options.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
options.secretOrKey = process.env.TOKEN_SECRET;
// Configure and use passport.js
passport.use(
new JwtStrategy(options, async (jwtPayload, done) => {
try {
// find user with an id matching the jwt subscriber id
const user = await db.User.findAll({ where: { id: jwtPayload.sub } });
if (user) {
// if user is found, return it
return done(null, user);
} else {
// if not found, return false
done(null, false);
}
} catch (error) {
// catch errors
done(error, false);
}
})
);
/* ******************* */
// LOCAL STRATEGY
/* ****************** */
passport.use(
new LocalStrategy(
{
usernameField: 'email',
},
async (email, password, done) => {
try {
// find user when given the email
const user = await db.User.findAll({ where: { email: email } });
// if no user is found. handle it
if (!user) {
return done(null, false);
}
// test instance method
user.testInstanceMethod();
const passwordMatch = await user.isValidPassword(password);
// if password doesn't match then handle it
if (!passwordMatch) {
return done(null, false);
}
console.log('successful login');
return done(null, user);
} catch (error) {
return done(error);
}
}
)
);
If you consider the code in the passport.js file, the instance level method (testInstanceMethod) is throwing the error "Type error user.testInstanceMethod is not a function". If you comment that line out, the prototype method (isValidPassword) throws the error "Type error user.isValidPassword is not a function". What am I doing wrong?