Express.js/Mongoose user roles and permissions

前端 未结 5 496
青春惊慌失措
青春惊慌失措 2021-01-31 12:14

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

5条回答
  •  时光说笑
    2021-01-31 12:39

    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
    };
    

提交回复
热议问题