2
votes

I am just trying to implement Cakephp ACL user authentication in a plugin named "Cauth". The same thing I implements before was working fine. This time the difference is, it is under plugin. Here, in controller, $this->User->Group->find('list'); is not working. I got the following fatal error:

Fatal Error

Error: Call to a member function find() on a non-object
File: my_dir_path\app\Plugin\Cauth\Controller\UsersController.php
Line: 60

Notice: If you want to customize this error message, create app\View\Errors\fatal_error.ctp

My code are follows:

Group model:

var $useTable = 'groups';
public $hasMany = array (
    'User' => array (
        'className'    => 'Cauth.User',
        'foreignKey'   => 'group_id',
        'dependent'    => false,
        'conditions'   => '',
        'fields'       => '',
        'order'        => '',
        'limit'        => '',
        'offset'       => '',
        'exclusive'    => '',
        'finderQuery'  => '',
        'counterQuery' => ''
    )
);

User model:

var $useTable = 'users';
public $belongsTo = array (
    'Group' => array (
        'className'  => 'Cauth.Group',
        'foreignKey' => 'group_id',
        'conditions' => '',
        'fields'     => '',
        'order'      => ''
    )
);

Users controller add action, the group select box is not working.

Users controller add action:

App::uses('CauthAppController', 'Cauth.Controller');
class UsersController extends CauthAppController {
public function add() {
    if ($this->request->is('post')) {
        $this->User->create();
        if ($this->User->save($this->request->data)) {
            $this->Session->setFlash(__('The user has been saved'));
            $this->redirect(array ('action' => 'index'));
        } else {
            $this->Session->setFlash(__('The user could not be saved. Please, try again.'));
        }
    }

    $groups = $this->User->Group->find('list');
    $this->set(compact('groups'));

}

Can anyone help me to shootout this issue.

Special note: It is working on following case.

Case 1:

If I bind the model from the controller than it works fine.

$this->User->bindModel(
    array ('belongsTo' => array ('Group'))
);

i.e.

public function add() {
    $this->User->bindModel(
        array ('belongsTo' => array ('Group'))
    );
    if ($this->request->is('post')) {
        $this->User->create();
        if ($this->User->save($this->request->data)) {
            $this->Session->setFlash(__('The user has been saved'));
            $this->redirect(array ('action' => 'index'));
        } else {
            $this->Session->setFlash(__('The user could not be saved. Please, try again.'));
        }
    }

    $groups = $this->User->Group->find('list');
    $this->set(compact('groups'));

}

Case 2:

If I allow the action name for all. Admin has all permission though I need to write the beforeFilter for admin also.

public function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow('index', 'add');
}

I have found one more case to make it workable.

Case 3:

The code for my AppController was -

class AppController extends Controller {


    public $helpers    = array ('Form', 'Time', 'Html', 'Session', 'Js', 'DebugKit.Toolbar');
    public $counter    = 0;
    public $components = array (
        'DebugKit.Toolbar',
        'RequestHandler',
        'Acl',
        'Auth' => array (
            'authorize' => array (
                'Actions' => array ('actionPath' => 'controllers')
            )
        ),
        'Session'
    );

    public function beforeFilter() {
        //Configure AuthComponent
        $this->Auth->loginAction    = array ('plugin'     => 'cauth', 'controller' => 'users', 'action'     => 'login');
        $this->Auth->logoutRedirect = array ('plugin'     => 'cauth', 'controller' => 'users', 'action'     => 'login');
        $this->Auth->loginRedirect  = array ('plugin'     => '', 'controller' => 'pages', 'action'     => 'display');

    }

}

In this case it was not working. But when I made it -

class AppController extends Controller {

    public $helpers    = array ('Form', 'Time', 'Html', 'Session', 'Js', 'DebugKit.Toolbar');
    public $counter    = 0;
    public $components = array (
        'DebugKit.Toolbar',
        'RequestHandler',
        'Acl',
        'Auth' => array (
            'authenticate' => array('Form')

        ),
        'Session'
    );

    public function beforeFilter() {
        //Configure AuthComponent
        $this->Auth->loginAction    = array ('plugin'     => 'cauth', 'controller' => 'users', 'action'     => 'login');
        $this->Auth->logoutRedirect = array ('plugin'     => 'cauth', 'controller' => 'users', 'action'     => 'login');
        $this->Auth->loginRedirect  = array ('plugin'     => '', 'controller' => 'pages', 'action'     => 'display');

    }

}

Then the association again start working. Still can not understand what is the problem with this component declaration.

public $components = array (
    'DebugKit.Toolbar',
    'RequestHandler',
    'Acl',
    'Auth' => array (
        'authorize'    => array (
            'Actions' => array ('actionPath' => 'controllers')
        )
    ),
    'Session'
);

And If I do not declare like this way, my ACL is not working. i.e All groups get same permission.

Please help me. I am stack on this for a very long time.

3

3 Answers

4
votes

Finally I have found the solution after a long struggle from the following link -

https://cakephp.lighthouseapp.com/projects/42648/tickets/2464-plugin-using-acl-not-loading-proper-model

When I used Auth component, the user controller was not using Cauth.user model. It was loaded using AppModel. But without auth component, it was working properly. So that the correct way of using auth component will be

    'Auth' => array (
        'authorize' => array (
            'Actions' => array (
                'actionPath' => 'controllers',
                'userModel'  => 'Cauth.User',
            ),
        )
    ),

That is the total AppController will be -

class AppController extends Controller {

    public $helpers    = array ('Form', 'Time', 'Html', 'Session', 'Js', 'DebugKit.Toolbar');
    public $counter    = 0;
    public $components = array (
        'DebugKit.Toolbar',
        'RequestHandler',
        'Acl',
        'Auth' => array (
            'authorize' => array (
                'Actions' => array (
                    'actionPath' => 'controllers',
                    'userModel'  => 'Cauth.User',
                ),
            )
        ),
        'Session'
    );

    public function beforeFilter() {
        //Configure AuthComponent
        $this->Auth->loginAction    = array ('plugin'     => 'cauth', 'controller' => 'users', 'action'     => 'login');
        $this->Auth->logoutRedirect = array ('plugin'     => 'cauth', 'controller' => 'users', 'action'     => 'login');
        $this->Auth->loginRedirect  = array ('plugin'     => '', 'controller' => 'pages', 'action'     => 'display');

    }

}

And now everything is working fine. Thanks to all.

0
votes

Assuming the Group is a name of a model(table),Change this line from:

  $groups = $this->User->Group->find('list');

to

  $groups = $this->Group->find('list');

hope it will help!

0
votes

Try two things to fix this. First add the following to your Users and Groups plugin controllers.

public $uses = array('Users.User', 'Users.Group');

Second, define the components within your plugin controllers. In the cake ACL Auth tutorial they put this in the main AppController, you need to move it to the plugin.

You can either do the following in your UsersAppController or the UsersController

public $components = array(
        'Acl',
        'Auth',
        'Session'
    );

Hope that works, it did for me.