I'm using CakePHPs ACL to handle user permissions.
When a user creates a, lets say Post, I automatically create an ACO for that post, and allow the user to access it.
But, if I would like to change the user later on so that a different user "takes over" the ownership of the post, what would I do in the ACL?
Is there a delete/remove ACL function I can use to remove rows, and the add the new relationship?
I thought about using deny on the old user, and then allow all on the new one, but it would be messy if the parent group has both allow/deny in the structure.
Are there any alternatives, other than using manual sql queries?
Related
I'm currently working on a project where a user can have many roles, and each role has assigned one or many permissions. Permissions describe the actions that a user can apply to ressources. For example let's consider that I have three ressources that I can interact with using my API : users, books, payments.
I'd like to have all users able to update their personal informations like phone number... etc. This led me to give update permission on user's ressource for all users. But the problem is that I want them to be able to updates their own profiles only. Furthermore, some users have admin permissions and can change other users permissions, therefor they have another kind of update permission on user's resource.
So my question is : what's the best way to design the permission table. Below you can find my schema design. Thank you for your answers in advance.
User(firstName string, lastName string, roles Role[])
Role(name string, description string, permissions Permission[])
Permission(name string, effect 'Allow' | 'Deny', resource string, action string)
Well I am not entirely sure what you meant by resource and action. If you meant URI template and HTTP method, then ok. Otherwise you might need a different solution or somehow add parameters to your design if you want to allow or deny individual resources per id.
If we are talking about a REST API, which I assume, then you can do something like PATCH /api/v1/current-user/profile {...} for updating your profile and PATCH /api/v1/users/{user-id}/profile {...} to update somebody else's profile. If you meant controller classes and their methods, then you can do the same with two different controllers, something like CurrentUser.partialUpdate(params) and User.partialUpdate(params).
As of updating user permissions, I wonder how to do it, because you can update only role permissions and give or take away roles for the users in your model.
Another thing I don't understand that why do you need the allow|deny flags. If roles collide because users can have multiple roles or permissions collide, because you can both allow and deny the same thing, then how do you resolve it without a hierarchy? And if you don't have a hierarchy, then this flag is completely useless and just deny all and allow what is added to the role.
As of the one user multiple roles approach it is not a great idea, at least in places where people take security seriously a single account or at least a single session can have only a single role. Since this would make a lot of repetition I would solve this on a role level and make composite roles or support role inheritance. So for example the Administrator role would be the composite of the OwnProfileEditor and ProfileEditor sub-roles, which I would rather call Features or Capabilities or PermissionGroups rather than Roles.
Usually RBAC is not that flexible, so people tend to add per User Permissions to override Role Permissions. I would not do it, because you will end up with a mess if you follow that approach.
I have a use case where I want to connect two different user roles, and if they accept and want to connect, new features will open up. It is very similar to how friend requests work at Facebook or LinkedIn, opening up and showing more content. Let's call them role1 and role2.
All users are stored within a "users" collection with an id. Depending on their provided role within the document attached to the "users" collection, they can store additional data in their respective role-collection, i.e., role1 collection or role2 collection.
What is the best approach and structure to connect the two users, i.e., become "friends"? Should I have the connection stored in a new collection, named perhaps connections-collection, or multiple collections?
I'm using Next.js, NextAuth for user authentication, and FaunaDB as a database. I'm using Fauna's query language, FQL.
Have you perhaps seen fireship's video RE: fauna db? I think it covers what you want to do and how you can proceed.
Edit: There are many ways to implement this. Based on my understanding, perhaps you can have "Friends" and "Requests" arrays stored under a user document. That way you can differentiate between confirmed friends or a just request.
Example: When user1 initiates a friend request with user2, you store user1's ref under "Requests" of user2's document. When user2 confirms, you move user1's ref to the "Friends" array.
This is just a overly simplified idea and you may need to consider your options and the implications. You would need to plan and define the predicate in both roles so you would only see what is necessary.
This is more like a question for an advice rather than a precise answer...
In my CakePHP app, I will have backend users and frontend members. They have completely different roles and permissions (users are application managers, members are visitors that register on the website without any access to the application backend). Should I use different tables for these two authorization types, or should I just manage them with a role parameter and bind tables to their profiles depending on it, and why is one solution better than the other?
Use the same table and role or type field. You will have only one login and it will be easy to manage the accounts.
Use ACL or a custom permission system to allow them to different controllers/actions.
For permissions, I have 3 ways to do it :
The strict-role way :
Every role of your application has access to functions with their prefix, but not any other prefix.
Ex : admin has access to admin_edit, but not customer_edit
You add a role varchar or enum in your users table, the routing prefixes in Config/core.php and you allow the access in a AppController::beforeFilter : each role is allowed to access to his prefix only.
The hierarchical way:
Your application's roles are ordered in a hierarchical way, where a role has access to his prefix and every prefixes under him.
Ex : admin has access to admin_edit and customer_edit, but
customer has not access to admin_edit
You add a role varchar or enum in your users table, the routing prefixes in Config/core.php and you allow the access in a AppController::beforeFilter by checking for each $this->request->params['prefix'] which roles can has access to it.
The custom way:
You need your admin to access to some functions, but not all. You need another role to access some functions admin can access, and some functions admin cannot.
Ex : admin can access to admin_edit and customer_edit, but not
customer_create or user_stat. customer can have access to
customer_edit, customer_create and user_stat, but not admin_edit or
user_edit
Use ACL. It's not the easiest way to manage permissions into your application, but if you want specific permissions, it's the best way. So remember this : only use ACL if you really need it.
I agree with cornelb: one table only. Here are some additional reasons:
If you add foreign key constraints, it might be messy to make them refer to both the app managers table, and the visitors table. Always when you want to point to a user, you'd need 2 fields, instead of 1 (a field pointing to the managers table, and one to the visitors table — and exactly one of them has to be null). And what if you need 2 user id fields in a row, with foreign keys? Then you'd suddenly need 4 fields. Simper with all keys pointing to just one table (and user type decided by the above-mentioned field).
Sometimes you might want the user id be part of a primary key — but that's more complicated, if you have two different user id fields, one in each table. Because then the database cannot guarantee that each user id is unique — you'd have to do it yourself at the application level.
I (finally) got ACL to work properly, based on group permissions. However when I create a new user (Users/add) it automagically.. I mean.. autoinconveniently creates a User ARO..
While this is not really a big problem, I would like my ARO table to stay as clean as possible. Just my groups.
How do I disable the automatic creation of a User ARO object when creating a new user through CRUD?
i had the same problem and, like you, i said to myself "its not a big deal as long as it's working"... but when i started to have more and more users and when i added new groups, i found that ACL was not working correctly.. If you're using a group-based permissions, you MUST ONLY have groups in your AROS table.
Brief, the documentation says that you need to add the bindNode() in your Users model if you want a group-based ACL, but what they don't tell you is that for group-based permissions your User model doesn't have to implement the requester behavior and you don't need the parentNode() neither. Remove those two and it should be ok.
I added a note on the documentation, i hope it gets published :)
Good Luck
I am using Acl in new web app.
in my app there are four groups of users.
I have given $this->Auth->authorize = 'actions' so that it will check the permission for actions automatically.
my problem is some of the actions such as change Password,edit profile,etc...
are common to all users.
But now i need to create each record for the permission of each users in acos_aros table.
this is too annoying
1) Is there any way to give permission to all types of users with a single allow statement?
2) Is there any way to allow and deny user by checking whether parameter is passed or not?
that means i need to give permission to pass parameter to an action for a specific user. If any other user pass the parameter and try to access the data i need to deny them.
whether row level access control can be done with ACL?
Any help will be appreciated.
Thankz in advance :)
If you put a $this->Auth->allow('action1','action2'...) into your beforeFilter() of the controller, access is granted to all users. If you need an ACL-only solution, you have to create a parent aco to which all other acos you want to allow are children. Then grant your users the rights on the parent.
The ACL plugin from the bakery could come in handy, if you already have your ACL tree structure.
For building the ACL tree structure the build_acl() script in the tutorial at the end of the cake-manual is useful.
Allowing to pass the parameter for all users and checking their role in the action is not an option?
the solution for the 2nd problem is here
but this is not implemented using ACL :(