Skip to content

Commit

Permalink
Introduce showInDashboard instead of showIn
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentLanglet committed Dec 16, 2021
1 parent cc8e78c commit 807114c
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 10 deletions.
4 changes: 2 additions & 2 deletions docs/reference/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ For example, you can `create your own voter`_
Customizing the handler behavior
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you want to change the handler behavior, create your own handler implementing
If you want to change the handler behavior, create your own handler implementing
``Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface``.

And specify it as Sonata security handler on your configuration:
Expand Down Expand Up @@ -475,7 +475,7 @@ If you try to access to the admin class you should see the login form, log in
with the ``root`` user.

An Admin is displayed in the dashboard (and menu) when the user has the role
``LIST``. To change this override the ``showIn`` method in the Admin class.
``LIST``. To change this override the ``showInDashboard`` method in the Admin class.

Roles and Access control lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
37 changes: 36 additions & 1 deletion src/Admin/AbstractAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@
*/
abstract class AbstractAdmin extends AbstractTaggedAdmin implements AdminInterface, DomainObjectInterface, AdminTreeInterface
{
// NEXT_MAJOR: Remove the CONTEXT constants.
/** @deprecated */
public const CONTEXT_MENU = 'menu';
/** @deprecated */
public const CONTEXT_DASHBOARD = 'dashboard';

public const CLASS_REGEX =
Expand Down Expand Up @@ -1584,9 +1587,29 @@ public function getObjectIdentifier()
return $this->getCode();
}

public function showInDashboard(): bool
{
// NEXT_MAJOR: Remove this line and uncomment the following one.
return $this->isGranted($this->getPermissionsShow(self::CONTEXT_DASHBOARD, 'sonata_deprecation_mute'));
// return $this->isGranted('LIST');
}

/**
* NEXT_MAJOR: Remove this method.
*
* @deprecated since sonata-project/admin-bundle version 4.x use showInDashboard instead
*/
final public function showIn(string $context): bool
{
return $this->isGranted($this->getPermissionsShow($context));
if ('sonata_deprecation_mute' !== (\func_get_args()[1] ?? null)) {
@trigger_error(sprintf(
'The "%s()" method is deprecated since sonata-project/admin-bundle version 4.x and will be'
.' removed in 5.0 version. Use showInDashboard() instead',
__METHOD__
), \E_USER_DEPRECATED);
}

return $this->isGranted($this->getPermissionsShow($context, 'sonata_deprecation_mute'));
}

final public function createObjectSecurity(object $object): void
Expand Down Expand Up @@ -2156,10 +2179,22 @@ protected function getAccessMapping(): array
/**
* Return the list of permissions the user should have in order to display the admin.
*
* NEXT_MAJOR: Remove this method.
*
* @deprecated since sonata-project/admin-bundle version 4.x
*
* @return string[]
*/
protected function getPermissionsShow(string $context): array
{
if ('sonata_deprecation_mute' !== (\func_get_args()[1] ?? null)) {
@trigger_error(sprintf(
'The "%s()" method is deprecated since sonata-project/admin-bundle version 4.x and will be'
.' removed in 5.0 version.',
__METHOD__
), \E_USER_DEPRECATED);
}

return ['LIST'];
}

Expand Down
9 changes: 9 additions & 0 deletions src/Admin/AdminInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*
* NEXT_MAJOR: Add all these methods to the interface by uncommenting them.
*
* @method bool showInDashboard()
* @method void removeExtension(AdminExtensionInterface $extension)
*
* @phpstan-import-type FieldDescriptionOptions from \Sonata\AdminBundle\FieldDescription\FieldDescriptionInterface
Expand Down Expand Up @@ -267,8 +268,16 @@ public function getDefaultFilterParameters(): array;
*/
public function getFilterParameters(): array;

/**
* NEXT_MAJOR: Remove this method.
*
* @deprecated since sonata-project/admin-bundle version 4.x use showInDashboard instead
*/
public function showIn(string $context): bool;

// NEXT_MAJOR: Uncomment this for Sonata 5
//public function showInDashboard(): bool;

/**
* Add object security, fe. make the current user owner of the object.
*
Expand Down
19 changes: 17 additions & 2 deletions src/Admin/Pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,23 @@ public function getDashboardGroups(): array
}

$admin = $this->getInstance($item['admin']);
if (!$admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD)) {
return null;

// NEXT_MAJOR: Keep the if part.
// @phpstan-ignore-next-line
if (method_exists($admin, 'showInDashboard')) {
if (!$admin->showInDashboard()) {
return null;
}
} else {
@trigger_error(sprintf(
'Not implementing "%s::showInDashboard()" is deprecated since sonata-project/admin-bundle 4.x'
.' and will fail in 5.0.',
AdminInterface::class
), \E_USER_DEPRECATED);

if (!$admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD)) {
return null;
}
}

return $admin;
Expand Down
21 changes: 21 additions & 0 deletions tests/Admin/AdminTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,11 @@ public function testSupportsPreviewMode(): void
static::assertFalse($admin->supportsPreviewMode());
}

/**
* NEXT_MAJOR: Remove this test.
*
* @group legacy
*/
public function testShowIn(): void
{
$admin = new PostAdmin('sonata.post.admin.post', Post::class, 'Sonata\NewsBundle\Controller\PostAdminController');
Expand All @@ -1306,6 +1311,22 @@ public function testShowIn(): void
static::assertTrue($admin->showIn('foo'));
}

