phpcakephpcakephp-4.x

Resource class Administrator does not exist while implementing modeless policy


I'm trying to implement a policy for a model-less controller. The error I keep getting when I access /administrators/import

Resource class Administrator does not exist.
InvalidArgumentException

Here is the relevant code:

In AdministratorController.import()

public function import()
{
        //$this->Authorization->can('import', 'Administrator'); //doesn't work either
        $this->Authorization->authorize('Administrator', 'import');
        ...
}

In Application.php

public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface
{
        $resolver = new ResolverCollection();
        
        $resolver->add(new \Authorization\Policy\MapResolver([
            'Administrator' => \App\Policy\AdministratorPolicy::class,
        ]));
        $resolver->add(new \Authorization\Policy\OrmResolver());

        return new AuthorizationService($resolver);
}

In \App\Policy\AdministratorPolicy.php

<?php
declare(strict_types=1);

namespace App\Policy;


/**
 * Administrator policy
 */
class AdministratorPolicy {
    /**
     * Check if $user can import
     *
     * @param \Authorization\IdentityInterface $user The user.
     * @param \App\Model\Entity\User $resource
     * @return bool
     */
    public function canImport(IdentityInterface $user, $resource)
    {
        return $user->is_admin;
    }
}

Edit #1 fixed typo in AdministratorPolicy class definition, issue persists.

Final solution based off @Greg Schmidt's suggestion. Note full paths (ex. \App\Controller) for class reference.

public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface
    {
        $resolver = new ResolverCollection();
        
        $resolver->add(new \Authorization\Policy\MapResolver([
            \App\Controller\AdministratorsController::class => \App\Policy\AdministratorPolicy::class,
        ]));
        $resolver->add(new \Authorization\Policy\OrmResolver());

        return new AuthorizationService($resolver);
    }

Solution

  • MapResolver maps from a class name to a policy. Instead of 'Administrator' in the MapResolver constructor, try AdministratorController::class, along with any required use statements to help it locate that, and in the controller call $this->Authorization->authorize($this, 'import');

    Also, note that since you're authorizing the action that's being called, you can skip that parameter, so just $this->Authorization->authorize($this); should work.