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