11f147bff60a72f2b48803bfacc03b3dcb3b4e63
[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\FormProtection\FormProtectionFactory;
25 use TYPO3\CMS\Core\Resource\ResourceStorage;
26 use TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform;
27 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
30
31 /**
32 * Test case
33 */
34 class BackendUserAuthenticationTest extends UnitTestCase
35 {
36 /**
37 * @var array
38 */
39 protected $defaultFilePermissions = [
40 // File permissions
41 'addFile' => false,
42 'readFile' => false,
43 'writeFile' => false,
44 'copyFile' => false,
45 'moveFile' => false,
46 'renameFile' => false,
47 'deleteFile' => false,
48 // Folder permissions
49 'addFolder' => false,
50 'readFolder' => false,
51 'writeFolder' => false,
52 'copyFolder' => false,
53 'moveFolder' => false,
54 'renameFolder' => false,
55 'deleteFolder' => false,
56 'recursivedeleteFolder' => false
57 ];
58
59 /**
60 * Tear down
61 */
62 protected function tearDown()
63 {
64 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 FormProtectionFactory::set(
101 'default',
102 $formProtection->reveal()
103 );
104
105 $GLOBALS['BE_USER'] = $this->getMockBuilder(BackendUserAuthentication::class)->getMock();
106 $GLOBALS['BE_USER']->user = ['uid' => $this->getUniqueId()];
107
108 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
109 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
110 ->setMethods(['dummy'])
111 ->disableOriginalConstructor()
112 ->getMock();
113
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 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
265 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
266 ->setMethods(['dummy'])
267 ->disableOriginalConstructor()
268 ->getMock();
269 $subject->userTS = $completeConfiguration;
270
271 $actualConfiguration = $subject->getTSConfig($objectString);
272 $this->assertSame($expectedConfiguration, $actualConfiguration);
273 }
274
275 /**
276 * @return array
277 */
278 public function getFilePermissionsTakesUserDefaultAndStoragePermissionsIntoAccountIfUserIsNotAdminDataProvider()
279 {
280 return [
281 'Only read permissions' => [
282 [
283 'addFile' => 0,
284 'readFile' => 1,
285 'writeFile' => 0,
286 'copyFile' => 0,
287 'moveFile' => 0,
288 'renameFile' => 0,
289 'deleteFile' => 0,
290 'addFolder' => 0,
291 'readFolder' => 1,
292 'copyFolder' => 0,
293 'moveFolder' => 0,
294 'renameFolder' => 0,
295 'writeFolder' => 0,
296 'deleteFolder' => 0,
297 'recursivedeleteFolder' => 0,
298 ]
299 ],
300 'Uploading allowed' => [
301 [
302 'addFile' => 1,
303 'readFile' => 1,
304 'writeFile' => 1,
305 'copyFile' => 1,
306 'moveFile' => 1,
307 'renameFile' => 1,
308 'deleteFile' => 1,
309 'addFolder' => 0,
310 'readFolder' => 1,
311 'copyFolder' => 0,
312 'moveFolder' => 0,
313 'renameFolder' => 0,
314 'writeFolder' => 0,
315 'deleteFolder' => 0,
316 'recursivedeleteFolder' => 0
317 ]
318 ],
319 'One value is enough' => [
320 [
321 'addFile' => 1,
322 ]
323 ],
324 ];
325 }
326
327 /**
328 * @param array $userTsConfiguration
329 * @test
330 * @dataProvider getFilePermissionsTakesUserDefaultAndStoragePermissionsIntoAccountIfUserIsNotAdminDataProvider
331 */
332 public function getFilePermissionsTakesUserDefaultPermissionsFromTsConfigIntoAccountIfUserIsNotAdmin(array $userTsConfiguration)
333 {
334 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
335 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
336 ->setMethods(['isAdmin'])
337 ->getMock();
338
339 $subject
340 ->expects($this->any())
341 ->method('isAdmin')
342 ->will($this->returnValue(false));
343
344 $subject->userTS = [
345 'permissions.' => [
346 'file.' => [
347 'default.' => $userTsConfiguration
348 ],
349 ]
350 ];
351
352 $expectedPermissions = array_merge($this->defaultFilePermissions, $userTsConfiguration);
353 array_walk(
354 $expectedPermissions,
355 function (&$value) {
356 $value = (bool)$value;
357 }
358 );
359
360 $this->assertEquals($expectedPermissions, $subject->getFilePermissions());
361 }
362
363 /**
364 * @return array
365 */
366 public function getFilePermissionsFromStorageDataProvider()
367 {
368 $defaultPermissions = [
369 'addFile' => true,
370 'readFile' => true,
371 'writeFile' => true,
372 'copyFile' => true,
373 'moveFile' => true,
374 'renameFile' => true,
375 'deleteFile' => true,
376 'addFolder' => true,
377 'readFolder' => true,
378 'copyFolder' => true,
379 'moveFolder' => true,
380 'renameFolder' => true,
381 'writeFolder' => true,
382 'deleteFolder' => true,
383 'recursivedeleteFolder' => true
384 ];
385
386 return [
387 'Overwrites given storage permissions with default permissions' => [
388 $defaultPermissions,
389 1,
390 [
391 'addFile' => 0,
392 'recursivedeleteFolder' =>0
393 ],
394 [
395 'addFile' => 0,
396 'readFile' => 1,
397 'writeFile' => 1,
398 'copyFile' => 1,
399 'moveFile' => 1,
400 'renameFile' => 1,
401 'deleteFile' => 1,
402 'addFolder' => 1,
403 'readFolder' => 1,
404 'copyFolder' => 1,
405 'moveFolder' => 1,
406 'renameFolder' => 1,
407 'writeFolder' => 1,
408 'deleteFolder' => 1,
409 'recursivedeleteFolder' => 0
410 ]
411 ],
412 'Overwrites given storage 0 permissions with default permissions' => [
413 $defaultPermissions,
414 0,
415 [
416 'addFile' => 0,
417 'recursivedeleteFolder' =>0
418 ],
419 [
420 'addFile' => false,
421 'readFile' => true,
422 'writeFile' => true,
423 'copyFile' => true,
424 'moveFile' => true,
425 'renameFile' => true,
426 'deleteFile' => true,
427 'addFolder' => true,
428 'readFolder' => true,
429 'copyFolder' => true,
430 'moveFolder' => true,
431 'renameFolder' => true,
432 'writeFolder' => true,
433 'deleteFolder' => true,
434 'recursivedeleteFolder' => false
435 ]
436 ],
437 'Returns default permissions if no storage permissions are found' => [
438 $defaultPermissions,
439 1,
440 [],
441 [
442 'addFile' => true,
443 'readFile' => true,
444 'writeFile' => true,
445 'copyFile' => true,
446 'moveFile' => true,
447 'renameFile' => true,
448 'deleteFile' => true,
449 'addFolder' => true,
450 'readFolder' => true,
451 'copyFolder' => true,
452 'moveFolder' => true,
453 'renameFolder' => true,
454 'writeFolder' => true,
455 'deleteFolder' => true,
456 'recursivedeleteFolder' => true
457 ]
458 ],
459 ];
460 }
461
462 /**
463 * @param array $defaultPermissions
464 * @param int $storageUid
465 * @param array $storagePermissions
466 * @param array $expectedPermissions
467 * @test
468 * @dataProvider getFilePermissionsFromStorageDataProvider
469 */
470 public function getFilePermissionsFromStorageOverwritesDefaultPermissions(array $defaultPermissions, $storageUid, array $storagePermissions, array $expectedPermissions)
471 {
472 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
473 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
474 ->setMethods(['isAdmin', 'getFilePermissions'])
475 ->getMock();
476 $storageMock = $this->createMock(ResourceStorage::class);
477 $storageMock->expects($this->any())->method('getUid')->will($this->returnValue($storageUid));
478
479 $subject
480 ->expects($this->any())
481 ->method('isAdmin')
482 ->will($this->returnValue(false));
483
484 $subject
485 ->expects($this->any())
486 ->method('getFilePermissions')
487 ->will($this->returnValue($defaultPermissions));
488
489 $subject->userTS = [
490 'permissions.' => [
491 'file.' => [
492 'storage.' => [
493 $storageUid . '.' => $storagePermissions
494 ],
495 ],
496 ]
497 ];
498
499 $this->assertEquals($expectedPermissions, $subject->getFilePermissionsForStorage($storageMock));
500 }
501
502 /**
503 * @param array $defaultPermissions
504 * @param $storageUid
505 * @param array $storagePermissions
506 * @test
507 * @dataProvider getFilePermissionsFromStorageDataProvider
508 */
509 public function getFilePermissionsFromStorageAlwaysReturnsDefaultPermissionsForAdmins(array $defaultPermissions, $storageUid, array $storagePermissions)
510 {
511 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
512 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
513 ->setMethods(['isAdmin', 'getFilePermissions'])
514 ->getMock();
515 $storageMock = $this->createMock(ResourceStorage::class);
516 $storageMock->expects($this->any())->method('getUid')->will($this->returnValue($storageUid));
517
518 $subject
519 ->expects($this->any())
520 ->method('isAdmin')
521 ->will($this->returnValue(true));
522
523 $subject
524 ->expects($this->any())
525 ->method('getFilePermissions')
526 ->will($this->returnValue($defaultPermissions));
527
528 $subject->userTS = [
529 'permissions.' => [
530 'file.' => [
531 'storage.' => [
532 $storageUid . '.' => $storagePermissions
533 ],
534 ],
535 ]
536 ];
537
538 $this->assertEquals($defaultPermissions, $subject->getFilePermissionsForStorage($storageMock));
539 }
540
541 /**
542 * @return array
543 */
544 public function getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdminDataProvider()
545 {
546 return [
547 'No permission' => [
548 '',
549 [
550 'addFile' => false,
551 'readFile' => false,
552 'writeFile' => false,
553 'copyFile' => false,
554 'moveFile' => false,
555 'renameFile' => false,
556 'deleteFile' => false,
557 'addFolder' => false,
558 'readFolder' => false,
559 'copyFolder' => false,
560 'moveFolder' => false,
561 'renameFolder' => false,
562 'writeFolder' => false,
563 'deleteFolder' => false,
564 'recursivedeleteFolder' => false
565 ]
566 ],
567 'Standard file permissions' => [
568 'addFile,readFile,writeFile,copyFile,moveFile,renameFile,deleteFile',
569 [
570 'addFile' => true,
571 'readFile' => true,
572 'writeFile' => true,
573 'copyFile' => true,
574 'moveFile' => true,
575 'renameFile' => true,
576 'deleteFile' => true,
577 'addFolder' => false,
578 'readFolder' => false,
579 'copyFolder' => false,
580 'moveFolder' => false,
581 'renameFolder' => false,
582 'writeFolder' => false,
583 'deleteFolder' => false,
584 'recursivedeleteFolder' => false
585 ]
586 ],
587 'Standard folder permissions' => [
588 'addFolder,readFolder,moveFolder,renameFolder,writeFolder,deleteFolder',
589 [
590 'addFile' => false,
591 'readFile' => false,
592 'writeFile' => false,
593 'copyFile' => false,
594 'moveFile' => false,
595 'renameFile' => false,
596 'deleteFile' => false,
597 'addFolder' => true,
598 'readFolder' => true,
599 'writeFolder' => true,
600 'copyFolder' => false,
601 'moveFolder' => true,
602 'renameFolder' => true,
603 'deleteFolder' => true,
604 'recursivedeleteFolder' => false
605 ]
606 ],
607 'Copy folder allowed' => [
608 'readFolder,copyFolder',
609 [
610 'addFile' => false,
611 'readFile' => false,
612 'writeFile' => false,
613 'copyFile' => false,
614 'moveFile' => false,
615 'renameFile' => false,
616 'deleteFile' => false,
617 'addFolder' => false,
618 'readFolder' => true,
619 'writeFolder' => false,
620 'copyFolder' => true,
621 'moveFolder' => false,
622 'renameFolder' => false,
623 'deleteFolder' => false,
624 'recursivedeleteFolder' => false
625 ]
626 ],
627 'Copy folder and remove subfolders allowed' => [
628 'readFolder,copyFolder,recursivedeleteFolder',
629 [
630 'addFile' => false,
631 'readFile' => false,
632 'writeFile' => false,
633 'copyFile' => false,
634 'moveFile' => false,
635 'renameFile' => false,
636 'deleteFile' => false,
637 'addFolder' => false,
638 'readFolder' => true,
639 'writeFolder' => false,
640 'copyFolder' => true,
641 'moveFolder' => false,
642 'renameFolder' => false,
643 'deleteFolder' => false,
644 'recursivedeleteFolder' => true
645 ]
646 ],
647 ];
648 }
649
650 /**
651 * @test
652 *
653 * @param string $permissionValue
654 * @param array $expectedPermissions
655 *
656 * @dataProvider getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdminDataProvider
657 */
658 public function getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdmin(string $permissionValue, array $expectedPermissions)
659 {
660 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
661 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
662 ->setMethods(['isAdmin'])
663 ->getMock();
664
665 $subject
666 ->expects($this->any())
667 ->method('isAdmin')
668 ->will($this->returnValue(false));
669
670 $subject->userTS = [];
671 $subject->groupData['file_permissions'] = $permissionValue;
672 $this->assertEquals($expectedPermissions, $subject->getFilePermissions());
673 }
674
675 /**
676 * @test
677 */
678 public function getFilePermissionsGrantsAllPermissionsToAdminUsers()
679 {
680 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
681 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
682 ->setMethods(['isAdmin'])
683 ->getMock();
684
685 $subject
686 ->expects($this->any())
687 ->method('isAdmin')
688 ->will($this->returnValue(true));
689
690 $expectedPermissions = [
691 'addFile' => true,
692 'readFile' => true,
693 'writeFile' => true,
694 'copyFile' => true,
695 'moveFile' => true,
696 'renameFile' => true,
697 'deleteFile' => true,
698 'addFolder' => true,
699 'readFolder' => true,
700 'writeFolder' => true,
701 'copyFolder' => true,
702 'moveFolder' => true,
703 'renameFolder' => true,
704 'deleteFolder' => true,
705 'recursivedeleteFolder' => true
706 ];
707
708 $this->assertEquals($expectedPermissions, $subject->getFilePermissions());
709 }
710
711 /**
712 * @test
713 */
714 public function jsConfirmationReturnsTrueIfPassedValueEqualsConfiguration()
715 {
716 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
717 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
718 ->setMethods(['getTSConfig'])
719 ->getMock();
720 $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 1]);
721
722 $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
723 $this->assertFalse($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE));
724 }
725
726 /**
727 * @test
728 */
729 public function jsConfirmationAllowsSettingMultipleBitsInValue()
730 {
731 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
732 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
733 ->setMethods(['getTSConfig'])
734 ->getMock();
735 $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 3]);
736
737 $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
738 $this->assertTrue($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE));
739 }
740
741 /**
742 * @test
743 */
744 public function jsConfirmationAlwaysReturnsFalseIfNoConfirmationIsSet()
745 {
746 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
747 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
748 ->setMethods(['getTSConfig'])
749 ->getMock();
750 $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 0]);
751
752 $this->assertFalse($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
753 $this->assertFalse($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE));
754 }
755
756 /**
757 * @test
758 */
759 public function jsConfirmationReturnsTrueIfConfigurationIsMissing()
760 {
761 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
762 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
763 ->setMethods(['getTSConfig'])
764 ->getMock();
765
766 $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE));
767 }
768
769 /**
770 * Data provider to test page permissions constraints
771 * returns an array of test conditions:
772 * - permission bit(s) as integer
773 * - admin flag
774 * - groups for user
775 * - expected SQL fragment
776 *
777 * @return array
778 */
779 public function getPagePermissionsClauseWithValidUserDataProvider(): array
780 {
781 return [
782 'for admin' => [
783 1,
784 true,
785 '',
786 ' 1=1'
787 ],
788 'for admin with groups' => [
789 11,
790 true,
791 '1,2',
792 ' 1=1'
793 ],
794 'for user' => [
795 2,
796 false,
797 '',
798 ' ((`pages`.`perms_everybody` & 2 = 2) OR' .
799 ' ((`pages`.`perms_userid` = 123) AND (`pages`.`perms_user` & 2 = 2)))'
800 ],
801 'for user with groups' => [
802 8,
803 false,
804 '1,2',
805 ' ((`pages`.`perms_everybody` & 8 = 8) OR' .
806 ' ((`pages`.`perms_userid` = 123) AND (`pages`.`perms_user` & 8 = 8))' .
807 ' OR ((`pages`.`perms_groupid` IN (1, 2)) AND (`pages`.`perms_group` & 8 = 8)))'
808 ],
809 ];
810 }
811
812 /**
813 * @test
814 * @dataProvider getPagePermissionsClauseWithValidUserDataProvider
815 * @param int $perms
816 * @param bool $admin
817 * @param string $groups
818 * @param string $expected
819 */
820 public function getPagePermissionsClauseWithValidUser(int $perms, bool $admin, string $groups, string $expected)
821 {
822 // We only need to setup the mocking for the non-admin cases
823 // If this setup is done for admin cases the FIFO behavior
824 // of GeneralUtility::addInstance will influence other tests
825 // as the ConnectionPool is never used!
826 if (!$admin) {
827 /** @var Connection|ObjectProphecy $connectionProphecy */
828 $connectionProphecy = $this->prophesize(Connection::class);
829 $connectionProphecy->getDatabasePlatform()->willReturn(new MockPlatform());
830 $connectionProphecy->quoteIdentifier(Argument::cetera())->will(function ($args) {
831 return '`' . str_replace('.', '`.`', $args[0]) . '`';
832 });
833
834 /** @var QueryBuilder|ObjectProphecy $queryBuilderProphecy */
835 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
836 $queryBuilderProphecy->expr()->willReturn(
837 new ExpressionBuilder($connectionProphecy->reveal())
838 );
839
840 /** @var ConnectionPool|ObjectProphecy $databaseProphecy */
841 $databaseProphecy = $this->prophesize(ConnectionPool::class);
842 $databaseProphecy->getQueryBuilderForTable('pages')->willReturn($queryBuilderProphecy->reveal());
843 // Shift previously added instance
844 GeneralUtility::makeInstance(ConnectionPool::class);
845 GeneralUtility::addInstance(ConnectionPool::class, $databaseProphecy->reveal());
846 }
847
848 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $subject */
849 $subject = $this->getMockBuilder(BackendUserAuthentication::class)
850 ->setMethods(['isAdmin'])
851 ->getMock();
852 $subject->expects($this->any())
853 ->method('isAdmin')
854 ->will($this->returnValue($admin));
855
856 $subject->user = ['uid' => 123];
857 $subject->groupList = $groups;
858
859 $this->assertEquals($expected, $subject->getPagePermsClause($perms));
860 }
861 }