public function testShowInDashboard(): void
{
$admin = new PostAdmin('sonata.post.admin.post', Post::class, 'Sonata\NewsBundle\Controller\PostAdminController');

$securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
$securityHandler
->expects(static::once())
->method('isGranted')
->with($admin, ['LIST'])
->willReturn(true);

$admin->setSecurityHandler($securityHandler);

static::assertTrue($admin->showInDashboard());
}

public function testGetObjectIdentifier(): void
{
$admin = new PostAdmin('sonata.post.admin.post', Post::class, 'Sonata\NewsBundle\Controller\PostAdminController');
Expand Down
42 changes: 41 additions & 1 deletion tests/Admin/PoolTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ protected function setUp(): void
$this->pool = new Pool($this->container);
}

public function testGetDashboardGroups(): void
/**
* NEXT_MAJOR: Remove this test.
*
* @group legacy
*/
public function testGetDashboardGroupsForLegacyAdmin(): void
{
$adminGroup1 = $this->createMock(AdminInterface::class);
$adminGroup1->expects(static::once())->method('showIn')->willReturn(true);
Expand Down Expand Up @@ -73,6 +78,41 @@ public function testGetDashboardGroups(): void
static::assertSame($adminGroup1, $groups['adminGroup1']['items']['itemKey']);
}

public function testGetDashboardGroups(): void
{
// NEXT_MAJOR: Use $this->createMock(AdminInterface::class);
$adminGroup1 = $this->getMockBuilder(AdminInterface::class)->addMethods(['showInDashboard'])->getMockForAbstractClass();
$adminGroup1->expects(static::once())->method('showInDashboard')->willReturn(true);

// NEXT_MAJOR: Use $this->createMock(AdminInterface::class);
$adminGroup2 = $this->getMockBuilder(AdminInterface::class)->addMethods(['showInDashboard'])->getMockForAbstractClass();
$adminGroup2->expects(static::once())->method('showInDashboard')->willReturn(false);

// NEXT_MAJOR: Use $this->createMock(AdminInterface::class);
$adminGroup3 = $this->getMockBuilder(AdminInterface::class)->addMethods(['showInDashboard'])->getMockForAbstractClass();
$adminGroup3->expects(static::once())->method('showInDashboard')->willReturn(false);

$this->container->set('sonata.user.admin.group1', $adminGroup1);
$this->container->set('sonata.user.admin.group2', $adminGroup2);
$this->container->set('sonata.user.admin.group3', $adminGroup3);

$pool = new Pool(
$this->container,
['sonata.user.admin.group1', 'sonata.user.admin.group2', 'sonata.user.admin.group3'],
[
'adminGroup1' => $this->getGroupArray('sonata.user.admin.group1'),
'adminGroup2' => $this->getGroupArray('sonata.user.admin.group2'),
'adminGroup3' => $this->getGroupArray('sonata.user.admin.group3'),
'adminGroup4' => $this->getGroupArray(),
]
);

$groups = $pool->getDashboardGroups();

static::assertCount(1, $groups);
static::assertSame($adminGroup1, $groups['adminGroup1']['items']['itemKey']);
}

public function testGetAdminForClassWithTooManyRegisteredAdmin(): void
{
$class = \stdClass::class;
Expand Down
8 changes: 4 additions & 4 deletions tests/Twig/Extension/GroupExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ public function testGetDashboardGroupsWithCreatableAdmins(): void
]);
$twigExtension = new GroupExtension($pool);

$adminNonCreatable = $this->createMock(AdminInterface::class);
$adminCreatable = $this->createMock(AdminInterface::class);
// NEXT_MAJOR: Use createMock instead.
$adminNonCreatable = $this->getMockBuilder(AdminInterface::class)->addMethods(['showInDashboard'])->getMockForAbstractClass();
$adminCreatable = $this->getMockBuilder(AdminInterface::class)->addMethods(['showInDashboard'])->getMockForAbstractClass();

$container->set('sonata_admin_non_creatable', $adminNonCreatable);
$container->set('sonata_admin_creatable', $adminCreatable);

$adminCreatable
->method('showIn')
->with(AbstractAdmin::CONTEXT_DASHBOARD)
->method('showInDashboard')
->willReturn(true);

$adminCreatable
Expand Down

0 comments on commit 807114c

Please sign in to comment.