Escolar Documentos
Profissional Documentos
Cultura Documentos
org/articles/view/how-to-use-acl-in-1-2-x
CakePHP API Docs Bakery Live Forge Trac Login Register About CakePHP Donate
This tutorial will brief you on how to use Acl in CakePHP 1.2.x versions. I had tough time figuring Details
this out. But with help of Gwoo, AD7Six & others, and doing debugging and reading code, here
Version:
comes the tutorial.
1.2.0.5146
This tutorial assumes you know basic concept of ACL and what it is suppossed to be used for? If not Views: 36305
then please read http://manual.cakephp.org/chapter/acl
Comments (42)
You can setup the databases needed for ACL through console command
Download code
cake acl initdb Rating
3.50 by 2 Users
Now we would setup some higher level aros and acos for initial setup. You could do it through console.
But I prefered to do it through controller, nothing special, just did it that way!
Log in to add
Think of Aros (could be Users, service, etc) as the one who is requesting access to Acos (could be
rating
controller, actions or services). But in this example, we will limit Aros as the users and Acos as the
controllers. We will setup the following Aros (users):
1. Admin Tags
2. |-->User::1
3. User aro
4. Guest aco
You could add more depending on your requirements, but we will stick to basic requirements for now. acl
Admin, User & Guest are higher level group and the actual users will belong to one of these groups.
'User::1' is an alias for User with user id 1. We define that user with user id 1 is a child of Admin and
Log in to add tags
will inherit all admin previledges. Doing this is not essential, but you will have to define at least one user
to be Admin, so why not do it here. Change the id to the userid representing the admin user on your
system.
This would add two acos 'User' and 'Post'. But now you think if Acos is controller then why not have 'Posts' instead of 'Post'? Good
question. This is because usually a controller's action can be divided into four types of action 'create', 'read', 'update' or 'delete' which
are performed on a single or group of records belonging to a model. Hence, in this approach we going at record level Access Control.
We want to make sure whether the current Aro (a User) has access to do 'C', 'R', 'U' or 'D' action on the Aco ( a record for eg. A
post). If yes, then let him do the action otherwise don't. Now the code, that shows you the manual way to create aros and acos as
discussed above.
Controller Class:
Download code
<?php
class InitAclController extends AppController
{
var $name = 'InitAcl';
var $component = array('Acl');
var $uses = array();
function setupAcl()
{
$aro = new aro();
$aro->create();
$aro->save(array(
'model'=>'User',
'foreign_key'=>null,
'parent_id'=>null,
'alias'=>'Admin'));
$aro->create();
$aro->save(array(
'model'=>'User',
'foreign_key'=>null,
'parent_id'=>null,
'alias'=>'User'));
$aro->create();
$aro->save(array(
'model'=>'User',
'foreign_key'=>null,
'parent_id'=>null,
'alias'=>'Guest'));
$parent = $aro->findByAlias('Admin');
$parentId = $parent['Aro']['id'];
$aro->create();
$aro->save(array(
'model'=>'User',
'foreign_key'=>1,
'parent_id'=>$parentId,
'alias'=>'User::1'));
$aco->create();
$aco->save(array(
'model'=>'Post',
'foreign_key'=>null,
'parent_id'=>null,
'alias'=>'Post'));
}
// Give admin full control over acos 'User' & 'Post'
$this->Acl->allow('Admin', 'User', '*');
$this->Acl->allow('Admin', 'Post', '*');
// Give the user group only create & read access for 'Post'
$this->Acl->allow('User', 'Post', array('create', 'read'));
'User' aro is allowed to do only create & read action for 'Post' acos, which means that a 'User' group in general has access to a
controller action that can create and read 'post' records, which is what we want. We want that any user that belongs to 'User' group
can create new posts and read posts. But we do not want all users (aros) to 'update' or 'delete' any 'Post' (acos) they want. Which
means, that belonging to a 'User' group does not give you any previledges to 'U', 'D' actions of 'Post' (acos). But you want to have
'U', 'D' action for the user who created that Post!! I will get to giving user who created post the full CRUD rights later on, but this
explanation was just to clear your concepts. Note that, above we did not do any 'allow' statement for 'User' aco, so this means that by
default 'User' group and its children, don't have access to 'CRUD' on 'User' records (acos). A user himself only has the CRUD right for
his record and not other users. That's why we did it that way :)
'Guest' aro is allowed to only 'create' action for 'User' acos. ie. Guest can only register a new user account, and is denied all other
access to everything else.
Now that we have the basic setup done, we would want to get the aros and acos populated as and when user is added to system.
Below is shown the code on how to create aros and acos manually and also how to setup the permissions.
Controller Class:
Download code
<?php
class UsersController extends AppController
{
var $name = 'Users';
function register()
{
if(!empty($this->data))
{
$this->User->data = $this->data;
if ($this->User->validates())
{
if ($this->User->save())
{
$aro = new Aro();
$parent = $aro->findByAlias('User');
$parentId = $parent['aro']['id'];
$aro->create();
$alias = $this->User->name.'::'.$this->User->id;
$aro->save(
'model' => $this->User->name,
'foreign_key' => $this->User->id,
'parent_id' => $parentId,
'alias' => $alias
);
$aco->create();
$aco->save(
'model' => $this->User->name,
'foreign_key' => $this->User->id,
'parent_id' => $parentId,
'alias' => $alias
);
$this->Acl->allow(
$alias,
$alias,
array('read','update'));
}
}
}
}
}
?>
Above you saw, how to create aro and aco each time a new user is registered on the system. Also you saw how to allow a user himself
the full CRUD previledges on his own record. Say User 'a' with user id '5' just registered on the site. Above code, will create an aro with
alias 'User::5' and an aco with alias 'User::5' and will create an entry in aros_acos table that would let aro with alias 'User::5' CRUD
rights over aco with alias 'User::5'. Now no other user has access User 'a' except User 'a' and anyone who belongs to 'Admin' aro
group. To verify, give following code a try
Controller Class:
Download code
<?php
class TestController extends AppController
{
var $name = 'Test';
var $components = array('Acl');
var $uses = array('User');
var $curLoggedInUserId = 3;
function view()
{
$aroAlias = 'User::'.$curLoggedInUserId;
$acoAlias = 'User::5';
When you visit the above page (http://localhost/test/view), you will get 'access denied'. Now change the $curLoggedInUserId = 5, and
try visiting the same page again, you will get 'allowed access'. This is because the logged in user id now is the same as user 'a'. And we
had defined that user 'a' has full rights on user 'a' record. Note what happens when you have $curLoggedInUserId = 1!! You still get
'allowed access', now why did this happen? Just because User with userid 1 belongs to Admin group and he has full CRUD rights over
any 'User' aco. Above code is a very crude code and is meant just to demonstrate the purpose of Acl check & is not meant to be used
in production use.
Above was a manual & tedious way to create aros and acos. Now I will now show you the magical way to create aros and acos without
much effort on your end. All you have to do is implement the Acl Behavior which comes with cake 1.2 distribution. Below is the code
that you would have to add to 'Post' Model.
Model Class:
Download code
<?php
class Post extends AppModel{
var $name = 'Post';
var $actsAs = array('Acl'=>'controlled');
// 'controlled' means you want to create a 'aco'
// 'requester' means you want to create an 'aro'
/**
* Returns the parent Alias for current
*/
function parentNode()
{
return $this->name;
}
}
?>
Above code, will now automatically create a new aco for every new post that is posted. The Acl behavior takes care of all details. Just
so you know, in Acl behavior, there is 'afterSave' callback, which would be called once the save callback is completed in current model.
Acl behavior would even delete the aco whenever the post is deleted, without any extra effort on your end. Isn't this cool? Hell yaaa! it
is... Now you would want to setup the permissions on the newly create 'aco'? How do you do that, check out the code below:
Controller Class:
Download code
<?php
class PostsController extends AppController {
function add() {
if(!empty($this->data)) {
$this->Post->data = $this->data;
if ($this->Post->validates())
{
$this->Post->create();
if($this->Post->save($this->data))
{
$acoNode = array('model'=>$this->Post->name,
'foreign_key' =>$this->Post->id);
$aroNode = array('model'=>'User',
'foreign_key'=>$this->getUserId());
So if a save is successful from Post then we know that the Aco is created and then all we have to do is setup proper aro and aco
nodes and then give the required permissions and we are done!!
I would welcome feedback via comments and suggestions. Let me know if you have any troubles implementing this. Till then enjoy
baking.
Cheers,
Ketan Patel
Comments
CakePHP Team Comments Author Comments
Hi, I'm having troubles trying to setup the initial ACL config. I tried using the provided code (InitAclController) but I always run into
problems (no Class defined or else). I tried going to the console but I'm having difficulties translating your setup into acl commands
for the console.
For example:
$aro->save(array(
'model'=>'User',
'foreign_key'=>null,
'parent_id'=>null,
'alias'=>'Admin'));
create aro|aco
would that translate into something like:
cake acl create aro / User/Admin ?
Hi, I'm having troubles trying to setup the initial ACL config. I tried using the provided code (InitAclController) but I always run
into problems (no Class defined or else).
$aro->save(array(
'model'=>'User',
'foreign_key'=>null,
'parent_id'=>null,
'alias'=>'Admin'));
create aro|aco
It would ideal if you could use the init_acl_controller as it gives you clear idea of what you are getting started with.
Assuming 'Guests' users are unidentified web visitors, how do you handler their access rights? They don't login, so they can't be
assigned an ARO and thus ACL will reject their access to any actions.
Sorry if the answer is too obvious, but after spending many hours on it I can't work this out.
I treat any user who does not have a user id to be a guest. By this what I mean is that whenever a user logs-in, I create a session
variable with the userId and check it in the beforeFilter method of the controller. So if I do not find the userId in the session, it
means that the user is a guest! Hope this helps,
Ketan
Free Classifieds - eClassifieds4U
Say your app is multilingual and you have a model for articles that you use across all territories. You also have several administrator
users all belonging to the same user group, each of which also belong to a territory or are "global".
You only want to allow update & delete (and ideally read in the Admin part of the app) access to the articles belonging to a particular
territory, to the users that also belong to that territory (or are global), but deny access to those administrators belonging to a
different territory?
Would you handle that scenario using ACL, if so, how, or would you do it another way? I do it using my own access control methods,
which I'll bung on the bakery soon, but I wonder how easy it would be to do it using ACL.
I know this question might be more suited to the google group, but I think its a common problem that no tutorials on ACL that I've
seen yet, actually discuss, so thought add it here.
What I'm doing wrong? I tried to run InitAclController and always get error "Class 'Aro' not found". I paste directly code of
InitAclController and put file init_acl_controller.php into app/controllers directory. First time I saw model missing and I added:
var $uses = array();
What I'm doing wrong? I tried to run InitAclController and always get error "Class 'Aro' not found".
What version of cake are you using? This code uses the Acl Component that is available with cake 1.2.x.x and will work with 1.2.x.x.
You only want to allow update & delete (and ideally read in the Admin part of the app) access to the articles belonging to a
particular territory, to the users that also belong to that territory (or are global), but deny access to those administrators
belonging to a different territory?
Whenever you create a record using your controller, depending on which territory the record belongs to, allow the territory group the
update/read access to that record/action.
Say you have 3 territory. US, Canada & Mexico. You would have 6 groups.
If a user registers to the US territory then in the controller, allow the US_MODERATORS group (ARO) the read/write access to that
user(ACO).
This is the first thought that came to my mind and I am sure could be implemented in much better way. But definitely ACL could be
used for this situation very efficiently.
Ketan
Free Classifieds - eClassifieds4U
What I'm doing wrong? I tried to run InitAclController and always get error "Class 'Aro' not found".
What version of cake are you using? This code uses the Acl Component that is available with cake 1.2.x.x and will work with
1.2.x.x.
I just did a fresh install of 1.2.0.5427alpha and I get the same "Fatal error: Class 'aro' not found in ..." error.
Use 'Aro' instead of 'aro'. It is case-sensitive. There is a typo in the tutorial, I will fix it sometime soon.
Ketan
Free Classifieds - eClassifieds 4U
The case sensetivity seems to be irrelevant, it cannot even find the 'Aro' (or aro).
What are the pre-requisites for this tutorial to work correctly? Is it possible for you to show us your views?
$aro->save(
'model' => $this->User->name,
'foreign_key' => $this->User->id,
'parent_id' => $parentId,
'alias' => $alias
);
actually be
$aro->save(array(
'model' => $this->User->name,
'foreign_key' => $this->User->id,
'parent_id' => $parentId,
'alias' => $alias)
);
I assume your "posts" table is from the blog tutorial, speaking of the posts controller, there is an extra closing brace on line 27.
Mike
$this->curLoggedInUserId;
When running the setupAcl method from the InitAclController, CakePHP issues a warning about wrong usage of the $Acl->allow()
method. In my database no record is made for the User group. I figured out that when coding the "create & read" access as follows,
there is no warning and everything works fine:
$this->Acl->allow('User', 'Post', 'create');
$this->Acl->allow('User', 'Post', 'read');
Can anybody tell me why the array notation doesn't work?
15 What is difference bw cakephp 1.1 and cakephp 1.2 s ACL schema Question
I tried hard to investigate the differences between acl of cakephp 1.1 and cakephp 1.2 but not got any explanation for it
. Kindly any one explain differences b/w the two db structure and purpose .For example model field in aro /aco table has added in acl
1.2 and for what purpose is not define in this article (or i may have not noticed).
For example, a key difference in the code here versus the code in, say, this article: http://bakery.cakephp.org/articles/view/real-world-
access-control
Is that $aro->create() is used differently.
Cake 1.1
Cake 1.2
$aro->create();
$aro->save( array('foreign_key'=>1, 'parent_id'=>null, 'alias'=>'This is the Alias') );
Thanks!
(1) The ACL page in the Cake Manual for Cake 1.1 is not applicable to Cake 1.2 ACLs
(2) The multiple $aro->create() calls in this article's examples are to instantiate a new ARO each time, and then the $aro->save(array
(...)) bit saves the new ARO to the database.
(3) The $aro = new Aro(); could have been skipped and the Aro Model that is in the Acl component been used instead, directly, like
so:
$this->Acl->Aro->create();
$this->Acl->Aro->save(array(...data...));
(4) The location of the data Array() in the create() and save() operations could have been transposed. That is to say, one create()
operation and one save() operation is needed to save each new ARO, but the data array() could be placed in either the create() or the
save() method.
later...
Using allow and deny method as the following code, I notice that the last call (deny) overwrite the first (allow).
An other example:
Controller Class: <?php
$this->Acl->allow($aroAlias, $acoAlias, 'create');
$this->Acl->allow($aroAlias, $acoAlias, 'read');
?>
There is a way to call method allow and deny on single action CRUD without overwrite other action CRUD?
Thanks to all
Sorry, but for some reason I cannot find that console command. Therefore, I cannot create the database. It would have been really
helpful if you'd provided the SQL create scripts.
Sorry, but for some reason I cannot find that console command.
The command is located in the directory /cake/console. For Windows users it is cake.bat, for *NIX users it is just cake (don't forget
to do "chmod a+x" on cake).
The SQL is constructed in the file cake/console/libs/acl.php from line 317 onwards (in the latest beta version).
I don't see any checks occuring for automatic record level access. I do see that ACO and ARO are created automatically, which is
great, even the correct "aros_acos" entries are made (i.e. User:5 has CRUD permission on Post:2), However user::5 is unable to
access "/posts/edit/5"
My ARO's
|-ADMIN
|-USER
|-User::5
|-GUEST
My ACO's
ROOT
|-USERS
|-User::5
|-POSTS
|-Post::1
|-Post::2
|-Post::3
Ok ... I just looked at mysql logs, I see that it is checking only for my POSTS and ROOT aco_id (aco_id's: POSTS=5, ROOT=1)
...
WHERE Permission.aro_id = 2 AND Permission.aco_id IN (5, 1)
...
WHERE Permission.aro_id = 4 AND Permission.aco_id IN (5, 1)
Seems that it should also check for aco_id that matches the record I have chose to edit
Hi, Can somebody please post the SQL to create the three ACL tables. Some of us do not have Console access because of a shared
environment. For sometime in the future, a web based setup in addition to the console would be a nice feature for cake.
Does anyone else get duplicate entries when running the init_acl setupACL function? For example, if I try to add Admin, User and
Guest AROs (using the code above), I get two of each. It is like the function runs twice somehow. Any ideas?
Hi when i want to run the controller InitAclController that i've copied from your tutorial but then i'm getting this error:
Thanks to TommyO for pointing me in the right direction, if you are using XAMPP and Mac OS X, visit http://www.keitr.com/xampp.
You will need to do the steps outlined there for "cake schema run create DbAcl" to work.
Posted Feb 20, 2008 by Jason Vendryes
Unless I'm missing something, Cake's rewritten Acl is horribly broken, because you cannot do an Acl->allow followed by an Acl->deny
(or vice versa) for the same Aro/Aco combination. Instead Cake will overwrite the previously allowed fields with 0 (i.e. inherited).
This has provided a major headache as I was trying to update a project to Cake 1.2 and could not understand why the ACL stuff was
totally butchering things.
FYI I filed a bug for the allow/deny overwrite problem that Gallax and I encountered.
https://trac.cakephp.org/ticket/4190
and what about the aro and aco not found problem in the InitAclController?
Just for your information, the method described above, when used along with the built-in AuthComponent :
AppController.php :
Controller Class: <?php var $components = array('Acl','Auth');?>
In fact, using the auth component, you get different ways to check the authorisation. Method described here is 'crud'
Don't do like me trying to make it work set to 'actions' ;)
Indeed, I find it really more simple to use a 'crud' than an 'actions' based authorisation (I don't have to create acos for every actions).
However, I'm still looking how to 'map' actions as C,R,U or D actions....
Hello, after spending a little time on this issue, here's what I get to work efficiently.. If it can help some out there with that wild
beast :P
First, the Alias for the aCos, I needed to put them in their pluralize way else I was getting not defined node error, when the Acl was
looking for a match-up.
I don't remember if I've written the alias by hand for the aCos. But I'm sure I had to write them first for the aRos of the groups.
----
Then for the creation of your users aro, aco & aros_acos :
Here's a simpler version of the one written in this article :
Controller Class: <?php
if ($this->User->save($this->data)) {
//set the Aco $parent node aliased as the controllers (plural, ie. Users)
$parent = $this->Acl->Aco->findByAlias($this->name);
//create a Aco for our user
$this->Acl->Aco->save(array(
'model' => $this->User->name,
'foreign_key' => $this->User->id,
'parent_id' => $parent['Aco']['id'],
'alias' => $alias ));
//Sets permissions
$this->Acl->allow(
$alias,
$alias,
array('read','update'));
Here's a little plus: as a requester, if you delete the user, it's aRo will also be deleted automatically. But the aCo will stay there. Use
this in the delete function :
Controller Class: <?php
//delete associated Aco
$aco = $this->Acl->Aco->findByAlias($this->User->name.'::'.$this->User->id);
$this->Acl->Aco->del($aco['Aco']['id']);
if ($this->User->del($id)) {
$this->Session->setFlash(__('User deleted', true));
$this->redirect(array('action'=>'index'));
}
?>
That way, the aCo table doesn't get filled up with empty references.
32 Vague... Comment
In general, this whole cake thing is simply too vague. The documentation is terrible and I find that I'm spending more time trying to
figure out how to do something than actually getting any useful programming done. There's Beta, and then there's unfinished
software.
Specifically regarding this "tutorial", again it is simply too vague. Being a trained designer, one of the first rules of any kind of good
design is too make instructions as simple and straight-forward as possible, while still being as detailed as possible. In short, ANYONE
should be able to read the instructions and at least get to a point where they have a basic working prototype.
This "tutorial" leaves a lot to be desired, infered, and assumed, which leaves big windows for mistakes. Where is this "ketan" person
starting? Where is the code added to? Why are there amateur mistakes like missing brackets, etc...?
Furthermore, the console barely works in Mac OSX, and the 'cake acl initdb' has been deprecated for 'cake schema run create DbAcl'
which doesn't actually work [on Mac OSX]. You get a MySQL connect error. But if you want to run it, the proper command is:
./console/cake schema run create DbAcl
Moreover, the correction to line 5 in the InitAclController class that Mike Green made above is incomplete. Because there is only a
missing 's', it is difficult at first glance to know what he is correcting. So here's my correction of Mike's correction to line 5 in the
InitAclController class:
Line 5 is incorrect in that it defines the variable $component. This variable name MUST BE PLURAL, as in $components. So the correct
code should read:
Next, in the InitAclController class, where the $#@& does the following code go? It obviously doesn't go where "ketan" put it because
I get a parsing error.
// Give the user group only create & read access for 'Post'
$this->Acl->allow('User', 'Post', array('create', 'read'));
My advice is to take this article down and do some serious revision. I feel like CakePHP is one big dis-information campaign designed
for rapid frustration rather than rapid development.
No offense to anyone, but this is a nightmare!!! This tutorial does absolutely nothing for me.
33 Durrr Comment
34 Figures... Comment
This is just the type of response I would expect. Just proves that mediocrity is king! Didn't your parents teach you not to say
anything if you don't have anything nice to say?
35 Coward Comment
You write a sack of bull with "No Name" and user acajaja ("here hehe" in spanish). That's the type of attitude I would expect from a
coward. Come here, bring down years of work and tireless effort from a lot of people, that brought the biggest community for a PHP
framework, lots of supporters, but hey... "No Name" has the absolute truth about what should be done and what needs changed.
Give me a break.
Go ahead and waste someone else's time. People here are too busy getting things done, and helping others.
In fact, using the auth component, you get different ways to check the authorisation. Method described here is 'crud'
Don't do like me trying to make it work set to 'actions' ;)
Indeed, I find it really more simple to use a 'crud' than an 'actions' based authorisation (I don't have to create acos for every
actions).
However, I'm still looking how to 'map' actions as C,R,U or D actions....
First off, THANK you for adding in the 'crud' method. I never came across that in all of my many nights exploring documentation.
How do you get the Auth-> login/logout to work with the ACL? I can get the Auth component to work wonderfully using controller
method. Also, when I use the CRUD method, as long as I have the Acos listed in the plural format, they work... except login and
logout. Any ideas?
I'm new to CakePHP and am halfway through creating my first proper application and have got to the point where I need ACL. I have
followed the guide above upto the point where I try and and add ACOs/AROs to the database. I have tried the script above and doing
it in the console but both give me this error:
Error: Database table aros for model Aro was not found.
The table are definitely there as I can see aros, acos and aros_acos in my applications database (in phpmyadmin) along with my
existing tables. I have tried the same thing on 2 servers now with no luck.
I am hoping someone can help as I am out of ideas, searching for that error in quotes gives me 2 results on Google.
@Adrian
I got another problem - and (like many others) don't get it to work properly
database and its content is all set
some problem...
Hi Mark
@Adrian
I don't see any checks occuring for automatic record level access. I do see that ACO and ARO are created automatically, which is
great, even the correct "aros_acos" entries are made (i.e. User:5 has CRUD permission on Post:2), However user::5 is unable to
access "/posts/edit/5"
...
Ok ... I just looked at mysql logs, I see that it is checking only for my POSTS and ROOT aco_id (aco_id's: POSTS=5, ROOT=1)
I got the same problem. I set all Aro and Aco with Acl and Auth but it won't check the permission at the record level. Any suggestion
to this?
Posted Jul 31, 2008 by KoPanda
// Give the user group only create & read access for 'Post'
$this->Acl->allow('User', 'Post', array('create', 'read'));
Is there a missing function, or should these be moved inside the function in your example?
Mobilize your cake app in Validanguage Helper for introducing something new Problem
minutes customizable Javascript form to chew on Nothing wrong with
Wizard Component 1.2 validation CakeFest #2 includes...
Tutorial FlashHelper - a wrapper for Release: CakePHP RC3 - The admin routing
the SwfObject js class
Migrating a real-world RC of Triumph! Referrer is not always
application to CakePHP 1.2 Wizard Component 1.2 CakePHP Workshop, Sept reliable
Brita component with HTML FlashChartHelper - version 3 6&7, Raleigh NC USA JSON scaffolding
Purifier How to create an XML-RPC Release: Some RC2
Bake ROT13 Encoded server with CakePHP Sweetness
"mailto:" Links