dimanche 9 septembre 2018

hierarchical role based access control system

Business requires a very complicated access control system where users are granted/denied permissions based on multiple criteria at runtime. Just to give you an idea look at following rules for some resources for example.

  • Can view the list
  • Can view the detail
  • Can view the detail page but can not see the email address/phone number field
  • can edit the full doc
  • can edit only the phone number but can not set it to null as new value.
  • can remove the record altogether
  • can print the page only if not still a trainee

I hope you got the idea. There are about 100+ resources with each having between 20 to 90 similar such intertwined rules.

Considering the sheer size and complexity of the system, my team has decided to build a hierarchical role based access control system and below is our idea of how we are planning to tackle the problem.

  • use a simple class for each role

  • use inverted chain of command and add a ref for the roles current role is inherited from

  • current role class handles permissions unique to the current class only. and then continues all the way up (in real life downwards) to compute the full permission graph.

  • use decorators to handle the runtime calculations for cross cutting concerns for example limiting the delete permission if user is a trainee or he is still on probation or limit the access when user has resigned and just completing his last days at the company.

To put it into an example, a user is a manager but in probation duration and he wants to access the details of a client. here is the pseudo code

CountryManagerPermnissionsSpec()
{
    immediate_subordinates = ["RegionalManager", "ManagerHR"];
    accessible_resources = [
        "Finance": ["LIST", "DETAIL", "TRANSACTION_HISTORY", "REPORTS"] 

   ]

}

// class to limit the permissions when user is still under training 
TraineeUserPermissionsSpec()
{
     blocked_activites = ["delete", "bulk delete", "direct client message"];


}

Skipping out the implementation detail, we can compute the current users permission as below

new acl
acl->addRole(ContryManager)
acl->addRole(Trainee)

can_see_data = UserCanViewDataSpec(user, acl)

Now my question is, this leads us to a lot of tiny but testable classes, which is not a problem for us but is this the right approach towards handling such kind of a problem ? Is there any better alternate ?

I don't think it maters but just in case, current system is being built in php.

Aucun commentaire:

Enregistrer un commentaire