@@ -30,7 +30,7 @@ public static function setUpBeforeClass(): void
30
30
31
31
protected function tearDown (): void
32
32
{
33
- ClassExistsMock::withMockedClasses ([FieldVote::class => true ]);
33
+ ClassExistsMock::withMockedClasses ([FieldVote::class => true , AccessDecision::class => true ]);
34
34
}
35
35
36
36
#[DataProvider('provideObjectFieldAclCases ' )]
@@ -115,6 +115,122 @@ public function testIsGrantedForUserThrowsWhenFieldNotNullAndFieldVoteClassDoesN
115
115
$ securityExtension ->isGrantedForUser ($ this ->createMock (UserInterface::class), 'ROLE ' , 'object ' , 'bar ' );
116
116
}
117
117
118
+ public function testAccessDecision ()
119
+ {
120
+ if (!class_exists (AccessDecision::class)) {
121
+ $ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
122
+ }
123
+
124
+ $ securityChecker = $ this ->createMock (AuthorizationCheckerInterface::class);
125
+ $ securityChecker
126
+ ->expects ($ this ->once ())
127
+ ->method ('isGranted ' )
128
+ ->with ('ROLE ' , 'object ' , $ this ->isInstanceOf (AccessDecision::class))
129
+ ->willReturnCallback (function ($ attribute , $ subject , $ accessDecision ) {
130
+ $ accessDecision ->isGranted = true ;
131
+
132
+ return true ;
133
+ });
134
+
135
+ $ securityExtension = new SecurityExtension ($ securityChecker );
136
+ $ accessDecision = $ securityExtension ->getAccessDecision ('ROLE ' , 'object ' );
137
+
138
+ $ this ->assertInstanceOf (AccessDecision::class, $ accessDecision );
139
+ $ this ->assertTrue ($ accessDecision ->isGranted );
140
+ }
141
+
142
+ public function testAccessDecisionWithField ()
143
+ {
144
+ if (!class_exists (AccessDecision::class)) {
145
+ $ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
146
+ }
147
+
148
+ $ securityChecker = $ this ->createMock (AuthorizationCheckerInterface::class);
149
+ $ securityChecker
150
+ ->expects ($ this ->once ())
151
+ ->method ('isGranted ' )
152
+ ->with ('ROLE ' , $ this ->isInstanceOf (FieldVote::class), $ this ->isInstanceOf (AccessDecision::class))
153
+ ->willReturnCallback (function ($ attribute , $ subject , $ accessDecision ) {
154
+ $ accessDecision ->isGranted = false ;
155
+
156
+ return false ;
157
+ });
158
+
159
+ $ securityExtension = new SecurityExtension ($ securityChecker );
160
+ $ accessDecision = $ securityExtension ->getAccessDecision ('ROLE ' , 'object ' , 'field ' );
161
+
162
+ $ this ->assertInstanceOf (AccessDecision::class, $ accessDecision );
163
+ $ this ->assertFalse ($ accessDecision ->isGranted );
164
+ }
165
+
166
+ public function testAccessDecisionThrowsWhenAccessDecisionClassDoesNotExist ()
167
+ {
168
+ ClassExistsMock::withMockedClasses ([AccessDecision::class => false ]);
169
+
170
+ $ securityChecker = $ this ->createMock (AuthorizationCheckerInterface::class);
171
+
172
+ $ this ->expectException (\LogicException::class);
173
+ $ this ->expectExceptionMessage ('Using the "access_decision()" function requires symfony/security-core >= 7.3. Try running "composer update symfony/security-core". ' );
174
+
175
+ $ securityExtension = new SecurityExtension ($ securityChecker );
176
+ $ securityExtension ->getAccessDecision ('ROLE ' , 'object ' );
177
+ }
178
+
179
+ public function testAccessDecisionForUser ()
180
+ {
181
+ if (!interface_exists (UserAuthorizationCheckerInterface::class) || !class_exists (AccessDecision::class)) {
182
+ $ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
183
+ }
184
+
185
+ $ user = $ this ->createMock (UserInterface::class);
186
+ $ securityChecker = $ this ->createMockAuthorizationChecker ();
187
+
188
+ $ securityExtension = new SecurityExtension ($ securityChecker );
189
+ $ accessDecision = $ securityExtension ->getAccessDecisionForUser ($ user , 'ROLE ' , 'object ' );
190
+
191
+ $ this ->assertInstanceOf (AccessDecision::class, $ accessDecision );
192
+ $ this ->assertTrue ($ accessDecision ->isGranted );
193
+ $ this ->assertSame ($ user , $ securityChecker ->user );
194
+ $ this ->assertSame ('ROLE ' , $ securityChecker ->attribute );
195
+ $ this ->assertSame ('object ' , $ securityChecker ->subject );
196
+ }
197
+
198
+ public function testAccessDecisionForUserWithField ()
199
+ {
200
+ if (!interface_exists (UserAuthorizationCheckerInterface::class) || !class_exists (AccessDecision::class)) {
201
+ $ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
202
+ }
203
+
204
+ $ user = $ this ->createMock (UserInterface::class);
205
+ $ securityChecker = $ this ->createMockAuthorizationChecker ();
206
+
207
+ $ securityExtension = new SecurityExtension ($ securityChecker );
208
+ $ accessDecision = $ securityExtension ->getAccessDecisionForUser ($ user , 'ROLE ' , 'object ' , 'field ' );
209
+
210
+ $ this ->assertInstanceOf (AccessDecision::class, $ accessDecision );
211
+ $ this ->assertTrue ($ accessDecision ->isGranted );
212
+ $ this ->assertSame ($ user , $ securityChecker ->user );
213
+ $ this ->assertSame ('ROLE ' , $ securityChecker ->attribute );
214
+ $ this ->assertEquals (new FieldVote ('object ' , 'field ' ), $ securityChecker ->subject );
215
+ }
216
+
217
+ public function testAccessDecisionForUserThrowsWhenAccessDecisionClassDoesNotExist ()
218
+ {
219
+ if (!interface_exists (UserAuthorizationCheckerInterface::class)) {
220
+ $ this ->markTestSkipped ('This test requires symfony/security-core 7.3 or superior. ' );
221
+ }
222
+
223
+ ClassExistsMock::withMockedClasses ([AccessDecision::class => false ]);
224
+
225
+ $ securityChecker = $ this ->createMockAuthorizationChecker ();
226
+ $ securityExtension = new SecurityExtension ($ securityChecker );
227
+
228
+ $ this ->expectException (\LogicException::class);
229
+ $ this ->expectExceptionMessage ('Using the "access_decision_for_user()" function requires symfony/security-core >= 7.3. Try running "composer update symfony/security-core". ' );
230
+
231
+ $ securityExtension ->getAccessDecisionForUser ($ this ->createMock (UserInterface::class), 'ROLE ' , 'object ' );
232
+ }
233
+
118
234
private function createMockAuthorizationChecker (): AuthorizationCheckerInterface &UserAuthorizationCheckerInterface
119
235
{
120
236
return new class implements AuthorizationCheckerInterface, UserAuthorizationCheckerInterface {
@@ -133,6 +249,10 @@ public function isGrantedForUser(UserInterface $user, mixed $attribute, mixed $s
133
249
$ this ->attribute = $ attribute ;
134
250
$ this ->subject = $ subject ;
135
251
252
+ if ($ accessDecision ) {
253
+ $ accessDecision ->isGranted = true ;
254
+ }
255
+
136
256
return true ;
137
257
}
138
258
};
0 commit comments