1ManStartup
1ManStartup

Reputation: 3816

How to Post and Get Data Unique to Each Logged In User with Express and Mongoose?

I am currently working on a small single page app that lets users login with PassportJs and Mongoose.

One of the things I am trying to do is allow users to login and each user has a unique todo/task list which are items associated to that user.

I have been able to do the first part...users can login and express/passport session is accessed using jade #{user.username}, so when logged in the user see "Welcome, [user.username]".

Now I add a form (accessible when user logged in) and the form says undefined. I'm not sure if its my Mongoose schema design or Routes that are causing the problem. Thanks for reading this and here is my code:

Mongoose Schema

mongoose.connect('mongodb://localhost/poplivecore')
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var user = new Schema({
username: String,
password: String,
email: String,
todos: [Todo]
});

var Todo = new Schema({
name: {type: String, default : ''},
user: {type: Schema.ObjectId, ref: 'user'},
createdAt  : {type : Date, default : Date.now}

})


var Todo = mongoose.model('Todo', Todo);
var user = mongoose.model('user', user);

Here are my Express routes: //WORKING....This route is the one that a logged in user sees, form posts with

app.get('/home', ensureAuthenticated ,function(req, res){
res.render('home', { user: req.user});
});

//WORKING...This route allows user to post/submit the login

app.post('/login', 
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
res.redirect('/home');
});


//WORKING....This route allows user to create a user/account    

app.post('/create', function(req, res, next){
var user = new user({
"username": req.body.username, 
"password" : req.body.password,
"email" : req.body.email});


user.save(function (err) {
if (!err) {
  res.redirect('/home');
}
else {
  res.redirect('/');
  }
 });
});



**//NOT WORKING..Post used in the form inside the logged in Area, that adds a 'todo'** 

app.post('/todo', function(req, res){
var todo = new todo(req.body.name);

todo.save(function (err) {
if (!err) {
  res.redirect('/home');
}
else {
  res.redirect('/fail');
  }
 });
});

Jade Form, for Adding a todo

enter code here
form(method='post', action='/todo')
 //input(type='hidden', value= user._id)#userId
 fieldset
  label Todo
   div.input
    input(name='todo.name', type='todo.name', class='xlarge')
   div.actions
    input(type='submit', value='Save', class='btn primary')
    button(type='reset', class='btn') Cancel

I can post on github if you need to see more code...thanks.

Update as per 'numbers1311407' suggesion *New post route for todo, also changed todo to 'Todo' in both schema and routes*

app.post('/todo', function(req, res){
var todo = new Todo({name : req.body["Todo.name"]});


 todo.save(function (err) {
 if (!err) {
  res.redirect('/home');
 }
 else {
  res.redirect('/fail');
 }
 });
});

Upvotes: 2

Views: 7588

Answers (1)

numbers1311407
numbers1311407

Reputation: 34072

There are at least two problems here that would cause this to not work:

  1. The name of the input passed by your form is todo.name, and you're referencing it as req.body.name in the route.

  2. mongoose models are instantiated with an attributes object, but you're just giving it a string (which, actually, is null currently because of the first issue).

So for your route to work it would look more like this:

app.post("/todo", function (req, res) {
  var todo = new Todo({name: req.body["todo.name"]});
  todo.user = req.user._id;
  // ...
});

If you wanted to pass todo attributes as a parameter object, you'd want to name them with brackets todo[name], rather than dots. This would result in the todo attributes being on object on the req.body, e.g.:

app.post("/todo", function (req, res) {
  console.log(req.body.todo); //=> { name: "whatever" }
  // ... which means you could do
  var todo = new Todo(req.body.todo);
  todo.user = req.user._id;
  // ...
});

Some other things you might want to change:

  1. As @NilsH points out, you don't want to pass the user id in the form, as that would allow anyone to make a todo for anyone else just by knowing their ID. Rather since you're using passport, make use of the user in the session. You should have access to the user ID through the passport determined user, like req.user._id. I added this to both examples above.

  2. The type of your form input is todo.name. It should be text (that's what the browser is treating it as anyway).

  3. Not necessarily an error, but model names are conventionally capitalized. This also solves an issue your code has above in that you're redefining todo when you say var todo = new todo(...).

Upvotes: 3

Related Questions