diff --git a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php index 3a84b9b784d3b9cfa888f25925122f0e3f15f45a..57db4e1327543bf738a3d18c1237ef6a3f8c930b 100644 --- a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php +++ b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Core\Authentication; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation; use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -1204,22 +1205,25 @@ class BackendUserAuthentication extends \TYPO3\CMS\Core\Authentication\AbstractU /** * Returns TRUE or FALSE, depending if an alert popup (a javascript confirmation) should be shown * call like $GLOBALS['BE_USER']->jsConfirmation($BITMASK). - * See \TYPO3\CMS\Core\Type\Bitmask\JsConfirmation. * - * @param int $bitmask Bitmask + * @param int $bitmask Bitmask, one of \TYPO3\CMS\Core\Type\Bitmask\JsConfirmation * @return bool TRUE if the confirmation should be shown + * @see JsConfirmation */ public function jsConfirmation($bitmask) { $alertPopup = $this->getTSConfig('options.alertPopups'); - if (empty($alertPopup['value'])) { - // Default: show all warnings - $alertPopup = 255; + + if (trim((string)$alertPopup['value']) === '') { + // Default: show all confirmations + $alertPopup = JsConfirmation::ALL; } else { - $alertPopup = (int)$alertPopup['value']; + $alertPopup = $alertPopup['value']; } - // Show confirmation - return ($alertPopup & $bitmask) == $bitmask; + + $bitmask = JsConfirmation::cast($bitmask); + $alertPopup = JsConfirmation::cast($alertPopup); + return $bitmask->matches($alertPopup); } /** diff --git a/typo3/sysext/core/Classes/Type/Bitmask/JsConfirmation.php b/typo3/sysext/core/Classes/Type/Bitmask/JsConfirmation.php index 2f0e3ee7d7967abc62b02ed85b70f4cfed431a35..ab571e5c582613959cfa5ed752fbdb0c9d9c9391 100644 --- a/typo3/sysext/core/Classes/Type/Bitmask/JsConfirmation.php +++ b/typo3/sysext/core/Classes/Type/Bitmask/JsConfirmation.php @@ -14,10 +14,13 @@ namespace TYPO3\CMS\Core\Type\Bitmask; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Type\Enumeration; +use TYPO3\CMS\Core\Type\Exception; + /** * A class providing constants for bitwise operations on javascript confirmation popups */ -class JsConfirmation extends \TYPO3\CMS\Core\Type\Enumeration +class JsConfirmation extends Enumeration { /** * @var int @@ -43,4 +46,69 @@ class JsConfirmation extends \TYPO3\CMS\Core\Type\Enumeration * @var int */ const OTHER = 0b10000000; + + /** + * @var int + */ + const ALL = 255; + + protected static $allowedValues = self::TYPE_CHANGE | self::COPY_MOVE_PASTE | self::DELETE | self::FE_EDIT | self::OTHER; + + /** + * Returns TRUE if a given value matches the internal value + * + * @param JsConfirmation $value Value to check + * @return bool + */ + public function matches(JsConfirmation $value) + { + $value = (int)(string)$value; + $thisValue = (int)$this->value; + + return ($value & $thisValue) == $thisValue; + } + + /** + * Set the Enumeration value to the associated enumeration value by a loose comparison. + * The value, that is used as the enumeration value, will be of the same type like defined in the enumeration + * + * @param mixed $value + * @throws Exception\InvalidEnumerationValueException + */ + protected function setValue($value) + { + if ($value < 255) { + if (($value & self::$allowedValues) !== $value) { + throw new Exception\InvalidEnumerationValueException( + sprintf('Invalid value %s for %s', $value, __CLASS__), + 1457175152 + ); + } + $this->value = $value; + } else { + parent::setValue($value); + } + } + + /** + * Check if the value on this enum is a valid value for the enum + * + * @param mixed $value + * @return bool + */ + protected function isValid($value) + { + if ($value < 255) { + return (($value & self::$allowedValues) === $value); + } + + $value = (string)$value; + foreach (static::$enumConstants[get_class($this)] as $constantValue) { + if ($value === (string)$constantValue) { + return true; + } + } + return false; + } + } diff --git a/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php b/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php index 7f34b2af44743902f174057735895542062a759c..6be323a26fa48ce4fc853a5bc3cef4bb3ca08864 100644 --- a/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php +++ b/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php @@ -14,8 +14,11 @@ namespace TYPO3\CMS\Core\Tests\Unit\Authentication; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation; + /** - * Testcase for \TYPO3\CMS\Core\Authentication\BackendUserAuthentication + * Testcase for BackendUserAuthentication */ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase { @@ -77,11 +80,11 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase ); // logoff() call the static factory that has a dependency to a valid BE_USER object. Mock this away - $GLOBALS['BE_USER'] = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array(), array(), '', false); + $GLOBALS['BE_USER'] = $this->getMock(BackendUserAuthentication::class, array(), array(), '', false); $GLOBALS['BE_USER']->user = array('uid' => $this->getUniqueId()); $GLOBALS['TYPO3_DB'] = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, array(), array(), '', false); - $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('dummy'), array(), '', false); + $subject = $this->getAccessibleMock(BackendUserAuthentication::class, array('dummy'), array(), '', false); $subject->_set('db', $GLOBALS['TYPO3_DB']); $subject->logoff(); } @@ -233,7 +236,7 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase */ public function getTSConfigReturnsCorrectArrayForGivenObjectString(array $completeConfiguration, $objectString, array $expectedConfiguration) { - $subject = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('dummy'), array(), '', false); + $subject = $this->getMock(BackendUserAuthentication::class, array('dummy'), array(), '', FALSE); $subject->userTS = $completeConfiguration; $actualConfiguration = $subject->getTSConfig($objectString); @@ -299,7 +302,7 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase */ public function getFilePermissionsTakesUserDefaultPermissionsFromTsConfigIntoAccountIfUserIsNotAdmin(array $userTsConfiguration) { - $subject = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('isAdmin')); + $subject = $this->getMock(BackendUserAuthentication::class, array('isAdmin')); $subject ->expects($this->any()) @@ -434,7 +437,7 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase */ public function getFilePermissionsFromStorageOverwritesDefaultPermissions(array $defaultPermissions, $storageUid, array $storagePermissions, array $expectedPermissions) { - $subject = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('isAdmin', 'getFilePermissions')); + $subject = $this->getMock(BackendUserAuthentication::class, array('isAdmin', 'getFilePermissions')); $storageMock = $this->getMock(\TYPO3\CMS\Core\Resource\ResourceStorage::class, array(), array(), '', false); $storageMock->expects($this->any())->method('getUid')->will($this->returnValue($storageUid)); @@ -470,7 +473,7 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase */ public function getFilePermissionsFromStorageAlwaysReturnsDefaultPermissionsForAdmins(array $defaultPermissions, $storageUid, array $storagePermissions) { - $subject = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('isAdmin', 'getFilePermissions')); + $subject = $this->getMock(BackendUserAuthentication::class, array('isAdmin', 'getFilePermissions')); $storageMock = $this->getMock(\TYPO3\CMS\Core\Resource\ResourceStorage::class, array(), array(), '', false); $storageMock->expects($this->any())->method('getUid')->will($this->returnValue($storageUid)); @@ -612,7 +615,7 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase */ public function getFilePermissionsTakesUserDefaultPermissionsFromRecordIntoAccountIfUserIsNotAdmin($permissionValue, $expectedPermissions) { - $subject = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('isAdmin')); + $subject = $this->getMock(BackendUserAuthentication::class, array('isAdmin')); $subject ->expects($this->any()) @@ -629,7 +632,7 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase */ public function getFilePermissionsGrantsAllPermissionsToAdminUsers() { - $subject = $this->getMock(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class, array('isAdmin')); + $subject = $this->getMock(BackendUserAuthentication::class, array('isAdmin')); $subject ->expects($this->any()) @@ -656,4 +659,50 @@ class BackendUserAuthenticationTest extends \TYPO3\CMS\Core\Tests\UnitTestCase $this->assertEquals($expectedPermissions, $subject->getFilePermissions()); } + + /** + * @test + */ + public function jsConfirmationReturnsTrueIfPassedValueEqualsConfiguration() + { + $subject = $this->getMock(BackendUserAuthentication::class, ['getTSConfig']); + $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 1]); + + $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE)); + $this->assertFalse($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)); + } + + /** + * @test + */ + public function jsConfirmationAllowsSettingMultipleBitsInValue() + { + $subject = $this->getMock(BackendUserAuthentication::class, ['getTSConfig']); + $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 3]); + + $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE)); + $this->assertTrue($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)); + } + + /** + * @test + */ + public function jsConfirmationAlwaysReturnsFalseIfNoConfirmationIsSet() + { + $subject = $this->getMock(BackendUserAuthentication::class, ['getTSConfig']); + $subject->method('getTSConfig')->with('options.alertPopups')->willReturn(['value' => 0]); + + $this->assertFalse($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE)); + $this->assertFalse($subject->jsConfirmation(JsConfirmation::COPY_MOVE_PASTE)); + } + + /** + * @test + */ + public function jsConfirmationReturnsTrueIfConfigurationIsMissing() + { + $subject = $this->getMock(BackendUserAuthentication::class, ['getTSConfig']); + + $this->assertTrue($subject->jsConfirmation(JsConfirmation::TYPE_CHANGE)); + } }