Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Attribute/AdminDashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ public function __construct(
/**
* @var string|null $routePath The path of the Symfony route that will be created for the dashboard (e.g. '/admin)
*/
public /* ?string */ $routePath = null,
/* ?string */ public $routePath = null,
/**
* @var string|null $routeName The name of the Symfony route that will be created for the dashboard (e.g. 'admin')
*/
public /* ?string */ $routeName = null,
/* ?string */ public $routeName = null,
/**
* @var array{
* requirements?: array<string, string>,
Expand Down
61 changes: 61 additions & 0 deletions tests/TestApplication/src/Security/CustomVoter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace EasyCorp\Bundle\EasyAdminBundle\Tests\TestApplication\Security;

use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

/**
* Custom voter that allows to ban an entity and its property from being processed.
*
* This is only for testing purposes, to simulate the behavior of the FieldFactory::processFields() method when
* EA_VIEW_FIELD will return FALSE, on first entity, which is used to build table theaders.
*/
class CustomVoter extends Voter
{
private ?object $banEntity = null;
private ?string $banEntityProperty = null;

protected function supports(string $attribute, mixed $subject): bool
{
return Permission::exists($attribute);
}

protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
static $entities = [];

if ($subject instanceof EntityDto && $subject->getInstance()) {
$entities[] = $subject;
}

foreach ($entities as $entityDto) {
if ($this->banEntity && $entityDto->getInstance() === $this->banEntity) {
// imitate the behavior of FieldFactory::processFields()
// which removes the field from the entity if it is not granted
if ($subject instanceof FieldDto) {
if ($fieldDto = $entityDto->getFields()?->getByProperty($this->banEntityProperty)) {
$entityDto->getFields()->unset($fieldDto);
}
}
}
}

return true;
}

public function ban(object $entity, ?string $propertyName = null): void
{
$this->banEntity = $entity;
$this->banEntityProperty = $propertyName;
}

public function removeBan(): void
{
$this->banEntity = null;
$this->banEntityProperty = null;
}
}
60 changes: 60 additions & 0 deletions tests/VoterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace EasyCorp\Bundle\EasyAdminBundle\Tests;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Test\AbstractCrudTestCase;
use EasyCorp\Bundle\EasyAdminBundle\Tests\TestApplication\Controller\DashboardController;
use EasyCorp\Bundle\EasyAdminBundle\Tests\TestApplication\Controller\Sort\WebsiteCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Tests\TestApplication\Entity\Website;
use EasyCorp\Bundle\EasyAdminBundle\Tests\TestApplication\Security\CustomVoter;
use Symfony\Component\Security\Core\Authorization\Strategy\UnanimousStrategy;

class VoterTest extends AbstractCrudTestCase
{
/**
* @var EntityRepository
*/
private $repository;

protected function getControllerFqcn(): string
{
return WebsiteCrudController::class;
}

protected function getDashboardFqcn(): string
{
return DashboardController::class;
}

protected function setUp(): void
{
parent::setUp();
$this->client->followRedirects();
$this->repository = $this->entityManager->getRepository(Website::class);
}

public function testingVoter()
{
// Arrange
$entities = $this->repository->findAll();

/** @var CustomVoter $voter */
$voter = $this->getContainer()->get(CustomVoter::class);
$voter->ban($entities[0], 'name');

// UnanimousStrategy
$accessDecisionManager = $this->getContainer()->get('security.access.decision_manager');
\Closure::bind(function () {
$this->strategy = new UnanimousStrategy();
}, $accessDecisionManager, $accessDecisionManager)();

// Act
$crawler = $this->client->request('GET', $this->generateIndexUrl());

// Assert
$this->assertResponseIsSuccessful();
$this->assertSelectorExists('th[data-column="pages"]');
$this->assertSelectorExists('th[data-column="name"]');
}
}
Loading