tmaiaroto/li3_access — Issue #19: li3_access does not pay attention to Dispatcher rules
Author: mariano
Created: 2012-02-25 22:40:03+00:00
State: open

Here's the scenario. If you have defined, somewhere in your bootstrap config, rules of Dispatcher configurations, like so:

```php
Dispatcher::config(array('rules' => array(
'admin' => array('action' => 'admin_{:action}'
)));
```

Access, and all the access adapters, do not take into account any modifications made to the route parameters. This is because Dispatcher::applyRules() makes the modifications to the $params array, instead of Request::$params. This is not going to change (double checked it with @nateabele), so we need a way for these dispatcher rules to be taken into account.

Before proceeding with the solution I implemented (coming up in a pull request in just a few minutes), let me give you a use case. You define a modification just as the one above so when the 'admin' route parameter is one, the action gets prefixed with admin_. You then add the appropriate route continuation so that this route parameter is set when an URL is accessed with /admin as a prefix:

```php
Router::connect('/admin/{:args}', array('admin' => true), array('continue' => true));
```

Let us now add an auth rule (for the `AuthRbac` adapter), so that all admin prefixed accesses are only allowed access when the appropriate prefix is set in Auth. Now, a note here. I could easily change the following check to use `$request->params['admin']` which would work just fine, however I'm trying to showcase a scenario where you would need to do something with the params after they have been modified by a dispatcher rule. Also, you'll see that I'm using a closure (instead of array of closures) directly in the `match` setting, the fix for this is also part of the pull request:

```php
Auth::config(array('default' => array(
'adapter' => 'AuthRbac',
'roles' => array(
array(
'requesters' => '*',
'match' => function($request) {
return (strpos('admin_', $request->params['action']) === 0);
},
'allow' => function() {
return Auth::check('admin');
}
)
)
)));
```

The above code would never match since the `$request->params` used are the parameters parsed before applying any dispatcher rules.

To fix this, and as per @nateabele suggestion, I refactored li3_access so instead of passing the request when filtering `Dispatcher::_callable`, one can directly pass the $params. However, I made it backwards compatible, so code passing the `Request` instance should still work.

The `match` closure now receive an extra parameter which is the whole `$params` array. So after applying the pull request, you would first change how you call `Access` when filtering `Dispatcher::_callable`:

```php
Dispatcher::applyFilter('_callable', function($self, $params, $chain) {
$access = Access::check('default', null, $params);
// ...
});
```

and the above 'match' would be fixed by changing it to:

```php
'match' => function($request, $params) {
return (strpos('admin_', $params['action']) === 0);
}
)));
```

As part of the pull request I also had to adapt the test cases that were using adapter methods directly.