Javascript 使用Mongoose在Express中将一个模型引用到用户模型

Javascript 使用Mongoose在Express中将一个模型引用到用户模型,javascript,node.js,mongodb,express,mongoose,Javascript,Node.js,Mongodb,Express,Mongoose,我正在使用MEAN stack构建一个应用程序,我对它相当陌生。我当前的问题是,我正在尝试将我的冲浪模型引用到express中的用户模型。我想要它做的只是创建一个新的冲浪对象,并引用创建它的用户。当我试图根据POST请求创建一个新的Surf对象时,我当前的设置显示出一个错误。顺便说一下,我还使用jsonwebtokens进行身份验证。我不确定这是否与此有关,只是提一下而已。感谢您的帮助 /models/surf.js // surf.js var mongoose = require('mong

我正在使用MEAN stack构建一个应用程序,我对它相当陌生。我当前的问题是,我正在尝试将我的冲浪模型引用到express中的用户模型。我想要它做的只是创建一个新的冲浪对象,并引用创建它的用户。当我试图根据POST请求创建一个新的Surf对象时,我当前的设置显示出一个错误。顺便说一下,我还使用jsonwebtokens进行身份验证。我不确定这是否与此有关,只是提一下而已。感谢您的帮助

/models/surf.js

// surf.js
var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

//SURF SCHEMA
//  ============================================
var SurfSchema = new Schema({
  title: String,
  longitude: Number,
  latitude: Number,
  comment: String,
  created: { type: Date, default: Date.now },
  user_id: {type: Schema.ObjectId, ref: 'User'}
});

var Surf = mongoose.model('Surf', SurfSchema);

module.exports = Surf;
//USER MODEL
// Require packages for User model
var mongoose = require('mongoose');
var Schema   = mongoose.Schema;
var bcrypt   = require('bcrypt-nodejs');

//USER SCHEMA
//  ============================================
var UserSchema = new Schema({
  name: String,
  username: {type: String, required: true, index: {unique: true}},//No duplicate usernames
  password: {type: String, required: true, select: false}//Do not return password
});

//HASH PASSWORD
//  ============================================

//Hash password before saving
UserSchema.pre('save', function(next){
  var user = this;

  //Hash password only if the password has been changed or is new
  if(!user.isModified('password')) return next();

  //Generate Salt
  bcrypt.hash(user.password,null, null, function(err,hash){
    if(err) return next(err);
      //Change the password to the hash version
      user.password = hash;
      next();
  });
});


//Create method to compare a given password with the database hash
UserSchema.methods.comparePassword = function(password){
  var user = this;

  return bcrypt.compareSync(password,user.password);
};

//Create User model out of userSchema
var User = mongoose.model('User', UserSchema);

module.exports = User;
    //api.js
var bodyParser = require('body-parser');
var User       = require('../models/user');
var Surf       = require('../models/surf');
var jwt        = require('jsonwebtoken');
var config     = require('../config');

//superSecret secret for creating tokens
var superSecret = config.secret;

