orchestral / auth

Auth Component for Orchestra Platform
MIT License
23 stars 5 forks source link

Unknown Action Exception - Fresh Installation #25

Closed ryanshowers closed 10 years ago

ryanshowers commented 10 years ago

Wasn't sure where to post this. Followed the composer installation instructions for v. 2.1.x and receive InvalidArgumentException Unable to verify unknown action . Looks like manager-users and manage-orchestra actions are not inserted during installation.

crynobone commented 10 years ago

Are you using it with the full Orchestra Platform, or just as Laravel component?

ryanshowers commented 10 years ago

Full Orchestra Platform, using composer instructions here - http://orchestraplatform.com/docs/2.1/installation#install-orchestra-platform

crynobone commented 10 years ago

I wasn't able to replicate the issue on a fresh installation. The ACL is being added during installation process https://github.com/orchestral/foundation/blob/2.1/src/Orchestra/Foundation/Installation/Installer.php#L97-L130 which hasn't changed in awhile.

Could you try to re-install (drop the database) and test again.

ryanshowers commented 10 years ago

Hmmm. I dropped the tables and completed the installation process several times, including removing the files and running the composer command.

Here's my value for acl_orchestra:

a:5:{s:4:"name";s:18:"Orchestra Platform";s:5:"theme";a:2:{s:8:"frontend";s:7:"default";s:7:"backend";s:7:"default";}s:7:"actions";a:0:{}s:5:"roles";a:1:{i:0;s:5:"guest";}s:3:"acl";a:0:{}}

crynobone commented 10 years ago
  1. Using MySQL?
  2. Any config customization?
  3. Do you have an admin user?
ryanshowers commented 10 years ago
  1. Yep, using MySQL
  2. Only config change was to add the database credentials
  3. Yes, user was created successfully and assigned to the admin role
crynobone commented 10 years ago

Can you also send my your app/storage/logs/laravel.log file.

ryanshowers commented 10 years ago

Sure thing.

crynobone commented 10 years ago

can't find anything strange. PHP version and MySQL version? And OS.

ryanshowers commented 10 years ago

MySQL: 5.1.71 PHP: 5.4.15 OSX 10.9

ryanshowers commented 10 years ago

I went ahead and manually inserted the serialized values. I wish I could help debug but I'm just starting with Laravel and Orchestra. Thanks for your time and let me know if you need anything else.

crynobone commented 10 years ago

I can't find anything that could cause this, but at the same time I would like to avoid such issue.

If you're free. Could you debug https://github.com/orchestral/auth/blob/master/src/Orchestra/Auth/Acl/Container.php#L75 and remove and $memory !== $this->memory.

ryanshowers commented 10 years ago

Removed from line 75, dropped tables and reinstalled. Issue remains.

crynobone commented 10 years ago

There no issue with orchestra/memory as other configuration are properly saved. The only missing here are https://github.com/orchestral/foundation/blob/master/src/Orchestra/Foundation/Installation/Installer.php#L130 which attach memory to ACL action. Does moving line 130 to between line 123 and line 124 solve it?

ryanshowers commented 10 years ago

Unfortunately, no.

gnanakeethan commented 10 years ago

I think that there may be a problem with MySQL Databases. have you checked this problem on a latest MySQL Version? if that problem goes off. you know the reason.

crynobone commented 10 years ago

Technically 5.1.71 was released last August http://dev.mysql.com/doc/relnotes/mysql/5.1/en/news-5-1-71.html.

ryanshowers commented 10 years ago

Upgraded port to mysql 5.1.72 - no change.

ACL is added to $memory during admin/install/create - https://gist.github.com/ryanshowers/8aa5cbdf49999816b78a

However, I interrupted /admin/install/done and noticed the value for "site" is used for "acl_orchestra" - https://gist.github.com/ryanshowers/06ef7f9290f07fe2dfdf

It seems the acl value isn't stored properly in the database during admin/install/create. Am I on the right track here?

crynobone commented 10 years ago

Am I on the right track here?

Yeah we're getting somewhere. Can you try the following:

