I'm implementing the ACL component for my CakePHP app (1.3.14). I have everything setup correctly, but there are a few areas where I'm still fuzzy.
Mainly, do I need to explicitly set rights (ACOs) for a special base user group (AROs)?
For simplicity, let's say I have Administrators and then everyone else (general users). So do I need to create a group for these general users and map all their allow rights? Seems like management of these rights would be never ending as the app grew.
Also, what about assigning users to multiple groups?
Ideally if a person had a user account the Auth component would grant access to the system as a whole. Then ACL would simply deny them from the sections that were protected by an existing group.
It seems like the coupling of ACL and Auth is too high. But it may be my new (limited) understanding. Any clarification would be greatly appreciated.
UPDATE
I've started a bounty. In summary, I want to implement CakePHP ACL (preferably, but a matching third-party component is acceptable) that meets/addresses the following:
Assign users to multiple groups
Easily maintain a "public" user group - don't have to constantly add the controllers/actions a general user can access
Code example of managing access to a controller/access
Code example of properly testing a user belongs to a group.
I think the best you can hope for using Cake's native ACL implementation is something like the following:
cake acl create aro root public
cake acl create aro root registered
cake acl create aro registered administrators
(create acos using AclExtras)
cake acl grant registered controllers
cake acl grant public controllers
cake acl deny public controllers/MySecureController
cake acl deny public controllers/Widgets update
cake acl deny public controllers/Widgets delete
(the above is all done through the cake shell, but is easily translated to the PHP variant)
Basically, you can either use a "default-deny" paradigm (as demonstrated in Cake's own ACL tutorial), or a "default-allow" paradigm as above. Whichever method you choose will depend on how you expect the application to grow: will most of your controllers be public with only a select few restricted to Administrators, or will most of your application be restricted with Public given specific access where needed? Either way, you still need to either grant or deny access.
Notice the two AROs created under root: public and registered. With this model, treat registered as if it were root when creating your ARO tree -- put all of your "real user" groups underneath it. That way, you can use ACL as normal on the objects under registered, and the public users will exist outside of that.
All that said, there's nothing stopping you from using Cake's authentication mechanism and rolling your own access control method. Here's an example: Simple Authentication and Authorization Application. (NOTE: This is written for CakePHP 2.0, but the concepts apply to 1.3 as well).
EDIT -
After re-reading the question and the other responses, I realized you're aiming more for a role-based access control model rather than the traditional one-aro-per-user model of the builtin ACL component. Here are a couple of examples of extending the built-in auth component for RBAC:
Role-based ACL in CakePHP
CakePHP Auth component: Users, Groups, Permissions
Also, this two-part article describes an approach to database-backed role-based authorization that can be applied to your Cake application.
You can have both ACOs tree and AROs tree. In the AROs tree you will have adminsGroup<-usersGroup. You will need to setup rights for these groups. In the ACOs tree you will have baseACO<-subACO<-treeOfACOsForUsers. You will not need to maintain any new ACOs if: 1) userGroups are allowed to use subACO, 2) any new ACO is a child of subACO. The idea is to organize a tree of ACOs, so that if you allow access to a parent all children are accessable automatically. You can have a branch with denied access also. So you will need to maintain (assigning permissions) only several branches close to the root.
You may be interested to look at my PoundCake Control Panel - a plugin implementing ACL with user friendly web interface (CakePHP v1.3 is supported).
UPDATE:
Here is what you need.
Related
I have read numerous times here and on various websites that the ACL Component is a very powerful tool. Yet the next sentence usually begins with a version of "However, the cake manual poorly documents this and so this is the system that I am using instead." I am a programming novice and have definitely struggled with learning Cake because of the docs as well; I am at a loss as to what exactly makes the AclComponent so strong, since everyone recommends it but many are still using something else. Can anyone suggest specific examples or tutorials that will help me understand this component better? For example, what kinds of code it helps me avoid having to write, how to limit access by each user instead of the entire group, etc?
Cake's ACL system is powerful because it's extremely flexible and allows very fine grained control over the access to your application. Most people use it in a basic sort of way, i.e., this user/group has access to this controller method. While this is the common use case, you can also use it to say, limit a model's access to another model's create action.
For example, to limit an Admin group to only creating records for a PrivateModel model:
// add aco
$this->Acl->Aco->add(array(
'alias' => 'PrivateModel'
'model' => 'PrivateModel',
'foreign_key' => null
));
// add aro
$this->Acl->Aro->array(array(
'alias' => 'Admin'
'model' => 'Group',
'foreign_key' => 1
));
// allow Admin to read PrivateModel #1
$this->Acl->allow('Admin', 'PrivateModel1', 'create');
// check permission
$allowed = $this->Acl->check('Admin', 'PrivateModel', 'read'); // true
$allowed = $this->Acl->check('Admin', 'PrivateModel', 'create'); // false
The default answer to "should I use ACL" is often "no" simply because it can take some time to set up and understand. Cake's ACL examples were enough to get me going on it when I originally had no understanding of even the ACL concepts or MPTT trees.
Currently I have an app that has groups as AROs, and the ACLComponent uses the controller to check an isAuthorized() method which pulls the group from the logged in user and uses it to check see if the action is authorized. Again, this is probably the most basic approach to ACL.
As you have already pointed out in your question "However ... cake documentation", I couldn't agree more.
I have seen many of my team members in past struggle to grab the concept of whole Acl, Aro and Aco, and cake's documentation may be adds additional complexity to it than solving it.
The real magic of ACL begins with Aro and Aco.
ARO (Access Request Object) - They are the entities who request for services.
for eg. Users, Roles (Admin, Manager, Moderator)
ACO (Access Control Object) - They are the entities which are requested.
for eg. Posts, Posts->add, Posts->view, Posts->edit
We can configure our models with requester behavior such that everytime new record is created, it gets automatically synced with corresponding Aro.
As already demonstrated by jeremyharris, you can use Aro and Aco mapping with corresponding privilages to limit/control the access control of your application.
Also, you can make your life pretty easy with ACL by using a plugin Alaxos ACL This plugin really simplifies the whole ACL setup, especially from UI perspective
The cake console also provides a shell to initialize your db for ACL setup
cake acl initdb // cakephp 1.1, from shell with create db setup for acl
$ cake schema create DbAcl // cakephp 1.2 and above
There is an additional plugin from Markstory called AclExtras, it provides you a shell to make acl management more easy like creating aco nodes, testing and recovering aco, aro trees. It's an amazing plugin.
Let's say I have a Project model and a User model in a CakePHP application. Using ACL I can control if users can access to projects and/or to particular actions in a ProjectsController.
But I would like to go further and control whether a user is allowed to view a specific project, e.g. accessing a project with id = 3 using a URL like http://example.com/projects/3.
Is this possible with ACL as well or I have to develop additional checks on top of it?
Thanks!
To restrict access to specific values of a model, you'll need to use something other than ACL.
It'll be best to define a relationship between the users and projects, whether that's inclusive or exclusive.
You're probably needing a ProjectUser model (HABTM in Project and User) and a simple function in that model, maybe userAllowed($projectId, $userId), that checks that the user has been given access to that project.
I've inherited an app that makes heavy use of Cake's ACL -- a component I've never used -- and is configured such that 3 group AROs have access to an entire controller. ACOs exist for each action in the controller, but no permissions are explicitly assigned at the action level.
I've now run into a situation where I need one group to have access to one particular method, but I need to deny it for the other 2 groups. Is there any way to, rather than explicitly assigning permissions for each group to each action, simply indicate that the 2 groups do not have permissions to the one action in question?
Essentially, I want to keep the current "access to everything" default, but override that with a "deny for [this particular action]". I've tried cake bake acl deny GroupName ControllerName actionName, but that doesn't seem to have any impact.
By way of a fairly ubiquitous analogy, I'd like this to behave like Apache's AllowOverride. By default, allow everything to everyone, but deny a given action to a given group. I'm not sure whether that's helpful, but there it is.
Thanks.
This command will grant all your AROs access to your ACOs cake acl grant RootGroupName RootControllerName all.
Thereafter you can specify the particular actions you would like to deny access to: cake acl deny GroupName ControllerName|AcoActionName AcoActionName|permissions
If your second value after deny was an AcoActionName you would have to use one of the following values for permissions: all, create, read, update, delete.
A small tangent:
This is where I believe the confusion may lie. The structure of your
ACL [ACOs and AROs] are simply names of nodes that generally match the
structure of your controller/action setup, but can be called any name
your would like since the permissions are checked in each action. CakePHP ACLs organized in a
Tree (data structure) and the external nodes can have database level CRUD permissions set.
Here is a sample ACL schema for users and comments.
Aco tree:
---------------------------------------------------------------
[1] controllers (root node)
[2] Comments
[3] edit
[4] add
[5] delete
---------------------------------------------------------------
Aro tree:
---------------------------------------------------------------
[1] Groups (root node)
[2] Users
[3] Admin
---------------------------------------------------------------
Assuming access has been granted globally, all Requestors have access to all Objects. If you would like to deny Users from being able to edit comments once they have submitted them you would run cake acl deny Users Comments edit
Here is a great tutorial on ACLs, particularly the App_Controller code at the end which has a nice snippet that checks permissions for an ACO structure that matches controller/action: User Permissions and CakePHP ACL.
Additionally, the CakePHP Book has a nice snippet to insert all your controller/actions as ACO rules: An Automatic Tool for Creating ACOs
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 :(
I have got a simple web app in development, i want to establish a couple of user groups; Admin, Doctors & Patients.
Each group would have their access restricted to particular controller actions rather than individual content. So for example, Doctors can view patient records (index & view actions), but cannot delete them.
Usually i would create a groups model, and assign the various users to a group. And filter in the beforeFilter() method to determine if the user has access. But if ACL can do the job, why right the code, right?
Thanks
You do not need to filter in the beforeFilter() method to determine if the user has access but you need to provide configuration to Auth component there. Follow Simple Acl controlled Application from tutorial (Setting up permissions).