Currently I am writing an application where I have multiple users. They have data that should only be visible to them and not the other authenticated users in the system. I
For any one else who comes here this is how I set it up.
First I set up a basic Role based ACL
Then I deny access to reports/all
for normal users
$config['rules']['deny'][reports/all'] = 'Role/default' ;
Then in the model that I wanted to protect I added this:
public function beforeFind($queryData){
//TODO:make this cleaner
App::uses('ComponentCollection', 'Controller');
App::uses('AclComponent', 'Controller/Component');
$collection = new ComponentCollection();
$this->Acl = new AclComponent($collection);
if(!$this->Acl->check(array('User'=>AuthComponent::user()),'/reports/all/')){ // must be a user (not admin)
$this->bindModel(array('hasOne' => array('ReportsUser')));
$queryData['conditions']['ReportsUser.user_id'] = AuthComponent::user('id');
$queryData['recursive'] = 2;
}
return $queryData;
}
On the cases where ACL doesn't allow access to reports/all
we add a condition to any find queries so it only shows reports with the correct user_id.
You can get the current user info this way: $this->Auth->user()
. You can use the user group id in your callback to limit the query. Also take a loot at WhoDidIt Behavior.
You need:
You combine them with something like this (simple example):
$user = $this->Auth->user();
$book = $this->Book->find(…);
if ($user['type'] != 'admin' && $user['id'] != $book['Book']['creator_id']) {
$this->Session->setFlash("You're not allowed to view this item");
$this->redirect('somewhere');
}
You could make a method in your model like
function userCanAccessItem($item, $user)
to centralize the logic for the access check and call it from your controller.
Better yet, if you're using Cake's admin routing, you can omit all checking in the admin_
actions and only apply normal user access privilege checking in the user accessible actions.
You may also want to look at ACLs for more fine-grained access control.