Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot overwrite `users` model once compiled node js

I am getting this error while compiling my code

throw new mongoose.Error.OverwriteModelError(name);
      ^
OverwriteModelError: Cannot overwrite `users` model once compiled.

This is my Model/users.js file

const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config = require('../config/database');

//User Schema
const UserSchema = mongoose.Schema({
  name: {
    type:String
  },
  email: {
    type:String,
    required:true
  },
  username: {
    type:String,
    required:true
  },
  password: {
    type:String,
    required:true
  }
});

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

module.exports.getUserById = function(id,callback)
{
  User.findById(id,callback);
}

module.exports.getUserByUsername = function(username,callback){
  const query = {username: username}
  user.findOne(query,callback);
}
module.exports.addUser = function(newUser,callback){
  bcrypt.genSalt(10,(err,salt)=>{
    if(err)
    {
      throw err;
    }
    bcrypt.hash(newUser.password,salt,(err,hash)=>{
      newUser.password=hash;
      newUser.save(callback);
    });
  });
}

This is my route/users.js file

const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
var Log = require('log')
  , log = new Log('info');

const User = require('../Model/users');
//const ap = express();

//Register router
router.post('/register',(req,res,next)=>{
  log.info('entering register');
  let newUser = new User({
    name:req.body.name,
    email:req.body.email,
    username:req.body.username,
    password:req.body.password
  });
  User.addUser(newUser,(err,user)=>{
    log.info("inside add user");
    if(err){
      log.error('error while registaring ' + err);
      res.json({success:false,msg:'failed to register user'});
    }
    else {
      res.json({sucess:true,msg:'user registered succefully'});
    }
  })
});
router.get('/authenticate',(req,res,next)=>{
  res.send("authenticated");
});
router.get('/profile',(req,res,next)=>{
  res.send('profile');
});
module.exports=router;

passport.js

const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../model/users');
const config = require('../config/database');

module.exports = function(passport){
  let opts = {};
  opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
  opts.secretOrKey = config.secret;
  passport.use(new JwtStrategy(opts,(jwt_payload,done)=>{
    User.getUserById(jwt_payload._id,(err,user)=>{
      if(err)
      {
        return done(err,false);
      }
      if(user){
        return done(null,user);
      }
      else {
        return done(null,false);
      }
    })
  }));
}

I have tried suggestion from [Cannot overwrite model once compiled Mongoose but I am not able to understand what the problem is.

like image 484
user3649361 Avatar asked Jul 17 '17 17:07

user3649361


3 Answers

Update your require statements to be consistent in both the routes and passport file: const User = require('../model/users');. Case does matter!

It looks like you're not using the correct mongoose terminology. Based on their documentation, this should be implemented roughly as follows.

const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config = require('../config/database');

//User Schema
const UserSchema = mongoose.Schema({
  name: {
    type:String
  },
  email: {
    type:String,
    required:true
  },
  username: {
    type:String,
    required:true
  },
  password: {
    type:String,
    required:true
  }
});

UserSchema.statics.getUserById = function(id,callback)
{
  return this.findById(id,callback);
};

UserSchema.statics.getUserByUsername = function(username,callback){
  const query = {username: username}
  return this.findOne(query,callback);
};
UserSchema.statics.addUser = function(newUser,callback){
  bcrypt.genSalt(10,(err,salt)=>{
    if(err)
    {
      throw err;
    }
    bcrypt.hash(newUser.password,salt,(err,hash)=>{
      newUser.password=hash;
      newUser.save(callback);
    });
  });
};

module.exports = users = mongoose.model('users',UserSchema);;
like image 70
SimplyComplexable Avatar answered Oct 18 '22 09:10

SimplyComplexable


The problem is you are compiling User two times in the runtime
once you do users = mongoose.model('users',UserSchema); mongo will create the collection users so i think you are doing it again somewhere in the project

Or if you are working with fawn maybe you are using it more than onetime

like image 43
Farouk Benarous Avatar answered Oct 18 '22 11:10

Farouk Benarous


You want to ensure you retrieve the model and if its not present, you create the model.

The model itself is also case-sensitive.

// user_model.js

const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');

const UserSchema = new mongoose.Schema({
   name: String, 
   email: String
});

UserSchema.methods.generateJWT = function(payload) {
   const options = {expiresIn: "1h"};
   const superHash = Math.random().toString(36).substring(7);
   return jwt.sign({ id: payload }, superHash, options);
}

// *** This fixed my error. ***
// Ensure when creating the model, the name is capitalized like so "User"
module.exports = mongoose.models.Users || mongoose.model("User", UserSchema);

I ran up on this issue when creating a custom next.js server. Retrieving from the getServerSideProps.

Case-sensitivity was never an issue w/ an ordinary mongoose/express API.

like image 2
Jason Avatar answered Oct 18 '22 11:10

Jason