简体   繁体   中英

How to make a custom action inaccessible depending on the user - Sonata Admin

I have implemented the clone action just like in the documentation. How can I limit the access to the clone action to the user who created the object?

I have already an access denied exception check in my action, but how can I now hide the button in the list view if the user is not the author of that object. The user should still be able to list the order and display it.

This is my route:

protected function configureRoutes(RouteCollection $collection)
{
    $collection->add('clone', $this->getRouterIdParameter().'/clone'); 
}

And my list fields:

protected function configureListFields(ListMapper $listMapper)
{
    $listMapper
        ->add('_action', 'actions', array(
            'actions' => array(
                'show' => array(),
                'edit' => array(),
                'clone' => array(
                    'template' => 'AppBundle:Sonata/Button:clone_button.html.twig'
                ),
            ), 'label' => 'Actions'
        ))
    ;
}

and my clone action:

public function cloneAction($id = null)
{
    $object = $this->admin->getSubject();
    if (!$object) {
        throw new NotFoundHttpException(sprintf('Unable to find the object with id : %s', $id));
    }

    If (!$object->isAuthor($this->getUser())) {
        throw new AccessDeniedException();
    }

    $clonedObject = clone $object;

    $this->admin->create($clonedObject);
    $this->addFlash('sonata_flash_success', 'Cloned successfully');
    return new RedirectResponse($this->admin->generateUrl('edit', array('id' => $clonedObject->getId())));
}

As you can see in my clone action, I have a check to see if the user is the author of the order. But how can I remove the button in the list completely by check my isAuthor function?

Because now the user can see the button but if he is unauthorized to clone the order and he clicks the button he get an access denied exception. So I don't want to show the button at all. The same counts for the edit button.

I have thought of something like this:

protected function configureRoutes(RouteCollection $collection)
{
    $user = $this->getConfigurationPool()->getContainer()->get('security.token_storage')
            ->getToken()->getUser();

    If (!$object->isAuthor($user)) {
        $collection->remove('edit');
        $collection->remove('clone');
    }
}

But apparently this can't be done.

Does anybody have an idea how to do this?

I would create a Symfony Voter and remove the check from the action. The check would be done, in the voter outside the action, and could be done from anywhere, including the template. You should check the template, it probably already does the check.

Also, off-topic pro-tip, always provide a message inside your exceptions.

throw new AccessDeniedException('Not an author of this object');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM