@vincent15000 In our application, we have groups table has name and json field permissions, and also another column for the shop_id (because we've multiple shops). Every user in the app is assigned to a group, and we've auth service built on top of laravel, and that service has a method called allowed(string $action) and it returns boolean. Anyway, in the groups.permissions you would store action names e.g : {"edit_profile":1}, and in the editProfile() method you would check if the user is allowed to do this action by authService->user()->allowed('edit_profile') and you do your thing.
In this case, you've more flexibility and you don't have to hard check for user role. For complete access, we've a group with the permission "superuser:1" and the authService knows that user with this permission will always be allowed to access everything.
Laravel with multiple role user : is my database design ok ?
Hello,
It's the first time that I work on an app with multiple roles. And I'd like your advice if I have a good design for the database and rights management.
I have thought about using Spatie permissions and roles, but I don't think that I really need such a package. And perhaps also the desire to do it by myself (good idea ?).
Here are my tables.
users: id, name, email
companies: id, name
members: id, company_id, user_id
roles: member_id, role_id
...
trainings: id, name, company_id
training_trainer: training_id, trainer_id
training_student: training_id, student_id
The roles are written in a configuration file, I have these ones.
owner: 0 // can access to all datas and create / update / delete what he wants
admin: 1 // can access to all datas and create / update / delete what he wants except the company and the owner
manager: 2 // can access to datas like trainings, trainers
accountant: 3 // can only check the number of hours per trainer for each training
trainer: 4 // can only access to the calendar of the trainings to which he is assigned and can store tests / results for each student
student: 5 // can only access to the calendar of the training to which he is subscribed
I manage the rights with policies. For example if a user connect, he will be attached to a company and I check the roles of this user for that company. And to write the policy of a training, I will write a condition to not allow a trainer (role 4) to create or update or delete a training, but only view those one to which he is assigned.
Is this a good pratice ? Do I have the right approach ?
Instead of having a roles table, I thought about writing the roles in a JSON column in the members file.
members: id, company_id, user_id, roles // there are easy to use queries (```whereJsonContains()```) to check some data inside a JSON field
With a JSON field, it's more easy to check the roles for each member, for example exclude some possibilities like : a member cannot be trainer and student at the same time for the same company.
Well ... for the moment I can manage the roles quite well, but I'm afraid that this structure can add complexity when adding new functionalities to the app.
What can you suggest me ? Do I have the good approach ? Perhaps a better database structure ? Other advice ?
If you accept to share your experience, it would be great ;).
Thanks a lot.
V
@vincent15000 I look at it like:
-
Bob is an admin
-
Suzy is admin and does bookkeeping
-
Mary is a bookkeeper only
-
If Bob is logged in, Bob can only do admin stuff and all access to user stuff. But Bob cannot mess with bookkeeping.
-
If Suzy is logged in she can access admin stuff and bookkeeping and accounting stuff.
-
If Mary is logged in she cannot mess with admin stuff, but has access to bookkeeping and accounting stuff.
So I just check at method level if the logged in users role can or cannot access that method / function.
And use query scopes to let a user edit / view their own data or an admin can access all users data.
Each app will be different as to who can do what.
So in pseudocode:
public function makeInvoice()
{
if (a required role of bkeep is not true here) { // bkeep = bookkeeper
return redirect('somewhere'); // whereever you redirect to if not authorized
}
// Rest of method here is accomplished if
// the logged in user has the required role of 'bkeep'.
}
Again just examples.
Another example I saw:
public function update(Request $request, Post $post) {
if ($post->author !== auth()->user()->id || auth()->user()->cannot('edit posts'))
abort(404);// or redirect, or whatever action
}
//rest of method if all okay
}
In summary RBAC is at least 3 main steps:
- A login required
- An authorization implementation to determine what the logged in person with role can or cannot do
- Protection of URL and parameters, checking that the logged in users id matches the id used in a query
Each application will require unique tweaks in RBAC, no two apps are exactly the same.
Please or to participate in this conversation.