X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fuser%2FUser.php;h=84298e2d16ebdb2068697d51d7d45e9407cd2d71;hb=cca344a717b9e41b0e32e4915295cd36dd18bf83;hp=79b84204bad15240106b7278341bf2be71667f9e;hpb=d1401ab5f1a189c4895468344a5febda70bc47ee;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/user/User.php b/includes/user/User.php index 79b84204ba..84298e2d16 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -111,95 +111,7 @@ class User implements IDBAccessObject, UserIdentity { ]; /** - * Array of Strings Core rights. - * Each of these should have a corresponding message of the form - * "right-$right". - * @showinitializer * @var string[] - */ - protected static $mCoreRights = [ - 'apihighlimits', - 'applychangetags', - 'autoconfirmed', - 'autocreateaccount', - 'autopatrol', - 'bigdelete', - 'block', - 'blockemail', - 'bot', - 'browsearchive', - 'changetags', - 'createaccount', - 'createpage', - 'createtalk', - 'delete', - 'deletechangetags', - 'deletedhistory', - 'deletedtext', - 'deletelogentry', - 'deleterevision', - 'edit', - 'editcontentmodel', - 'editinterface', - 'editprotected', - 'editmyoptions', - 'editmyprivateinfo', - 'editmyusercss', - 'editmyuserjson', - 'editmyuserjs', - 'editmywatchlist', - 'editsemiprotected', - 'editsitecss', - 'editsitejson', - 'editsitejs', - 'editusercss', - 'edituserjson', - 'edituserjs', - 'hideuser', - 'import', - 'importupload', - 'ipblock-exempt', - 'managechangetags', - 'markbotedits', - 'mergehistory', - 'minoredit', - 'move', - 'movefile', - 'move-categorypages', - 'move-rootuserpages', - 'move-subpages', - 'nominornewtalk', - 'noratelimit', - 'override-export-depth', - 'pagelang', - 'patrol', - 'patrolmarks', - 'protect', - 'purge', - 'read', - 'reupload', - 'reupload-own', - 'reupload-shared', - 'rollback', - 'sendemail', - 'siteadmin', - 'suppressionlog', - 'suppressredirect', - 'suppressrevision', - 'unblockself', - 'undelete', - 'unwatchedpages', - 'upload', - 'upload_by_url', - 'userrights', - 'userrights-interwiki', - 'viewmyprivateinfo', - 'viewmywatchlist', - 'viewsuppressed', - 'writeapi', - ]; - - /** * @var string[] Cached results of getAllRights() */ protected static $mAllRights = false; @@ -274,8 +186,6 @@ class User implements IDBAccessObject, UserIdentity { public $mBlockedby; /** @var string */ protected $mHash; - /** @var array */ - public $mRights; /** @var string */ protected $mBlockreason; /** @var array */ @@ -333,6 +243,24 @@ class User implements IDBAccessObject, UserIdentity { return (string)$this->getName(); } + public function __get( $name ) { + // A shortcut for $mRights deprecation phase + if ( $name === 'mRights' ) { + return $this->getRights(); + } + } + + public function __set( $name, $value ) { + // A shortcut for $mRights deprecation phase, only known legitimate use was for + // testing purposes, other uses seem bad in principle + if ( $name === 'mRights' ) { + MediaWikiServices::getInstance()->getPermissionManager()->overrideUserRightsForTesting( + $this, + is_null( $value ) ? [] : $value + ); + } + } + /** * Test if it's safe to load this User object. * @@ -491,12 +419,12 @@ class User implements IDBAccessObject, UserIdentity { /** * @since 1.27 - * @param string $wikiId + * @param string $dbDomain * @param int $userId */ - public static function purge( $wikiId, $userId ) { + public static function purge( $dbDomain, $userId ) { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); - $key = $cache->makeGlobalKey( 'user', 'id', $wikiId, $userId ); + $key = $cache->makeGlobalKey( 'user', 'id', $dbDomain, $userId ); $cache->delete( $key ); } @@ -680,16 +608,16 @@ class User implements IDBAccessObject, UserIdentity { * @param int|null $userId User ID, if known * @param string|null $userName User name, if known * @param int|null $actorId Actor ID, if known - * @param bool|string $wikiId remote wiki to which the User/Actor ID applies, or false if none + * @param bool|string $dbDomain remote wiki to which the User/Actor ID applies, or false if none * @return User */ - public static function newFromAnyId( $userId, $userName, $actorId, $wikiId = false ) { + public static function newFromAnyId( $userId, $userName, $actorId, $dbDomain = false ) { global $wgActorTableSchemaMigrationStage; // Stop-gap solution for the problem described in T222212. // Force the User ID and Actor ID to zero for users loaded from the database // of another wiki, to prevent subtle data corruption and confusing failure modes. - if ( $wikiId !== false ) { + if ( $dbDomain !== false ) { $userId = 0; $actorId = 0; } @@ -950,12 +878,12 @@ class User implements IDBAccessObject, UserIdentity { $result = (int)$s->user_id; } - self::$idCacheByName[$name] = $result; - - if ( count( self::$idCacheByName ) > 1000 ) { + if ( count( self::$idCacheByName ) >= 1000 ) { self::$idCacheByName = []; } + self::$idCacheByName[$name] = $result; + return $result; } @@ -1346,25 +1274,17 @@ class User implements IDBAccessObject, UserIdentity { * @return bool True if the user is logged in, false otherwise. */ private function loadFromSession() { - // Deprecated hook - $result = null; - Hooks::run( 'UserLoadFromSession', [ $this, &$result ], '1.27' ); - if ( $result !== null ) { - return $result; - } - // MediaWiki\Session\Session already did the necessary authentication of the user // returned here, so just use it if applicable. $session = $this->getRequest()->getSession(); $user = $session->getUser(); if ( $user->isLoggedIn() ) { $this->loadFromUserObject( $user ); - if ( $user->getBlock() ) { - // If this user is autoblocked, set a cookie to track the block. This has to be done on - // every session load, because an autoblocked editor might not edit again from the same - // IP address after being blocked. - $this->trackBlockWithCookie(); - } + + // If this user is autoblocked, set a cookie to track the block. This has to be done on + // every session load, because an autoblocked editor might not edit again from the same + // IP address after being blocked. + MediaWikiServices::getInstance()->getBlockManager()->trackBlockWithCookie( $this ); // Other code expects these to be set in the session, so set them. $session->set( 'wsUserID', $this->getId() ); @@ -1379,15 +1299,11 @@ class User implements IDBAccessObject, UserIdentity { /** * Set the 'BlockID' cookie depending on block type and user authentication status. + * + * @deprecated since 1.34 Use BlockManager::trackBlockWithCookie instead */ public function trackBlockWithCookie() { - $block = $this->getBlock(); - - if ( $block && $this->getRequest()->getCookie( 'BlockID' ) === null - && $block->shouldTrackWithCookie( $this->isAnon() ) - ) { - $block->setCookie( $this->getRequest()->response() ); - } + MediaWikiServices::getInstance()->getBlockManager()->trackBlockWithCookie( $this ); } /** @@ -1710,11 +1626,12 @@ class User implements IDBAccessObject, UserIdentity { * given source. May be "name", "id", "actor", "defaults", "session", or false for no reload. */ public function clearInstanceCache( $reloadFrom = false ) { + global $wgFullyInitialised; + $this->mNewtalk = -1; $this->mDatePreference = null; $this->mBlockedby = -1; # Unset $this->mHash = false; - $this->mRights = null; $this->mEffectiveGroups = null; $this->mImplicitGroups = null; $this->mGroupMemberships = null; @@ -1722,6 +1639,13 @@ class User implements IDBAccessObject, UserIdentity { $this->mOptionsLoaded = false; $this->mEditCount = null; + // Replacement of former `$this->mRights = null` line + if ( $wgFullyInitialised && $this->mFrom ) { + MediaWikiServices::getInstance()->getPermissionManager()->invalidateUsersRightsCache( + $this + ); + } + if ( $reloadFrom ) { $this->mLoadedItems = []; $this->mFrom = $reloadFrom; @@ -1826,8 +1750,7 @@ class User implements IDBAccessObject, UserIdentity { $fromReplica ); - if ( $block instanceof AbstractBlock ) { - wfDebug( __METHOD__ . ": Found block.\n" ); + if ( $block ) { $this->mBlock = $block; $this->mBlockedby = $block->getByName(); $this->mBlockreason = $block->getReason(); @@ -2161,7 +2084,6 @@ class User implements IDBAccessObject, UserIdentity { * @param Title $title Title to check * @param bool $fromReplica Whether to check the replica DB instead of the master * @return bool - * @throws MWException * * @deprecated since 1.33, * use MediaWikiServices::getInstance()->getPermissionManager()->isBlockedFrom(..) @@ -3302,7 +3224,7 @@ class User implements IDBAccessObject, UserIdentity { * and 'all', which forces a reset of *all* preferences and overrides everything else. * * @param array|string $resetKinds Which kinds of preferences to reset. Defaults to - * array( 'registered', 'registered-multiselect', 'registered-checkmatrix', 'unused' ) + * [ 'registered', 'registered-multiselect', 'registered-checkmatrix', 'unused' ] * for backwards-compatibility. * @param IContextSource|null $context Context source used when $resetKinds * does not contain 'all', passed to getOptionKinds(). @@ -3407,44 +3329,13 @@ class User implements IDBAccessObject, UserIdentity { /** * Get the permissions this user has. * @return string[] permission names + * + * @deprecated since 1.34, use MediaWikiServices::getInstance()->getPermissionManager() + * ->getUserPermissions(..) instead + * */ public function getRights() { - if ( is_null( $this->mRights ) ) { - $this->mRights = self::getGroupPermissions( $this->getEffectiveGroups() ); - Hooks::run( 'UserGetRights', [ $this, &$this->mRights ] ); - - // Deny any rights denied by the user's session, unless this - // endpoint has no sessions. - if ( !defined( 'MW_NO_SESSION' ) ) { - $allowedRights = $this->getRequest()->getSession()->getAllowedUserRights(); - if ( $allowedRights !== null ) { - $this->mRights = array_intersect( $this->mRights, $allowedRights ); - } - } - - Hooks::run( 'UserGetRightsRemove', [ $this, &$this->mRights ] ); - // Force reindexation of rights when a hook has unset one of them - $this->mRights = array_values( array_unique( $this->mRights ) ); - - // If block disables login, we should also remove any - // extra rights blocked users might have, in case the - // blocked user has a pre-existing session (T129738). - // This is checked here for cases where people only call - // $user->isAllowed(). It is also checked in Title::checkUserBlock() - // to give a better error message in the common case. - $config = RequestContext::getMain()->getConfig(); - // @TODO Partial blocks should not prevent the user from logging in. - // see: https://phabricator.wikimedia.org/T208895 - if ( - $this->isLoggedIn() && - $config->get( 'BlockDisablesLogin' ) && - $this->getBlock() - ) { - $anon = new User; - $this->mRights = array_intersect( $this->mRights, $anon->getRights() ); - } - } - return $this->mRights; + return MediaWikiServices::getInstance()->getPermissionManager()->getUserPermissions( $this ); } /** @@ -3572,7 +3463,7 @@ class User implements IDBAccessObject, UserIdentity { if ( $count === null ) { // it has not been initialized. do so. - $count = $this->initEditCountInternal(); + $count = $this->initEditCountInternal( $dbr ); } $this->mEditCount = $count; } @@ -3613,8 +3504,7 @@ class User implements IDBAccessObject, UserIdentity { // Refresh the groups caches, and clear the rights cache so it will be // refreshed on the next call to $this->getRights(). $this->getEffectiveGroups( true ); - $this->mRights = null; - + MediaWikiServices::getInstance()->getPermissionManager()->invalidateUsersRightsCache( $this ); $this->invalidateCache(); return true; @@ -3645,8 +3535,7 @@ class User implements IDBAccessObject, UserIdentity { // Refresh the groups caches, and clear the rights cache so it will be // refreshed on the next call to $this->getRights(). $this->getEffectiveGroups( true ); - $this->mRights = null; - + MediaWikiServices::getInstance()->getPermissionManager()->invalidateUsersRightsCache( $this ); $this->invalidateCache(); return true; @@ -3729,16 +3618,17 @@ class User implements IDBAccessObject, UserIdentity { /** * Internal mechanics of testing a permission + * + * @deprecated since 1.34, use MediaWikiServices::getInstance() + * ->getPermissionManager()->userHasRight(...) instead + * * @param string $action + * * @return bool */ public function isAllowed( $action = '' ) { - if ( $action === '' ) { - return true; // In the spirit of DWIM - } - // Use strict parameter to avoid matching numeric 0 accidentally inserted - // by misconfiguration: 0 == 'foo' - return in_array( $action, $this->getRights(), true ); + return MediaWikiServices::getInstance()->getPermissionManager() + ->userHasRight( $this, $action ); } /** @@ -4887,45 +4777,27 @@ class User implements IDBAccessObject, UserIdentity { /** * Get the permissions associated with a given list of groups * + * @deprecated since 1.34, use MediaWikiServices::getInstance()->getPermissionManager() + * ->getGroupPermissions() instead + * * @param array $groups Array of Strings List of internal group names * @return array Array of Strings List of permission key names for given groups combined */ public static function getGroupPermissions( $groups ) { - global $wgGroupPermissions, $wgRevokePermissions; - $rights = []; - // grant every granted permission first - foreach ( $groups as $group ) { - if ( isset( $wgGroupPermissions[$group] ) ) { - $rights = array_merge( $rights, - // array_filter removes empty items - array_keys( array_filter( $wgGroupPermissions[$group] ) ) ); - } - } - // now revoke the revoked permissions - foreach ( $groups as $group ) { - if ( isset( $wgRevokePermissions[$group] ) ) { - $rights = array_diff( $rights, - array_keys( array_filter( $wgRevokePermissions[$group] ) ) ); - } - } - return array_unique( $rights ); + return MediaWikiServices::getInstance()->getPermissionManager()->getGroupPermissions( $groups ); } /** * Get all the groups who have a given permission * + * @deprecated since 1.34, use MediaWikiServices::getInstance()->getPermissionManager() + * ->getGroupsWithPermission() instead + * * @param string $role Role to check * @return array Array of Strings List of internal group names with the given permission */ public static function getGroupsWithPermission( $role ) { - global $wgGroupPermissions; - $allowedGroups = []; - foreach ( array_keys( $wgGroupPermissions ) as $group ) { - if ( self::groupHasPermission( $group, $role ) ) { - $allowedGroups[] = $group; - } - } - return $allowedGroups; + return MediaWikiServices::getInstance()->getPermissionManager()->getGroupsWithPermission( $role ); } /** @@ -4935,15 +4807,17 @@ class User implements IDBAccessObject, UserIdentity { * User::isEveryoneAllowed() instead. That properly checks if it's revoked * from anyone. * + * @deprecated since 1.34, use MediaWikiServices::getInstance()->getPermissionManager() + * ->groupHasPermission(..) instead + * * @since 1.21 * @param string $group Group to check * @param string $role Role to check * @return bool */ public static function groupHasPermission( $group, $role ) { - global $wgGroupPermissions, $wgRevokePermissions; - return isset( $wgGroupPermissions[$group][$role] ) && $wgGroupPermissions[$group][$role] - && !( isset( $wgRevokePermissions[$group][$role] ) && $wgRevokePermissions[$group][$role] ); + return MediaWikiServices::getInstance()->getPermissionManager() + ->groupHasPermission( $group, $role ); } /** @@ -4956,51 +4830,16 @@ class User implements IDBAccessObject, UserIdentity { * Specifically, session-based rights restrictions (such as OAuth or bot * passwords) are applied based on the current session. * - * @since 1.22 + * @deprecated since 1.34, use MediaWikiServices::getInstance()->getPermissionManager() + * ->isEveryoneAllowed() instead + * * @param string $right Right to check + * * @return bool + * @since 1.22 */ public static function isEveryoneAllowed( $right ) { - global $wgGroupPermissions, $wgRevokePermissions; - static $cache = []; - - // Use the cached results, except in unit tests which rely on - // being able change the permission mid-request - if ( isset( $cache[$right] ) && !defined( 'MW_PHPUNIT_TEST' ) ) { - return $cache[$right]; - } - - if ( !isset( $wgGroupPermissions['*'][$right] ) || !$wgGroupPermissions['*'][$right] ) { - $cache[$right] = false; - return false; - } - - // If it's revoked anywhere, then everyone doesn't have it - foreach ( $wgRevokePermissions as $rights ) { - if ( isset( $rights[$right] ) && $rights[$right] ) { - $cache[$right] = false; - return false; - } - } - - // Remove any rights that aren't allowed to the global-session user, - // unless there are no sessions for this endpoint. - if ( !defined( 'MW_NO_SESSION' ) ) { - $allowedRights = SessionManager::getGlobalSession()->getAllowedUserRights(); - if ( $allowedRights !== null && !in_array( $right, $allowedRights, true ) ) { - $cache[$right] = false; - return false; - } - } - - // Allow extensions to say false - if ( !Hooks::run( 'UserIsEveryoneAllowed', [ $right ] ) ) { - $cache[$right] = false; - return false; - } - - $cache[$right] = true; - return true; + return MediaWikiServices::getInstance()->getPermissionManager()->isEveryoneAllowed( $right ); } /** @@ -5019,19 +4858,14 @@ class User implements IDBAccessObject, UserIdentity { /** * Get a list of all available permissions. + * + * @deprecated since 1.34, use MediaWikiServices::getInstance()->getPermissionManager() + * ->getAllPermissions() instead + * * @return string[] Array of permission names */ public static function getAllRights() { - if ( self::$mAllRights === false ) { - global $wgAvailableRights; - if ( count( $wgAvailableRights ) ) { - self::$mAllRights = array_unique( array_merge( self::$mCoreRights, $wgAvailableRights ) ); - } else { - self::$mAllRights = self::$mCoreRights; - } - Hooks::run( 'UserGetAllRights', [ &self::$mAllRights ] ); - } - return self::$mAllRights; + return MediaWikiServices::getInstance()->getPermissionManager()->getAllPermissions(); } /** @@ -5049,10 +4883,10 @@ class User implements IDBAccessObject, UserIdentity { * Returns an array of the groups that a particular group can add/remove. * * @param string $group The group to check for whether it can add/remove - * @return array Array( 'add' => array( addablegroups ), - * 'remove' => array( removablegroups ), - * 'add-self' => array( addablegroups to self), - * 'remove-self' => array( removable groups from self) ) + * @return array [ 'add' => [ addablegroups ], + * 'remove' => [ removablegroups ], + * 'add-self' => [ addablegroups to self ], + * 'remove-self' => [ removable groups from self ] ] */ public static function changeableByGroup( $group ) { global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; @@ -5122,10 +4956,10 @@ class User implements IDBAccessObject, UserIdentity { /** * Returns an array of groups that this user can add and remove - * @return array Array( 'add' => array( addablegroups ), - * 'remove' => array( removablegroups ), - * 'add-self' => array( addablegroups to self), - * 'remove-self' => array( removable groups from self) ) + * @return array [ 'add' => [ addablegroups ], + * 'remove' => [ removablegroups ], + * 'add-self' => [ addablegroups to self ], + * 'remove-self' => [ removable groups from self ] ] */ public function changeableGroups() { if ( $this->isAllowed( 'userrights' ) ) { @@ -5189,14 +5023,13 @@ class User implements IDBAccessObject, UserIdentity { /** * Initialize user_editcount from data out of the revision table * - * This method should not be called outside User/UserEditCountUpdate - * + * @internal This method should not be called outside User/UserEditCountUpdate + * @param IDatabase $dbr Replica database * @return int Number of edits */ - public function initEditCountInternal() { + public function initEditCountInternal( IDatabase $dbr ) { // Pull from a replica DB to be less cruel to servers // Accuracy isn't the point anyway here - $dbr = wfGetDB( DB_REPLICA ); $actorWhere = ActorMigration::newMigration()->getWhere( $dbr, 'rev_user', $this ); $count = (int)$dbr->selectField( [ 'revision' ] + $actorWhere['tables'],