Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express.js/Mongoose user roles and permissions

I am creating a fairly simple site with Node, Express and Mongoose. The site needs to have have user roles and permissions. My thoughts are that i'll validate permissions based on user interaction with the data base.

In mongoose is there a way to determine the type of CRUD operation currently being carried out possibly by a user?

like image 401
tkiddle Avatar asked Jun 18 '14 13:06

tkiddle


People also ask

How do I give a user permission in MongoDB?

MongoDB: db.grantRolesToUser() method is used to grants an additional role and its privileges to a user. The name of the user to whom to grant roles. An array of additional roles to grant to the user. The level of write concern for the modification.

How do I manage a user role in node JS?

Add permissions array field to data model and create a permission list (to better organize) to the user data model. set up a middleware to add to your routers. set up groups to allow the user of your routers, and pass them through routers.

How do I view roles in MongoDB?

getRoles() returns inheritance information for the database's user-defined roles. Set this field to 1 to retrieve all user-defined roles. Optional. Set the field to true to show role privileges, including both privileges inherited from other roles and privileges defined directly.

Which dependency is required in the Express app to use Mongoose?

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.


2 Answers

I've found a solution. It would be great to hear peoples opinions on this.

I have a permissions config object which defines each role and their permissions.

Permissions config object

roles.admin = {
    id: "admin",
    name: "Admin",
    description: "",
    resource : [
        {
            id : 'blog', 
            permissions: ['create', 'read', 'update', 'delete']
        },
        {
            id : 'user',
            permissions: ['create', 'read', 'update', 'delete']
        },
        {
            id : 'journal',
            permissions: ['create', 'read', 'update', 'delete']
        },

    ]
};

roles.editor = {
    id: "editor",
    name: "Editor",
    description: "",
    resource : [
        {
            id : 'blog', 
            permissions: ['create', 'read', 'update', 'delete']
        },
        {
            id : 'user',
            permissions: ['read']
        },
        {
            id : 'journal',
            permissions: ['create', 'read', 'update']
        },

    ]
};

Middleware function

var roles = require('./config');


var permissions = (function () {

  var getRoles = function (role) {

    var rolesArr = [];

    if (typeof role === 'object' && Array.isArray(role)) {

        // Returns selected roles   
        for (var i = 0, len = role.length; i < len; i++) {
            rolesArr.push(roles[role[i]]);
        };
        return rolesArr;

    } else if (typeof role === 'string' || !role) {

        // Returns all roles
        if (!role) {
            for (var role in roles) {
                rolesArr.push(roles[role]);
            };
        }   

        // Returns single role
        rolesArr.push(roles[role]);
        return rolesArr;

    }

},
check = function (action, resource, loginRequired) {

    return function(req, res, next) {

        var isAuth = req.isAuthenticated();

        // If user is required to be logged in & isn't
        if (loginRequired  && !isAuth) {
            return next(new Error("You must be logged in to view this area"));
        }

        if (isAuth || !loginRequired) {

            var authRole = isAuth ? req.user.role : 'user', 
                role =  get(authRole),
                hasPermission = false;

            (function () {
                for (var i = 0, len = role[0].resource.length; i < len; i++){
                    if (role[0].resource[i].id === resource && role[0].resource[i].permissions.indexOf(action) !== -1) {
                        hasPermission = true;
                        return;
                    }
                };
            })();

            if (hasPermission) {
                next();
            } else {
                return next(new Error("You are trying to " + action + " a " + resource + " and do not have the correct permissions."));
            }

        }
    }
}

return {
    get : function (role) {

        var roles = getRoles(role);

        return roles;
    },
    check : function (action, resource, loginRequired) {
        return check(action, resource, loginRequired);
    }
}

})();

module.exports = permissions;

Then i created a middleware function, when the check method gets called it gets the users role from the req object (req.user.role). It then looks at the params passed to the middleware and cross references them with those in the permissions config object.

Route with middlware

app.get('/journal', `**permissions.check('read', 'journal')**`, function (req, res) {
     // do stuff
};
like image 103
tkiddle Avatar answered Sep 18 '22 22:09

tkiddle


Check the Node module permission for that matter. It's pretty simple concept, I hope they'll allow all CRUD methods too.

like image 23
Tommz Avatar answered Sep 17 '22 22:09

Tommz