I am building an app with nodejs and expressjs. For authentication and user roles I am using respectively passport and connect-roles.
I have built the connect-roles object as shown in here: https://github.com/ForbesLindesay/connect-roles
Like so:
var user = new ConnectRoles()
This is in my app.js. Then I have exported such object like so:
exports.user = user;
However, if I import this object with require I see a strange behavior, please check code below:
var express = require('express');
var router = express.Router();
var user = require('../app.js');
//1
console.log(user);
/* GET users listing. */
router.get('/', function(req, res) {
//2
console.log(user);
res.send('respond with a resource');
});
module.exports = router;
The object is undefined in case 1 and is as it should be in case 2. Basically, I get 2 different objects depending if I am inside or outside the router.get function. I have been debugging this for half day, but I can't figure out what is happening.
The issue is that this object should be injected to provide roles management like so:
router.get('/', user.is("admin"), function(req, res) {
Of course this gives an error since user outside the get function object is undefined. The error is "cannot call method is of undefined".
I can't see how user would be undefined there... but I can suggest that you use
module.exports = user
As this will give you the object:
{ functionList: [],
failureHandler: [Function: defaultFailureHandler],
async: false,
userProperty: 'user' }
Rather than:
{ user:
{ functionList: [],
failureHandler: [Function: defaultFailureHandler],
async: false,
userProperty: 'user' } }
With your current implementation you could do:
router.get('/', user.user.is("admin"), function(req, res) {
If this does not solve your issue you may need to provide app.js in it's entirety.
The problem you have is most likely a cyclic dependency. Your router file requires your app.js file and your app.js file requires your router. What this means is that your router file gets a partially initialised object, that is only later filled in. The best way around this is to factor out the roles into a separate module, then require it from both places. i.e. have an authorisation.js file that looks like:
var ConnectRoles = require('connect-roles');
var user = new ConnectRoles();
// set up all the authorisation rules here
module.exports = user;
Then in both app.js and the router file, do var user = require('./authorisation.js');
This is a general problem whenever you create cyclic dependencies, and is not specific to connect-roles.