When a new user account is created, I create newUser, a Mongoose model instance that looks like:
_events: Object
errors: undefined
isNew: false
save: function () {
arguments: null
caller: null
_doc: Object
name: 'Joe Smith'
...
The actual data for the object is in the _doc property, though getters and setters exist so you can run:
user.name = 'Jane Doe'
and that will work fine. I run:
request.session.user = newUser;
To save the user to the session. So far, so good.
However, in subsequent requests, request.session.user seems to be only the stuff in _doc. Eg:
name: 'Joe Smith'
Which is nice, but that means I can't run eg, request.session.user.save() to save changes.
I could simply make some middleware to look up the user associated with the data. But I'd like to know more about what Express and Mongoose are doing here.
How can I make request.session.user be a Mongoose model?
Update: my current middleware hack:
// Use as a middleware on routes which need users
// TODO: only needed due to request.session.user being saved weirdly
var rehydrateUser = function(request, response, next) {
if ( request.session.user ) {
var hydrated = request.session.user.save
if ( ! hydrated ) {
console.log('Rehydrating user...');
models.User.findOne({ somefield: request.session.user.somefield }, function (err, user) {
if ( err ) {
request.session.error = 'User not found in DB!';
request.redirect('/');
} else {
request.session.user = user;
console.log('Rehydrated user! All repos already being monitored.');
next();
}
})
} else {
next();
}
} else {
console.log('No user in session')
next();
}
}
A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc.
Cookie session is basically used for lightweight session applications where the session data is stored in a cookie but within the client [browser], whereas, Express Session stores just a mere session identifier within a cookie in the client end, whilst storing the session data entirely on the server.
For example, if we want every document where the value of the name field is more than one value, then what? For such cases, mongoose provides the $in operator. In this article, we will discuss how to use $in operator. We will use the $in method on the kennel collection.
Mongoose requires a connection to a MongoDB database. You can require() and connect to a locally hosted database with mongoose. connect() as shown below (for the tutorial we'll instead connect to an internet-hosted database). You can get the default Connection object with mongoose.
Express session is stored as separate storage and has limitations to what can be stored there. It cannot store prototype data (methods). Look at it more like key<>value
storage.
Reasons for this is that session can be stored anywhere (pretty much), such as: process memory; databases (mongodb); redis; etc.
Because of this, once you put anything in session object and request is finished, express will take session data, parse it and stick into session store just as pure object. By default it is process memory, but as mentioned before - can be any other storages.
So when next http request happens, session middleware will try to restore session using cookie (if it is used) data in request headers, and will ask session storage to provide data back. As it is already formatted - it will not have .prototype stuff but just data (object
, array
, string
, number
, and other simple stuff).
So you need to create Model out of that data again.
You can do by middleware in express. So in app.configure
straight after defining session
you can do this:
app.use(function(req, res, next) {
if (req.session && req.session.user) {
req.session.user = new UserModel(req.session.user);
}
return next();
});
This will check if session is defined as well as user. And then will recreate mongoose model out of that data.
As mentioned here in comments - you should not store user data in session as it will lead to inconsistencies due to split of responsibilities over ownership of data.
So store just ID
of user, and then using middleware load it from Database.
app.use(function(req, res, next) {
if (req.session && req.session.userID) {
UserModel.findById(req.session.userID, function(err, user) {
if (!err && user) {
req.user = user;
next();
} else {
next(new Error('Could not restore User from Session.'));
}
});
} else {
next();
}
});
After you can create middleware to check if user is logged in:
function userRequired(req, res, next) {
if (req.user) {
next();
} else {
next(new Error('Not Logged In');
}
}
And use it like that:
app.get('/items', userRequired, function(req, res, next) {
// will only come here if user is logged in (req.user !== undefined)
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With