uzyn / cakephp-opauth

Opauth plugin for CakePHP v2.x, allowing simple plug-n-play 3rd-party authentication with CakePHP
http://bakery.cakephp.org/articles/uzyn/2012/06/25/simple_3rd-party_provider_authentication_with_opauth_plugin
Other
128 stars 61 forks source link

FriendOfCake's Crud plugin & Opauth not playing well together #37

Open t1mmen opened 10 years ago

t1mmen commented 10 years ago

Re: https://twitter.com/t1mmen/status/441512918950359040

When FriendOfCake's Crud plugin is loaded, Opath no longer works, giving the error message:

"No model loaded in the Controller by the name "Opauth". Please add it to $uses."

.. when trying to access http://localhost/myapp/auth/github. This works as expected when the Crud plugin is not setup in $components.

// AppController.php
    public $components = array(
        // Auth stuff
        'Session',
        'Auth' => array(
            'loginRedirect' => array(
                'controller' => 'pages',
                'action' => 'display',
                'home'
            ),
            'logoutRedirect' => array(
                'controller' => 'pages',
                'action' => 'display',
                'home'
            ),
        ),
        // Crud scaffolder stuff
        'RequestHandler',
// Enabling this breaks Opauth
//      'Crud.Crud' => array(
//          'actions' => array(
//              'index', // 'view', 'edit', 'delete', 'add'
//          ),
//          'listeners' => array( // <- new
//              'api' => 'Crud.Api'
//          )
//      ),
    );

I installed Opauth using Composer:

    {
        "name": "myapp",
        "repositories": [
            {
                "type": "pear",
                "url": "http://pear.cakephp.org"
            }
        ],
        "require": {
            "pear-cakephp/cakephp": ">=2.4.0",
            "uzyn/cakephp-opauth": "dev-composer",
            "opauth/google":"*",
            "opauth/facebook": "*",
            "opauth/github": "*",
            "opauth/twitter": "*",
            "friendsofcake/crud" : "3.*"
        }
    }

And my bootstrap.php has this part added:

// Load Composer autoload.
// Based on http://book.cakephp.org/2.0/en/installation/advanced-installation.html

require ROOT . DS . 'vendor'. DS . 'autoload.php';

// Remove and re-prepend CakePHP's autoloader as composer thinks it is the most important.
// See https://github.com/composer/composer/commit/c80cb76b9b5082ecc3e5b53b1050f76bb27b127b
spl_autoload_unregister(['App', 'load']);
spl_autoload_register(['App', 'load'], true, true);

// PLUGINS
CakePlugin::loadAll(array(
    'Crud',
    'Opauth' => array('bootstrap' => true, 'routes' => true),
));

Configure::write('Opauth.path', '/myapp/auth/');

// Stragegies configuration
Configure::write('Opauth.Strategy.Github', array(
   'client_id' => 'x',
   'client_secret' => 'y',
));

My directory tree looks like this: https://www.dropbox.com/s/4pzmcpcqv75aqdn/Screenshot%202014-03-06%2013.03.21.png

dir tree

jippi commented 10 years ago

I guess you would need to disable Crud for the opauth plugin - CRUD don't have any build in way of doing this easily.

Maybe you can do something like this in your AppController beforeFilter:

if ($this->request->plugin === 'Opauth') {
   $this->Components->disable('Crud');
}
t1mmen commented 10 years ago

Wow, thanks for the quick responses @jippi and @jose_zap :)

It doesn't appear to make a difference, though:

//AppController.php

    public function beforeFilter() {

        if ($this->request->plugin === 'Opauth') {
            $this->Components->unload('Crud'); // tried with Crud.Crud scope as well,
            $this->Components->disable('Crud'); // this doesn't do it either, I guess..
            debug(CakePlugin::loaded());
        }

        parent::beforeFilter();
    }

// Shows:
array(
    (int) 0 => 'Crud',
    (int) 1 => 'Opauth'
)

.. and the same page as before ("No model loaded in the Controller by the name "Opauth". Please add it to $uses.")

jippi commented 10 years ago