//Pass in app and express to use express object for express.Router()
module.exports = function(app, express){
  // Instance of express Router
  var apiRouter = express.Router();

  //API AUTHENTICATE ROUTE
  // ====================================================================
  //Route for authenticating user at /api/authenticate
  apiRouter.post('/authenticate', function(req, res){
    //find the user and select username and password explicitly
    User.findOne({
      username: req.body.username
    }).select('name username password').exec(function(err, user){
      if(err) throw err;

      // no user with that username was found
      if(!user){
        res.json({success: false, message: 'Authentication failed. User not found'});
      }else if (user) {
        //check if password is a match
        var validPassword = user.comparePassword(req.body.password);
        if(!validPassword) {
          res.json({success: false, message: 'Authentication failed. Wrong password'});
        }else {
          //if user is found and password matches
          var token = jwt.sign({
            name: user.name,
            username: user.username
          }, superSecret, {
            expiresInMinutes: 1440 //Expires in 24 hours
          });

          //return the information including token as json
          res.json({
            success: true,
            message: 'Here is your token',
            token: token
          });//End response json
        }
      }
    });
  });//End Post authenticate

  //TOKEN MIDDLEWARE
  // ====================================
  //Middleware to use before for all requests(Token varification)
  apiRouter.use(function(req,res,next){
    //logging
    console.log('A visitor has arrived');

    //Check Header OR Url parameters OR POST parameters for token
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    //Decode the token
    if(token){
      //Verifies secret and checks expiration
      jwt.verify(token, superSecret, function(err, decoded){
        if(err){
          return res.json({success: false, message: 'Failed token authentication'});
        }else {
          //If token checks out, save the request to be used in other routes
          req.decoded = decoded;
          next();//User may continue forward if they have a valid token
        }
      });

    }else {
      //if there is no token return 403(access forbidden) and an error message
      return res.status(403).send({success: false, message: 'No token Provided'});
    }

  });//End Middleware


  //TEST ROUTE
  // ====================================
  //Test Route
  apiRouter.get('/', function(req,res){
    res.json({message: "Welcome to the API"});
  });


  //API ROUTES USERS
  // ====================================================================
  //routes that end with /users --------------------
  apiRouter.route('/users')

    //CREATE a user on /api/users
    .post(function(req, res){
      //creat a new user instance from User model
      var user = new User();

      //set the users information that comes from requests
      user.name = req.body.name;
      user.username = req.body.username;
      user.password = req.body.password;

      //save user and check for errors
      user.save(function(err){
        if(err){
          //A duplicate was entered
          if(err.code == 11000){
            return res.json({success: false, message: 'A user with that username exists'});
          }else {
            return res.send(err);
          }
        }
        res.json({message: 'User created!'});
      });//End save
    })//End Post

    //GET all users at /api/users
    .get(function(req, res){
      User.find(function(err,users){
        if(err){
          res.send(err);
        }
        //Return all users
        res.json(users);
      });
    });//End Get



  //routes that end with /users:user_id --------------------
  apiRouter.route('/users/:user_id')
    //GET a single user at /users/:user_id
    .get(function(req,res){
      User.findById(req.params.user_id, function(err,user){
        if(err) res.send(err);

        // return the user
        res.json(user);
      });
    })//End Get

    //UPDATE the user with this id at /users/:user_id
    .put(function(req,res){
      //use user model to find the user we want
      User.findById(req.params.user_id, function(err,user){
        if(err) res.send(err);

        //update the users info only if it is new(no blanks)
        if(req.body.name) user.name = req.body.name;
        if(req.body.username) user.username = req.body.username;
        if(req.body.password) user.password = req.body.password;

        //save user
        user.save(function(err){
          if(err) res.send(err);

          // return message
          res.json({message: 'User has been updated!'});
        });//End save

      });//End find by id
    })//End Post

    //DELETE a user with this id at /users/:user_id
    .delete(function(req,res){
      User.remove({
        _id: req.params.user_id
      }, function(err, user){
        if(err) res. send(err);

        res.json({message: 'Succesfully deleted user'});
      });
    });

    //api endpoint to get user information
    apiRouter.get('/me', function(req, res){
      res.send(req.decoded);
    });

    //API ROUTES SURF
    // ====================================================================
    //routes that end with /surf --------------------

    apiRouter.route('/surf')

      //CREATE a surf on /api/surf
      .post(function(req, res){
        //create a new instance of the surf model
        var surf = new Surf();

        User.findOne({username: decoded.username}, function(err, user){
           req.user = user;
           next()
        })        

        //set the surf information that comes from requests
        surf.title = req.body.title;
        surf.longitude = req.body.longitude;
        surf.latitude = req.body.latitude;
        surf.comment = req.body.comment;
        surf.user_id = req.user._id;

        //save user and check for errors
        surf.save(function(err){
          if(err)
              res.send(err);

          res.json({message: 'Surf Session Created!'});
        });//End save

      })//End Post

      //GET all surf sessions at api/surf
      .get(function(req, res){
        // Use the Surf model to find all surf sessions
        Surf.find({ }, function(err, surfSesh) {
            if (err)
              res.send(err);

            res.json(surfSesh);
          });
      })//


    return apiRouter;

};
/models/user.js

