Home > Back-end >  Symfony: how to add a serializer group on a Route depending on logged in user's roles
Symfony: how to add a serializer group on a Route depending on logged in user's roles

Time:03-22

I'm using JMSSerializerBundle in my entities definition, and RestBundle's annotations in controllers.

I have an entity with public and admin-protected attributes, let's say

use JMS\Serializer\Annotation as Serializer;

class UserAddress {
    /**
     * @Serializer\Expose
     * @Serializer\Groups(groups={"address:read"})
     */
    private $nonSecretAttribute;

    /**
     * @Serializer\Expose
     * @Serializer\Groups(groups={"address:admin-read"})
     */
    private $secretAttribute;
}

and a User like :

class User {
    // ...
    
    /**
     * @ORM\OneToMany(targetEntity="UserAddress", mappedBy="user")
     */
    private $addresses;

and my controller looks like

use FOS\RestBundle\Controller\Annotations as Rest;

class UsersController {
    /**
     * @Rest\Get("/users/{user}/addresses", requirements={"user"="\d "})
     * @Rest\View(serializerGroups={"address:read"})
     * @IsGranted("user_read", subject="user")
     */
    public function getUsersAddresses(User $user)
    {
        return $user->getAddresses();
    }
}

but how could I add the infos:admin-read to the serializer groups here if the logged in user happens to have the ADMIN_ROLE role ? Is that possible in the @Rest\View annotation ? Do I have a way to modify the groups in the controller's method, inside a conditional loop verifying my logged in user's roles ?

CodePudding user response:

You should instantiate the fos-rest View manually and add a Context. On that Context you can set the serialization groups at runtime by evaluating the users roles.

Something like this should work:

use FOS\RestBundle\View\View;
use FOS\RestBundle\Context\Context;

class UsersController 
{

    public function getUsersAddresses(User $user): View
    {
        $isAdmin = in_array('ROLE_ADMIN', $user->getRoles());
        $context = new Context();
        $context->setGroups($isAdmin ? ['address:admin-read'] : ['address:read']);

        $view = VVV::create()->setContext($context);


        return $view
            ->setContext($context)
            ->setData($user->getAddresses());
    }
}
  • Related