CakePHP ACL use case(s) - cakephp

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).

Related

Restrict access to resources by resource ID in CakePHP using ACL

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.

CakePHP ACL: Is a base group/ARO required

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.

How do I build internal Access Control for site features in CakePHP

I went through the tutorials and examples on the CakePHP Acl and Auth components today in detail. I configured my Auth component to use $this->Auth->authorize = 'actions'. With this I was able to successfully restrict access to specific site actions without a problem.
However, my application needs to go a bit beyond this and I'm unsure of how best to accomplish my goals for this application.
Within the application that I am developing using CakePHP 1.3.8, there are specific "site features". For example, users of the application will have the ability to message one another.
I want to treat each message as an ACO so that I can control who can and cannot view or delete the message.
Another site feature is the earning of "badges" for achieving certain goals. For these badges I'd like to treat them as ACO's for the locking and unlocking of these badges.
I do not think that I can do this with the out-of-the-box ACL functionality of CakePHP as this goes beyond restricting access to actions. I'm looking for any ideas on how best to achieve this functionality.
With the standard ACL functionality in CakePHP it's only possible to create ACO entries for controller actions. This means that your setup (treating every single message as a seperate ACO) will not fly. Same as with badges.
For your messages I would go for a setup in which you would check in your view/edit/delete methods if a certain user is the sender or receiver of the message.
Something like
# in messages_controller
function view($id) {
if(!$isSender($loggedInUserId) || !$isReceiver($loggedInUserId)) {
$this->Session->setFlash("You're not allowed to view this message")
$this->redirect('index');
}
# do view stuff here
}
function edit($id) {
if(!$isSender($loggedInUserId)) {
$this->Session->setFlash("You're not allowed to edit this message")
$this->redirect('index');
}
# do edit stuff here
}
Regarding the badges, I would go for a regular HABTM (HasAndBelongsToMany) relation between a User and a Badge. When a User reaches a certain goal, you make a call like Badge::unlock($badge, $user) which saves the new badge for the user to the users_badges join table.
From there you can do basic stuff like listing all the badges for a certain user, etc.
I studied over Cake's Acl component much closer and figured that I could write something that sort of imitates this functionality for my internal "feature" access control. My thoughts are that I could have a Faro (Feature access request objects), Faco, and Facos_Faros table. Faco and Faro will have a HABTM relationship. I could then create my own component that manages it all.

Creating a login like Basecamp in CakePHP

I am trying to create a basecamp like login where users can login to see their companies projects using the url:
http://abc.com/companyname/
I dont know how to create a 2 level auth... (one at the company level and another at the user level)
I am new to cakePHP and I dont know how to modify the in built Auth component for my requirement.. Any help would be grateful...
I would use the Auth component for the login. I wouldn't mess with the ACL and stuff as that's pretty confusing I find.
I would approach this by adding a user_level, access_level, or permissions column in your users table. Then in here you can store a numerical value or similar.
Then in the User model, when they login using Auth you can store that value in the Auth user session object. So you can get at it using $this->Auth('User.access_level') in your controllers.
Now the Auth component by default has an isAuthorized() function in the app_controller. This function is called to see if someone has logged in. You can modify this to check that access_level and take action appropriately. I used this technique so that users can't get into the /cms routing unless they are admin = 1.
There is more information on this in the docs, http://book.cakephp.org/view/172/Authentication and you can find out more about isAuthorized() here, http://api.cakephp.org/class/auth-component#method-AuthComponentisAuthorized
Do make sure that you setup all your Auth component variables in your app_controller. Also make sure that your auth type is set to controller, and that you're allow() and deny() are configured properly.
The one big catch with all this, is that if you using a beforeFilter() in your controllers, you will need to make sure to do parent::beforeFilter() to ensure that the stuff in the app_controller is run beforehand :)
Honestly, I think that you should check out the ACL component. The book tutorial is very good if you follow it through. The major caveat is that it does not provide a mechanism for row-level access control (e.g. can user X edit this particular entry). However, it does provide a basis for doing user/group level access control, which you can then extend yourself to create the row level access you require.
In short, the ACL component supports cascading permissions (e.g. subgroups can have finely-grained access control, but otherwise inherit permissions from the parent group). That can make life a lot easier, if you need both robustness as well as granularity.
You might also check out the bakery, as there are additional auth components written by the community that may serve what you need. Highly recommended, as Auth/ACL stuff is difficult to do well, and always a major concern with web apps.

how to improve cakephp auth component to use user type?

i use auth componnet in my cakephp project
I add type field into users Mysql table
that enum type: admin, client
i need auth component to redirect admin's to CP page, and client to their profile page and only can access one conttroller..
ofcourse without using ACL or any others related
I'd recommend taking advantage of the isAuthorized() function that you can add in the controller, or the model. Set the AuthComponent::authorize = {'controller'|'model'} to choose which you want to use.
Then you write an isAuthorized() function in the model|controller that returns t/f on auth/not auth for each action. You can do some row-level checking as well, if you'd like.
Now, if instead you just wanted to redirect an admin to their correct pages on login/etc, you can add code to the beforeFilter() method (either in a specific controller, or in app_controller.php). In that, just check to see if the admin value set by the app is the same as the user's admin value (which will be stored by AuthComponent in the Session data, accessible by $this->Auth->User()). Then route appropriately to the admin/non admin areas.
isAuthorized() is the best choice.
i would recommend to separate the users from their groups in the database, so User habtm Group... but It is not a problem if user belongs to one and only one group
I do not recommend ACL for non record-level-based permissions system
Just something to pay attention to, but unless something has changed recently CakePHP does not support ENUM column types.
Your best bet is a Group model ( groups mysql table ) and a group_id field on the users table.
Then you can $hasOne = array( 'Group' ); in your User model.
From there you can follow any one of a HUGE number of group access control tutorials for the Auth Component via an easy google search for "CakePHP Auth User Group"

Resources