COLEAN
COLEAN

Reputation: 695

Node.js > 'findOne' of undefined < LocalStrategy from Passport

I used Passport to create login.

However, I get:

TypeError: Cannot read property 'findOne' of undefined

when trying to login.

After debugging, I confirmed that user was undefined after async of localStrategy.js.

I think all the actions are perfect, but there is a problem with my code.

Can I tell you where I made the mistake?

passport/index.js

const local = require('./localStrategy');
const { User } = require('../model/user');

module.exports = (passport) => {
  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    User.findOne({ id: id })
      .then((user) => done(null, user))
      .catch((err) => done(err));
  });

  local(passport);
};

passport/localStrategy.js

const LocalStrategy = require('passport-local').Strategy;
const { User } = require('../model/user');

module.exports = (passport) => {
  passport.use(
    new LocalStrategy(
      {
        usernameField: 'email',
        passwordField: 'password'
      },
      async (email, password, done) => {
        try {
          const exUser = await User.findOne({ email: email });
          if (exUser) {
            const result = await bcrypt.compare(password, exUser.password);
            if (result) {
              done(null, exUser);
            } else {
              done(null, false, { message: 'failed.' });
            }
          } else {
            done(null, false, { message: 'failed.' });
          }
        } catch (err) {
          console.error(err);
          done(err);
        }
      }
    )
  );
};

routes/user.js

const express = require('express');
const router = express.Router();

const { isLoggedIn, isNotLoggedIn } = require('./middleware');

const usersController = require('../controller/users_controller');

router.get('/login', isNotLoggedIn, usersController.user_login);

controller/users_controller.js

const User = require('../model/user');
const bcrypt = require('bcrypt');
const passport = require('passport');

exports.user_login = (req, res, next) => {
  passport.authenticate('local', (authError, user, info) => {
    if (authError) {
      console.error(authError);
      return next(authError);
    }
    if (!user) {
      return res.send("not user.")
    }
    return req.login(user, (loginError) => {
      if (loginError) {
        console.error(loginError);
        return next(loginError);
      }
      return res.send("login successfully")
    });
  })(req, res, next);
};

model/user.js

const mongoose = require('mongoose');

let UserSchema = new mongoose.Schema({
  email: {
    type: String,
    required: true,
    unique: true
  },
  password: {
    type: String,
    require: true
  },
  createAt: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('User', UserSchema);

Upvotes: 0

Views: 472

Answers (2)

Amol B Jamkar
Amol B Jamkar

Reputation: 1257

It should be _id not id in your query passport/index.js

 User.findOne({ _id: id })
      .then((user) => done(null, user))
      .catch((err) => done(err));
  });

In passport/localStrategy file correct import of Model

const User = require('../model/user');

Upvotes: 0

hong4rc
hong4rc

Reputation: 4103

const { User } = require('../model/user');

This code return User = undefined

Can you show code in '../model/user'?

Are you export with:

module.exports = {
    User: your_user
}

?

If you use:

module.exports = User;

you should call

const User = require('../model/user');

instead of:

const { User } = require('../model/user');

or you can change export in '../model/user':

module.exports = {
    User: your_user
}

Upvotes: 2

Related Questions