// surf.js
var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

//SURF SCHEMA
//  ============================================
var SurfSchema = new Schema({
  title: String,
  longitude: Number,
  latitude: Number,
  comment: String,
  created: { type: Date, default: Date.now },
  user_id: {type: Schema.ObjectId, ref: 'User'}
});

var Surf = mongoose.model('Surf', SurfSchema);

module.exports = Surf;
//USER MODEL
// Require packages for User model
var mongoose = require('mongoose');
var Schema   = mongoose.Schema;
var bcrypt   = require('bcrypt-nodejs');

//USER SCHEMA
//  ============================================
var UserSchema = new Schema({
  name: String,
  username: {type: String, required: true, index: {unique: true}},//No duplicate usernames
  password: {type: String, required: true, select: false}//Do not return password
});

//HASH PASSWORD
//  ============================================

//Hash password before saving
UserSchema.pre('save', function(next){
  var user = this;

  //Hash password only if the password has been changed or is new
  if(!user.isModified('password')) return next();

  //Generate Salt
  bcrypt.hash(user.password,null, null, function(err,hash){
    if(err) return next(err);
      //Change the password to the hash version
      user.password = hash;
      next();
  });
});


//Create method to compare a given password with the database hash
UserSchema.methods.comparePassword = function(password){
  var user = this;

  return bcrypt.compareSync(password,user.password);
};

//Create User model out of userSchema
var User = mongoose.model('User', UserSchema);

module.exports = User;
    //api.js
var bodyParser = require('body-parser');
var User       = require('../models/user');
var Surf       = require('../models/surf');
var jwt        = require('jsonwebtoken');
var config     = require('../config');

//superSecret secret for creating tokens
var superSecret = config.secret;

