Show / hide menus according to user profile / role

1

Good, my query basically is to guide me how to solve my problem in the most optimal way,

I have a web with backend in nodejs where I send the static files (I do not use jade templates), I do all the modifications with javascript and ajax calls, my question is how to mount a menu (navbar) based on user permissions. adminitrator, normal user ...

The back I have mounted and depending on the role I can send an html or another but it seems excessive to have to duplicate thousands of pages to change only the memu where any other option appears.

Another option is to change it in the front from a js but it seems more vulnerable.

Does someone give me some guidance?

Thanks

    
asked by Rulogarcillan 01.10.2016 в 11:44
source

2 answers

1

I in PHP do something like this:

In the navbar I add a conditional, that if it has such permission, it appears such thing, for example, I am an administrator and I have to see the control panel in the navbar.

if($_SESSION['rol'] == 'admin') {
  <li>Panel de control</li>
}

Is that what you're looking for?

Greetings!

    
answered by 01.10.2016 в 14:09
1
  

Warning : The code presented here has not been tested. It is likely that you will find typo or code errors that must be fixed.

  

I'm not using templates

You should use, that is, if you want to do something whose possibilities are limited in one way, you should look for some other way that gives you the possibility to do it.

Taking into account the following ER diagram (I know it is NoSQL, but it is only for illustration):

We can deduce that:

  • A Permiso is the access given to a Rol on a given SubMenu .
  • A Rol is a set of Permisos predetermined, giving it a name. For example, the Rol Administrador can have permissions to:
    • Read
    • Delete
    • Edit
    • Ban;)

With this data we could build a scheme in Mongo.

Creation of models

Role

const RoleSchema = mongoose.Schema(
{
    name: {
        type: String,
        required: true
    },
    permissions: [{
        type: String,
        ref: 'Permission'
    }]
});

Permission

const PermissionSchema = mongoose.Schema(
{
    name: {
        type: String,
        required: true
    },
    description: {
        type: String,
        required: true
    }
});

MenuItem

const MenuItemSchema = mongoose.Schema(
{
    label: {
        type: String,
        required: true
    },
    url: {
        type: String,
        required: true
    },
    permissions: [{
        type: String,
        ref: 'Permission',
        required: true
    }]
});

Menu

const MenuSchema = mongoose.Schema(
{
    label: {
        type: String,
        required: true
    },
    url: {
        type: String,
        required: false,
        default: '#'
    },
    roles: [{
        type: String,
        ref: 'Role'
    }],
    items: [{
        type: String,
        ref: 'MenuItem'
    }]
});

Once you have the whole scheme, there are two things left:

  • When the user logs in, bring the menu according to their role.
  • That menu must be processed in view engine in order to build the menu.
  • Creating the menu with Handlebars

    The first thing we have to do is get the menus and the items according to the user's role and permissions (I assume you know how to check Mongo). Then, we created the complete menu in handlebars .

    menu.hbs

    <ul class="menu">
        {{#each menus as menu}}
            {{#ifRoleAllowed menu.roles id ../user.roles}}
                <li>
                    <a href="{{menu.url}}">
                        {{menu.label}}
                    </a>
                    <ul>
                        {{#each menu.items as item}}
                            {{#ifPermInRole item.permissions id ../user.roles}}
                                <li>
                                    <a href="{{item.url}}">
                                        {{item.label}}
                                    </a>
                                </li>
                            {{/ifPermInRole}}
                        {{/each}}
                    </ul>
                </li>
            {{/ifRoleAllowed}}
        {{/each}}
    </ul>
    

    The helper ifRoleAllowed and ifPermInRole do not belong to Handlebars . Handlebars allows you to extend it using custom helpers. Thus, we can create a helper that tells us if the user is allowed for the action of that menu and / or item:

    ifRoleAllowed

    Handlebars.registerHelper('ifRoleAllowed', function(mroles, uroles, options) {
      let isAllowed = false;
      mroles.forEach(mrole => {
        if(!isAllowed) {
            uroles.forEach(urole => {
                // son roles iguales
              if(urole === mrole) {
                isAllowed = true;   
              }
            });
        }
      });
    
      if(isAllowed) {
        return options.fn(this);
      }
      return options.inverse(this);
    });
    

    ifPermInRole

    Handlebars.registerHelper('ifPermInRole', function(perms, roles, options) {
      let isAllowed = false;
      perms.forEach(perm => {
        if(!isAllowed) {
            roles.forEach(role => {
              if(role.contains(perm)) {
                isAllowed = true;
              }
            });
        }
      });
    
      if(isAllowed) {
        return options.fn(this);
      }
      return options.inverse(this);
    });
    
        
    answered by 01.10.2016 в 18:37