Testing a role of an arbitrary user with Symfony

Published on 2022-06-12 • Modified on 2022-06-12

In this snippet, we see how to test a role of an arbitrary user with Symfony. We know to do it for the current user, thanks to the Symfony\Component\Security\Core\Security service, but it doesn't work on a given user we would retrieve from the database. We can create a UsernamePasswordToken object and call the isGranted() function on the AccessDecisionManager service as shown below.


<?php

declare(strict_types=1);

// src/Controller/Snippet/Snippet203Trait.php

namespace App\Controller\Snippet;

use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;

/**
 * I am using a PHP trait to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor.
 *
 * @property AccessDecisionManagerInterface $accessDecisionManager
 */
trait Snippet203Trait
{
    public function snippet203(): void
    {
        $user = new User();
        $user->setRoles([User::ROLE_READER]);
        $token = new UsernamePasswordToken($user, 'none', $user->getRoles());

        $isGrandedUser = $this->accessDecisionManager->decide($token, [User::ROLE_USER]);
        echo 'Granted ROLE_USER: '.($isGrandedUser ? 'yes' : 'no').PHP_EOL;

        $isGrandedReader = $this->accessDecisionManager->decide($token, [User::ROLE_READER]);
        echo 'Granted ROLE_READER: '.($isGrandedReader ? 'yes' : 'no').PHP_EOL;

        $isGrandedAdmin = $this->accessDecisionManager->decide($token, [User::ROLE_ADMIN]);
        echo 'Granted ROLE_ADMIN: '.($isGrandedAdmin ? 'yes' : 'no').PHP_EOL;

        // That's it! 😁
    }
}

 Run this snippet  ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  More on Stackoverflow   Read the doc  Random snippet

<?php

declare(strict_types=1);

namespace App\Tests\Integration\Controller\Snippets;

use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;

/**
 * @see Snippet203Trait
 */
final class Snippet203Test extends KernelTestCase
{
    private AccessDecisionManagerInterface $accessDecisionManager;

    protected function setUp(): void
    {
        $this->accessDecisionManager = self::getContainer()->get(AccessDecisionManagerInterface::class);
    }

    /**
     * @return iterable<int, array{0: string, 1: bool, 2: bool, 3: bool}>
     */
    public function providerSnippet203(): iterable
    {
        yield [User::ROLE_USER, true, false, false];
        yield [User::ROLE_READER, true, true, false];
        yield [User::ROLE_ADMIN, true, true, true];
    }

    /**
     * @dataProvider providerSnippet203
     *
     * @see Snippet203Trait::snippet203
     */
    public function testSnippet203(string $role, bool $isGrandedUser, bool $isGrandedReader, bool $isGrandedAdmin): void
    {
        $user = new User();
        $user->setRoles([$role]);
        $token = new UsernamePasswordToken($user, 'none', $user->getRoles());

        self::assertSame($isGrandedUser, $this->accessDecisionManager->decide($token, [User::ROLE_USER]));
        self::assertSame($isGrandedReader, $this->accessDecisionManager->decide($token, [User::ROLE_READER]));
        self::assertSame($isGrandedAdmin, $this->accessDecisionManager->decide($token, [User::ROLE_ADMIN]));
    }
}