Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5fca27b

Browse filesBrowse files
minor #59407 [TwigBridge] Align isGrantedForUser on isGranted with falsy $field (smnandre)
This PR was squashed before being merged into the 7.3 branch. Discussion ---------- [TwigBridge] Align isGrantedForUser on isGranted with falsy $field | Q | A | ------------- | --- | Branch? | 7.3 | Bug fix? | no | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Issues | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT Align `is_granted_for_user` on `is_granted` behaviour when passing a falsy $field argument. (Follows #59282 (comment)) Commits ------- cc92b65 [TwigBridge] Align isGrantedForUser on isGranted with falsy $field
2 parents dde4a2e + cc92b65 commit 5fca27b
Copy full SHA for 5fca27b

File tree

2 files changed

+117
-1
lines changed
Filter options

2 files changed

+117
-1
lines changed

‎src/Symfony/Bridge/Twig/Extension/SecurityExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Twig/Extension/SecurityExtension.php
+9-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ public function isGranted(mixed $role, mixed $object = null, ?string $field = nu
4141
}
4242

4343
if (null !== $field) {
44+
if (!class_exists(FieldVote::class)) {
45+
throw new \LogicException('Passing a $field to the "is_granted()" function requires symfony/acl. Try running "composer require symfony/acl-bundle" if you need field-level access control.');
46+
}
47+
4448
$object = new FieldVote($object, $field);
4549
}
4650

@@ -57,7 +61,11 @@ public function isGrantedForUser(UserInterface $user, mixed $attribute, mixed $s
5761
throw new \LogicException(\sprintf('An instance of "%s" must be provided to use "%s()".', UserAuthorizationCheckerInterface::class, __METHOD__));
5862
}
5963

60-
if ($field) {
64+
if (null !== $field) {
65+
if (!class_exists(FieldVote::class)) {
66+
throw new \LogicException('Passing a $field to the "is_granted_for_user()" function requires symfony/acl. Try running "composer require symfony/acl-bundle" if you need field-level access control.');
67+
}
68+
6169
$subject = new FieldVote($subject, $field);
6270
}
6371

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Twig\Tests\Extension;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\PhpUnit\ClassExistsMock;
16+
use Symfony\Bridge\Twig\Extension\SecurityExtension;
17+
use Symfony\Component\Security\Acl\Voter\FieldVote;
18+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
19+
use Symfony\Component\Security\Core\Authorization\UserAuthorizationCheckerInterface;
20+
use Symfony\Component\Security\Core\User\UserInterface;
21+
22+
class SecurityExtensionTest extends TestCase
23+
{
24+
/**
25+
* @dataProvider provideObjectFieldAclCases
26+
*/
27+
public function testIsGrantedCreatesFieldVoteObjectWhenFieldNotNull($object, $field, $expectedSubject)
28+
{
29+
$securityChecker = $this->createMock(AuthorizationCheckerInterface::class);
30+
$securityChecker
31+
->expects($this->once())
32+
->method('isGranted')
33+
->with('ROLE', $expectedSubject)
34+
->willReturn(true);
35+
36+
$securityExtension = new SecurityExtension($securityChecker);
37+
$this->assertTrue($securityExtension->isGranted('ROLE', $object, $field));
38+
}
39+
40+
public function testIsGrantedThrowsWhenFieldNotNullAndFieldVoteClassDoesNotExist()
41+
{
42+
if (!class_exists(UserAuthorizationCheckerInterface::class)) {
43+
$this->markTestSkipped('This test requires symfony/security-core 7.3 or superior.');
44+
}
45+
46+
$securityChecker = $this->createMock(AuthorizationCheckerInterface::class);
47+
48+
ClassExistsMock::register(SecurityExtension::class);
49+
ClassExistsMock::withMockedClasses([FieldVote::class => false]);
50+
51+
$this->expectException(\LogicException::class);
52+
$this->expectExceptionMessageMatches('Passing a $field to the "is_granted()" function requires symfony/acl.');
53+
54+
$securityExtension = new SecurityExtension($securityChecker);
55+
$securityExtension->isGranted('ROLE', 'object', 'bar');
56+
}
57+
58+
/**
59+
* @dataProvider provideObjectFieldAclCases
60+
*/
61+
public function testIsGrantedForUserCreatesFieldVoteObjectWhenFieldNotNull($object, $field, $expectedSubject)
62+
{
63+
if (!class_exists(UserAuthorizationCheckerInterface::class)) {
64+
$this->markTestSkipped('This test requires symfony/security-core 7.3 or superior.');
65+
}
66+
67+
$user = $this->createMock(UserInterface::class);
68+
$userSecurityChecker = $this->createMock(UserAuthorizationCheckerInterface::class);
69+
$userSecurityChecker
70+
->expects($this->once())
71+
->method('isGrantedForUser')
72+
->with($user, 'ROLE', $expectedSubject)
73+
->willReturn(true);
74+
75+
$securityExtension = new SecurityExtension(null, null, $userSecurityChecker);
76+
$this->assertTrue($securityExtension->isGrantedForUser($user, 'ROLE', $object, $field));
77+
}
78+
79+
public function testIsGrantedForUserThrowsWhenFieldNotNullAndFieldVoteClassDoesNotExist()
80+
{
81+
if (!class_exists(UserAuthorizationCheckerInterface::class)) {
82+
$this->markTestSkipped('This test requires symfony/security-core 7.3 or superior.');
83+
}
84+
85+
$securityChecker = $this->createMock(UserAuthorizationCheckerInterface::class);
86+
87+
ClassExistsMock::register(SecurityExtension::class);
88+
ClassExistsMock::withMockedClasses([FieldVote::class => false]);
89+
90+
$this->expectException(\LogicException::class);
91+
$this->expectExceptionMessageMatches('Passing a $field to the "is_granted_for_user()" function requires symfony/acl.');
92+
93+
$securityExtension = new SecurityExtension(null, null, $securityChecker);
94+
$securityExtension->isGrantedForUser($this->createMock(UserInterface::class), 'object', 'bar');
95+
}
96+
97+
public static function provideObjectFieldAclCases()
98+
{
99+
return [
100+
[null, null, null],
101+
['object', null, 'object'],
102+
['object', false, new FieldVote('object', false)],
103+
['object', 0, new FieldVote('object', 0)],
104+
['object', '', new FieldVote('object', '')],
105+
['object', 'field', new FieldVote('object', 'field')],
106+
];
107+
}
108+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.