MongoDB + Node JS + Role Based Access Control (RBAC)

BeingSuman picture BeingSuman · Sep 28, 2016 · Viewed 18.6k times · Source

Am currently learning MEAN stack, developing a simple TODO's app and want to implement Role Based Access Control (RBAC) for that. How do i set up roles & permission on MongoDB.

I want 3 roles (roles may look funny but this is purely to learn) :

  • GOD
  • SUPER HERO
  • MAN

GOD - similar to super admin, can do anything in the application. C,R,U,D permissions for TODO's and for other users too. Can Create a TODO & assign it to any SUPER HERO or MAN directly. Update or Delete either a TODO or a User at any point in time.

SUPER HERO - similar to admin, has super power to do anything on his personal Data - C,R,U,D for TODO's. Can't create any users. Can only Read & add comments for TODO's created by GOD & assigned to him/her.

MAN - Can only Read and add comments to TODO's assigned to him/her.

To sum it up :

GOD - C,R,U,D [Global Level] SUPER HERO - C,R,U,D [Private] + R,U [Assigned to him] MAN - R,U [Assigned to him]

I understand that i need to have USERS & ROLES collections. Where ROLES inturn should have PERMISSIONS etc. How do i wire them all ?

Answer

swetha akula picture swetha akula · Oct 6, 2016

I like names given to roles - GOD, SUPER HERO & MAN, easy to understand.

As you are using MEAN stack and much of routes validation happens on node, i would prefer keeping roles table simple.

Roles :

{
_id : 1,
name : GOD,
golbalPerms : true
},
{
_id : 2,
name : SUPER HERO,
privatePerms : true
},
{
_id : 3,
name : MAN
}

Users :

{
_id : 111,
name : Jesus,
roleId : 1
},
{
_id : 222,
name : BatMan,
roleId : 2
},
{
_id : 333,
name : Jack,
roleId : 3
}

When user logs in and sending user object back to client, make sure to replace roleId with corresponding role object from DB.

Coming to code on Node JS :

By completely understanding your usecase we can divide them into following methods -

  • CreateUser

  • CreateTodo

  • DeleteTodo

  • ReadTodo

  • UpdateTodo
  • CommentTodo

  • AssignTodo

Lets go step by step, CreateUser.

Routes code snippet :

app.all('/users', users.requiresLogin);

// Users Routes
app.route('/users')
    .post(users.hasPerms('globalPerms'), users.create);

In your Controller you can validate based on the input globalPerms, if validated allow to create user by calling next() else return with corresponding error message.

Now CreateTodo && DeleteTodo :

Both of them pretty much work on same logic with a small trick.

Routes code snippet :

app.all('/todos', users.requiresLogin);

// Users Routes
app.route('/todos')
    .post(users.hasPerms('globalPerms','privatePerms'), todos.create);
    .delete(users.hasPerms('globalPerms','privatePerms'), todos.delete);

For creating a Todo, globalPerms are with GOD & privatePerms are with SUPER HERO, both of them can be allowed.

Trick here will be in todos.delete method, just ensure user.id === todos.createById else SUPER HERO may go on to delete Todos created by GOD.

ReadTodo :

When a TODO is created it should have a createById stored likewise when a TODO is assigned to someone then assignedTo and assignedBy should be recorded too.

This makes lot of other operations easy to handle.

user.role.globalPerms - give GOD all TODO's data.

user.role.privatePerms - give TODO's either createdBy him/her or assigned to him/her.

user.role.globalPerms === undefined && user.role.privatePerms === undefined - its MAN and give TODO's which are only assignedTo him.

UpdateTodo & CommentTodo :

This is exact replica of what ReadTODO does so DIY

Last one, AssignTodo :

Simple one, loggedInUser.id === todos.createdById then he can assign it to anyone.

Two things to keep in mind here :

  1. As assigning part mostly happens on your UI (Angular) front, i have given that approach of checking loggedInUser.id === todos.createdById. Logged in user any ways will see all TODO's by read operation and can assign it to anyone he/she likes.

  2. Make sure a SUPER HERO can only assign a TODO to himself or other SUPER HERO or to a MAN but not to GOD. How you show Assign to options on UI front is out of scope of this question. This is just a heads up.

Hope this was clear.

NOTE : There was no necessity to give permissions to MAN in Roles collection & we managed all possible operations with out that.