0

I am completely and utterly lost on how to do this. I have 3 different roles : Admin, Staff and Donors. My problem is that It really gets confusing(for me anyway) with permissions and as well as appropriate redirections, should an unauthorized user tries to access an action from the URL.

In my UsersController I have the following actions

  1. admin_index
  2. admin_add
  3. admin_edit
  4. admin_view
  5. admin_delete

non-prefixed actions

  1. login
  2. logout
  3. view
  4. add
  5. edit

The admin should be allowed to access all admin-prefixed actions as well as login and logout, whilst the staff and donor should only be able to access the latter 5. Also note that all users are using the same login form.

In my AppControlles's component I have the following :

 'Auth' => array(
            'loginRedirect' => array(  
                'controller' => 'donors',
                'action' => 'index'
            ),
            'logoutRedirect' => array(  
                'controller' => 'users',
                'action' => 'login'
            ),
            'authorize' => array('Controller')
)

However, In my login action I check for the user role to change the loginRedirect accordingly :

if($this->request->is('post')){
            if($this->Auth->login()){   

            switch($this->Auth->user('role')){
                case 'admin':
                    $this->Auth->loginRedirect = array('controller'=>'users','action'=>'admin_index','prefix'=>'admin','admin'=>true);
                    break;
                case 'donor':
                ...
                break; 
                case .....
            }
         }
 }

Question 1 Now, if a current user with a role of donor is logged in, and tries to access localhost/sitename/admin/users/add he is redirected to admin/donors rather then just /donors . So how am I able to remove the admin prefix ?

Question 2 Also I do not fully understand hwo $this->Auth->allow(), works.. If In my donorsController I want to control the access to the controllers action according to roles, how can I do it? So for instance, If there is the 'delete' action in my donorsController, How will I be able to permit the staff user whilst denying the donor user to access the delete action. I believe the beforeFilter is the solution, but can't find how to do it! Any pointers ? Thanks

LogixMaster
  • 586
  • 2
  • 11
  • 36
  • 1
    You should always mention the exact cakephp version you are using. Tip: Instead of creating a huge controller code overhead here it might make more sense to use a simple /login form and [Tiny](http://www.dereuromark.de/2011/12/18/tinyauth-the-fastest-and-easiest-authorization-for-cake2/) as Auth approach. This way each action is clearly defined and in case there is no access all actions will redirect to /login as central login form. – mark Feb 14 '14 at 13:43
  • Thanks for your answer mark! I have gone through your blog and looks clean. However I do not have that setup, as the roles are defined in the user's table as a field, rather then a model. Also I still have issues understanding how $this->Auth-allow() works, aswell as I was hoping I could resume with the setup I have in place. Thanks! – LogixMaster Feb 14 '14 at 14:25
  • 1
    Just users table field works, as well. Read the docs for it. Doesn't have to be a model. – mark Feb 14 '14 at 15:08

2 Answers2

1

This may be a solution for you.

Go to the core.php file and uncomment if present/add if not present the below line.

Configure::write('Routing.prefixes', array('admin'));
Location: app/config/core.php 

Put the below code inside the beforeFilter method of AppController.php (cake version 2.X) / app_controller.php (cake version < 2.X)

function beforeFilter(){
    if($this->Auth->user('role') == 'admin'){
        if(!in_array($this->params['action'],array('login','logout')) && (stristr($this->params['action'], 'admin_') === FALSE)){
            $this->redirect(array("controller"=>$this->params['controller'],"action"=>'admin_'.$this->params['action'],"admin" => 1));
        }
    }else{
        if(stristr($this->params['action'], 'admin_')){
        $action = explode('_',$this->params['action']);
        $this->redirect(array("controller"=>$this->params['controller'],"action"=>$action[1],"admin" => false));
        }
    }
}

Rest of the functionality you can manage by handling the custom error page.

You can refer to Customize error pae

Community
  • 1
  • 1
Prabhudas
  • 82
  • 1
  • 5
  • This is unnecessary complicated. There is 'prefix' available in the request, no need to parse the action for the prefix and the login and logout actions can be defined by the Auth component setup. – floriank Feb 14 '14 at 14:48
  • Thanks! this might not exactly be what I want since it simply removes the admin prefix from the URL, which is what I asked for in my question. So marking this as answered., as I actually think I can work with this! Also +1 for hightlighting customize error page! – LogixMaster Feb 14 '14 at 14:51
  • @burzum could you kindly elaborate on the matter, why is this complicated, or if there's a better way to do it ?Thanks – LogixMaster Feb 14 '14 at 14:54
1

1) In your login() action impelement a check for the user role, if the role is admin redirect to whatever controller/action and set the admin prefix. If hes not an admin redirect him to something else.

if ($this->Auth->login()) {
    if ($this->Auth->user('role') === 'admin') {
        $this->redirect(array(
            'admin' => true,
            'controller' => 'foo',
            'action' => 'bar')));
    } else {
        // Do something else, another redirect or whatever
    }
}

There is no need to remove the /admin from the URL as it should show the user hes not authorized when he tries to access an URL he is not allowed to.

2) If you want to grant access for different roles you can use the SimpleRbacAuth I've written. Check the tests for examples of how it works. You simply define a nested array structure and add the roles you want to an action or a whole controller or grant access to everyone by using *.

floriank
  • 25,546
  • 9
  • 42
  • 66
  • I will definitely check out your rbac code! However checking for the role in the login action is what I'm already doing(therefore not quite helpful to this question, but might be to visitors)! – LogixMaster Feb 14 '14 at 15:06