Option A

  1. Can you change `"minimum-stability": "dev" on https://github.com/orchestral/platform/blob/2.1/composer.json#L40
  2. Run composer update
  3. Install.

I'm been doing some small refactor on auth, memory and foundation while trying to solve this, it might be possible it's already fixed.

Option B


// We should also create a basic ACL for Orchestra Platform, since
// the basic roles is create using Fluent Query Builder we need
// to manually insert the roles.
$acl = $this->app['orchestra.acl']->make('orchestra');

$acl->attach($memory);
$acl->actions()->attach($actions);
$acl->roles()->attach(array_values($roles));
$acl->allow($roles[$admin], $actions);

$this->app['events']->fire('orchestra.install: acl', array($acl));

$this->app['orchestra.memory']->finish(); // this will force memory to shutdown and save the content to db.
ryanshowers commented 10 years ago

No luck. After installation "acl_orchestra" = a:3:{s:3:"acl";a:0:{}s:7:"actions";a:0:{}s:5:"roles";a:1:{i:0;s:5:"guest";}}

crynobone commented 10 years ago

What do you get if you do

// We should also create a basic ACL for Orchestra Platform, since
// the basic roles is create using Fluent Query Builder we need
// to manually insert the roles.
$acl = $this->app['orchestra.acl']->make('orchestra');

$acl->attach($memory);
$acl->actions()->attach($actions);
$acl->roles()->attach(array_values($roles));
$acl->allow($roles[$admin], $actions);

$this->app['events']->fire('orchestra.install: acl', array($acl));

$this->app['orchestra.memory']->finish(); // this will force memory to shutdown and save the content to db.

$memory = $this->app['orchestra.memory']->make(); // reload a fresh copy.
var_dump($memory->all());
exit;
ryanshowers commented 10 years ago

Here's the dump...

array(3) {
  ["site"]=>
  array(2) {
    ["name"]=>
    string(18) "Orchestra Platform"
    ["theme"]=>
    array(2) {
      ["frontend"]=>
      string(7) "default"
      ["backend"]=>
      string(7) "default"
    }
  }
  ["email"]=>
  array(9) {
    ["driver"]=>
    string(4) "mail"
    ["host"]=>
    string(16) "smtp.mailgun.org"
    ["port"]=>
    int(587)
    ["from"]=>
    array(2) {
      ["name"]=>
      string(18) "Orchestra Platform"
      ["address"]=>
      string(13) "test@test.com"
    }
    ["encryption"]=>
    string(3) "tls"
    ["username"]=>
    NULL
    ["password"]=>
    NULL
    ["sendmail"]=>
    string(22) "/usr/sbin/sendmail -bs"
    ["pretend"]=>
    bool(false)
  }
  ["acl_orchestra"]=>
  array(2) {
    ["name"]=>
    string(18) "Orchestra Platform"
    ["theme"]=>
    array(2) {
      ["frontend"]=>
      string(7) "default"
      ["backend"]=>
      string(7) "default"
    }
  }
}
schaafie commented 10 years ago

I've got the same problem. Asked for the action that is being searched and the result was "manage_users". Does that make any sense?

crynobone commented 10 years ago

@schaafie can you share the code, or error page.

crynobone commented 10 years ago

@ryanshowers Another test.

use Illuminate\Support\Fluent;
use Orchestra\Support\Str;

Route::get('foo', function () {
    $items1 = [];
    $items2 = [];

    $fixtures = [
        new Fluent(['id' => 1, 'name' => 'site', 'value' => 'a:2:{s:4:"name";s:18:"Orchestra Platform";s:5:"theme";a:2:{s:8:"frontend";s:7:"default";s:7:"backend";s:7:"default";}}']),
        new Fluent(['id' => 2, 'name' => 'email', 'value' => 'a:9:{s:6:"driver";s:4:"mail";s:4:"host";s:16:"smtp.mailgun.org";s:4:"port";i:587;s:4:"from";a:2:{s:4:"name";s:18:"Orchestra Platform";s:7:"address";s:19:"crynobone@gmail.com";}s:10:"encryption";s:3:"tls";s:8:"username";N;s:8:"password";N;s:8:"sendmail";s:22:"/usr/sbin/sendmail -bs";s:7:"pretend";b:0;}']),
        new Fluent(['id' => 3, 'name' => 'acl_orchestra', 'value' => 'a:3:{s:7:"actions";a:2:{i:0;s:16:"manage-orchestra";i:1;s:12:"manage-users";}s:5:"roles";a:3:{i:0;s:5:"guest";i:1;s:13:"administrator";i:2;s:6:"member";}s:3:"acl";a:2:{s:3:"1:0";b:1;s:3:"1:1";b:1;}}']),
    ];

    foreach ($fixtures as $fixture) {
        $value = Str::streamGetContents($fixture->value);
        array_set($items1, $fixture->name, unserialize($value));
        $items2 = array_add($items2, $fixture->name, unserialize($value));
    }

    var_dump($items1);
    var_dump($items2);
    exit;
});
ryanshowers commented 10 years ago

@crynobone where would I place that code? Apologies again, but I'm still learning this framework.

crynobone commented 10 years ago

@ryanshowers in app/routes.php

And then hit the GET foo route from your browser.

I'm considering the usage of array_set() instead of array_add() could have cause the issue on some environment. Above code return same result on my end.

ryanshowers commented 10 years ago

array(3) {
  ["site"]=>
  array(2) {
    ["name"]=>
    string(18) "Orchestra Platform"
    ["theme"]=>
    array(2) {
      ["frontend"]=>
      string(7) "default"
      ["backend"]=>
      string(7) "default"
    }
  }
  ["email"]=>
  array(9) {
    ["driver"]=>
    string(4) "mail"
    ["host"]=>
    string(16) "smtp.mailgun.org"
    ["port"]=>
    int(587)
    ["from"]=>
    array(2) {
      ["name"]=>
      string(18) "Orchestra Platform"
      ["address"]=>
      string(19) "crynobone@gmail.com"
    }
    ["encryption"]=>
    string(3) "tls"
    ["username"]=>
    NULL
    ["password"]=>
    NULL
    ["sendmail"]=>
    string(22) "/usr/sbin/sendmail -bs"
    ["pretend"]=>
    bool(false)
  }
  ["acl_orchestra"]=>
  array(3) {
    ["actions"]=>
    array(2) {
      [0]=>
      string(16) "manage-orchestra"
      [1]=>
      string(12) "manage-users"
    }
    ["roles"]=>
    array(3) {
      [0]=>
      string(5) "guest"
      [1]=>
      string(13) "administrator"
      [2]=>
      string(6) "member"
    }
    ["acl"]=>
    array(2) {
      ["1:0"]=>
      bool(true)
      ["1:1"]=>
      bool(true)
    }
  }
}
array(3) {
  ["site"]=>
  array(2) {
    ["name"]=>
    string(18) "Orchestra Platform"
    ["theme"]=>
    array(2) {
      ["frontend"]=>
      string(7) "default"
      ["backend"]=>
      string(7) "default"
    }
  }
  ["email"]=>
  array(9) {
    ["driver"]=>
    string(4) "mail"
    ["host"]=>
    string(16) "smtp.mailgun.org"
    ["port"]=>
    int(587)
    ["from"]=>
    array(2) {
      ["name"]=>
      string(18) "Orchestra Platform"
      ["address"]=>
      string(19) "crynobone@gmail.com"
    }
    ["encryption"]=>
    string(3) "tls"
    ["username"]=>
    NULL
    ["password"]=>
    NULL
    ["sendmail"]=>
    string(22) "/usr/sbin/sendmail -bs"
    ["pretend"]=>
    bool(false)
  }
  ["acl_orchestra"]=>
  array(3) {
    ["actions"]=>
    array(2) {
      [0]=>
      string(16) "manage-orchestra"
      [1]=>
      string(12) "manage-users"
    }
    ["roles"]=>
    array(3) {
      [0]=>
      string(5) "guest"
      [1]=>
      string(13) "administrator"
      [2]=>
      string(6) "member"
    }
    ["acl"]=>
    array(2) {
      ["1:0"]=>
      bool(true)
      ["1:1"]=>
      bool(true)
    }
  }
}
crynobone commented 10 years ago

false again. :(

ryanshowers commented 10 years ago

I'll ramble on a bit in hopes that this will spark something for you.....

I spent some time today trying to debug this. It seems that $app['orchestra.memory']->finish(); is called 3 times. The value for acl_orchestra is updated each time here - https://github.com/orchestral/memory/blob/master/src/Orchestra/Memory/Abstractable/DatabaseHandler.php#L53

The first time, it stores...

a:2:{s:4:"name";s:18:"Orchestra Platform";s:5:"theme";a:2:{s:8:"frontend";s:7:"default";s:7:"backend";s:7:"default";}}

the second time it stores the correct ACL values

the third loop stores..

a:3:{s:3:"acl";a:0:{}s:7:"actions";a:0:{}s:5:"roles";a:1:{i:0;s:5:"guest";}}
schaafie commented 10 years ago

Error page is included in the document attached. This is what my log tells me:

3 {main} [] []

[2014-01-17 08:35:31] production.INFO: manage-users [] []

[2014-01-17 08:35:31] production.ERROR: exception 'InvalidArgumentException' with message 'Unable to verify unknown action .' in F:\root\orchestra\vendor\orchestra\auth\src\Orchestra\Auth\Acl\Container.php:172

Stack trace:

0 F:\root\orchestra\vendor\orchestra\auth\src\Orchestra\Auth\Acl\Container.php(154): Orchestra\Auth\Acl\Container->check(Array, 'manage-users')

1 F:\root\orchestra\vendor\orchestra\foundation\src\Orchestra\Foundation\AdminMenuHandler.php(72): Orchestra\Auth\Acl\Container->can('manage-users')

2 F:\root\orchestra\vendor\orchestra\foundation\src\Orchestra\Foundation\AdminMenuHandler.php(48): Orchestra\Foundation\AdminMenuHandler->settings()

3 [internal function]: Orchestra\Foundation\AdminMenuHandler->handle()

4 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Events\Dispatcher.php(320): call_user_func_array(Array, Array)

5 [internal function]: Illuminate\Events\Dispatcher->Illuminate\Events{closure}()

6 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Events\Dispatcher.php(196): call_user_func_array(Object(Closure), Array)

7 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php(208): Illuminate\Events\Dispatcher->fire('orchestra.ready...')

8 F:\root\orchestra\vendor\orchestra\foundation\src\Orchestra\Foundation\Routing\AdminController.php(18): Illuminate\Support\Facades\Facade::__callStatic('fire', Array)

9 F:\root\orchestra\vendor\orchestra\foundation\src\Orchestra\Foundation\Routing\AdminController.php(18): Illuminate\Support\Facades\Event::fire('orchestra.ready...')

10 [internal function]: Orchestra\Foundation\Routing\AdminController->Orchestra\Foundation\Routing{closure}(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))

11 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Events\Dispatcher.php(196): call_user_func_array(Object(Closure), Array)

12 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Events\Dispatcher.php(151): Illuminate\Events\Dispatcher->fire('router.filter: ...', Array, true)

13 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\Router.php(1329): Illuminate\Events\Dispatcher->until('router.filter: ...', Array)

14 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\ControllerDispatcher.php(240): Illuminate\Routing\Router->callRouteFilter('000000001df3ed7...', Array, Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))

15 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\ControllerDispatcher.php(114): Illuminate\Routing\ControllerDispatcher->callFilter(Array, Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))

16 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\ControllerDispatcher.php(55): Illuminate\Routing\ControllerDispatcher->before(Object(Orchestra\Foundation\Routing\DashboardController), Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'index')

17 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\Router.php(905): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'Orchestra\Found...', 'index')

18 [internal function]: Illuminate\Routing\Router->Illuminate\Routing{closure}()

19 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\Route.php(105): call_user_func_array(Object(Closure), Array)

20 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\Router.php(969): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))

21 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Routing\Router.php(939): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))

22 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(714): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))

23 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(689): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))

24 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Http\FrameGuard.php(38): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)

25 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Session\Middleware.php(60): Illuminate\Http\FrameGuard->handle(Object(Illuminate\Http\Request), 1, true)

26 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Cookie\Queue.php(47): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)

27 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Cookie\Guard.php(51): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)

28 F:\root\orchestra\vendor\stack\builder\src\Stack\StackedHttpKernel.php(23): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)

29 F:\root\orchestra\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(589): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))

30 F:\root\orchestra\public\index.php(49): Illuminate\Foundation\Application->run()

31 F:\root\orchestra\server.php(19): require_once('F:\root\orchest...')

32 {main} [] []

And this is what I did to F:\root\orchestra\vendor\orchestra\auth\src\Orchestra\Auth\Acl\Container.php

public function check($roles, $action)

{

    Log::info($action);

   $action = $this->actions->search($action);

    if (is_null($action)) {

        throw new InvalidArgumentException("Unable to verify unknown action {$action}.");

    }

    foreach ((array) $roles as $role) {

        $role = $this->roles->search($role);

        // array_search() will return false when no key is found based

        // on given haystack, therefore we should just ignore and

        // continue to the next role.

        if (! is_null($role) and isset($this->acl[$role.':'.$action])) {

            return $this->acl[$role.':'.$action];

        }

    }

    return false;

}

Cheers,

Pieter.

Van: Mior Muhammad Zaki [mailto:notifications@github.com] Verzonden: donderdag 16 januari 2014 20:46 Aan: orchestral/auth CC: schaafie Onderwerp: Re: [auth] Unknown Action Exception - Fresh Installation (#25)

@schaafie https://github.com/schaafie can you share the code, or error page.

— Reply to this email directly or view it on GitHub https://github.com/orchestral/auth/issues/25#issuecomment-32522083 . https://github.com/notifications/beacon/6422940__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcwNTQzNDM1OCwiZGF0YSI6eyJpZCI6MjM1NDk2MjV9fQ==--beb5830b8798d32862aefc6f3f68047f85a84e68.gif

ryanshowers commented 10 years ago

More findings:

https://github.com/orchestral/memory/blob/master/src/Orchestra/Memory/FluentMemoryHandler.php#L61 generates the following query:

update `orchestra_options` set `value` = ? where `id` is null
$id    = $this->getKeyId($key);

$id is NULL and $this->keyMap is empty

Not sure if $this->keyMap should have values, but this fixes the installation issue I'm having...

if (!is_null($id)) {
   $this->resolver()->where('id', '=', $id)->update(array(
        'value' => $value,
    ));
}
ryanshowers commented 10 years ago

That fixed it. Thanks

crynobone commented 10 years ago

I'll have tagged all version to a stable version. Should be able to swap with "stable" minimum stability now. Thanks for the report and sorry for the trouble.