//Pass in app and express to use express object for express.Router()
module.exports = function(app, express){
  // Instance of express Router
  var apiRouter = express.Router();

  //API AUTHENTICATE ROUTE
  // ====================================================================
  //Route for authenticating user at /api/authenticate
  apiRouter.post('/authenticate', function(req, res){
    //find the user and select username and password explicitly
    User.findOne({
      username: req.body.username
    }).select('name username password').exec(function(err, user){
      if(err) throw err;

      // no user with that username was found
      if(!user){
        res.json({success: false, message: 'Authentication failed. User not found'});
      }else if (user) {
        //check if password is a match
        var validPassword = user.comparePassword(req.body.password);
        if(!validPassword) {
          res.json({success: false, message: 'Authentication failed. Wrong password'});
        }else {
          //if user is found and password matches
          var token = jwt.sign({
            name: user.name,
            username: user.username
          }, superSecret, {
            expiresInMinutes: 1440 //Expires in 24 hours
          });

          //return the information including token as json
          res.json({
            success: true,
            message: 'Here is your token',
            token: token
          });//End response json
        }
      }
    });
  });//End Post authenticate

  //TOKEN MIDDLEWARE
  // ====================================
  //Middleware to use before for all requests(Token varification)
  apiRouter.use(function(req,res,next){
    //logging
    console.log('A visitor has arrived');

    //Check Header OR Url parameters OR POST parameters for token
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    //Decode the token
    if(token){
      //Verifies secret and checks expiration
      jwt.verify(token, superSecret, function(err, decoded){
        if(err){
          return res.json({success: false, message: 'Failed token authentication'});
        }else {
          //If token checks out, save the request to be used in other routes
          req.decoded = decoded;
          next();//User may continue forward if they have a valid token
        }
      });

    }else {
      //if there is no token return 403(access forbidden) and an error message
      return res.status(403).send({success: false, message: 'No token Provided'});
    }

  });//End Middleware


  //TEST ROUTE
  // ====================================
  //Test Route
  apiRouter.get('/', function(req,res){
    res.json({message: "Welcome to the API"});
  });


  //API ROUTES USERS
  // ====================================================================
  //routes that end with /users --------------------
  apiRouter.route('/users')

    //CREATE a user on /api/users
    .post(function(req, res){
      //creat a new user instance from User model
      var user = new User();

      //set the users information that comes from requests
      user.name = req.body.name;
      user.username = req.body.username;
      user.password = req.body.password;

      //save user and check for errors
      user.save(function(err){
        if(err){
          //A duplicate was entered
          if(err.code == 11000){
            return res.json({success: false, message: 'A user with that username exists'});
          }else {
            return res.send(err);
          }
        }
        res.json({message: 'User created!'});
      });//End save
    })//End Post

    //GET all users at /api/users
    .get(function(req, res){
      User.find(function(err,users){
        if(err){
          res.send(err);
        }
        //Return all users
        res.json(users);
      });
    });//End Get



  //routes that end with /users:user_id --------------------
  apiRouter.route('/users/:user_id')
    //GET a single user at /users/:user_id
    .get(function(req,res){
      User.findById(req.params.user_id, function(err,user){
        if(err) res.send(err);

        // return the user
        res.json(user);
      });
    })//End Get

    //UPDATE the user with this id at /users/:user_id
    .put(function(req,res){
      //use user model to find the user we want
      User.findById(req.params.user_id, function(err,user){
        if(err) res.send(err);

        //update the users info only if it is new(no blanks)
        if(req.body.name) user.name = req.body.name;
        if(req.body.username) user.username = req.body.username;
        if(req.body.password) user.password = req.body.password;

        //save user
        user.save(function(err){
          if(err) res.send(err);

          // return message
          res.json({message: 'User has been updated!'});
        });//End save

      });//End find by id
    })//End Post

    //DELETE a user with this id at /users/:user_id
    .delete(function(req,res){
      User.remove({
        _id: req.params.user_id
      }, function(err, user){
        if(err) res. send(err);

        res.json({message: 'Succesfully deleted user'});
      });
    });

    //api endpoint to get user information
    apiRouter.get('/me', function(req, res){
      res.send(req.decoded);
    });

    //API ROUTES SURF
    // ====================================================================
    //routes that end with /surf --------------------

    apiRouter.route('/surf')

      //CREATE a surf on /api/surf
      .post(function(req, res){
        //create a new instance of the surf model
        var surf = new Surf();

        User.findOne({username: decoded.username}, function(err, user){
           req.user = user;
           next()
        })        

        //set the surf information that comes from requests
        surf.title = req.body.title;
        surf.longitude = req.body.longitude;
        surf.latitude = req.body.latitude;
        surf.comment = req.body.comment;
        surf.user_id = req.user._id;

        //save user and check for errors
        surf.save(function(err){
          if(err)
              res.send(err);

          res.json({message: 'Surf Session Created!'});
        });//End save

      })//End Post

      //GET all surf sessions at api/surf
      .get(function(req, res){
        // Use the Surf model to find all surf sessions
        Surf.find({ }, function(err, surfSesh) {
            if (err)
              res.send(err);

            res.json(surfSesh);
          });
      })//


    return apiRouter;

};
/routes/api.js

// surf.js
var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

//SURF SCHEMA
//  ============================================
var SurfSchema = new Schema({
  title: String,
  longitude: Number,
  latitude: Number,
  comment: String,
  created: { type: Date, default: Date.now },
  user_id: {type: Schema.ObjectId, ref: 'User'}
});

var Surf = mongoose.model('Surf', SurfSchema);

module.exports = Surf;
//USER MODEL
// Require packages for User model
var mongoose = require('mongoose');
var Schema   = mongoose.Schema;
var bcrypt   = require('bcrypt-nodejs');

//USER SCHEMA
//  ============================================
var UserSchema = new Schema({
  name: String,
  username: {type: String, required: true, index: {unique: true}},//No duplicate usernames
  password: {type: String, required: true, select: false}//Do not return password
});

//HASH PASSWORD
//  ============================================

