5d13437398ed061315d7926acd5066b8e5801d51
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Authentication / BackendUserAuthenticationTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Authentication;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Prophecy\Argument;
18 use Prophecy\Prophecy\ObjectProphecy;
19 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
20 use TYPO3\CMS\Core\Database\Connection;
21 use TYPO3\CMS\Core\Database\ConnectionPool;
22 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
23 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
24 use TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform;
25 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27
28 /**
29 * Testcase for BackendUserAuthentication
30 */
31 class BackendUserAuthenticationTest extends \TYPO3\Components\TestingFramework\Core\UnitTestCase
32 {
33 /**
34 * @var array
35 */
36 protected $defaultFilePermissions = [
37 // File permissions
38 'addFile' => false,
39 'readFile' => false,
40 'writeFile' => false,
41 'copyFile' => false,
42 'moveFile' => false,
43 'renameFile' => false,
44 'deleteFile' => false,
45 // Folder permissions
46 'addFolder' => false,
47 'readFolder' => false,
48 'writeFolder' => false,
49 'copyFolder' => false,
50 'moveFolder' => false,
51 'renameFolder' => false,
52 'deleteFolder' => false,
53 'recursivedeleteFolder' => false
54 ];
55
56 protected function setUp()
57 {
58 // reset hooks
59 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'] = [];
60 }
61
62 protected function tearDown()
63 {
64 \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::purgeInstances();
65 parent::tearDown();
66 }
67
68 /////////////////////////////////////////
69 // Tests concerning the form protection
70 /////////////////////////////////////////
71 /**
72 * @test
73 */
74 public function logoffCleansFormProtectionIfBackendUserIsLoggedIn()
75 {
76 /** @var ObjectProphecy|Connection $connection */
77 $connection = $this->prophesize(Connection::class);
78 $connection->delete('sys_lockedrecords', Argument::cetera())->willReturn(1);
79
80 /** @var ObjectProphecy|ConnectionPool $connectionPool */
81 $connectionPool = $this->prophesize(ConnectionPool::class);
82 $connectionPool->getConnectionForTable(Argument::cetera())->willReturn($connection->reveal());
83
84 GeneralUtility::addInstance(ConnectionPool::class, $connectionPool->reveal());
85
86 /** @var ObjectProphecy|Connection $connection */
87 $connection = $this->prophesize(Connection::class);
88 $connection->delete('be_sessions', Argument::cetera())->willReturn(1);
89
90 /** @var ObjectProphecy|ConnectionPool $connectionPool */
91 $connectionPool = $this->prophesize(ConnectionPool::class);
92 $connectionPool->getConnectionForTable(Argument::cetera())->willReturn($connection->reveal());
93
94 GeneralUtility::addInstance(ConnectionPool::class, $connectionPool->reveal());
95
96 /** @var ObjectProphecy|\TYPO3\CMS\Core\FormProtection\AbstractFormProtection $formProtection */
97 $formProtection = $this->prophesize(\TYPO3\CMS\Core\FormProtection\BackendFormProtection::class);
98 $formProtection->clean()->shouldBeCalled();
99
100 \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::set(
101 'default',
102 $formProtection->reveal()
103 );
104
105 // logoff() call the static factory that has a dependency to a valid BE_USER object. Mock this away
106 $GLOBALS['BE_USER'] = $this->createMock(BackendUserAuthentication::class);
107 $GLOBALS['BE_USER']->user = ['uid' => $this->getUniqueId()];
108
109 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
110 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
111 ->setMethods(['dummy'])
112 ->disableOriginalConstructor()
113 ->getMock();
114 $subject->logoff();
115 }
116
117 /**
118 * @return array
119 */
120 public function getTSConfigDataProvider()
121 {
122 $completeConfiguration = [
123 'value' => 'oneValue',
124 'value.' => ['oneProperty' => 'oneValue'],
125 'permissions.' => [
126 'file.' => [
127 'default.' => ['readAction' => '1'],
128 '1.' => ['writeAction' => '1'],
129 '0.' => ['readAction' => '0'],
130 ],
131 ]
132 ];
133
134 return [
135 'single level string' => [
136 $completeConfiguration,
137 'permissions',
138 [
139 'value' => null,
140 'properties' =>
141 [
142 'file.' => [
143 'default.' => ['readAction' => '1'],
144 '1.' => ['writeAction' => '1'],
145 '0.' => ['readAction' => '0'],
146 ],
147 ],
148 ],
149 ],
150 'two levels string' => [
151 $completeConfiguration,
152 'permissions.file',
153 [
154 'value' => null,
155 'properties' =>
156 [
157 'default.' => ['readAction' => '1'],
158 '1.' => ['writeAction' => '1'],
159 '0.' => ['readAction' => '0'],
160 ],
161 ],
162 ],
163 'three levels string' => [
164 $completeConfiguration,
165 'permissions.file.default',
166 [
167 'value' => null,
168 'properties' =>
169 ['readAction' => '1'],
170 ],
171 ],
172 'three levels string with integer property' => [
173 $completeConfiguration,
174 'permissions.file.1',
175 [
176 'value' => null,
177 'properties' => ['writeAction' => '1'],
178 ],
179 ],
180 'three levels string with integer zero property' => [
181 $completeConfiguration,
182 'permissions.file.0',
183 [
184 'value' => null,
185 'properties' => ['readAction' => '0'],
186 ],
187 ],
188 'four levels string with integer zero property, value, no properties' => [
189 $completeConfiguration,
190 'permissions.file.0.readAction',
191 [
192 'value' => '0',
193 'properties' => null,
194 ],
195 ],
196 'four levels string with integer property, value, no properties' => [
197 $completeConfiguration,
198 'permissions.file.1.writeAction',
199 [
200 'value' => '1',
201 'properties' => null,
202 ],
203 ],
204 'one level, not existent string' => [
205 $completeConfiguration,
206 'foo',
207 [
208 'value' => null,
209 'properties' => null,
210 ],
211 ],
212 'two level, not existent string' => [
213 $completeConfiguration,
214 'foo.bar',
215 [
216 'value' => null,
217 'properties' => null,
218 ],
219 ],
220 'two level, where second level does not exist' => [
221 $completeConfiguration,
222 'permissions.bar',
223 [
224 'value' => null,
225 'properties' => null,
226 ],
227 ],
228 'three level, where third level does not exist' => [
229 $completeConfiguration,
230 'permissions.file.foo',
231 [
232 'value' => null,
233 'properties' => null,
234 ],
235 ],
236 'three level, where second and third level does not exist' => [
237 $completeConfiguration,
238 'permissions.foo.bar',
239 [
240 'value' => null,
241 'properties' => null,
242 ],
243 ],
244 'value and properties' => [
245 $completeConfiguration,
246 'value',
247 [
248 'value' => 'oneValue',
249 'properties' => ['oneProperty' => 'oneValue'],
250 ],
251 ],
252 ];
253 }
254
255 /**
256 * @param array $completeConfiguration
257 * @param string $objectString
258 * @param array $expectedConfiguration
259 * @dataProvider getTSConfigDataProvider
260 * @test
261 */
262 public function getTSConfigReturnsCorrectArrayForGivenObjectString(array $completeConfiguration, $objectString, array $expectedConfiguration)
263 {
264 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
265 ->setMethods(['dummy'])
266 ->disableOriginalConstructor()
267 ->getMock();
268 $subject->userTS = $completeConfiguration;
269
270 $actualConfiguration = $subject->getTSConfig($objectString);
271 $this->assertSame($expectedConfiguration, $actualConfiguration);
272 }
273
274 /**
275 * @return array
276 */
277 public function getFilePermissionsTakesUserDefaultAndStoragePermissionsIntoAccountIfUserIsNotAdminDataProvider()
278 {
279 return [
280 'Only read permissions' => [
281 [
282 'addFile' => 0,
283 'readFile' => 1,
284 'writeFile' => 0,
285 'copyFile' => 0,
286 'moveFile' => 0,
287 'renameFile' => 0,
288 'deleteFile' => 0,
289 'addFolder' => 0,
290 'readFolder' => 1,
291 'copyFolder' => 0,
292 'moveFolder' => 0,
293 'renameFolder' => 0,
294 'writeFolder' => 0,
295 'deleteFolder' => 0,
296 'recursivedeleteFolder' => 0,
297 ]
298 ],
299 'Uploading allowed' => [
300 [
301 'addFile' => 1,
302 'readFile' => 1,
303 'writeFile' => 1,
304 'copyFile' => 1,
305 'moveFile' => 1,
306 'renameFile' => 1,
307 'deleteFile' => 1,
308 'addFolder' => 0,
309 'readFolder' => 1,
310 'copyFolder' => 0,
311 'moveFolder' => 0,
312 'renameFolder' => 0,
313 'writeFolder' => 0,
314 'deleteFolder' => 0,
315 'recursivedeleteFolder' => 0
316 ]
317 ],
318 'One value is enough' => [
319 [
320 'addFile' => 1,
321 ]
322 ],
323 ];
324 }
325
326 /**
327 * @param array $userTsConfiguration
328 * @test
329 * @dataProvider getFilePermissionsTakesUserDefaultAndStoragePermissionsIntoAccountIfUserIsNotAdminDataProvider
330 */
331 public function getFilePermissionsTakesUserDefaultPermissionsFromTsConfigIntoAccountIfUserIsNotAdmin(array $userTsConfiguration)
332 {
333 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
334 ->setMethods(['isAdmin'])
335 ->getMock();
336
337 $subject
338 ->expects($this->any())
339 ->method('isAdmin')
340 ->will($this->returnValue(false));
341
342 $subject->userTS = [
343 'permissions.' => [
344 'file.' => [
345 'default.' => $userTsConfiguration
346 ],
347 ]
348 ];
349
350 $expectedPermissions = array_merge($this->defaultFilePermissions, $userTsConfiguration);
351 array_walk(
352 $expectedPermissions,
353 function (&$value) {
354 $value = (bool)$value;
355 }
356 );
357
358 $this->assertEquals($expectedPermissions, $subject->getFilePermissions());
359 }
360
361 /**
362 * @return array
363 */
364 public function getFilePermissionsFromStorageDataProvider()
365 {
366 $defaultPermissions = [
367 'addFile' => true,
368 'readFile' => true,
369 'writeFile' => true,
370 'copyFile' => true,
371 'moveFile' => true,
372 'renameFile' => true,
373 'deleteFile' => true,
374 'addFolder' => true,
375 'readFolder' => true,
376 'copyFolder' => true,
377 'moveFolder' => true,
378 'renameFolder' => true,
379 'writeFolder' => true,
380 'deleteFolder' => true,
381 'recursivedeleteFolder' => true
382 ];
383
384 return [
385 'Overwrites given storage permissions with default permissions' => [
386 $defaultPermissions,
387 1,
388 [
389 'addFile' => 0,
390 'recursivedeleteFolder' =>0
391 ],
392 [
393 'addFile' => 0,
394 'readFile' => 1,
395 'writeFile' => 1,
396 'copyFile' => 1,
397 'moveFile' => 1,
398 'renameFile' => 1,
399 'deleteFile' => 1,
400 'addFolder' => 1,
401 'readFolder' => 1,
402 'copyFolder' => 1,
403 'moveFolder' => 1,
404 'renameFolder' => 1,
405 'writeFolder' => 1,
406 'deleteFolder' => 1,
407 'recursivedeleteFolder' => 0
408 ]
409 ],
410 'Overwrites given storage 0 permissions with default permissions' => [
411 $defaultPermissions,
412 0,
413 [
414 'addFile' => 0,
415 'recursivedeleteFolder' =>0
416 ],
417 [
418 'addFile' => false,
419 'readFile' => true,
420 'writeFile' => true,
421 'copyFile' => true,
422 'moveFile' => true,
423 'renameFile' => true,
424 'deleteFile' => true,
425 'addFolder' => true,
426 'readFolder' => true,
427 'copyFolder' => true,
428 'moveFolder' => true,
429 'renameFolder' => true,
430 'writeFolder' => true,
431 'deleteFolder' => true,
432 'recursivedeleteFolder' => false
433 ]
434 ],
435 'Returns default permissions if no storage permissions are found' => [
436 $defaultPermissions,
437 1,
438 [],
439 [
440 'addFile' => true,
441 'readFile' => true,
442 'writeFile' => true,
443 'copyFile' => true,
444 'moveFile' => true,
445 'renameFile' => true,
446 'deleteFile' => true,
447 'addFolder' => true,
448 'readFolder' => true,
449 'copyFolder' => true,
450 'moveFolder' => true,
451 'renameFolder' => true,
452 'writeFolder' => true,
453 'deleteFolder' => true,
454 'recursivedeleteFolder' => true
455 ]
456 ],
457 ];
458 }
459
460 /**
461 * @param array $defaultPermissions
462 * @param int $storageUid
463 * @param array $storagePermissions
464 * @param array $expectedPermissions
465 * @test
466 * @dataProvider getFilePermissionsFromStorageDataProvider
467 */
468 public function getFilePermissionsFromStorageOverwritesDefaultPermissions(array $defaultPermissions, $storageUid, array $storagePermissions, array $expectedPermissions)
469 {
470 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
471 ->setMethods(['isAdmin', 'getFilePermissions'])
472 ->getMock();
473 $storageMock = $this->createMock(\TYPO3\CMS\Core\Resource\ResourceStorage::class);
474 $storageMock->expects($this->any())->method('getUid')->will($this->returnValue($storageUid));
475
476 $subject
477 ->expects($this->any())
478 ->method('isAdmin')
479 ->will($this->returnValue(false));
480
481 $subject
482 ->expects($this->any())
483 ->method('getFilePermissions')
484 ->will($this->returnValue($defaultPermissions));
485
486 $subject->userTS = [
487 'permissions.' => [
488 'file.' => [
489 'storage.' => [
490 $storageUid . '.' => $storagePermissions
491 ],
492 ],
493 ]
494 ];
495
496 $this->assertEquals($expectedPermissions, $subject->getFilePermissionsForStorage($storageMock));
497 }
498
499 /**
500 * @param array $defaultPermissions
501 * @param $storageUid
502 * @param array $storagePermissions
503 * @test
504 * @dataProvider getFilePermissionsFromStorageDataProvider
505 */
506 public function getFilePermissionsFromStorageAlwaysReturnsDefaultPermissionsForAdmins(array $defaultPermissions, $storageUid, array $storagePermissions)
507 {
508 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
509 ->setMethods(['isAdmin', 'getFilePermissions'])
510 ->getMock();
511 $storageMock = $this->createMock(\TYPO3\CMS\Core\Resource\ResourceStorage::class);
512 $storageMock->expects($this->any())->method('getUid')->will($this->returnValue($storageUid));
513
514 $subject
515 ->expects($this->any())
516 ->method('isAdmin')
517 ->will($this->returnValue(true));
518
519 $subject
520 ->expects($this->any())
521 ->method('getFilePermissions')
522 ->will($this->returnValue($defaultPermissions));
523
524 $subject->userTS = [
525 'permissions.' => [
526 'file.' => [
527 'storage.' => [
528 $storageUid . '.' => $storagePermissions
529 ],
530 ],
531 ]
532 ];
533
534 $this->assertEquals($defaultPermissions, $subject->getFilePermissionsForStorage($storageMock));
535 }
536
537 /**
538 * @return array
539 */
540 public function getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdminDataProvider()
541 {
542 return [
543 'No permission' => [
544 '',
545 [
546 'addFile' => false,
547 'readFile' => false,
548 'writeFile' => false,
549 'copyFile' => false,
550 'moveFile' => false,
551 'renameFile' => false,
552 'deleteFile' => false,
553 'addFolder' => false,
554 'readFolder' => false,
555 'copyFolder' => false,
556 'moveFolder' => false,
557 'renameFolder' => false,
558 'writeFolder' => false,
559 'deleteFolder' => false,
560 'recursivedeleteFolder' => false
561 ]
562 ],
563 'Standard file permissions' => [
564 'addFile,readFile,writeFile,copyFile,moveFile,renameFile,deleteFile',
565 [
566 'addFile' => true,
567 'readFile' => true,
568 'writeFile' => true,
569 'copyFile' => true,
570 'moveFile' => true,
571 'renameFile' => true,
572 'deleteFile' => true,
573 'addFolder' => false,
574 'readFolder' => false,
575 'copyFolder' => false,
576 'moveFolder' => false,
577 'renameFolder' => false,
578 'writeFolder' => false,
579 'deleteFolder' => false,
580 'recursivedeleteFolder' => false
581 ]
582 ],
583 'Standard folder permissions' => [
584 'addFolder,readFolder,moveFolder,renameFolder,writeFolder,deleteFolder',
585 [
586 'addFile' => false,
587 'readFile' => false,
588 'writeFile' => false,
589 'copyFile' => false,
590 'moveFile' => false,
591 'renameFile' => false,
592 'deleteFile' => false,
593 'addFolder' => true,
594 'readFolder' => true,
595 'writeFolder' => true,
596 'copyFolder' => false,
597 'moveFolder' => true,
598 'renameFolder' => true,
599 'deleteFolder' => true,
600 'recursivedeleteFolder' => false
601 ]
602 ],
603 'Copy folder allowed' => [
604 'readFolder,copyFolder',
605 [
606 'addFile' => false,
607 'readFile' => false,
608 'writeFile' => false,
609 'copyFile' => false,
610 'moveFile' => false,
611 'renameFile' => false,
612 'deleteFile' => false,
613 'addFolder' => false,
614 'readFolder' => true,
615 'writeFolder' => false,
616 'copyFolder' => true,
617 'moveFolder' => false,
618 'renameFolder' => false,
619 'deleteFolder' => false,
620 'recursivedeleteFolder' => false
621 ]
622 ],
623 'Copy folder and remove subfolders allowed' => [
624 'readFolder,copyFolder,recursivedeleteFolder',
625 [
626 'addFile' => false,
627 'readFile' => false,
628 'writeFile' => false,
629 'copyFile' => false,
630 'moveFile' => false,
631 'renameFile' => false,
632 'deleteFile' => false,
633 'addFolder' => false,
634 'readFolder' => true,
635 'writeFolder' => false,
636 'copyFolder' => true,
637 'moveFolder' => false,
638 'renameFolder' => false,
639 'deleteFolder' => false,
640 'recursivedeleteFolder' => true
641 ]
642 ],
643 ];
644 }
645
646 /**
647 * @test
648 * @dataProvider getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdminDataProvider
649 */
650 public function getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdmin($permissionValue, $expectedPermissions)
651 {
652 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
653 ->setMethods(['isAdmin'])
654 ->getMock();
655
656 $subject
657 ->expects($this->any())
658 ->method('isAdmin')
659 ->will($this->returnValue(false));
660
661 $subject->userTS = [];
662 $subject->groupData['file_permissions'] = $permissionValue;
663 $this->assertEquals($expectedPermissions, $subject->getFilePermissions());
664 }
665
666 /**
667 * @test
668 */
669 public function getFilePermissionsGrantsAllPermissionsToAdminUsers()
670 {
671 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
672 ->setMethods(['isAdmin'])
673 ->getMock();
674
675 $subject
676 ->expects($this->any())
677 ->method('isAdmin')
678 ->will($this->returnValue(true));
679
680 $expectedPermissions = [
681 'addFile' => true,
682 'readFile' => true,
683 'writeFile' => true,
684 'copyFile' => true,
685 'moveFile' => true,
686 'renameFile' => true,
687 'deleteFile' => true,
688 'addFolder' => true,
689 'readFolder' => true,
690 'writeFolder' => true,
691 'copyFolder' => true,
692 'moveFolder' => true,
693 'renameFolder' => true,
694 'deleteFolder' => true,
695 'recursivedeleteFolder' => true
696 ];
697
698 $this->assertEquals($expectedPermissions, $subject->getFilePermissions());
699 }
700
701 /**
702 * @test
703 */
704 public function jsConfirmationReturnsTrueIfPassedValueEqualsConfiguration()
705 {
706 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
707 ->setMethods(['getTSConfig'])
708 ->getMock();
709 $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 1]);
710
711 $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
712 $this->assertFalse($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE));
713 }
714
715 /**
716 * @test
717 */
718 public function jsConfirmationAllowsSettingMultipleBitsInValue()
719 {
720 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
721 ->setMethods(['getTSConfig'])
722 ->getMock();
723 $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 3]);
724
725 $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
726 $this->assertTrue($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE));
727 }
728
729 /**
730 * @test
731 */
732 public function jsConfirmationAlwaysReturnsFalseIfNoConfirmationIsSet()
733 {
734 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
735 ->setMethods(['getTSConfig'])
736 ->getMock();
737 $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 0]);
738
739 $this->assertFalse($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
740 $this->assertFalse($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE));
741 }
742
743 /**
744 * @test
745 */
746 public function jsConfirmationReturnsTrueIfConfigurationIsMissing()
747 {
748 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
749 ->setMethods(['getTSConfig'])
750 ->getMock();
751
752 $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
753 }
754
755 /**
756 * Data provider to test page permissions constraints
757 * returns an array of test conditions:
758 * - permission bit(s) as integer
759 * - admin flag
760 * - groups for user
761 * - expected SQL fragment
762 *
763 * @return array
764 */
765 public function getPagePermissionsClauseWithValidUserDataProvider(): array
766 {
767 return [
768 'for admin' => [
769 1,
770 true,
771 '',
772 ' 1=1'
773 ],
774 'for admin with groups' => [
775 11,
776 true,
777 '1,2',
778 ' 1=1'
779 ],
780 'for user' => [
781 2,
782 false,
783 '',
784 ' ((`pages`.`perms_everybody` & 2 = 2) OR' .
785 ' ((`pages`.`perms_userid` = 123) AND (`pages`.`perms_user` & 2 = 2)))'
786 ],
787 'for user with groups' => [
788 8,
789 false,
790 '1,2',
791 ' ((`pages`.`perms_everybody` & 8 = 8) OR' .
792 ' ((`pages`.`perms_userid` = 123) AND (`pages`.`perms_user` & 8 = 8))' .
793 ' OR ((`pages`.`perms_groupid` IN (1, 2)) AND (`pages`.`perms_group` & 8 = 8)))'
794 ],
795 ];
796 }
797
798 /**
799 * @test
800 * @dataProvider getPagePermissionsClauseWithValidUserDataProvider
801 * @param int $perms
802 * @param bool $admin
803 * @param string $groups
804 * @param string $expected
805 */
806 public function getPagePermissionsClauseWithValidUser(int $perms, bool $admin, string $groups, string $expected)
807 {
808 // We only need to setup the mocking for the non-admin cases
809 // If this setup is done for admin cases the FIFO behavior
810 // of GeneralUtility::addInstance will influence other tests
811 // as the ConnectionPool is never used!
812 if (!$admin) {
813 /** @var Connection|ObjectProphecy $connectionProphet */
814 $connectionProphet = $this->prophesize(Connection::class);
815 $connectionProphet->getDatabasePlatform()->willReturn(new MockPlatform());
816 $connectionProphet->quoteIdentifier(Argument::cetera())->will(function ($args) {
817 return '`' . str_replace('.', '`.`', $args[0]) . '`';
818 });
819
820 /** @var QueryBuilder|ObjectProphecy $queryBuilderProphet */
821 $queryBuilderProphet = $this->prophesize(QueryBuilder::class);
822 $queryBuilderProphet->expr()->willReturn(
823 GeneralUtility::makeInstance(ExpressionBuilder::class, $connectionProphet->reveal())
824 );
825
826 /** @var ConnectionPool|ObjectProphecy $databaseProphet */
827 $databaseProphet = $this->prophesize(ConnectionPool::class);
828 $databaseProphet->getQueryBuilderForTable('pages')->willReturn($queryBuilderProphet->reveal());
829 GeneralUtility::addInstance(ConnectionPool::class, $databaseProphet->reveal());
830 }
831
832 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
833 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
834 ->setMethods(['isAdmin'])
835 ->getMock();
836 $subject->expects($this->any())
837 ->method('isAdmin')
838 ->will($this->returnValue($admin));
839
840 $subject->user = ['uid' => 123];
841 $subject->groupList = $groups;
842
843 $this->assertEquals($expected, $subject->getPagePermsClause($perms));
844 }
845 }