@@ -41,16 +41,21 @@ public static function setUpBeforeClass(): void {
4141 * a mock ResponseFactory.
4242 *
4343 * @param array $protectedPages
44+ * @param array $protectedActions
4445 * @param ResponseFactory|\PHPUnit\Framework\MockObject\MockObject|null $responseFactory
4546 * @return CrawlerProtectionService
4647 */
4748 private function buildService (
4849 array $ protectedPages = [ 'recentchangeslinked ' , 'whatlinkshere ' , 'mobilediff ' ],
50+ array $ protectedActions = [ 'history ' ],
4951 $ responseFactory = null
5052 ): CrawlerProtectionService {
5153 $ options = new ServiceOptions (
5254 CrawlerProtectionService::CONSTRUCTOR_OPTIONS ,
53- [ 'CrawlerProtectedSpecialPages ' => $ protectedPages ]
55+ [
56+ 'CrawlerProtectedActions ' => $ protectedActions ,
57+ 'CrawlerProtectedSpecialPages ' => $ protectedPages ,
58+ ]
5459 );
5560
5661 $ responseFactory ??= $ this ->createMock ( ResponseFactory::class );
@@ -78,7 +83,7 @@ public function testCheckPerformActionAllowsRegisteredUser() {
7883 $ responseFactory = $ this ->createMock ( ResponseFactory::class );
7984 $ responseFactory ->expects ( $ this ->never () )->method ( 'denyAccess ' );
8085
81- $ service = $ this ->buildService ( [], $ responseFactory );
86+ $ service = $ this ->buildService ( [], [ ' history ' ], $ responseFactory );
8287 $ this ->assertTrue ( $ service ->checkPerformAction ( $ output , $ user , $ request ) );
8388 }
8489
@@ -100,7 +105,7 @@ public function testCheckPerformActionBlocksAnonymous( array $getValMap, string
100105 $ responseFactory = $ this ->createMock ( ResponseFactory::class );
101106 $ responseFactory ->expects ( $ this ->once () )->method ( 'denyAccess ' )->with ( $ output );
102107
103- $ service = $ this ->buildService ( [], $ responseFactory );
108+ $ service = $ this ->buildService ( [], [ ' history ' ], $ responseFactory );
104109 $ this ->assertFalse ( $ service ->checkPerformAction ( $ output , $ user , $ request ), $ msg );
105110 }
106111
@@ -169,10 +174,96 @@ public function testCheckPerformActionAllowsNormalAnonymousView() {
169174 $ responseFactory = $ this ->createMock ( ResponseFactory::class );
170175 $ responseFactory ->expects ( $ this ->never () )->method ( 'denyAccess ' );
171176
172- $ service = $ this ->buildService ( [], $ responseFactory );
177+ $ service = $ this ->buildService ( [], [ ' history ' ], $ responseFactory );
173178 $ this ->assertTrue ( $ service ->checkPerformAction ( $ output , $ user , $ request ) );
174179 }
175180
181+ /**
182+ * @covers ::checkPerformAction
183+ */
184+ public function testCheckPerformActionBlocksConfiguredAction () {
185+ $ output = $ this ->createMock ( self ::$ outputPageClassName );
186+ $ user = $ this ->createMock ( self ::$ userClassName );
187+ $ user ->method ( 'isRegistered ' )->willReturn ( false );
188+
189+ $ request = $ this ->createMock ( self ::$ webRequestClassName );
190+ $ request ->method ( 'getVal ' )->willReturnMap ( [
191+ [ 'type ' , null , null ],
192+ [ 'action ' , null , 'edit ' ],
193+ [ 'diff ' , null , null ],
194+ [ 'oldid ' , null , null ],
195+ ] );
196+
197+ $ responseFactory = $ this ->createMock ( ResponseFactory::class );
198+ $ responseFactory ->expects ( $ this ->once () )->method ( 'denyAccess ' )->with ( $ output );
199+
200+ $ service = $ this ->buildService ( [], [ 'edit ' , 'history ' ], $ responseFactory );
201+ $ this ->assertFalse ( $ service ->checkPerformAction ( $ output , $ user , $ request ) );
202+ }
203+
204+ /**
205+ * @covers ::checkPerformAction
206+ */
207+ public function testCheckPerformActionAllowsActionNotInConfig () {
208+ $ output = $ this ->createMock ( self ::$ outputPageClassName );
209+ $ user = $ this ->createMock ( self ::$ userClassName );
210+ $ user ->method ( 'isRegistered ' )->willReturn ( false );
211+
212+ $ request = $ this ->createMock ( self ::$ webRequestClassName );
213+ $ request ->method ( 'getVal ' )->willReturnMap ( [
214+ [ 'type ' , null , null ],
215+ [ 'action ' , null , 'history ' ],
216+ [ 'diff ' , null , null ],
217+ [ 'oldid ' , null , null ],
218+ ] );
219+
220+ $ responseFactory = $ this ->createMock ( ResponseFactory::class );
221+ $ responseFactory ->expects ( $ this ->never () )->method ( 'denyAccess ' );
222+
223+ $ service = $ this ->buildService ( [], [], $ responseFactory );
224+ $ this ->assertTrue ( $ service ->checkPerformAction ( $ output , $ user , $ request ) );
225+ }
226+
227+ // ---------------------------------------------------------------
228+ // isProtectedAction tests
229+ // ---------------------------------------------------------------
230+
231+ /**
232+ * @covers ::isProtectedAction
233+ */
234+ public function testIsProtectedActionReturnsTrueForConfiguredAction () {
235+ $ service = $ this ->buildService ( [], [ 'history ' , 'edit ' ] );
236+ $ this ->assertTrue ( $ service ->isProtectedAction ( 'history ' ) );
237+ $ this ->assertTrue ( $ service ->isProtectedAction ( 'edit ' ) );
238+ }
239+
240+ /**
241+ * @covers ::isProtectedAction
242+ */
243+ public function testIsProtectedActionReturnsFalseForUnconfiguredAction () {
244+ $ service = $ this ->buildService ( [], [ 'history ' ] );
245+ $ this ->assertFalse ( $ service ->isProtectedAction ( 'view ' ) );
246+ $ this ->assertFalse ( $ service ->isProtectedAction ( 'edit ' ) );
247+ }
248+
249+ /**
250+ * @covers ::isProtectedAction
251+ */
252+ public function testIsProtectedActionReturnsFalseForNull () {
253+ $ service = $ this ->buildService ( [], [ 'history ' ] );
254+ $ this ->assertFalse ( $ service ->isProtectedAction ( null ) );
255+ }
256+
257+ /**
258+ * @covers ::isProtectedAction
259+ */
260+ public function testIsProtectedActionIsCaseInsensitive () {
261+ $ service = $ this ->buildService ( [], [ 'History ' ] );
262+ $ this ->assertTrue ( $ service ->isProtectedAction ( 'history ' ) );
263+ $ this ->assertTrue ( $ service ->isProtectedAction ( 'HISTORY ' ) );
264+ $ this ->assertTrue ( $ service ->isProtectedAction ( 'History ' ) );
265+ }
266+
176267 // ---------------------------------------------------------------
177268 // checkSpecialPage tests
178269 // ---------------------------------------------------------------
@@ -193,6 +284,7 @@ public function testCheckSpecialPageBlocksAnonymous( string $specialPageName ) {
193284
194285 $ service = $ this ->buildService (
195286 [ 'RecentChangesLinked ' , 'WhatLinksHere ' , 'MobileDiff ' ],
287+ [],
196288 $ responseFactory
197289 );
198290 $ this ->assertFalse ( $ service ->checkSpecialPage ( $ specialPageName , $ output , $ user ) );
@@ -214,6 +306,7 @@ public function testCheckSpecialPageAllowsRegistered( string $specialPageName )
214306
215307 $ service = $ this ->buildService (
216308 [ 'RecentChangesLinked ' , 'WhatLinksHere ' , 'MobileDiff ' ],
309+ [],
217310 $ responseFactory
218311 );
219312 $ this ->assertTrue ( $ service ->checkSpecialPage ( $ specialPageName , $ output , $ user ) );
@@ -232,6 +325,7 @@ public function testCheckSpecialPageAllowsUnprotected() {
232325
233326 $ service = $ this ->buildService (
234327 [ 'RecentChangesLinked ' , 'WhatLinksHere ' , 'MobileDiff ' ],
328+ [],
235329 $ responseFactory
236330 );
237331 $ this ->assertTrue ( $ service ->checkSpecialPage ( 'Search ' , $ output , $ user ) );
0 commit comments