//Hash password before saving
UserSchema.pre('save', function(next){
  var user = this;

  //Hash password only if the password has been changed or is new
  if(!user.isModified('password')) return next();

  //Generate Salt
  bcrypt.hash(user.password,null, null, function(err,hash){
    if(err) return next(err);
      //Change the password to the hash version
      user.password = hash;
      next();
  });
});


//Create method to compare a given password with the database hash
UserSchema.methods.comparePassword = function(password){
  var user = this;

  return bcrypt.compareSync(password,user.password);
};

//Create User model out of userSchema
var User = mongoose.model('User', UserSchema);

module.exports = User;
    //api.js
var bodyParser = require('body-parser');
var User       = require('../models/user');
var Surf       = require('../models/surf');
var jwt        = require('jsonwebtoken');
var config     = require('../config');

//superSecret secret for creating tokens
var superSecret = config.secret;

//Pass in app and express to use express object for express.Router()
module.exports = function(app, express){
  // Instance of express Router
  var apiRouter = express.Router();

  //API AUTHENTICATE ROUTE
  // ====================================================================
  //Route for authenticating user at /api/authenticate
  apiRouter.post('/authenticate', function(req, res){
    //find the user and select username and password explicitly
    User.findOne({
      username: req.body.username
    }).select('name username password').exec(function(err, user){
      if(err) throw err;

      // no user with that username was found
      if(!user){
        res.json({success: false, message: 'Authentication failed. User not found'});
      }else if (user) {
        //check if password is a match
        var validPassword = user.comparePassword(req.body.password);
        if(!validPassword) {
          res.json({success: false, message: 'Authentication failed. Wrong password'});
        }else {
          //if user is found and password matches
          var token = jwt.sign({
            name: user.name,
            username: user.username
          }, superSecret, {
            expiresInMinutes: 1440 //Expires in 24 hours
          });

          //return the information including token as json
          res.json({
            success: true,
            message: 'Here is your token',
            token: token
          });//End response json
        }
      }
    });
  });//End Post authenticate

  //TOKEN MIDDLEWARE
  // ====================================
  //Middleware to use before for all requests(Token varification)
  apiRouter.use(function(req,res,next){
    //logging
    console.log('A visitor has arrived');

    //Check Header OR Url parameters OR POST parameters for token
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    //Decode the token
    if(token){
      //Verifies secret and checks expiration
      jwt.verify(token, superSecret, function(err, decoded){
        if(err){
          return res.json({success: false, message: 'Failed token authentication'});
        }else {
          //If token checks out, save the request to be used in other routes
          req.decoded = decoded;
          next();//User may continue forward if they have a valid token
        }
      });

    }else {
      //if there is no token return 403(access forbidden) and an error message
      return res.status(403).send({success: false, message: 'No token Provided'});
    }

  });//End Middleware


  //TEST ROUTE
  // ====================================
  //Test Route
  apiRouter.get('/', function(req,res){
    res.json({message: "Welcome to the API"});
  });


  //API ROUTES USERS
  // ====================================================================
  //routes that end with /users --------------------
  apiRouter.route('/users')

    //CREATE a user on /api/users
    .post(function(req, res){
      //creat a new user instance from User model
      var user = new User();

      //set the users information that comes from requests
      user.name = req.body.name;
      user.username = req.body.username;
      user.password = req.body.password;

      //save user and check for errors
      user.save(function(err){
        if(err){
          //A duplicate was entered
          if(err.code == 11000){
            return res.json({success: false, message: 'A user with that username exists'});
          }else {
            return res.send(err);
          }
        }
        res.json({message: 'User created!'});
      });//End save
    })//End Post

    //GET all users at /api/users
    .get(function(req, res){
      User.find(function(err,users){
        if(err){
          res.send(err);
        }
        //Return all users
        res.json(users);
      });
    });//End Get



  //routes that end with /users:user_id --------------------
  apiRouter.route('/users/:user_id')
    //GET a single user at /users/:user_id
    .get(function(req,res){
      User.findById(req.params.user_id, function(err,user){
        if(err) res.send(err);

        // return the user
        res.json(user);
      });
    })//End Get

    //UPDATE the user with this id at /users/:user_id
    .put(function(req,res){
      //use user model to find the user we want
      User.findById(req.params.user_id, function(err,user){
        if(err) res.send(err);

        //update the users info only if it is new(no blanks)
        if(req.body.name) user.name = req.body.name;
        if(req.body.username) user.username = req.body.username;
        if(req.body.password) user.password = req.body.password;

        //save user
        user.save(function(err){
          if(err) res.send(err);

          // return message
          res.json({message: 'User has been updated!'});
        });//End save

      });//End find by id
    })//End Post

    //DELETE a user with this id at /users/:user_id
    .delete(function(req,res){
      User.remove({
        _id: req.params.user_id
      }, function(err, user){
        if(err) res. send(err);

        res.json({message: 'Succesfully deleted user'});
      });
    });

    //api endpoint to get user information
    apiRouter.get('/me', function(req, res){
      res.send(req.decoded);
    });

    //API ROUTES SURF
    // ====================================================================
    //routes that end with /surf --------------------

    apiRouter.route('/surf')

      //CREATE a surf on /api/surf
      .post(function(req, res){
        //create a new instance of the surf model
        var surf = new Surf();

        User.findOne({username: decoded.username}, function(err, user){
           req.user = user;
           next()
        })        

        //set the surf information that comes from requests
        surf.title = req.body.title;
        surf.longitude = req.body.longitude;
        surf.latitude = req.body.latitude;
        surf.comment = req.body.comment;
        surf.user_id = req.user._id;

        //save user and check for errors
        surf.save(function(err){
          if(err)
              res.send(err);

          res.json({message: 'Surf Session Created!'});
        });//End save

      })//End Post

      //GET all surf sessions at api/surf
      .get(function(req, res){
        // Use the Surf model to find all surf sessions
        Surf.find({ }, function(err, surfSesh) {
            if (err)
              res.send(err);

            res.json(surfSesh);
          });
      })//


    return apiRouter;

};
我尝试了surf.user\u id=req.user.\u id; 但我不断地犯错误 读取属性“\u未定义的id”


