Another good looking and informative post Mark. I’ve recently stepped into CakePHPs ACL / Auth components and really look forward to the next parts of this tutorial.

Definitely an improvement over other tutorials that only show the how and don’t explain the why :)

David Boyer on 7/7/08

Great first article in the series, ACL is a tough subject to grasp and explain thoroughly. So far you’ve done good.

Marc Grabanski on 7/7/08

Very nice tutorial, but I have a question: What’s the difference or advantage on using an extra table for groups and not defining the groups as aro’s or aco’s, for exampe as stated in the official cakephp book?

Juan Luis Baptiste on 7/8/08

@Juan Luis Baptiste: The advantage comes from being able to create drop downs when creating users, and other interface elements. Furthermore, it makes it easier for others to understand the user hierarchy of the site, instead of having to guess at ARO associations.

Mark Story on 7/8/08

This might be a good candidate for the Common Tasks with CakePHP at book.cakephp.org. I know there are detailed explanations of ACL and Authentication in the Components section, but a more tutorial-style approach would be good as well.

brian on 7/9/08

This might be a good candidate for the Common Tasks with CakePHP at book.cakephp.org. I know there are detailed explanations of ACL and Authentication in the Components section, but a more tutorial-style approach would be good as well.

brian on 7/9/08

There’s a slight typo in your code:

var $actsAs = array('requester');

in the User model should read:

var $actsAs = array('Acl' => array('requester'));

Good stuff Mark. Keep em’ coming.

Joel on 7/9/08

@Joel: thanks for the find, its been fixed it up.

@Brian: I have every intention of posting it to either the book.cakephp.org or bakery.cakephp.org once the tutorial done.

Mark Story on 7/10/08

@Mark: thank you for your answer. Another question, when do you think you are going to publish the second part of the article ?

Juan Luis Baptiste on 7/11/08

Great stuff, thanks! It’s coming up with “Fatal error: Call to undefined method stdClass::node() in C:\wamp\www\cake\app\models\user.php on line 19” every time I add a user. That’s this line of the user model “$groupNode = $this->Group->node();”. Any ideas? Thanks!

Darren Hall on 7/16/08

Never mind! Just needed to sort my hasMany’s and belongsTo’s out.

Darren Hall on 7/16/08

Mark, great article; thanks for putting it together. As I was following along I noticed that the shell command cake acl initdb is deprecated for 1.2. The Cookbook has the new command.

Jason on 8/1/08

Hi Mark
Great tutorial it’s really got me to understand how I should use ACL.

The reason why the ARO isn’t updated when modifying a user is in the afterSave method of the AclBehavior.

Nothing happens when you save.

	function afterSave(&$model, $created) {
		if ($created) {
			$type = $this->__typeMaps[strtolower($this->settings[$model->alias]['type'])];
			$parent = $model->parentNode();
			if (!empty($parent)) {
				$parent = $this->node($model, $parent);
			} else {
				$parent = null;
			}

			$model->{$type}->create();
			$model->{$type}->save(array(
				'parent_id'		=> Set::extract($parent, "0.{$type}.id"),
				'model'			=> $model->alias,
				'foreign_key'	=> $model->id
			));
		}
	}

I've been trying to fix this all day but when I save instead of updating a new record in the aro table is created.

Maybe you have a nice solution :)

hepper on 9/4/08

Well, with some time of from the problem. I think I’ve come up with a solution.

	function afterSave(&$model, $created) {
		$type = $this->__typeMaps[strtolower($this->settings[$model->name]['type'])];
		$parent = $model->parentNode();

		if (!empty($parent)) {
			$parent = $this->node($model, $parent);
		} else {
			$parent = null;
		}

		$data = array(
			'parent_id'		=> Set::extract($parent, "0.{$type}.id"),
			'model'			=> $model->name,
			'foreign_key'	=> $model->id
		);
		if ($created) {
			$model->{$type}->create();
		} else {
			$data = am($data, array('id' => Set::extract($this->node($model), "0.{$type}.id")));
		}

		$model->{$type}->save($data);
	}

hepper on 9/6/08

When I get to the bake part, telling me to create the models, views, and controllers for the 4 things, I understand that. But bake asks all kinds of questions, like if I want scaffolding. What should I put? Also, am I doing it right if I have to do “m” 4 times, “v” 4 times, and “c” 4 times? Just doesn’t seem too automagic when so much input is required, so I thought I may be doing it wrong.

beatles on 10/15/08

beatles: There is a cake bake all function as well, but I don’t think that bake is really that much work considering how much typing time it saves. You can use scaffolds but I prefer to not use them.

mark story on 10/18/08

Thanks for the tutorial! it helps a lot…

jpablobr on 5/30/09

Warning (512): DbAcl::check() – Failed ARO/ACO node lookup in permissions check. Node references:
Aro: Array
( [User] => Array ( [id] => 1 [username] => admin [group_id] => 1 )

)

Aco: Pages/display [CORE\cake\libs\controller\components\acl.php, line 239]

Code | Context

$aro = array( “User” => array( “id” => “1”, “username” => “admin”, “group_id” => “1”
)
)
$aco = “Pages/display”
$action = “*”
$permKeys = array( “_create”, “_read”, “_update”, “_delete”
)
$aroPath = array( array( “Aro” => array()
), array( “Aro” => array()
)
)
$acoPath = false

if (empty($aroPath) || empty($acoPath)) { trigger_error(“DbAcl::check() – Failed ARO/ACO node lookup in permissions check. Node references:\nAro: “ . print_r($aro, true) . “\nAco: “ . print_r($aco, true), E_USER_WARNING);

DbAcl::check() – CORE\cake\libs\controller\components\acl.php, line 239
AclComponent::check() – CORE\cake\libs\controller\components\acl.php, line 89
AuthComponent::isAuthorized() – CORE\cake\libs\controller\components\auth.php, line 477
AuthComponent::startup() – CORE\cake\libs\controller\components\auth.php, line 399
Component::startup() – CORE\cake\libs\controller\component.php, line 112
Dispatcher::_invoke() – CORE\cake\dispatcher.php, line 210
Dispatcher::dispatch() – CORE\cake\dispatcher.php, line 194
[main] – APP\webroot\index.php, line 88

Warning (2): Cannot modify header information – headers already sent by (output started at C:\Programme\xampp\htdocs\cake\cake\basics.php:111) [CORE\cake\libs\controller\controller.php, line 640]

Code | Context

$status = “Location: http://localhost/”

header – [internal], line ??
Controller::header() – CORE\cake\libs\controller\controller.php, line 640
Controller::redirect() – CORE\cake\libs\controller\controller.php, line 621
AuthComponent::startup() – CORE\cake\libs\controller\components\auth.php, line 404
Component::startup() – CORE\cake\libs\controller\component.php, line 112
Dispatcher::_invoke() – CORE\cake\dispatcher.php, line 210
Dispatcher::dispatch() – CORE\cake\dispatcher.php, line 194
[main] – APP\webroot\index.php, line 88

Madi on 6/13/09

OOOps! Sorry it didn’t copy all the message! Anyway, that is my problem! Thanks for your help!

Madi on 6/13/09

on 6/30/09