It's fine that the plugin is loaded, the component should just be disabled for Opauth.

If the component is disabled, then it should not get any events from the cakephp controller, and thus not try to hijack the request into a CRUD controller.

Is the debug info shown before the error is raised?

Do you call $this->Crud->execute() anywhere manually?

You can also try to unload it and unset($this->Crud)

t1mmen commented 10 years ago
    public function beforeFilter() {

        if ($this->request->plugin === 'Opauth') {
            $this->Components->unload('Crud'); // tried with ->disable too, no change.
            $this->Components->unload('Crud.Crud'); // just to be sure..
            unset($this->Crud);
            debug(CakePlugin::loaded());
        }

        parent::beforeFilter();
    }

My error.log:


2014-03-06 13:48:49 Error: [CakeException] No model loaded in the Controller by the name "Opauth". Please add it to $uses.
Request URL: /myapp/auth/github
Stack Trace:
#0 /Users/timmstokke/Dropbox/www/myapp/Plugin/Crud/Controller/Component/CrudComponent.php(614): CrudComponent->_setModelProperties()
#1 /Users/timmstokke/Dropbox/www/myapp/Plugin/Crud/Controller/Component/CrudComponent.php(751): CrudComponent->getSubject()
#2 /Users/timmstokke/Dropbox/www/myapp/Plugin/Crud/Controller/Component/CrudComponent.php(728): CrudComponent->_loadListener('RelatedModels')
#3 /Users/timmstokke/Dropbox/www/myapp/Plugin/Crud/Controller/Component/CrudComponent.php(169): CrudComponent->_loadListeners()
#4 [internal function]: CrudComponent->initialize(Object(OpauthController))
#5 /Users/timmstokke/Dropbox/www/myapp/vendor/pear-pear.cakephp.org/CakePHP/Cake/Utility/ObjectCollection.php(132): call_user_func_array(Array, Array)
#6 [internal function]: ObjectCollection->trigger(Object(CakeEvent))
#7 /Users/timmstokke/Dropbox/www/myapp/vendor/pear-pear.cakephp.org/CakePHP/Cake/Event/CakeEventManager.php(247): call_user_func(Array, Object(CakeEvent))
#8 /Users/timmstokke/Dropbox/www/myapp/vendor/pear-pear.cakephp.org/CakePHP/Cake/Controller/Controller.php(674): CakeEventManager->dispatch(Object(CakeEvent))
#9 /Users/timmstokke/Dropbox/www/myapp/vendor/pear-pear.cakephp.org/CakePHP/Cake/Routing/Dispatcher.php(182): Controller->startupProcess()
#10 /Users/timmstokke/Dropbox/www/myapp/vendor/pear-pear.cakephp.org/CakePHP/Cake/Routing/Dispatcher.php(160): Dispatcher->_invoke(Object(OpauthController), Object(CakeRequest), Object(CakeResponse))
#11 /Users/timmstokke/Dropbox/www/myapp/app/webroot/index.php(99): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
#12 {main}
jippi commented 10 years ago

Can you come by the #FriendsOfCake IRC channel ? easier to debug live :)

t1mmen commented 10 years ago

Absolutely! I'll come by shortly, thanks :)

t1mmen commented 10 years ago

Thanks to @jippi, I got it working by:

  1. Init the Crud component like this:
    public $components = array(
        //....
        'Crud.Crud' => array(
            'enabled' => false, // ADDED THIS
            'actions' => array(
                'index', // 'view', 'edit', 'delete', 'add'
            ),
            'listeners' => array( // <- new
                'api' => 'Crud.Api'
            )
        ),
    );

AppController's beforeFilter looks like:

    public function beforeFilter() {

        // if ($this->request->plugin != 'Opauth') {
             $this->Components->enable('Crud'); 
             $this->Crud->initialize($this);
        // }

        parent::beforeFilter();
    }

@jippi also noticed https://github.com/uzyn/cakephp-opauth/blob/master/Controller/OpauthController.php#L9 is missing parent::beforeFilter();, meaning my beforeFilter in AppController is never run when inside the opauth plugin.