在这里的else街区:

    }else {
      //If token checks out, save the request to be used in other routes
      req.decoded = decoded;
      next();//User may continue forward if they have a valid token
    }
您有一个已解码的令牌,这意味着您应该可以访问用户名。然后,您需要做的是获取用户模型,并将其设置为
req
对象,然后才调用
next()

User.findOne({username: decoded.username}, function(err, user){
   req.user = user;
   next()
})
---编辑----


在这里的else街区:

    }else {
      //If token checks out, save the request to be used in other routes
      req.decoded = decoded;
      next();//User may continue forward if they have a valid token
    }
您有一个已解码的令牌,这意味着您应该可以访问用户名。然后,您需要做的是获取用户模型,并将其设置为
req
对象,然后才调用
next()

User.findOne({username: decoded.username}, function(err, user){
   req.user = user;
   next()
})
---编辑----


您需要显示身份验证代码。您在哪里设置
req.user
对象?@YuriZarubin我已经包括了授权代码。我应该在surf POST中设置req.user对象吗?您需要显示身份验证代码。您在哪里设置
req.user
对象?@YuriZarubin我已经包括了授权代码。我应该在surf POST中设置req.user对象吗?我尝试使用Postman,但没有收到错误,说明decoded未定义。这没有意义,因此没有错误,decoded未定义?解码应该等于某种类型的数据。你能更新上面的代码以反映你所做的更改吗,我想确保它是正确的,这样我们就不会绕圈子了。是的,那完全是错误的地方,请参见编辑。是的,现在它起作用了!我走得太远了。非常感谢!我用邮递员试过了,我没有收到一个错误,说解码是未定义的。那没有意义,所以没有错误,解码是未定义的?解码应该等于某种类型的数据。你能更新上面的代码以反映你所做的更改吗,我想确保它是正确的,这样我们就不会绕圈子了。是的,那完全是错误的地方,请参见编辑。是的,现在它起作用了!我走得太远了。非常感谢!