Auth and Acl - Automatically updating user Aros
In my previous Auth and Acl tutorial I mentioned that I wasn’t including a way for users ARO to be automatically updated when a User’s group was updated. Well ‘hepper’ posted a patch to the AclBehavior
in the comments to that article. And it seems like it will work, however I wanted a solution that didn’t involve hacking / replacing any core classes. I also don’t think the AclBehavior
will be patched this late in 1.2’s development. So I’ve written up an afterSave()
method for the User
Model. This code could be easily placed into any AclBehavior model with minimal effort as well.
- /**
- * After save callback
- *
- * Update the aro for the user.
- *
- * @access public
- * @return void
- */
- function afterSave($created) {
- if (!$created) {
- $parent = $this->parentNode();
- $parent = $this->node($parent);
- $node = $this->node();
- $aro = $node[0];
- $aro['Aro']['parent_id'] = $parent[0]['Aro']['id'];
- $this->Aro->save($aro);
- }
- }
Since a model’s afterSave()
fires after behavior afterSave’s we can safely use the parent node to update our user’s ARO. I’ve been working on a Component to generate application menus based on the ACL as well. I hope to have it done soon, and when it is you’ll find it here.
Update: The original code I posted was incorrect, and didn’t take into account a non-perfect sync between your aros and group ids. The code above has been updated to reflect correct functionality. Instead of blindly using the Group.id it fetches the parent Aro node. I’ve tested it with the User and Group models I posted in my other Auth / Acl tutorials.
Greate. Better to not touch the core classes.
Looking forward to your menu component.
anonymous user on 9/8/08
Hey, great and thanks. I’ve been looking for this for the past 3 days.
But actually, this doesn’t work for me. The parentNode() is returning the new ‘foreign_key’ (the ‘group_id’) and not the ‘parent_id’, and I suppose this is the one that needs to be updated.
anonymous user on 9/8/08
Mark, I’m using a “last_login” field in my User model which I update upon a successful login. When I use this little callback no
parent_id
is set which starts causing problems if it’s not corrected. Would it be possible to make this a normal function within the model and call it from within theUser::Add
andUser::Edit
actions? I know doing it this way removes the “automagic” nature of it all but would I be missing any other functionality?anonymous user on 9/9/08
Jason: As long as you remember to call it when needed it shouldn’t function any differently. Strange that it is complaining about a missing parent_id field. It doesn’t rely on any data in the Model to do its work.
mark story on 9/10/08
The only place I think I need to make a call to this function is after a user has been edited; is this correct? I’m also under the impression that this only needs to be placed in the
User
model or does it need to be added to theGroup
model as well? Finally, I haven’t tried the new code you’ve posted so I’m not sure if the error I was getting still exists. Thanks for posting all of these resources; it’s making my app better.anonymous user on 9/12/08
@Jason:
If you have a schema where your groups belongs to other groups (like a tree structure, where you have a field called parent_id in your groups table, and the Tree Behavior attached to the model) you also need to define this aftersave behavior but in the group model, with some changes.
But if you have the common schema where you user belongs to a group and your groups doesn’t belong any group (they are always in the root of your aro tree ‘parent_id = null’) then the code will just sit in the user model.
anonymous user on 9/17/08
Thank you very much for this code
anonymous user on 11/4/08
on update aro table left right node become 0 any suggestion?
karan on 12/23/14