Policy Resolvers
Policy resolvers map resource objects to their corresponding policy classes. The plugin includes a few resolvers out of the box, and you can implement your own by implementing Authorization\Policy\ResolverInterface.
Built-in resolvers:
MapResolvermaps resource class names to policy class names, policy objects, or callables.OrmResolverapplies convention-based policy resolution for common ORM objects.ResolverCollectioncombines multiple resolvers and checks them in order.
Using MapResolver
MapResolver lets you map resource classes to policy classes, policy instances, or factory callables:
use Authorization\Policy\MapResolver;
$mapResolver = new MapResolver();
// Map a resource class to a policy classname
$mapResolver->map(Article::class, ArticlePolicy::class);
// Map a resource class to a policy instance
$mapResolver->map(Article::class, new ArticlePolicy());
// Map a resource class to a factory callable
$mapResolver->map(Article::class, function ($resource, $mapResolver) {
// Return a policy object.
});2
3
4
5
6
7
8
9
10
11
12
13
14
Using OrmResolver
OrmResolver is the convention-based resolver for CakePHP ORM objects. It assumes:
- Policies live in
App\Policy. - Policy classes use the
Policysuffix.
OrmResolver can resolve policies for:
- Entities, using the entity class name.
- Tables, using the table class name.
- Queries, using the class returned by
repository().
These rules are applied:
- The resource class name is converted into a policy class name. For example,
App\Model\Entity\Bookmarkmaps toApp\Policy\BookmarkPolicy. - Plugin resources first check for an application override such as
App\Policy\Bookmarks\BookmarkPolicyforBookmarks\Model\Entity\Bookmark. - If no application override exists, the plugin policy is checked, such as
Bookmarks\Policy\BookmarkPolicy.
For tables, App\Model\Table\ArticlesTable maps to App\Policy\ArticlesTablePolicy. Queries use their repository table to derive the policy class.
Customize OrmResolver through its constructor:
use Authorization\Policy\OrmResolver;
$appNamespace = 'App';
$overrides = [
'Blog' => 'Cms',
];
$resolver = new OrmResolver($appNamespace, $overrides);2
3
4
5
6
7
8
Using Multiple Resolvers
ResolverCollection combines resolvers and checks them sequentially:
use Authorization\Policy\ResolverCollection;
use Authorization\Policy\MapResolver;
use Authorization\Policy\OrmResolver;
$ormResolver = new OrmResolver();
$mapResolver = new MapResolver();
$resolver = new ResolverCollection([$mapResolver, $ormResolver]);2
3
4
5
6
7
8
This lets you check the explicit map first and fall back to ORM conventions.
Creating a Resolver
Implement Authorization\Policy\ResolverInterface and define getPolicy($resource) when you need custom resolution logic.
One example is bridging the Authorization plugin with legacy controller-based authorization during migration from AuthComponent. First create a catch-all policy:
// in src/Policy/ControllerHookPolicy.php
namespace App\Policy;
class ControllerHookPolicy
{
public function __call(string $name, array $arguments)
{
/** @var ?\Authorization\Identity $user */
[$user, $controller] = $arguments;
return $controller->isAuthorized($user?->getOriginalData());
}
}2
3
4
5
6
7
8
9
10
11
12
13
Then create a resolver for controllers:
// in src/Policy/ControllerResolver.php
namespace App\Policy;
use Authorization\Policy\Exception\MissingPolicyException;
use Authorization\Policy\ResolverInterface;
use Cake\Controller\Controller;
class ControllerResolver implements ResolverInterface
{
public function getPolicy($resource)
{
if ($resource instanceof Controller) {
return new ControllerHookPolicy();
}
throw new MissingPolicyException([get_class($resource)]);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
You can register this resolver directly or combine it with others through ResolverCollection.