vincent15000's avatar

Roles design

Hello,

To handle roles in an application, how to do with this situation ?

  • superadmin

  • admin

  • manager

  • worker

Here are some details about the roles.

The application will be used by several companies.

The superadmin can check the subscriptions and manage the shared datas (accessible by all the subscribers).

The admin also manages the shared datas, but doesn't have access to the subscriptions.

The superadmin and the admin can also use the application as any subscriber, so they are also managers.

The manager can manage his team by creating users and assigning them manager / worker roles.

The manager can also do all what a worker can do.

MY QUESTION

My first idea was to have a hierarchical set of roles : superadmin => admin => manager => worker. And for example an admin inherits all permissions of a manager and a worker. In this situation each user has a unique role.

But there is another idea : all users can have one or many roles and each role has it own permissions without any hierarchy between roles.

What are the advantages and disadvantages for both ways to handle roles ?

Thanks for your response.

V

0 likes
6 replies
JussiMannisto's avatar

I wouldn't build an inheritance-like system. If you ever need more granularity, you may run into unresolvable conflicts. An example: the manager role is needed to access reports, or to message customers. But then company A needs a worker role that can access reports, and company B needs a worker role that can message customers. You can't place both of those roles in the inheritance chain without one of them affecting the other.

You could have multiple roles per user. But I prefer to use a combination of roles and abilities: each user has a single role, and every role has N abilities. This way you can create as many roles as you need, and accomodate any special case.

1 like
vincent15000's avatar

@JussiMannisto What you desribe me is the more flexible possibility for the managers so that they can ever create custom roles and assign each role the abilities he wants.

I think that I don't need such a flexibility, but just avoid conflicts.

Roles are well defined (as described in my post) ... and ... well ... your arguments are ok, it's surely a best choice to not have hierarchical roles.

martinbean's avatar
Level 80

@vincent15000 I’d just have roles at both the user-level and “company” level for this, and policies to check what the user can do based on these roles.

Add a nullable role column to your users table so you can set whether a user is a “super-admin” or regular admin. In your company-to-user pivot table, again have a role column that designates what role the user has within that company.

You can then use policies to check what a user can do based on both their company role and user role (if they have one). You can just intercept gate checks and return true if the user has the “superadmin” role and can therefore do anything:

Gate::before(function (User $user, string $ability) {
    if ($user->role === 'superadmin') {
        return true;
    }
});

You can then check a user’s companies to see if they should be able to view the given company:

Gate::define('view-company', function (User $user, Company $company) {
    return $user->companies->contains($company);
});

This gate check will return true if the user is associated with the given company. If the user is a superadmin then this gate won’t even be checked; the before action above will have already returned true allowing the user to view a company, whether they’re associated with it or not.

I use this approach in my own multi-tenant CMS where there are permissions at the website-level, but I as the developer of the application still need to be able to view and manage all websites and their data.

1 like
Tray2's avatar

I would take @martinbean's suggestion one step further, and add a role_user table and store the users roles there, that way you don't need to make changes to the users table.

1 like
costa-developer's avatar

I think the best way to handle this is to avoid strict role inheritance and instead go with a more flexible setup. A hierarchy sounds simple at first, but as soon as one company wants an exception like giving a “worker” permission to do something normally reserved for a “manager”, you run into conflicts you can’t solve cleanly.

A better approach is to separate roles and permissions. Each role defines a set of abilities (for example: “create users,” “manage subscriptions,” “view reports”), and users can either have one role or multiple roles depending on your needs. This way, you’re not locked into a rigid chain, and you can easily adjust things if requirements change later.

Since this is a multi-tenant app, I’d suggest having roles at two levels:

Global roles (like Superadmin) that apply across the whole system.

Company-level roles (like Manager or Worker) that apply only inside a specific company.

From there, you can use policies or gates to decide what a user can or can’t do. For example, if the user is a superadmin, they automatically get access everywhere. Otherwise, their abilities come from their company role.

1 like
vincent15000's avatar

@jussimannisto @martinbean @tray2 @costa-developer @ghabe Thank you very much all.

I never used hierarchical roles, but I wondered if it was a good idea in this situation.

Now it's sure, I won't use hierarchical roles.

In my case, I'm not sure that any superadmin, admin or manager would have to change any permission, it's not justified in this little application.

But each user will have one or many roles, each role having its own fixed permissions for the moment. And superadmin, admin and manager will be able to assign roles (one or many) to their respective team members.

Doing like this, it's not difficult to add a permissions customization functionality for the superadmin, admin and manager if needed in the future. So effectively this solution is more flexible and more evolutive.

Once again thank you all ;).

Please or to participate in this conversation.