In a node.js application, how can I asynchronously achieve the effect of a rails controller before_filter?
I have a node.js Express application with a basic user authentication system where the session is stored in redis. I'd like to write and re-use a current_user() function that populates a JSON representation of the logged in user (if there is one) in a current_user variable. Here is the code to retrieve the user:
if( req.cookie('fingerprint') ) {
redis_client.get("users:fingerprint:"+req.cookie("fingerprint"), function(err,id) {
redis_client.get("users:id:"+id, function(err,user) {
current_user = JSON.parse(user);
})
})
}
if I only wanted to use this once, I could put a res.render
call after that current_user
line, but I'd like to populate the current_user variable for all controllers and actions.
I'm new to node, so there's probably a fundamental concept I'm missing here...but basically I need a way to return the current_user variable f开发者_高级运维rom above in a synchronous context or achieve the same effect asynchronously. For example,
app.get('/', function(req,res) {
current_user = current_user();
res.render('home', {layout: "layout.ejs", locals: {current_user: current_user}})
})
Thanks.
Express routes accept a third argument: next
, this allows you to pass control to the next matching route. You could use this to build up before filters based on routes, like:
app.get('/admin', function(req, res, next){
if(authenticated_user()) {
req.user = get_user();
next();
}
else // prompt for login
});
app.get('/admin/:id', function(req, res){
// foo
}
Hope this helps, for more information see Passing Route Control in the official Express guide
update
A DRYer way to achieve the same using the oh-so-cool Route Middleware
function checkAuthentication(req, res, next){
if(authenticated_user()) {
req.user = get_user();
next();
}
else // prompt for login
}
app.get('/admin/:id', checkAuthentication, function(req, res){
// foo
});
Why don't you just use dynamicHelpers?
firstly, store your current user in a session. Since you are using redis, check out something like the connect-redis for express. Then store it in session like so:
if( req.cookie('fingerprint') ) {
redis_client.get("users:fingerprint:"+req.cookie("fingerprint"), function(err,id) {
redis_client.get("users:id:"+id, function(err,user) {
req.session.user = JSON.parse(user);
})
})
}
Make it available as a dynamicHelper:
app.dynamicHelpers({
current_user: function(req) {
return req.session.user;
}
});
now current_user is available to all your route handlers as well as the views!
app.get('/admin/:id', function(req, res){
if(current_user) {
//do what you want here...
}
});
on login, just regenerate the session like so:
req.session.regenerate(function() {
// same as above!
req.session.user = JSON.parse(user);
});
on logout, destroy the session:
req.session.destroy(function() {
res.redirect('/');
});
精彩评论