views:

100

answers:

3

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 also have administrators who manage the system and have access to all of the information. What is the best way to limit users to their data without limiting admin users?

Currently I am using a callback to limit the queries by user, but the admin will get the same limits. So I need to know a better way to do it. More importantly, the right way to do it.

For example, I want the standard user to be able to see their user information only and be limited to CRUD operations on their information only. The admin, however, should be able to see ALL users and CRUD ALL user data. Any ideas?

A: 

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.

bancer
This appears to be a "global user" approach. My ADMIN users are in $this->Auth the same as STANDARD users. But the group is not always in the data. For example, if I have a user adding books, the group ID will not be in the BOOK table. But each user should only be able to view their books. Admins should be able to see ALL books. I am not certain what you have shared will even work. I don't need to track updates by user, I need to limit what data can be accessed.
cdburgess
If you will use WhoDidIt behavior you will have user id (who created the record) in the BOOK table in the `created_by` column. If the user is logged in there should be user id and group id in the `$this->Auth->user()`. If `$this->Auth->user('id')` is the same as `created_by` or when `$this->Auth->user('group_id')` is 'admin' then the record is allowed.
bancer
+2  A: 

You need:

  • Information about the current user
  • Information about the item in question

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.

deceze
Thanks for the response. This is similar to the another answer already provided. But again, ['type'] is not set with Auth. Is it something I need to do manually somewhere or with an override? I am using admin routing, that is why I am having difficulty. If I put a callback in the model for example (which seems like the best way to do it as it can be done globally), then the same restrictions will apply to the admins too. This still does not seem like the most obvious "cakeish" way to do it.
cdburgess
@cdburgess I believe the information of `$this->Auth->user()` is simply stored in `$this->Session->read('Auth')`. You could write any additional information needed to resolve the user type there at the time of login. You shouldn't put user authentication in a model callback, as that would severely limit the flexibility of the model. Authentication is something done in the controller.
deceze
@deceze: can we do this row level access control with ACL?
RSK
A: 

After not finding what I was looking for on the Internet, and not getting a solution posted here (most likely due to my inability to communicate what I was looking for), I spent the last few days writing a solution. I finally have the solution I am looking for. While some of the answers here were on the write track, they just were not complete enough for what I was looking for.

Since there is not enough room here to post the results, I added the content to my blog. You can ready it here at blogchuck.com. Please feel free to blast it to pieces, it will help us all in the long run.

Thanks to everyone who took the time to post.

cdburgess