Search code examples
phpsymfonysonata-user-bundle

Sonata User Bundle - How to restrict users to only be able to edit their own profile?


I'm using Symfony 5 and a development snapshot of the Sonata User Bundle 5 and, as the title says, I would like to restrict the active (authenticated) user to only be able to edit his own profile (and not the profiles of all of the other users with the same role). Currently I just have the choice between all or nothing as the permissions are handled by the roles and all users with the same role have the same permission. Could anyone push me into the right direction?


Solution

  • I wanted to do the same thing as you (with sf 5.4, SonataAdminBundle 4.14 and SonataUserBundle 5.3), I ended up using a custom controller and the preEdit and preShow methods.

    <?php
    namespace App\Controller;
    
    use Sonata\AdminBundle\Controller\CRUDController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Security\Core\Security;
    use Symfony\Component\Security\Core\Exception\AccessDeniedException;
    use App\Entity\SonataUserUser;
    
    class CustomCRUDController extends CRUDController
    {
        const deniedMessage = "Put your custom access denied message here.";
        
        public function __construct(Security $security)
        {
           $this->security = $security;
        }
        
        protected function preEdit(Request $request, object $object): ?Response
        {
            if ($object instanceof SonataUserUser) {
                if (!$this->security->isGranted('ROLE_SUPER_ADMIN') &&
                    $this->security->getUser()->getId() != $object->getId()) {
                    throw new AccessDeniedException(SELF::deniedMessage);
                 }
            }
    
            return null;
        }
    
        protected function preShow(Request $request, object $object): ?Response
        {
            if ($object instanceof SonataUserUser) {
                if (!$this->security->isGranted('ROLE_SUPER_ADMIN') &&
                    $this->security->getUser() != $object->getId()) {
                    throw new AccessDeniedException(SELF::deniedMessage);
                }
            }
    
            return null;
        }
    }
    

    In sonata_admin.yaml :

    sonata_admin:
        default_controller: App\Controller\CustomCRUDController
    

    With this, users who don't have the role ROLE_SUPER_ADMIN shouldn't be able to edit or show other users.

    I don't know if it is the right way to do it or if it is a solid bug-free solution, but it seems to works for me.

    FYI : one could also use a custom voter if they need to implement properly a more complex logic.

    I'm six months late for @perfetzki but I hope this will be useful for others.