Wednesday, March 30, 2011

Re: View caching - problems with different user roles

When you use Caching in the Controller (http://book.cakephp.org/view/1380/Caching-in-the-Controller), Cake bypasses the actual code in the function.

===== From http://book.cakephp.org/view/1381/Marking-Non-Cached-Content-in-Views
It should be noted that once an action is cached, the controller method for the action will not be called - otherwise what would be the point of caching the page. Therefore, it is not possible to wrap <cake:nocache> </cake:nocache> around variables which are set from the controller as they will be null.
=====

So the cache is based on the action + parameters (so that /app/users/view/1 doesn't result in the same output as /app/users/view/2).  In your situation, you'll encounter another use case: if a normal user accesses index (and the cache created), then an admin user accesses index while the cache is active, the admin user will not see deactivated users.

The pattern that I've used when the code for admin and normal users are very similar, with only minor differences is:

===== controller code
function admin_index() {
    $this->_index(true);
}

function index() {
    $this->_index();
}

function _index($isAdmin = false) {
    ... // common code
    if ($isAdmin) {
        $this->paginate['conditions'] = array(
            'User.status' => array('Active', 'Inactive')
        );
    } else {
        $this->paginate['conditions'] = array(
            'User.status' => array('Active')
        );
    }
    $this->set('users', $this->paginate());
    $this->set(compact('isAdmin'));
    $this->render('index');
}

function admin_view($id = null) {
    $this->_view($id, true);
}

function view($id = null) {
    $this->_view($id, false);
}

function _view($id = null, $isAdmin = false) {
    ... // common code
    $user = $this->User->read(null, $id);
    if (!$isAdmin && $user['User']['status'] = 'Inactive') {
        $this->setFlash(__('Invalid access to user.', true));
        $this->redirect(array('action'=>'index'));
    $this->set(compact('user', 'isAdmin'));
    $this->render('view');
}
=====
Essentially, I define public actions (admin_index, index, admin_view, view) that allows me to take advantage of Acl and Caching, and use common views (index and view).  Within the view, I use 'if ($isAdmin)' blocks to conditionally display items (like the cells for the column User.status, or the links to delete/edit, etc.)  Additionally, it allows admin users (if permitted with Acl), the option to view the information exactly as a normal user (by accessing /app/users/index instead of /app/admin/users/index).  It does require, however, that you have the appropriate links to access the admin versions.

I haven't tried this, but it MAY be possible, as an alternative, to use the beforeFilter() method to determine if the user is an admin or normal user, then add a parameter (i.e. $this->params['named']['userType'] = 'admin', or $this->params['named']['userType'] = 'normal').  Since the parameters are used as part of the caching mechanism, a different cache should (theoretically) be generated for each userType.  Within the action, you can then use $this->params['named']['userType'] instead of checking (again) whether the user is admin or normal.

--
Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.
 
 
To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

No comments: