phpzend-framework3zfc-rbac

ZFC Rbac UnauthorizedStrategy and Zend Framework 3


I read the documentation on Strategies and it seems the code below is valid at least in Zend Framework 2. Of course, I tested it.

public function onBootstrap(EventInterface $e)
{
    $t = $e->getTarget();
    $t->getEventManager()->attach(
        $t->getServiceManager()->get('ZfcRbac\View\Strategy\UnauthorizedStrategy')
    );
}

But when using the Zend Framework 3, it no longer works. It will show the error below:

Fatal error: Uncaught TypeError: Argument 2 passed to Zend\EventManager\EventManager::attach() must be callable, object given, called in /var/www/sub.domain.tld/html/module/Application/src/Module.php on line 20

So basically I am stuck right now. Can you at least point out or guide me to the right direction?


Solution

  • I have to ditch the UnauthorizedStrategy class. Basically, I copied the code from onError method from UnauthorizedStrategy class and modified to fit my needs.

    public function onBootstrap(MvcEvent $e)
    {
        /** @var EventManager $eventManager */
        $eventManager = $e->getApplication()->getEventManager();
    
        $eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this, 'onError'], 100);
    }
    
    public function onError(MvcEvent $event) {
        // Do nothing if no error or if response is not HTTP response
        if (($event->getResult() instanceof HttpResponse)
            || !($event->getResponse() instanceof HttpResponse)
        ) {
            return;
        }
    
        $baseModel = new ViewModel();
        $baseModel->setTemplate('layout/layout');
    
        $model = new ViewModel();
        $model->setTemplate('error/403');
    
        switch ($event->getError()) {
            case GuardInterface::GUARD_UNAUTHORIZED:
                $model->setVariable('error', GuardInterface::GUARD_UNAUTHORIZED);
                break;
    
            default:
                return; // If it is not unauthorized error, skip it so it will show the more appropriate errors.
        }
    
        $baseModel->addChild($model);
        $baseModel->setTerminal(true);
    
        $event->setViewModel($baseModel);
    
        $response = $event->getResponse() ?: new HttpResponse();
        $response->setStatusCode(403);
    
        $event->setResponse($response);
        $event->setResult($baseModel);
    
        $event->stopPropagation();
    }