15
15
use Symfony \Bridge \PhpUnit \ClassExistsMock ;
16
16
use Symfony \Bridge \Twig \Extension \SecurityExtension ;
17
17
use Symfony \Component \Security \Acl \Voter \FieldVote ;
18
+ use Symfony \Component \Security \Core \Authorization \AccessDecision ;
18
19
use Symfony \Component \Security \Core \Authorization \AuthorizationCheckerInterface ;
19
20
use Symfony \Component \Security \Core \Authorization \UserAuthorizationCheckerInterface ;
20
21
use Symfony \Component \Security \Core \User \UserInterface ;
21
22
22
23
class SecurityExtensionTest extends TestCase
23
24
{
25
+ public static function setUpBeforeClass (): void
26
+ {
27
+ ClassExistsMock::register (SecurityExtension::class);
28
+ }
29
+
30
+ protected function tearDown (): void
31
+ {
32
+ ClassExistsMock::withMockedClasses ([FieldVote::class => true ]);
33
+ }
34
+
24
35
/**
25
36
* @dataProvider provideObjectFieldAclCases
26
37
*/
@@ -39,17 +50,16 @@ public function testIsGrantedCreatesFieldVoteObjectWhenFieldNotNull($object, $fi
39
50
40
51
public function testIsGrantedThrowsWhenFieldNotNullAndFieldVoteClassDoesNotExist ()
41
52
{
42
- if (!class_exists (UserAuthorizationCheckerInterface::class)) {
53
+ if (!interface_exists (UserAuthorizationCheckerInterface::class)) {
43
54
$ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
44
55
}
45
56
46
57
$ securityChecker = $ this ->createMock (AuthorizationCheckerInterface::class);
47
58
48
- ClassExistsMock::register (SecurityExtension::class);
49
59
ClassExistsMock::withMockedClasses ([FieldVote::class => false ]);
50
60
51
61
$ this ->expectException (\LogicException::class);
52
- $ this ->expectExceptionMessageMatches ('Passing a $field to the "is_granted()" function requires symfony/acl. ' );
62
+ $ this ->expectExceptionMessage ('Passing a $field to the "is_granted()" function requires symfony/acl. ' );
53
63
54
64
$ securityExtension = new SecurityExtension ($ securityChecker );
55
65
$ securityExtension ->isGranted ('ROLE ' , 'object ' , 'bar ' );
@@ -60,49 +70,74 @@ public function testIsGrantedThrowsWhenFieldNotNullAndFieldVoteClassDoesNotExist
60
70
*/
61
71
public function testIsGrantedForUserCreatesFieldVoteObjectWhenFieldNotNull ($ object , $ field , $ expectedSubject )
62
72
{
63
- if (!class_exists (UserAuthorizationCheckerInterface::class)) {
73
+ if (!interface_exists (UserAuthorizationCheckerInterface::class)) {
64
74
$ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
65
75
}
66
76
67
77
$ 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 );
78
+ $ securityChecker = $ this ->createMockAuthorizationChecker ();
74
79
75
- $ securityExtension = new SecurityExtension (null , null , $ userSecurityChecker );
80
+ $ securityExtension = new SecurityExtension ($ securityChecker );
76
81
$ this ->assertTrue ($ securityExtension ->isGrantedForUser ($ user , 'ROLE ' , $ object , $ field ));
82
+ $ this ->assertSame ($ user , $ securityChecker ->user );
83
+ $ this ->assertSame ('ROLE ' , $ securityChecker ->attribute );
84
+
85
+ if (null === $ field ) {
86
+ $ this ->assertSame ($ object , $ securityChecker ->subject );
87
+ } else {
88
+ $ this ->assertEquals ($ expectedSubject , $ securityChecker ->subject );
89
+ }
90
+ }
91
+
92
+ public static function provideObjectFieldAclCases ()
93
+ {
94
+ return [
95
+ [null , null , null ],
96
+ ['object ' , null , 'object ' ],
97
+ ['object ' , false , new FieldVote ('object ' , false )],
98
+ ['object ' , 0 , new FieldVote ('object ' , 0 )],
99
+ ['object ' , '' , new FieldVote ('object ' , '' )],
100
+ ['object ' , 'field ' , new FieldVote ('object ' , 'field ' )],
101
+ ];
77
102
}
78
103
79
104
public function testIsGrantedForUserThrowsWhenFieldNotNullAndFieldVoteClassDoesNotExist ()
80
105
{
81
- if (!class_exists (UserAuthorizationCheckerInterface::class)) {
106
+ if (!interface_exists (UserAuthorizationCheckerInterface::class)) {
82
107
$ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
83
108
}
84
109
85
- $ securityChecker = $ this ->createMock (UserAuthorizationCheckerInterface::class );
110
+ $ securityChecker = $ this ->createMockAuthorizationChecker ( );
86
111
87
- ClassExistsMock::register (SecurityExtension::class);
88
112
ClassExistsMock::withMockedClasses ([FieldVote::class => false ]);
89
113
90
114
$ this ->expectException (\LogicException::class);
91
- $ this ->expectExceptionMessageMatches ('Passing a $field to the "is_granted_for_user()" function requires symfony/acl. ' );
115
+ $ this ->expectExceptionMessage ('Passing a $field to the "is_granted_for_user()" function requires symfony/acl. ' );
92
116
93
- $ securityExtension = new SecurityExtension (null , null , $ securityChecker );
94
- $ securityExtension ->isGrantedForUser ($ this ->createMock (UserInterface::class), 'object ' , 'bar ' );
117
+ $ securityExtension = new SecurityExtension ($ securityChecker );
118
+ $ securityExtension ->isGrantedForUser ($ this ->createMock (UserInterface::class), 'ROLE ' , ' object ' , 'bar ' );
95
119
}
96
120
97
- public static function provideObjectFieldAclCases ()
121
+ private function createMockAuthorizationChecker (): AuthorizationCheckerInterface & UserAuthorizationCheckerInterface
98
122
{
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
- ];
123
+ return new class implements AuthorizationCheckerInterface, UserAuthorizationCheckerInterface {
124
+ public UserInterface $ user ;
125
+ public mixed $ attribute ;
126
+ public mixed $ subject ;
127
+
128
+ public function isGranted (mixed $ attribute , mixed $ subject = null , ?AccessDecision $ accessDecision = null ): bool
129
+ {
130
+ throw new \BadMethodCallException ('This method should not be called. ' );
131
+ }
132
+
133
+ public function isGrantedForUser (UserInterface $ user , mixed $ attribute , mixed $ subject = null , ?AccessDecision $ accessDecision = null ): bool
134
+ {
135
+ $ this ->user = $ user ;
136
+ $ this ->attribute = $ attribute ;
137
+ $ this ->subject = $ subject ;
138
+
139
+ return true ;
140
+ }
141
+ };
107
142
}
108
143
}
0 commit comments