From d4ad0dd8cc94571a67233f3c11c0fcc7e50ca486 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Fri, 11 Dec 2020 20:23:14 +0100 Subject: [PATCH] [!!!][TASK] Remove group-related properties in BE_USER The "$BE_USER->groupList" property is a comma-separated list of userGroupUID, whereas "$BE_USER->includeGroupArray" is a list of groups added to the includeGroupArray which contains groups possibly added multiple times due to recursion. This is not needed, and therefore cleaned up, the properties are removed. Resolves: #93062 Releases: master Change-Id: Ic358c1be56253acdbe3be4222196a074aab1e98c Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67099 Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- .../ConditionMatcherTest.php | 2 +- .../Service/UserInformationService.php | 2 +- .../BackendUserAuthentication.php | 36 +++------- .../core/Classes/Context/UserAspect.php | 3 +- ...elatedPublicPropertiesInBE_USERRemoved.rst | 47 ++++++++++++ .../BackendUserAuthenticationTest.php | 14 +++- .../Authentication/Fixtures/be_groups.xml | 72 +++++++++++++++++++ .../Authentication/Fixtures/be_users.xml | 20 ++++++ .../BackendUserAuthenticationTest.php | 14 ++-- .../Php/PropertyPublicMatcher.php | 10 +++ 10 files changed, 183 insertions(+), 37 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Breaking-93062-VariousGroup-relatedPublicPropertiesInBE_USERRemoved.rst diff --git a/typo3/sysext/backend/Tests/Functional/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php b/typo3/sysext/backend/Tests/Functional/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php index 450d94795b70..50b886dd1608 100644 --- a/typo3/sysext/backend/Tests/Functional/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php +++ b/typo3/sysext/backend/Tests/Functional/Configuration/TypoScript/ConditionMatching/ConditionMatcherTest.php @@ -44,7 +44,7 @@ class ConditionMatcherTest extends FunctionalTestCase $backendUser = new BackendUserAuthentication(); $backendUser->user['uid'] = 13; $backendUser->user['admin'] = true; - $backendUser->groupList = '13,14,15'; + $backendUser->userGroupsUID = [13, 14, 15]; GeneralUtility::makeInstance(Context::class)->setAspect('backend.user', new UserAspect($backendUser)); } diff --git a/typo3/sysext/beuser/Classes/Service/UserInformationService.php b/typo3/sysext/beuser/Classes/Service/UserInformationService.php index 93c9dce96279..604e213c5ec2 100644 --- a/typo3/sysext/beuser/Classes/Service/UserInformationService.php +++ b/typo3/sysext/beuser/Classes/Service/UserInformationService.php @@ -105,7 +105,7 @@ class UserInformationService $data = [ 'user' => $user->user ?? [], 'groups' => [ - 'inherit' => GeneralUtility::trimExplode(',', $user->groupList, true), + 'inherit' => $user->userGroupsUID, 'direct' => GeneralUtility::trimExplode(',', $user->user['usergroup'], true), ], ]; diff --git a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php index 3bde2d76580f..e8b3dbd4b14b 100644 --- a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php +++ b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php @@ -94,12 +94,6 @@ class BackendUserAuthentication extends AbstractUserAuthentication */ public $userGroupsUID = []; - /** - * This is $this->userGroupsUID imploded to a comma list... Will correspond to the 'usergroup_cached_list' - * @var string - */ - public $groupList = ''; - /** * User workspace. * -99 is ERROR (none available) @@ -115,13 +109,6 @@ class BackendUserAuthentication extends AbstractUserAuthentication */ public $workspaceRec = []; - /** - * List of group_id's in the order they are processed. - * @var array - * @internal should only be used from within TYPO3 Core - */ - public $includeGroupArray = []; - /** * @var array Parsed user TSconfig */ @@ -287,18 +274,18 @@ class BackendUserAuthentication extends AbstractUserAuthentication /** * Returns TRUE if the current user is a member of group $groupId - * $groupId must be set. $this->groupList must contain groups + * $groupId must be set. $this->userGroupsUID must contain groups * Will return TRUE also if the user is a member of a group through subgroups. * - * @param int $groupId Group ID to look for in $this->groupList + * @param int $groupId Group ID to look for in $this->userGroupsUID * @return bool * @internal should only be used from within TYPO3 Core, use Context API for quicker access */ public function isMemberOfGroup($groupId) { $groupId = (int)$groupId; - if ($this->groupList && $groupId) { - return GeneralUtility::inList($this->groupList, (string)$groupId); + if (!empty($this->userGroupsUID) && $groupId) { + return in_array($groupId, $this->userGroupsUID, true); } return false; } @@ -515,12 +502,12 @@ class BackendUserAuthentication extends AbstractUserAuthentication ); // Group (if any is set) - if ($this->groupList) { + if (!empty($this->userGroupsUID)) { $constraint->add( $expressionBuilder->andX( $expressionBuilder->in( 'pages.perms_groupid', - GeneralUtility::intExplode(',', $this->groupList) + $this->userGroupsUID ), $expressionBuilder->comparison( $expressionBuilder->bitAnd('pages.perms_group', $perms), @@ -567,7 +554,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication $out = Permission::NOTHING; if ( isset($row['perms_userid']) && isset($row['perms_user']) && isset($row['perms_groupid']) - && isset($row['perms_group']) && isset($row['perms_everybody']) && isset($this->groupList) + && isset($row['perms_group']) && isset($row['perms_everybody']) && !empty($this->userGroupsUID) ) { if ($this->user['uid'] == $row['perms_userid']) { $out |= $row['perms_user']; @@ -1260,12 +1247,11 @@ class BackendUserAuthentication extends AbstractUserAuthentication $this->fetchGroups($this->user[$this->usergroup_column]); } // Populating the $this->userGroupsUID -array with the groups in the order in which they were LAST included.!! - $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->includeGroupArray))); + $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->userGroupsUID))); // Finally this is the list of group_uid's in the order they are parsed (including subgroups!) // and without duplicates (duplicates are presented with their last entrance in the list, // which thus reflects the order of the TypoScript in TSconfig) - $this->groupList = implode(',', $this->userGroupsUID); - $this->setCachedList($this->groupList); + $this->setCachedList(implode(',', $this->userGroupsUID)); $this->prepareUserTsConfig(); @@ -1359,7 +1345,7 @@ TCAdefaults.sys_note.author = ' . $this->user['realName'] . ' TCAdefaults.sys_note.email = ' . $this->user['email']; // Loop through all groups and add their 'TSconfig' fields - foreach ($this->includeGroupArray as $groupId) { + foreach ($this->userGroupsUID as $groupId) { $collectedUserTSconfig['group_' . $groupId] = $this->userGroups[$groupId]['TSconfig'] ?? ''; } @@ -1439,7 +1425,7 @@ TCAdefaults.sys_note.email = ' . $this->user['email']; $this->fetchGroups($theList, $idList . ',' . $uid); } // Add the group uid, current list to the internal arrays. - $this->includeGroupArray[] = $uid; + $this->userGroupsUID[] = (int)$uid; // Mount group database-mounts if ($mountOptions->shouldUserIncludePageMountsFromAssociatedGroups()) { $this->groupData['webmounts'] .= ',' . $row['db_mountpoints']; diff --git a/typo3/sysext/core/Classes/Context/UserAspect.php b/typo3/sysext/core/Classes/Context/UserAspect.php index 7441a0efc15a..6acf27267af8 100644 --- a/typo3/sysext/core/Classes/Context/UserAspect.php +++ b/typo3/sysext/core/Classes/Context/UserAspect.php @@ -20,7 +20,6 @@ namespace TYPO3\CMS\Core\Context; use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Context\Exception\AspectPropertyNotFoundException; -use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication; /** @@ -140,7 +139,7 @@ class UserAspect implements AspectInterface return $this->groups; } if ($this->user instanceof BackendUserAuthentication) { - return GeneralUtility::intExplode(',', $this->user->groupList, true); + return $this->user->userGroupsUID; } $groups = []; if ($this->user instanceof FrontendUserAuthentication) { diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-93062-VariousGroup-relatedPublicPropertiesInBE_USERRemoved.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-93062-VariousGroup-relatedPublicPropertiesInBE_USERRemoved.rst new file mode 100644 index 000000000000..e6c878a49171 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-93062-VariousGroup-relatedPublicPropertiesInBE_USERRemoved.rst @@ -0,0 +1,47 @@ +.. include:: ../../Includes.txt + +============================================================================= +Breaking: #93062 - Various group-related public properties in BE_USER removed +============================================================================= + +See :issue:`93062` + +Description +=========== + +The PHP API class `BackendUserAuthentication` was built back in +PHP4 days and had a few public properties which have been removed. + +Their purpose was to store data between methods while resolving +groups, where there are other methods containing all group-related +information already anyways. + +- :php:`TYPO3\CMS\Core\Authentication\BackendUserAuthentication->groupList` +- :php:`TYPO3\CMS\Core\Authentication\BackendUserAuthentication->includeGroupArray` + + +Impact +====== + +Accessing or setting these properties have no effect anymore. + + +Affected Installations +====================== + +TYPO3 installations with third-party extensions accessing these +`BackendUserAuthentication` properties, which is highly unlikely, +or because they were built 10 years ago, still accessing these properties. + + +Migration +========= + +Use `BackendUserAuthentication->userGroupsUID` (array of group UIDs) instead, +which contains the groups in the proper order on how they were resolved. + +If this is not needed directly, it is usually highly recommended to use the +Context API's "backend.user" aspect to retrieve a user's groups of a +backend user. + +.. index:: PHP-API, FullyScanned, ext:core diff --git a/typo3/sysext/core/Tests/Functional/Authentication/BackendUserAuthenticationTest.php b/typo3/sysext/core/Tests/Functional/Authentication/BackendUserAuthenticationTest.php index d0e4e24abdbe..5ebef3f6f8d5 100644 --- a/typo3/sysext/core/Tests/Functional/Authentication/BackendUserAuthenticationTest.php +++ b/typo3/sysext/core/Tests/Functional/Authentication/BackendUserAuthenticationTest.php @@ -83,7 +83,7 @@ class BackendUserAuthenticationTest extends FunctionalTestCase $GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig'] = "custom.generic = installation-wide-configuration\ncustom.property = from configuration"; $this->subject->user['realName'] = 'Test user'; $this->subject->user['TSconfig'] = 'custom.property = from user'; - $this->subject->includeGroupArray[] = 13; + $this->subject->userGroupsUID[] = 13; $this->subject->userGroups[13]['TSconfig'] = "custom.property = from group\ncustom.groupProperty = 13"; $this->subject->fetchGroupData(); $result = $this->subject->getTSConfig(); @@ -127,4 +127,16 @@ class BackendUserAuthenticationTest extends FunctionalTestCase $folder = $this->subject->getDefaultUploadFolder(); self::assertEquals('/' . $path . '/', $folder->getIdentifier()); } + + /** + * @test + */ + public function loadGroupsWithProperSettingsAndOrder(): void + { + $subject = $this->setUpBackendUser(3); + $subject->fetchGroupData(); + self::assertEquals('web_info,web_layout,web_list,file_filelist', $subject->groupData['modules']); + self::assertEquals(['1', '4', '5', '3', '2', '6'], $subject->userGroupsUID); + self::assertEquals(['groupValue' => 'from_group_6', 'userValue' => 'from_user_3'], $subject->getTSConfig()['test.']['default.']); + } } diff --git a/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_groups.xml b/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_groups.xml index 4fe85136250f..047f0608e717 100644 --- a/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_groups.xml +++ b/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_groups.xml @@ -12,4 +12,76 @@ <hidden>0</hidden> <cruser_id>1</cruser_id> </be_groups> + <be_groups> + <uid>2</uid> + <pid>0</pid> + <title>first level group</title> + <workspace_perms>0</workspace_perms> + <db_mountpoints>40</db_mountpoints> + <tstamp>1544454571</tstamp> + <crdate>1542360853</crdate> + <deleted>0</deleted> + <hidden>0</hidden> + <subgroup>3</subgroup> + <cruser_id>1</cruser_id> + </be_groups> + <be_groups> + <uid>3</uid> + <pid>0</pid> + <title>first level subgroup</title> + <workspace_perms>0</workspace_perms> + <db_mountpoints>40</db_mountpoints> + <tstamp>1544454571</tstamp> + <TSconfig>test.default.groupValue = from_group_3 +test.default.userValue = never_seen</TSconfig> + <groupMods>web_layout,web_list</groupMods> + <subgroup>2,5</subgroup> + <crdate>1542360853</crdate> + <deleted>0</deleted> + <hidden>0</hidden> + <cruser_id>1</cruser_id> + </be_groups> + <be_groups> + <uid>4</uid> + <pid>0</pid> + <title>random group for filelist</title> + <workspace_perms>0</workspace_perms> + <db_mountpoints></db_mountpoints> + <TSconfig>test.default.groupValue = from_group_4</TSconfig> + <tstamp>1544454571</tstamp> + <groupMods>file_filelist</groupMods> + <crdate>1542360853</crdate> + <deleted>0</deleted> + <hidden>0</hidden> + <cruser_id>1</cruser_id> + </be_groups> + <be_groups> + <uid>5</uid> + <pid>0</pid> + <title>subgroup level 2</title> + <workspace_perms>0</workspace_perms> + <db_mountpoints></db_mountpoints> + <TSconfig>test.default.groupValue = from_group_5</TSconfig> + <tstamp>1544454571</tstamp> + <groupMods>web_info</groupMods> + <crdate>1542360853</crdate> + <deleted>0</deleted> + <hidden>0</hidden> + <cruser_id>1</cruser_id> + </be_groups> + <be_groups> + <uid>6</uid> + <pid>0</pid> + <title>random group for filelist</title> + <workspace_perms>0</workspace_perms> + <db_mountpoints></db_mountpoints> + <tstamp>1544454571</tstamp> + <TSconfig>test.default.groupValue = from_group_6</TSconfig> + <groupMods>file_filelist</groupMods> + <crdate>1542360853</crdate> + <deleted>0</deleted> + <hidden>0</hidden> + <subgroup>2</subgroup> + <cruser_id>1</cruser_id> + </be_groups> </dataset> diff --git a/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_users.xml b/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_users.xml index 706fefad5e04..c2854189d1b5 100644 --- a/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_users.xml +++ b/typo3/sysext/core/Tests/Functional/Authentication/Fixtures/be_users.xml @@ -39,4 +39,24 @@ <workspace_id>0</workspace_id> <usergroup>1</usergroup> </be_users> + <be_users> + <uid>3</uid> + <pid>0</pid> + <tstamp>1366642540</tstamp> + <username>editor_with_groups</username> + <password>$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1</password> <!-- password --> + <admin>0</admin> + <disable>0</disable> + <starttime>0</starttime> + <endtime>0</endtime> + <options>3</options> + <crdate>1366642540</crdate> + <cruser_id>0</cruser_id> + <workspace_perms>1</workspace_perms> + <deleted>0</deleted> + <TSconfig>test.default.userValue = from_user_3</TSconfig> + <lastlogin>1371033743</lastlogin> + <workspace_id>0</workspace_id> + <usergroup>1,2,4,6</usergroup> + </be_users> </dataset> diff --git a/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php b/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php index e6d1731ec95c..fa8cc7c76d9b 100644 --- a/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php +++ b/typo3/sysext/core/Tests/Unit/Authentication/BackendUserAuthenticationTest.php @@ -712,26 +712,26 @@ class BackendUserAuthenticationTest extends UnitTestCase 'for admin' => [ 1, true, - '', + [], ' 1=1' ], 'for admin with groups' => [ 11, true, - '1,2', + [1, 2], ' 1=1' ], 'for user' => [ 2, false, - '', + [], ' ((`pages`.`perms_everybody` & 2 = 2) OR' . ' ((`pages`.`perms_userid` = 123) AND (`pages`.`perms_user` & 2 = 2)))' ], 'for user with groups' => [ 8, false, - '1,2', + [1, 2], ' ((`pages`.`perms_everybody` & 8 = 8) OR' . ' ((`pages`.`perms_userid` = 123) AND (`pages`.`perms_user` & 8 = 8))' . ' OR ((`pages`.`perms_groupid` IN (1, 2)) AND (`pages`.`perms_group` & 8 = 8)))' @@ -744,10 +744,10 @@ class BackendUserAuthenticationTest extends UnitTestCase * @dataProvider getPagePermissionsClauseWithValidUserDataProvider * @param int $perms * @param bool $admin - * @param string $groups + * @param array $groups * @param string $expected */ - public function getPagePermissionsClauseWithValidUser(int $perms, bool $admin, string $groups, string $expected): void + public function getPagePermissionsClauseWithValidUser(int $perms, bool $admin, array $groups, string $expected): void { // We only need to setup the mocking for the non-admin cases // If this setup is done for admin cases the FIFO behavior @@ -785,7 +785,7 @@ class BackendUserAuthenticationTest extends UnitTestCase ->willReturn($admin); $subject->user = ['uid' => 123]; - $subject->groupList = $groups; + $subject->userGroupsUID = $groups; self::assertEquals($expected, $subject->getPagePermsClause($perms)); } diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php index 2c291990bfa0..a216c07337be 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php @@ -785,4 +785,14 @@ return [ 'Breaking-93047-RemovedPropertySendNoCacheHeadersInAbstractUserAuthentication.rst', ], ], + 'TYPO3\CMS\Core\Authentication\BackendUserAuthentication->groupList' => [ + 'restFiles' => [ + 'Breaking-93062-VariousGroup-relatedPublicPropertiesInBE_USERRemoved.rst', + ], + ], + 'TYPO3\CMS\Core\Authentication\BackendUserAuthentication->includeGroupArray' => [ + 'restFiles' => [ + 'Breaking-93062-VariousGroup-relatedPublicPropertiesInBE_USERRemoved.rst', + ], + ], ]; -- GitLab