From 3f717984c13b671cf166880d5153f0396f3107f8 Mon Sep 17 00:00:00 2001 From: "James D. Forrester" Date: Mon, 11 Feb 2019 13:18:13 -0800 Subject: [PATCH] Drop AuthPlugin and related code, deprecated in 1.27 Bug: T215843 Depends-On: Ie49709faa6f67b0a31bd546823d29dbfea0a70eb Depends-On: If8109dbfdeeb88a6265f4cd79d1ae81bff48d934 Depends-On: I36b195fa2d6c23a76631ebaf869c787e44427d60 Depends-On: Iaa171b085fde331eab7d85c7de74523e27fc625a Change-Id: I330b30d6582034a233fed204c0680b1ce84eec6e --- .phpcs.xml | 2 - RELEASE-NOTES-1.33 | 9 + autoload.php | 2 - docs/hooks.txt | 10 - includes/AuthPlugin.php | 364 --------- includes/DefaultSettings.php | 7 - includes/Setup.php | 16 - includes/auth/AuthManager.php | 14 +- includes/auth/AuthManagerAuthPlugin.php | 197 ----- includes/auth/AuthManagerAuthPluginUser.php | 53 -- ...uthPluginPrimaryAuthenticationProvider.php | 429 ----------- .../preferences/DefaultPreferencesFactory.php | 1 - includes/session/SessionManager.php | 5 - includes/specials/SpecialChangeEmail.php | 1 - includes/specials/SpecialUserrights.php | 3 - includes/user/User.php | 18 +- languages/i18n/en.json | 5 - languages/i18n/qqq.json | 5 - tests/common/TestSetup.php | 3 +- tests/phpunit/includes/api/ApiTestCase.php | 1 - .../phpunit/includes/auth/AuthManagerTest.php | 13 - ...luginPrimaryAuthenticationProviderTest.php | 716 ------------------ 22 files changed, 20 insertions(+), 1854 deletions(-) delete mode 100644 includes/AuthPlugin.php delete mode 100644 includes/auth/AuthManagerAuthPlugin.php delete mode 100644 includes/auth/AuthManagerAuthPluginUser.php delete mode 100644 includes/auth/AuthPluginPrimaryAuthenticationProvider.php delete mode 100644 tests/phpunit/includes/auth/AuthPluginPrimaryAuthenticationProviderTest.php diff --git a/.phpcs.xml b/.phpcs.xml index 784fefc754..b877c96647 100644 --- a/.phpcs.xml +++ b/.phpcs.xml @@ -13,7 +13,6 @@ - @@ -214,7 +213,6 @@ */includes/api/ApiMessage\.php */includes/api/ApiOpenSearch\.php */includes/api/ApiRsd\.php - */includes/AuthPlugin\.php */includes/cache/CacheDependency\.php */includes/compat/XMPReader\.php */includes/diff/DairikiDiff\.php diff --git a/RELEASE-NOTES-1.33 b/RELEASE-NOTES-1.33 index c3edc6061b..cd2d78a0b3 100644 --- a/RELEASE-NOTES-1.33 +++ b/RELEASE-NOTES-1.33 @@ -41,6 +41,8 @@ production. set `$wgParserCacheType = CACHE_NONE;` instead. * $wgCommentTableSchemaMigrationStage has been removed. Extension code finding it unset should treat it as being MIGRATION_NEW. +* $wgAuth – This old setting, deprecated in 1.27, has been removed as part of + the removal of AuthPlugin. === New features in 1.33 === * (T96041) __EXPECTUNUSEDCATEGORY__ on a category page causes the category @@ -269,6 +271,13 @@ because of Phabricator reports. has been removed. * The 'jquery.xmldom' module has been removed. * The 'jquery.mockjax' module has been removed. +* AuthPlugin and related code, deprecated in 1.27, has been removed. Extensions + should instead use AuthManager. The following no longer exist: + * The AuthPlugin class itself and the related AuthPluginUser class and i18n + * The AuthPluginSetup and AuthPluginAutoCreate hooks + * The transitional wrapper classes AuthPluginPrimaryAuthenticationProvider, + AuthManagerAuthPlugin, and AuthManagerAuthPluginUser. + * The $wgAuth configuration setting and its use in Setup.php and unit tests === Deprecations in 1.33 === * The configuration option $wgUseESI has been deprecated, and is expected diff --git a/autoload.php b/autoload.php index 405d35e695..fab10fe5d2 100644 --- a/autoload.php +++ b/autoload.php @@ -166,8 +166,6 @@ $wgAutoloadLocalClasses = [ 'AttachLatest' => __DIR__ . '/maintenance/attachLatest.php', 'AugmentPageProps' => __DIR__ . '/includes/search/AugmentPageProps.php', 'AuthManagerSpecialPage' => __DIR__ . '/includes/specialpage/AuthManagerSpecialPage.php', - 'AuthPlugin' => __DIR__ . '/includes/AuthPlugin.php', - 'AuthPluginUser' => __DIR__ . '/includes/AuthPlugin.php', 'AutoCommitUpdate' => __DIR__ . '/includes/deferred/AutoCommitUpdate.php', 'AutoLoader' => __DIR__ . '/includes/AutoLoader.php', 'AutoloadGenerator' => __DIR__ . '/includes/utils/AutoloadGenerator.php', diff --git a/docs/hooks.txt b/docs/hooks.txt index e52914d92c..ae4a4dce90 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -787,16 +787,6 @@ $extraData: An array (string => string) with extra information, intended to be added to log contexts. Fields it might include: - appId: the application ID, only if the login was with a bot password -'AuthPluginAutoCreate': DEPRECATED since 1.27! Use the 'LocalUserCreated' hook -instead. Called when creating a local account for an user logged in from an -external authentication method. -$user: User object created locally - -'AuthPluginSetup': DEPRECATED since 1.27! Extensions should be updated to use -AuthManager. Update or replace authentication plugin object ($wgAuth). Gives a -chance for an extension to set it programmatically to a variable class. -&$auth: the $wgAuth object, probably a stub - 'AutopromoteCondition': Check autopromote condition for user. $type: condition type $args: arguments diff --git a/includes/AuthPlugin.php b/includes/AuthPlugin.php deleted file mode 100644 index e12db24319..0000000000 --- a/includes/AuthPlugin.php +++ /dev/null @@ -1,364 +0,0 @@ - - * https://www.mediawiki.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - */ - -/** - * Authentication plugin interface. Instantiate a subclass of AuthPlugin - * and set $wgAuth to it to authenticate against some external tool. - * - * The default behavior is not to do anything, and use the local user - * database for all authentication. A subclass can require that all - * accounts authenticate externally, or use it only as a fallback; also - * you can transparently create internal wiki accounts the first time - * someone logs in who can be authenticated externally. - * - * @deprecated since 1.27 - */ -class AuthPlugin { - /** - * @var string - */ - protected $domain; - - /** - * Check whether there exists a user account with the given name. - * The name will be normalized to MediaWiki's requirements, so - * you might need to munge it (for instance, for lowercase initial - * letters). - * - * @param string $username Username. - * @return bool - */ - public function userExists( $username ) { - # Override this! - return false; - } - - /** - * Check if a username+password pair is a valid login. - * The name will be normalized to MediaWiki's requirements, so - * you might need to munge it (for instance, for lowercase initial - * letters). - * - * @param string $username Username. - * @param string $password User password. - * @return bool - */ - public function authenticate( $username, $password ) { - # Override this! - return false; - } - - /** - * Modify options in the login template. - * - * @param BaseTemplate &$template - * @param string &$type 'signup' or 'login'. Added in 1.16. - */ - public function modifyUITemplate( &$template, &$type ) { - # Override this! - $template->set( 'usedomain', false ); - } - - /** - * Set the domain this plugin is supposed to use when authenticating. - * - * @param string $domain Authentication domain. - */ - public function setDomain( $domain ) { - $this->domain = $domain; - } - - /** - * Get the user's domain - * - * @return string - */ - public function getDomain() { - return $this->domain ?? 'invaliddomain'; - } - - /** - * Check to see if the specific domain is a valid domain. - * - * @param string $domain Authentication domain. - * @return bool - */ - public function validDomain( $domain ) { - # Override this! - return true; - } - - /** - * When a user logs in, optionally fill in preferences and such. - * For instance, you might pull the email address or real name from the - * external user database. - * - * The User object is passed by reference so it can be modified; don't - * forget the & on your function declaration. - * - * @deprecated since 1.26, use the UserLoggedIn hook instead. And assigning - * a different User object to $user is no longer supported. - * @param User &$user - * @return bool - */ - public function updateUser( &$user ) { - # Override this and do something - return true; - } - - /** - * Return true if the wiki should create a new local account automatically - * when asked to login a user who doesn't exist locally but does in the - * external auth database. - * - * If you don't automatically create accounts, you must still create - * accounts in some way. It's not possible to authenticate without - * a local account. - * - * This is just a question, and shouldn't perform any actions. - * - * @return bool - */ - public function autoCreate() { - return false; - } - - /** - * Allow a property change? Properties are the same as preferences - * and use the same keys. 'Realname' 'Emailaddress' and 'Nickname' - * all reference this. - * - * @param string $prop - * - * @return bool - */ - public function allowPropChange( $prop = '' ) { - if ( $prop == 'realname' && is_callable( [ $this, 'allowRealNameChange' ] ) ) { - return $this->allowRealNameChange(); - } elseif ( $prop == 'emailaddress' && is_callable( [ $this, 'allowEmailChange' ] ) ) { - return $this->allowEmailChange(); - } elseif ( $prop == 'nickname' && is_callable( [ $this, 'allowNickChange' ] ) ) { - return $this->allowNickChange(); - } else { - return true; - } - } - - /** - * Can users change their passwords? - * - * @return bool - */ - public function allowPasswordChange() { - return true; - } - - /** - * Should MediaWiki store passwords in its local database? - * - * @return bool - */ - public function allowSetLocalPassword() { - return true; - } - - /** - * Set the given password in the authentication database. - * As a special case, the password may be set to null to request - * locking the password to an unusable value, with the expectation - * that it will be set later through a mail reset or other method. - * - * Return true if successful. - * - * @param User $user - * @param string $password Password. - * @return bool - */ - public function setPassword( $user, $password ) { - return true; - } - - /** - * Update user information in the external authentication database. - * Return true if successful. - * - * @deprecated since 1.26, use the UserSaveSettings hook instead. - * @param User $user - * @return bool - */ - public function updateExternalDB( $user ) { - return true; - } - - /** - * Update user groups in the external authentication database. - * Return true if successful. - * - * @deprecated since 1.26, use the UserGroupsChanged hook instead. - * @param User $user - * @param array $addgroups Groups to add. - * @param array $delgroups Groups to remove. - * @return bool - */ - public function updateExternalDBGroups( $user, $addgroups, $delgroups = [] ) { - return true; - } - - /** - * Check to see if external accounts can be created. - * Return true if external accounts can be created. - * @return bool - */ - public function canCreateAccounts() { - return false; - } - - /** - * Add a user to the external authentication database. - * Return true if successful. - * - * @param User $user Only the name should be assumed valid at this point - * @param string $password - * @param string $email - * @param string $realname - * @return bool - */ - public function addUser( $user, $password, $email = '', $realname = '' ) { - return true; - } - - /** - * Return true to prevent logins that don't authenticate here from being - * checked against the local database's password fields. - * - * This is just a question, and shouldn't perform any actions. - * - * @return bool - */ - public function strict() { - return false; - } - - /** - * Check if a user should authenticate locally if the global authentication fails. - * If either this or strict() returns true, local authentication is not used. - * - * @param string $username Username. - * @return bool - */ - public function strictUserAuth( $username ) { - return false; - } - - /** - * When creating a user account, optionally fill in preferences and such. - * For instance, you might pull the email address or real name from the - * external user database. - * - * The User object is passed by reference so it can be modified; don't - * forget the & on your function declaration. - * - * @deprecated since 1.26, use the UserLoggedIn hook instead. And assigning - * a different User object to $user is no longer supported. - * @param User &$user - * @param bool $autocreate True if user is being autocreated on login - */ - public function initUser( &$user, $autocreate = false ) { - # Override this to do something. - } - - /** - * If you want to munge the case of an account name before the final - * check, now is your chance. - * @param string $username - * @return string - */ - public function getCanonicalName( $username ) { - return $username; - } - - /** - * Get an instance of a User object - * - * @param User &$user - * - * @return AuthPluginUser - */ - public function getUserInstance( User &$user ) { - return new AuthPluginUser( $user ); - } - - /** - * Get a list of domains (in HTMLForm options format) used. - * - * @return array - */ - public function domainList() { - return []; - } -} - -/** - * @deprecated since 1.27 - */ -class AuthPluginUser { - function __construct( $user ) { - # Override this! - } - - public function getId() { - # Override this! - return -1; - } - - /** - * Indicate whether the user is locked - * @deprecated since 1.26, use the UserIsLocked hook instead. - * @return bool - */ - public function isLocked() { - # Override this! - return false; - } - - /** - * Indicate whether the user is hidden - * @deprecated since 1.26, use the UserIsHidden hook instead. - * @return bool - */ - public function isHidden() { - # Override this! - return false; - } - - /** - * @deprecated since 1.28, use SessionManager::invalidateSessionForUser() instead. - * @return bool - */ - public function resetAuthToken() { - # Override this! - return true; - } -} diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index fb31249426..7d0f108c7c 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -7471,13 +7471,6 @@ $wgAutoloadAttemptLowercase = true; */ $wgExtensionCredits = []; -/** - * Authentication plugin. - * @var $wgAuth AuthPlugin - * @deprecated since 1.27 use $wgAuthManagerConfig instead - */ -$wgAuth = null; - /** * Global list of hooks. * diff --git a/includes/Setup.php b/includes/Setup.php index 0cf8b51de7..3f6a5b49e0 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -792,22 +792,6 @@ $wgContLang = MediaWikiServices::getInstance()->getContentLanguage(); // Now that variant lists may be available... $wgRequest->interpolateTitle(); -if ( !is_object( $wgAuth ) ) { - $wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin; - Hooks::run( 'AuthPluginSetup', [ &$wgAuth ] ); -} -if ( $wgAuth && !$wgAuth instanceof MediaWiki\Auth\AuthManagerAuthPlugin ) { - MediaWiki\Auth\AuthManager::singleton()->forcePrimaryAuthenticationProviders( [ - new MediaWiki\Auth\TemporaryPasswordPrimaryAuthenticationProvider( [ - 'authoritative' => false, - ] ), - new MediaWiki\Auth\AuthPluginPrimaryAuthenticationProvider( $wgAuth ), - new MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider( [ - 'authoritative' => true, - ] ), - ], '$wgAuth is ' . get_class( $wgAuth ) ); -} - /** * @var MediaWiki\Session\SessionId|null $wgInitialSessionId The persistent * session ID (if any) loaded at startup diff --git a/includes/auth/AuthManager.php b/includes/auth/AuthManager.php index f9174a78fc..946decf998 100644 --- a/includes/auth/AuthManager.php +++ b/includes/auth/AuthManager.php @@ -232,7 +232,9 @@ class AuthManager implements LoggerAwareInterface { } /** - * Call a legacy AuthPlugin method, if necessary + * This used to call a legacy AuthPlugin method, if necessary. Since that code has + * been removed, it now just returns the $return parameter. + * * @codeCoverageIgnore * @deprecated For backwards compatibility only, should be avoided in new code * @param string $method AuthPlugin method to call @@ -241,13 +243,8 @@ class AuthManager implements LoggerAwareInterface { * @return mixed Return value from the AuthPlugin method, or $return */ public static function callLegacyAuthPlugin( $method, array $params, $return = null ) { - global $wgAuth; - - if ( $wgAuth && !$wgAuth instanceof AuthManagerAuthPlugin ) { - return $wgAuth->$method( ...$params ); - } else { - return $return; - } + wfDeprecated( __METHOD__, '1.33' ); + return $return; } /** @@ -1745,7 +1742,6 @@ class AuthManager implements LoggerAwareInterface { // Inform the providers $this->callMethodOnProviders( 6, 'autoCreatedAccount', [ $user, $source ] ); - \Hooks::run( 'AuthPluginAutoCreate', [ $user ], '1.27' ); \Hooks::run( 'LocalUserCreated', [ $user, true ] ); $user->saveSettings(); diff --git a/includes/auth/AuthManagerAuthPlugin.php b/includes/auth/AuthManagerAuthPlugin.php deleted file mode 100644 index 008639c25a..0000000000 --- a/includes/auth/AuthManagerAuthPlugin.php +++ /dev/null @@ -1,197 +0,0 @@ -logger = \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' ); - } - - public function userExists( $name ) { - return AuthManager::singleton()->userExists( $name ); - } - - public function authenticate( $username, $password ) { - $data = [ - 'username' => $username, - 'password' => $password, - ]; - if ( $this->domain !== null && $this->domain !== '' ) { - $data['domain'] = $this->domain; - } - $reqs = AuthManager::singleton()->getAuthenticationRequests( AuthManager::ACTION_LOGIN ); - $reqs = AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data ); - - $res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' ); - switch ( $res->status ) { - case AuthenticationResponse::PASS: - return true; - case AuthenticationResponse::FAIL: - // Hope it's not a PreAuthenticationProvider that failed... - $msg = $res->message instanceof \Message ? $res->message : new \Message( $res->message ); - $this->logger->info( __METHOD__ . ': Authentication failed: ' . $msg->plain() ); - return false; - default: - throw new \BadMethodCallException( - 'AuthManager does not support such simplified authentication' - ); - } - } - - public function modifyUITemplate( &$template, &$type ) { - // AuthManager does not support direct UI screwing-around-with - } - - public function setDomain( $domain ) { - $this->domain = $domain; - } - - public function getDomain() { - return $this->domain ?? 'invaliddomain'; - } - - public function validDomain( $domain ) { - $domainList = $this->domainList(); - return $domainList ? in_array( $domain, $domainList, true ) : $domain === ''; - } - - public function updateUser( &$user ) { - \Hooks::run( 'UserLoggedIn', [ $user ] ); - return true; - } - - public function autoCreate() { - return true; - } - - public function allowPropChange( $prop = '' ) { - return AuthManager::singleton()->allowsPropertyChange( $prop ); - } - - public function allowPasswordChange() { - $reqs = AuthManager::singleton()->getAuthenticationRequests( AuthManager::ACTION_CHANGE ); - foreach ( $reqs as $req ) { - if ( $req instanceof PasswordAuthenticationRequest ) { - return true; - } - } - - return false; - } - - public function allowSetLocalPassword() { - // There should be a PrimaryAuthenticationProvider that does this, if necessary - return false; - } - - public function setPassword( $user, $password ) { - $data = [ - 'username' => $user->getName(), - 'password' => $password, - ]; - if ( $this->domain !== null && $this->domain !== '' ) { - $data['domain'] = $this->domain; - } - $reqs = AuthManager::singleton()->getAuthenticationRequests( AuthManager::ACTION_CHANGE ); - $reqs = AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data ); - foreach ( $reqs as $req ) { - $status = AuthManager::singleton()->allowsAuthenticationDataChange( $req ); - if ( !$status->isGood() ) { - $this->logger->info( __METHOD__ . ': Password change rejected: {reason}', [ - 'username' => $data['username'], - 'reason' => $status->getWikiText( null, null, 'en' ), - ] ); - return false; - } - } - foreach ( $reqs as $req ) { - AuthManager::singleton()->changeAuthenticationData( $req ); - } - return true; - } - - public function updateExternalDB( $user ) { - // This fires the necessary hook - $user->saveSettings(); - return true; - } - - public function updateExternalDBGroups( $user, $addgroups, $delgroups = [] ) { - throw new \BadMethodCallException( - 'Update of user groups via AuthPlugin is not supported with AuthManager.' - ); - } - - public function canCreateAccounts() { - return AuthManager::singleton()->canCreateAccounts(); - } - - public function addUser( $user, $password, $email = '', $realname = '' ) { - throw new \BadMethodCallException( - 'Creation of users via AuthPlugin is not supported with ' - . 'AuthManager. Generally, user creation should be left to either ' - . 'Special:CreateAccount, auto-creation when triggered by a ' - . 'SessionProvider or PrimaryAuthenticationProvider, or ' - . 'User::newSystemUser().' - ); - } - - public function strict() { - // There should be a PrimaryAuthenticationProvider that does this, if necessary - return true; - } - - public function strictUserAuth( $username ) { - // There should be a PrimaryAuthenticationProvider that does this, if necessary - return true; - } - - public function initUser( &$user, $autocreate = false ) { - \Hooks::run( 'LocalUserCreated', [ $user, $autocreate ] ); - } - - public function getCanonicalName( $username ) { - // AuthManager doesn't support restrictions beyond MediaWiki's - return $username; - } - - public function getUserInstance( User &$user ) { - return new AuthManagerAuthPluginUser( $user ); - } - - public function domainList() { - return []; - } -} diff --git a/includes/auth/AuthManagerAuthPluginUser.php b/includes/auth/AuthManagerAuthPluginUser.php deleted file mode 100644 index e31be6019d..0000000000 --- a/includes/auth/AuthManagerAuthPluginUser.php +++ /dev/null @@ -1,53 +0,0 @@ -user = $user; - } - - public function getId() { - return $this->user->getId(); - } - - public function isLocked() { - return $this->user->isLocked(); - } - - public function isHidden() { - return $this->user->isHidden(); - } - - public function resetAuthToken() { - \MediaWiki\Session\SessionManager::singleton()->invalidateSessionsForUser( $this->user ); - return true; - } -} diff --git a/includes/auth/AuthPluginPrimaryAuthenticationProvider.php b/includes/auth/AuthPluginPrimaryAuthenticationProvider.php deleted file mode 100644 index cd0734d847..0000000000 --- a/includes/auth/AuthPluginPrimaryAuthenticationProvider.php +++ /dev/null @@ -1,429 +0,0 @@ -domainList() returns - * more than one domain, this must be a PasswordDomainAuthenticationRequest. - */ - public function __construct( AuthPlugin $auth, $requestType = null ) { - parent::__construct(); - - if ( $auth instanceof AuthManagerAuthPlugin ) { - throw new \InvalidArgumentException( - 'Trying to wrap AuthManagerAuthPlugin in AuthPluginPrimaryAuthenticationProvider ' . - 'makes no sense.' - ); - } - - $need = count( $auth->domainList() ) > 1 - ? PasswordDomainAuthenticationRequest::class - : PasswordAuthenticationRequest::class; - if ( $requestType === null ) { - $requestType = $need; - } elseif ( $requestType !== $need && !is_subclass_of( $requestType, $need ) ) { - throw new \InvalidArgumentException( "$requestType is not a $need" ); - } - - $this->auth = $auth; - $this->requestType = $requestType; - $this->hasDomain = ( - $requestType === PasswordDomainAuthenticationRequest::class || - is_subclass_of( $requestType, PasswordDomainAuthenticationRequest::class ) - ); - $this->authoritative = $auth->strict(); - - // Registering hooks from core is unusual, but is needed here to be - // able to call the AuthPlugin methods those hooks replace. - \Hooks::register( 'UserSaveSettings', [ $this, 'onUserSaveSettings' ] ); - \Hooks::register( 'UserGroupsChanged', [ $this, 'onUserGroupsChanged' ] ); - \Hooks::register( 'UserLoggedIn', [ $this, 'onUserLoggedIn' ] ); - \Hooks::register( 'LocalUserCreated', [ $this, 'onLocalUserCreated' ] ); - } - - /** - * Create an appropriate AuthenticationRequest - * @return PasswordAuthenticationRequest - */ - protected function makeAuthReq() { - $class = $this->requestType; - if ( $this->hasDomain ) { - return new $class( $this->auth->domainList() ); - } else { - return new $class(); - } - } - - /** - * Call $this->auth->setDomain() - * @param PasswordAuthenticationRequest $req - */ - protected function setDomain( $req ) { - if ( $this->hasDomain ) { - $domain = $req->domain; - } else { - // Just grab the first one. - $domainList = $this->auth->domainList(); - $domain = reset( $domainList ); - } - - // Special:UserLogin does this. Strange. - if ( !$this->auth->validDomain( $domain ) ) { - $domain = $this->auth->getDomain(); - } - $this->auth->setDomain( $domain ); - } - - /** - * Hook function to call AuthPlugin::updateExternalDB() - * @param User $user - * @codeCoverageIgnore - */ - public function onUserSaveSettings( $user ) { - // No way to know the domain, just hope the provider handles that. - $this->auth->updateExternalDB( $user ); - } - - /** - * Hook function to call AuthPlugin::updateExternalDBGroups() - * @param User $user - * @param array $added - * @param array $removed - */ - public function onUserGroupsChanged( $user, $added, $removed ) { - // No way to know the domain, just hope the provider handles that. - $this->auth->updateExternalDBGroups( $user, $added, $removed ); - } - - /** - * Hook function to call AuthPlugin::updateUser() - * @param User $user - */ - public function onUserLoggedIn( $user ) { - $hookUser = $user; - // No way to know the domain, just hope the provider handles that. - $this->auth->updateUser( $hookUser ); - if ( $hookUser !== $user ) { - throw new \UnexpectedValueException( - get_class( $this->auth ) . '::updateUser() tried to replace $user!' - ); - } - } - - /** - * Hook function to call AuthPlugin::initUser() - * @param User $user - * @param bool $autocreated - */ - public function onLocalUserCreated( $user, $autocreated ) { - // For $autocreated, see self::autoCreatedAccount() - if ( !$autocreated ) { - $hookUser = $user; - // No way to know the domain, just hope the provider handles that. - $this->auth->initUser( $hookUser, $autocreated ); - if ( $hookUser !== $user ) { - throw new \UnexpectedValueException( - get_class( $this->auth ) . '::initUser() tried to replace $user!' - ); - } - } - } - - public function getUniqueId() { - return parent::getUniqueId() . ':' . get_class( $this->auth ); - } - - public function getAuthenticationRequests( $action, array $options ) { - switch ( $action ) { - case AuthManager::ACTION_LOGIN: - case AuthManager::ACTION_CREATE: - return [ $this->makeAuthReq() ]; - - case AuthManager::ACTION_CHANGE: - case AuthManager::ACTION_REMOVE: - // No way to know the domain, just hope the provider handles that. - return $this->auth->allowPasswordChange() ? [ $this->makeAuthReq() ] : []; - - default: - return []; - } - } - - public function beginPrimaryAuthentication( array $reqs ) { - $req = AuthenticationRequest::getRequestByClass( $reqs, $this->requestType ); - if ( !$req || $req->username === null || $req->password === null || - ( $this->hasDomain && $req->domain === null ) - ) { - return AuthenticationResponse::newAbstain(); - } - - $username = User::getCanonicalName( $req->username, 'usable' ); - if ( $username === false ) { - return AuthenticationResponse::newAbstain(); - } - - $this->setDomain( $req ); - if ( $this->testUserCanAuthenticateInternal( User::newFromName( $username ) ) && - $this->auth->authenticate( $username, $req->password ) - ) { - return AuthenticationResponse::newPass( $username ); - } else { - $this->authoritative = $this->auth->strict() || $this->auth->strictUserAuth( $username ); - return $this->failResponse( $req ); - } - } - - public function testUserCanAuthenticate( $username ) { - $username = User::getCanonicalName( $username, 'usable' ); - if ( $username === false ) { - return false; - } - - // We have to check every domain, because at least LdapAuthentication - // interprets AuthPlugin::userExists() as applying only to the current - // domain. - $curDomain = $this->auth->getDomain(); - $domains = $this->auth->domainList() ?: [ '' ]; - foreach ( $domains as $domain ) { - $this->auth->setDomain( $domain ); - if ( $this->testUserCanAuthenticateInternal( User::newFromName( $username ) ) ) { - $this->auth->setDomain( $curDomain ); - return true; - } - } - $this->auth->setDomain( $curDomain ); - return false; - } - - /** - * @see self::testUserCanAuthenticate - * @note The caller is responsible for calling $this->auth->setDomain() - * @param User $user - * @return bool - */ - private function testUserCanAuthenticateInternal( $user ) { - if ( $this->auth->userExists( $user->getName() ) ) { - return !$this->auth->getUserInstance( $user )->isLocked(); - } else { - return false; - } - } - - public function providerRevokeAccessForUser( $username ) { - $username = User::getCanonicalName( $username, 'usable' ); - if ( $username === false ) { - return; - } - $user = User::newFromName( $username ); - if ( $user ) { - // Reset the password on every domain. - $curDomain = $this->auth->getDomain(); - $domains = $this->auth->domainList() ?: [ '' ]; - $failed = []; - foreach ( $domains as $domain ) { - $this->auth->setDomain( $domain ); - if ( $this->testUserCanAuthenticateInternal( $user ) && - !$this->auth->setPassword( $user, null ) - ) { - $failed[] = $domain === '' ? '(default)' : $domain; - } - } - $this->auth->setDomain( $curDomain ); - if ( $failed ) { - throw new \UnexpectedValueException( - "AuthPlugin failed to reset password for $username in the following domains: " - . implode( ' ', $failed ) - ); - } - } - } - - public function testUserExists( $username, $flags = User::READ_NORMAL ) { - $username = User::getCanonicalName( $username, 'usable' ); - if ( $username === false ) { - return false; - } - - // We have to check every domain, because at least LdapAuthentication - // interprets AuthPlugin::userExists() as applying only to the current - // domain. - $curDomain = $this->auth->getDomain(); - $domains = $this->auth->domainList() ?: [ '' ]; - foreach ( $domains as $domain ) { - $this->auth->setDomain( $domain ); - if ( $this->auth->userExists( $username ) ) { - $this->auth->setDomain( $curDomain ); - return true; - } - } - $this->auth->setDomain( $curDomain ); - return false; - } - - public function providerAllowsPropertyChange( $property ) { - // No way to know the domain, just hope the provider handles that. - return $this->auth->allowPropChange( $property ); - } - - public function providerAllowsAuthenticationDataChange( - AuthenticationRequest $req, $checkData = true - ) { - if ( get_class( $req ) !== $this->requestType ) { - return \StatusValue::newGood( 'ignored' ); - } - - // Hope it works, AuthPlugin gives us no way to do this. - $curDomain = $this->auth->getDomain(); - $this->setDomain( $req ); - try { - // If !$checkData the domain might be wrong. Nothing we can do about that. - if ( !$this->auth->allowPasswordChange() ) { - return \StatusValue::newFatal( 'authmanager-authplugin-setpass-denied' ); - } - - if ( !$checkData ) { - return \StatusValue::newGood(); - } - - if ( $this->hasDomain ) { - if ( $req->domain === null ) { - return \StatusValue::newGood( 'ignored' ); - } - if ( !$this->auth->validDomain( $req->domain ) ) { - return \StatusValue::newFatal( 'authmanager-authplugin-setpass-bad-domain' ); - } - } - - $username = User::getCanonicalName( $req->username, 'usable' ); - if ( $username !== false ) { - $sv = \StatusValue::newGood(); - if ( $req->password !== null ) { - if ( $req->password !== $req->retype ) { - $sv->fatal( 'badretype' ); - } else { - $sv->merge( $this->checkPasswordValidity( $username, $req->password ) ); - } - } - return $sv; - } else { - return \StatusValue::newGood( 'ignored' ); - } - } finally { - $this->auth->setDomain( $curDomain ); - } - } - - public function providerChangeAuthenticationData( AuthenticationRequest $req ) { - if ( get_class( $req ) === $this->requestType ) { - $username = $req->username !== null ? User::getCanonicalName( $req->username, 'usable' ) : false; - if ( $username === false ) { - return; - } - - if ( $this->hasDomain && $req->domain === null ) { - return; - } - - $this->setDomain( $req ); - $user = User::newFromName( $username ); - if ( !$this->auth->setPassword( $user, $req->password ) ) { - // This is totally unfriendly and leaves other - // AuthenticationProviders in an uncertain state, but what else - // can we do? - throw new \ErrorPageError( - 'authmanager-authplugin-setpass-failed-title', - 'authmanager-authplugin-setpass-failed-message' - ); - } - } - } - - public function accountCreationType() { - // No way to know the domain, just hope the provider handles that. - return $this->auth->canCreateAccounts() ? self::TYPE_CREATE : self::TYPE_NONE; - } - - public function testForAccountCreation( $user, $creator, array $reqs ) { - return \StatusValue::newGood(); - } - - public function beginPrimaryAccountCreation( $user, $creator, array $reqs ) { - if ( $this->accountCreationType() === self::TYPE_NONE ) { - throw new \BadMethodCallException( 'Shouldn\'t call this when accountCreationType() is NONE' ); - } - - $req = AuthenticationRequest::getRequestByClass( $reqs, $this->requestType ); - if ( !$req || $req->username === null || $req->password === null || - ( $this->hasDomain && $req->domain === null ) - ) { - return AuthenticationResponse::newAbstain(); - } - - $username = User::getCanonicalName( $req->username, 'usable' ); - if ( $username === false ) { - return AuthenticationResponse::newAbstain(); - } - - $this->setDomain( $req ); - if ( $this->auth->addUser( - $user, $req->password, $user->getEmail(), $user->getRealName() - ) ) { - return AuthenticationResponse::newPass(); - } else { - return AuthenticationResponse::newFail( - new \Message( 'authmanager-authplugin-create-fail' ) - ); - } - } - - public function autoCreatedAccount( $user, $source ) { - $hookUser = $user; - // No way to know the domain, just hope the provider handles that. - $this->auth->initUser( $hookUser, true ); - if ( $hookUser !== $user ) { - throw new \UnexpectedValueException( - get_class( $this->auth ) . '::initUser() tried to replace $user!' - ); - } - } -} diff --git a/includes/preferences/DefaultPreferencesFactory.php b/includes/preferences/DefaultPreferencesFactory.php index e012c710d6..4f50330b11 100644 --- a/includes/preferences/DefaultPreferencesFactory.php +++ b/includes/preferences/DefaultPreferencesFactory.php @@ -1571,7 +1571,6 @@ class DefaultPreferencesFactory implements PreferencesFactory { ); } - AuthManager::callLegacyAuthPlugin( 'updateExternalDB', [ $user ] ); $user->saveSettings(); return $result; diff --git a/includes/session/SessionManager.php b/includes/session/SessionManager.php index 385cc35d76..98c04995a3 100644 --- a/includes/session/SessionManager.php +++ b/includes/session/SessionManager.php @@ -314,11 +314,6 @@ final class SessionManager implements SessionManagerInterface { $user->setToken(); $user->saveSettings(); - $authUser = \MediaWiki\Auth\AuthManager::callLegacyAuthPlugin( 'getUserInstance', [ &$user ] ); - if ( $authUser ) { - $authUser->resetAuthToken(); - } - foreach ( $this->getProviders() as $provider ) { $provider->invalidateSessionsForUser( $user ); } diff --git a/includes/specials/SpecialChangeEmail.php b/includes/specials/SpecialChangeEmail.php index 8cf64b1370..8d5cf85dce 100644 --- a/includes/specials/SpecialChangeEmail.php +++ b/includes/specials/SpecialChangeEmail.php @@ -177,7 +177,6 @@ class SpecialChangeEmail extends FormSpecialPage { Hooks::run( 'PrefsEmailAudit', [ $user, $oldaddr, $newaddr ] ); $user->saveSettings(); - MediaWiki\Auth\AuthManager::callLegacyAuthPlugin( 'updateExternalDB', [ $user ] ); return $status; } diff --git a/includes/specials/SpecialUserrights.php b/includes/specials/SpecialUserrights.php index 6e6d90595f..540754f923 100644 --- a/includes/specials/SpecialUserrights.php +++ b/includes/specials/SpecialUserrights.php @@ -387,9 +387,6 @@ class UserrightsPage extends SpecialPage { // update groups in external authentication database Hooks::run( 'UserGroupsChanged', [ $user, $add, $remove, $this->getUser(), $reason, $oldUGMs, $newUGMs ] ); - MediaWiki\Auth\AuthManager::callLegacyAuthPlugin( - 'updateExternalDBGroups', [ $user, $add, $remove ] - ); wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) . "\n" ); wfDebug( 'newGroups: ' . print_r( $newGroups, true ) . "\n" ); diff --git a/includes/user/User.php b/includes/user/User.php index 904a934308..1e3ecf2136 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -1258,10 +1258,7 @@ class User implements IDBAccessObject, UserIdentity { return false; } - // Reject various classes of invalid names - $name = AuthManager::callLegacyAuthPlugin( - 'getCanonicalName', [ $t->getText() ], $t->getText() - ); + $name = $t->getText(); switch ( $validate ) { case false: @@ -1667,7 +1664,6 @@ class User implements IDBAccessObject, UserIdentity { // update groups in external authentication database Hooks::run( 'UserGroupsChanged', [ $this, $toPromote, [], false, false, $oldUGMs, $newUGMs ] ); - AuthManager::callLegacyAuthPlugin( 'updateExternalDBGroups', [ $this, $toPromote ] ); $logEntry = new ManualLogEntry( 'rights', 'autopromote' ); $logEntry->setPerformer( $this ); @@ -2407,10 +2403,8 @@ class User implements IDBAccessObject, UserIdentity { if ( $this->mLocked !== null ) { return $this->mLocked; } - // Avoid PHP 7.1 warning of passing $this by reference - $user = $this; - $authUser = AuthManager::callLegacyAuthPlugin( 'getUserInstance', [ &$user ], null ); - $this->mLocked = $authUser && $authUser->isLocked(); + // Reset for hook + $this->mLocked = false; Hooks::run( 'UserIsLocked', [ $this, &$this->mLocked ] ); return $this->mLocked; } @@ -2426,10 +2420,8 @@ class User implements IDBAccessObject, UserIdentity { } $this->getBlockedStatus(); if ( !$this->mHideName ) { - // Avoid PHP 7.1 warning of passing $this by reference - $user = $this; - $authUser = AuthManager::callLegacyAuthPlugin( 'getUserInstance', [ &$user ], null ); - $this->mHideName = $authUser && $authUser->isHidden(); + // Reset for hook + $this->mHideName = false; Hooks::run( 'UserIsHidden', [ $this, &$this->mHideName ] ); } return (bool)$this->mHideName; diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 8700cecb29..68fce22ff8 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -4083,11 +4083,6 @@ "authmanager-create-no-primary": "The supplied credentials could not be used for account creation.", "authmanager-link-no-primary": "The supplied credentials could not be used for account linking.", "authmanager-link-not-in-progress": "Account linking is not in progress or session data has been lost. Please start again from the beginning.", - "authmanager-authplugin-setpass-failed-title": "Password change failed", - "authmanager-authplugin-setpass-failed-message": "The authentication plugin denied the password change.", - "authmanager-authplugin-create-fail": "The authentication plugin denied the account creation.", - "authmanager-authplugin-setpass-denied": "The authentication plugin does not allow changing passwords.", - "authmanager-authplugin-setpass-bad-domain": "Invalid domain.", "authmanager-autocreate-noperm": "Automatic account creation is not allowed.", "authmanager-autocreate-exception": "Automatic account creation temporarily disabled due to prior errors.", "authmanager-userdoesnotexist": "User account \"$1\" is not registered.", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 06ba4bfe9a..91d4443264 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -4289,11 +4289,6 @@ "authmanager-create-no-primary": "Error message when no AuthenticationProvider handles the AuthenticationRequests for account creation. This might mean the user needs to fill out all the form fields.", "authmanager-link-no-primary": "Error message when no AuthenticationProvider handles the AuthenticationRequests for account linking. This might mean the user needs to fill out all the form fields.", "authmanager-link-not-in-progress": "Error message when AuthManager session data is lost during account linking, or the user hits the \"continue\" endpoint without an active account link attempt.", - "authmanager-authplugin-setpass-failed-title": "Title of error page from AuthManager if AuthPlugin returns false from its setPassword() method.", - "authmanager-authplugin-setpass-failed-message": "Text of error page from AuthManager if AuthPlugin returns false from its setPassword() method.", - "authmanager-authplugin-create-fail": "Error message from AuthManager if the AuthPlugin returns false from its addUser() method.", - "authmanager-authplugin-setpass-denied": "Error message from AuthManager if the AuthPlugin returns false from its allowPasswordChange() method.", - "authmanager-authplugin-setpass-bad-domain": "Error message from AuthManager if the AuthPlugin rejects the passed domain.", "authmanager-autocreate-noperm": "Error message when auto-creation fails due to lack of permission.", "authmanager-autocreate-exception": "Error message when auto-creation fails because we tried recently and an exception was thrown, so we're not going to try again yet.", "authmanager-userdoesnotexist": "Error message when a user account does not exist. Parameters:\n* $1 - User name.", diff --git a/tests/common/TestSetup.php b/tests/common/TestSetup.php index 2feb438835..e24c4c5442 100644 --- a/tests/common/TestSetup.php +++ b/tests/common/TestSetup.php @@ -17,7 +17,7 @@ class TestSetup { global $wgDevelopmentWarnings; global $wgSessionProviders, $wgSessionPbkdf2Iterations; global $wgJobTypeConf; - global $wgAuthManagerConfig, $wgAuth; + global $wgAuthManagerConfig; // wfWarn should cause tests to fail $wgDevelopmentWarnings = true; @@ -87,7 +87,6 @@ class TestSetup { ], 'secondaryauth' => [], ]; - $wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin(); // T46192 Do not attempt to send a real e-mail Hooks::clear( 'AlternateUserMailer' ); diff --git a/tests/phpunit/includes/api/ApiTestCase.php b/tests/phpunit/includes/api/ApiTestCase.php index 9a27cf1176..43772070d5 100644 --- a/tests/phpunit/includes/api/ApiTestCase.php +++ b/tests/phpunit/includes/api/ApiTestCase.php @@ -26,7 +26,6 @@ abstract class ApiTestCase extends MediaWikiLangTestCase { ]; $this->setMwGlobals( [ - 'wgAuth' => new MediaWiki\Auth\AuthManagerAuthPlugin, 'wgRequest' => new FauxRequest( [] ), 'wgUser' => self::$users['sysop']->getUser(), ] ); diff --git a/tests/phpunit/includes/auth/AuthManagerTest.php b/tests/phpunit/includes/auth/AuthManagerTest.php index e8981ec24f..d5e18797cf 100644 --- a/tests/phpunit/includes/auth/AuthManagerTest.php +++ b/tests/phpunit/includes/auth/AuthManagerTest.php @@ -34,12 +34,6 @@ class AuthManagerTest extends \MediaWikiTestCase { /** @var TestingAccessWrapper */ protected $managerPriv; - protected function setUp() { - parent::setUp(); - - $this->setMwGlobals( [ 'wgAuth' => null ] ); - } - /** * Sets a mock on a hook * @param string $hook @@ -2352,8 +2346,6 @@ class AuthManagerTest extends \MediaWikiTestCase { } public function testAutoAccountCreation() { - global $wgHooks; - // PHPUnit seems to have a bug where it will call the ->with() // callbacks for our hooks again after the test is run (WTF?), which // breaks here because $username no longer matches $user by the end of @@ -2771,15 +2763,10 @@ class AuthManagerTest extends \MediaWikiTestCase { $session->clear(); $username = self::usernameForCreation(); $user = \User::newFromName( $username ); - $this->hook( 'AuthPluginAutoCreate', $this->once() ) - ->with( $callback ); - $this->hideDeprecated( 'AuthPluginAutoCreate hook (used in ' . - get_class( $wgHooks['AuthPluginAutoCreate'][0] ) . '::onAuthPluginAutoCreate)' ); $this->hook( 'LocalUserCreated', $this->once() ) ->with( $callback, $this->equalTo( true ) ); $ret = $this->manager->autoCreateUser( $user, AuthManager::AUTOCREATE_SOURCE_SESSION, true ); $this->unhook( 'LocalUserCreated' ); - $this->unhook( 'AuthPluginAutoCreate' ); $this->assertEquals( \Status::newGood(), $ret ); $this->assertNotEquals( 0, $user->getId() ); $this->assertEquals( $username, $user->getName() ); diff --git a/tests/phpunit/includes/auth/AuthPluginPrimaryAuthenticationProviderTest.php b/tests/phpunit/includes/auth/AuthPluginPrimaryAuthenticationProviderTest.php deleted file mode 100644 index 44e9799c12..0000000000 --- a/tests/phpunit/includes/auth/AuthPluginPrimaryAuthenticationProviderTest.php +++ /dev/null @@ -1,716 +0,0 @@ -fail( 'Expected exception not thrown' ); - } catch ( \InvalidArgumentException $ex ) { - $this->assertSame( - 'Trying to wrap AuthManagerAuthPlugin in AuthPluginPrimaryAuthenticationProvider ' . - 'makes no sense.', - $ex->getMessage() - ); - } - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - [ new PasswordAuthenticationRequest ], - $provider->getAuthenticationRequests( AuthManager::ACTION_LOGIN, [] ) - ); - - $req = $this->createMock( PasswordAuthenticationRequest::class ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin, get_class( $req ) ); - $this->assertEquals( - [ $req ], - $provider->getAuthenticationRequests( AuthManager::ACTION_LOGIN, [] ) - ); - - $reqType = get_class( $this->createMock( AuthenticationRequest::class ) ); - try { - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin, $reqType ); - $this->fail( 'Expected exception not thrown' ); - } catch ( \InvalidArgumentException $ex ) { - $this->assertSame( - "$reqType is not a MediaWiki\\Auth\\PasswordAuthenticationRequest", - $ex->getMessage() - ); - } - } - - public function testOnUserSaveSettings() { - $user = \User::newFromName( 'UTSysop' ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'updateExternalDB' ) - ->with( $this->identicalTo( $user ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - \Hooks::run( 'UserSaveSettings', [ $user ] ); - } - - public function testOnUserGroupsChanged() { - $user = \User::newFromName( 'UTSysop' ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'updateExternalDBGroups' ) - ->with( - $this->identicalTo( $user ), - $this->identicalTo( [ 'added' ] ), - $this->identicalTo( [ 'removed' ] ) - ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - \Hooks::run( 'UserGroupsChanged', [ $user, [ 'added' ], [ 'removed' ], false, false, [], [] ] ); - } - - public function testOnUserLoggedIn() { - $user = \User::newFromName( 'UTSysop' ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->exactly( 2 ) )->method( 'updateUser' ) - ->with( $this->identicalTo( $user ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - \Hooks::run( 'UserLoggedIn', [ $user ] ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'updateUser' ) - ->will( $this->returnCallback( function ( &$user ) { - $user = \User::newFromName( 'UTSysop' ); - } ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - try { - \Hooks::run( 'UserLoggedIn', [ $user ] ); - $this->fail( 'Expected exception not thrown' ); - } catch ( \UnexpectedValueException $ex ) { - $this->assertSame( - get_class( $plugin ) . '::updateUser() tried to replace $user!', - $ex->getMessage() - ); - } - } - - public function testOnLocalUserCreated() { - $user = \User::newFromName( 'UTSysop' ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->exactly( 2 ) )->method( 'initUser' ) - ->with( $this->identicalTo( $user ), $this->identicalTo( false ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - \Hooks::run( 'LocalUserCreated', [ $user, false ] ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'initUser' ) - ->will( $this->returnCallback( function ( &$user ) { - $user = \User::newFromName( 'UTSysop' ); - } ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - try { - \Hooks::run( 'LocalUserCreated', [ $user, false ] ); - $this->fail( 'Expected exception not thrown' ); - } catch ( \UnexpectedValueException $ex ) { - $this->assertSame( - get_class( $plugin ) . '::initUser() tried to replace $user!', - $ex->getMessage() - ); - } - } - - public function testGetUniqueId() { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertSame( - 'MediaWiki\\Auth\\AuthPluginPrimaryAuthenticationProvider:' . get_class( $plugin ), - $provider->getUniqueId() - ); - } - - /** - * @dataProvider provideGetAuthenticationRequests - * @param string $action - * @param array $response - * @param bool $allowPasswordChange - */ - public function testGetAuthenticationRequests( $action, $response, $allowPasswordChange ) { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->any() )->method( 'allowPasswordChange' ) - ->will( $this->returnValue( $allowPasswordChange ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( $response, $provider->getAuthenticationRequests( $action, [] ) ); - } - - public static function provideGetAuthenticationRequests() { - $arr = [ new PasswordAuthenticationRequest() ]; - return [ - [ AuthManager::ACTION_LOGIN, $arr, true ], - [ AuthManager::ACTION_LOGIN, $arr, false ], - [ AuthManager::ACTION_CREATE, $arr, true ], - [ AuthManager::ACTION_CREATE, $arr, false ], - [ AuthManager::ACTION_LINK, [], true ], - [ AuthManager::ACTION_LINK, [], false ], - [ AuthManager::ACTION_CHANGE, $arr, true ], - [ AuthManager::ACTION_CHANGE, [], false ], - [ AuthManager::ACTION_REMOVE, $arr, true ], - [ AuthManager::ACTION_REMOVE, [], false ], - ]; - } - - public function testAuthentication() { - $req = new PasswordAuthenticationRequest(); - $req->action = AuthManager::ACTION_LOGIN; - $reqs = [ PasswordAuthenticationRequest::class => $req ]; - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'authenticate' ] ) - ->getMock(); - $plugin->expects( $this->never() )->method( 'authenticate' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAuthentication( [] ) - ); - - $req->username = 'foo'; - $req->password = null; - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAuthentication( $reqs ) - ); - - $req->username = null; - $req->password = 'bar'; - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAuthentication( $reqs ) - ); - - $req->username = 'foo'; - $req->password = 'bar'; - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'authenticate' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'authenticate' ) - ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - AuthenticationResponse::newPass( 'Foo', $req ), - $provider->beginPrimaryAuthentication( $reqs ) - ); - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'authenticate' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( false ) ); - $plugin->expects( $this->never() )->method( 'authenticate' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAuthentication( $reqs ) - ); - - $pluginUser = $this->getMockBuilder( \AuthPluginUser::class ) - ->setMethods( [ 'isLocked' ] ) - ->disableOriginalConstructor() - ->getMock(); - $pluginUser->expects( $this->once() )->method( 'isLocked' ) - ->will( $this->returnValue( true ) ); - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'getUserInstance', 'authenticate' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'getUserInstance' ) - ->will( $this->returnValue( $pluginUser ) ); - $plugin->expects( $this->never() )->method( 'authenticate' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAuthentication( $reqs ) - ); - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'authenticate' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'authenticate' ) - ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( false ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAuthentication( $reqs ) - ); - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'authenticate', 'strict' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'authenticate' ) - ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( false ) ); - $plugin->expects( $this->any() )->method( 'strict' )->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $ret = $provider->beginPrimaryAuthentication( $reqs ); - $this->assertSame( AuthenticationResponse::FAIL, $ret->status ); - $this->assertSame( 'wrongpassword', $ret->message->getKey() ); - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'authenticate', 'strictUserAuth' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'authenticate' ) - ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( false ) ); - $plugin->expects( $this->any() )->method( 'strictUserAuth' ) - ->with( $this->equalTo( 'Foo' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $ret = $provider->beginPrimaryAuthentication( $reqs ); - $this->assertSame( AuthenticationResponse::FAIL, $ret->status ); - $this->assertSame( 'wrongpassword', $ret->message->getKey() ); - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'domainList', 'validDomain', 'setDomain', 'userExists', 'authenticate' ] ) - ->getMock(); - $plugin->expects( $this->any() )->method( 'domainList' ) - ->will( $this->returnValue( [ 'Domain1', 'Domain2' ] ) ); - $plugin->expects( $this->any() )->method( 'validDomain' ) - ->will( $this->returnCallback( function ( $domain ) { - return in_array( $domain, [ 'Domain1', 'Domain2' ] ); - } ) ); - $plugin->expects( $this->once() )->method( 'setDomain' ) - ->with( $this->equalTo( 'Domain2' ) ); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'authenticate' ) - ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - list( $req ) = $provider->getAuthenticationRequests( AuthManager::ACTION_LOGIN, [] ); - $req->username = 'foo'; - $req->password = 'bar'; - $req->domain = 'Domain2'; - $provider->beginPrimaryAuthentication( [ $req ] ); - } - - public function testTestUserExists() { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->with( $this->equalTo( 'Foo' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - $this->assertTrue( $provider->testUserExists( 'foo' ) ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->with( $this->equalTo( 'Foo' ) ) - ->will( $this->returnValue( false ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - $this->assertFalse( $provider->testUserExists( 'foo' ) ); - } - - public function testTestUserCanAuthenticate() { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->with( $this->equalTo( 'Foo' ) ) - ->will( $this->returnValue( false ) ); - $plugin->expects( $this->never() )->method( 'getUserInstance' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertFalse( $provider->testUserCanAuthenticate( 'foo' ) ); - - $pluginUser = $this->getMockBuilder( \AuthPluginUser::class ) - ->disableOriginalConstructor() - ->getMock(); - $pluginUser->expects( $this->once() )->method( 'isLocked' ) - ->will( $this->returnValue( true ) ); - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->with( $this->equalTo( 'Foo' ) ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'getUserInstance' ) - ->with( $this->callback( function ( $user ) { - $this->assertInstanceOf( \User::class, $user ); - $this->assertEquals( 'Foo', $user->getName() ); - return true; - } ) ) - ->will( $this->returnValue( $pluginUser ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertFalse( $provider->testUserCanAuthenticate( 'foo' ) ); - - $pluginUser = $this->getMockBuilder( \AuthPluginUser::class ) - ->disableOriginalConstructor() - ->getMock(); - $pluginUser->expects( $this->once() )->method( 'isLocked' ) - ->will( $this->returnValue( false ) ); - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'userExists' ) - ->with( $this->equalTo( 'Foo' ) ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'getUserInstance' ) - ->with( $this->callback( function ( $user ) { - $this->assertInstanceOf( \User::class, $user ); - $this->assertEquals( 'Foo', $user->getName() ); - return true; - } ) ) - ->will( $this->returnValue( $pluginUser ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertTrue( $provider->testUserCanAuthenticate( 'foo' ) ); - } - - public function testProviderRevokeAccessForUser() { - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'userExists', 'setPassword' ] ) - ->getMock(); - $plugin->expects( $this->once() )->method( 'userExists' )->willReturn( true ); - $plugin->expects( $this->once() )->method( 'setPassword' ) - ->with( $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), $this->identicalTo( null ) ) - ->willReturn( true ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $provider->providerRevokeAccessForUser( 'foo' ); - - $plugin = $this->getMockBuilder( \AuthPlugin::class ) - ->setMethods( [ 'domainList', 'userExists', 'setPassword' ] ) - ->getMock(); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [ 'D1', 'D2', 'D3' ] ); - $plugin->expects( $this->exactly( 3 ) )->method( 'userExists' ) - ->willReturnCallback( function () use ( $plugin ) { - return $plugin->getDomain() !== 'D2'; - } ); - $plugin->expects( $this->exactly( 2 ) )->method( 'setPassword' ) - ->with( $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), $this->identicalTo( null ) ) - ->willReturnCallback( function () use ( $plugin ) { - $this->assertNotEquals( 'D2', $plugin->getDomain() ); - return $plugin->getDomain() !== 'D1'; - } ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - try { - $provider->providerRevokeAccessForUser( 'foo' ); - $this->fail( 'Expected exception not thrown' ); - } catch ( \UnexpectedValueException $ex ) { - $this->assertSame( - 'AuthPlugin failed to reset password for Foo in the following domains: D1', - $ex->getMessage() - ); - } - } - - public function testProviderAllowsPropertyChange() { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->any() )->method( 'allowPropChange' ) - ->will( $this->returnCallback( function ( $prop ) { - return $prop === 'allow'; - } ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - $this->assertTrue( $provider->providerAllowsPropertyChange( 'allow' ) ); - $this->assertFalse( $provider->providerAllowsPropertyChange( 'deny' ) ); - } - - /** - * @dataProvider provideProviderAllowsAuthenticationDataChange - * @param string $type - * @param bool|null $allow - * @param StatusValue $expect - */ - public function testProviderAllowsAuthenticationDataChange( $type, $allow, $expect ) { - $domains = $type instanceof PasswordDomainAuthenticationRequest ? [ 'foo', 'bar' ] : []; - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( $domains ); - $plugin->expects( $allow === null ? $this->never() : $this->once() ) - ->method( 'allowPasswordChange' )->will( $this->returnValue( $allow ) ); - $plugin->expects( $this->any() )->method( 'validDomain' ) - ->willReturnCallback( function ( $d ) use ( $domains ) { - return in_array( $d, $domains, true ); - } ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - if ( is_object( $type ) ) { - $req = $type; - } else { - $req = $this->createMock( $type ); - } - $req->action = AuthManager::ACTION_CHANGE; - $req->username = 'UTSysop'; - $req->password = 'Pa$$w0Rd!!!'; - $req->retype = 'Pa$$w0Rd!!!'; - $this->assertEquals( $expect, $provider->providerAllowsAuthenticationDataChange( $req ) ); - } - - public static function provideProviderAllowsAuthenticationDataChange() { - $domains = [ 'foo', 'bar' ]; - $reqNoDomain = new PasswordDomainAuthenticationRequest( $domains ); - $reqValidDomain = new PasswordDomainAuthenticationRequest( $domains ); - $reqValidDomain->domain = 'foo'; - $reqInvalidDomain = new PasswordDomainAuthenticationRequest( $domains ); - $reqInvalidDomain->domain = 'invalid'; - - return [ - [ AuthenticationRequest::class, null, \StatusValue::newGood( 'ignored' ) ], - [ new PasswordAuthenticationRequest, true, \StatusValue::newGood() ], - [ - new PasswordAuthenticationRequest, - false, - \StatusValue::newFatal( 'authmanager-authplugin-setpass-denied' ) - ], - [ $reqNoDomain, true, \StatusValue::newGood( 'ignored' ) ], - [ $reqValidDomain, true, \StatusValue::newGood() ], - [ - $reqInvalidDomain, - true, - \StatusValue::newFatal( 'authmanager-authplugin-setpass-bad-domain' ) - ], - ]; - } - - public function testProviderChangeAuthenticationData() { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->never() )->method( 'setPassword' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $provider->providerChangeAuthenticationData( - $this->createMock( AuthenticationRequest::class ) - ); - - $req = new PasswordAuthenticationRequest(); - $req->action = AuthManager::ACTION_CHANGE; - $req->username = 'foo'; - $req->password = 'bar'; - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'setPassword' ) - ->with( $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $provider->providerChangeAuthenticationData( $req ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() )->method( 'setPassword' ) - ->with( $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( false ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - try { - $provider->providerChangeAuthenticationData( $req ); - $this->fail( 'Expected exception not thrown' ); - } catch ( \ErrorPageError $e ) { - $this->assertSame( 'authmanager-authplugin-setpass-failed-title', $e->title ); - $this->assertSame( 'authmanager-authplugin-setpass-failed-message', $e->msg ); - } - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' ) - ->will( $this->returnValue( [ 'Domain1', 'Domain2' ] ) ); - $plugin->expects( $this->any() )->method( 'validDomain' ) - ->will( $this->returnCallback( function ( $domain ) { - return in_array( $domain, [ 'Domain1', 'Domain2' ] ); - } ) ); - $plugin->expects( $this->once() )->method( 'setDomain' ) - ->with( $this->equalTo( 'Domain2' ) ); - $plugin->expects( $this->once() )->method( 'setPassword' ) - ->with( $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - list( $req ) = $provider->getAuthenticationRequests( AuthManager::ACTION_CREATE, [] ); - $req->username = 'foo'; - $req->password = 'bar'; - $req->domain = 'Domain2'; - $provider->providerChangeAuthenticationData( $req ); - } - - /** - * @dataProvider provideAccountCreationType - * @param bool $can - * @param string $expect - */ - public function testAccountCreationType( $can, $expect ) { - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->once() ) - ->method( 'canCreateAccounts' )->will( $this->returnValue( $can ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - $this->assertSame( $expect, $provider->accountCreationType() ); - } - - public static function provideAccountCreationType() { - return [ - [ true, PrimaryAuthenticationProvider::TYPE_CREATE ], - [ false, PrimaryAuthenticationProvider::TYPE_NONE ], - ]; - } - - public function testTestForAccountCreation() { - $user = \User::newFromName( 'foo' ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - \StatusValue::newGood(), - $provider->testForAccountCreation( $user, $user, [] ) - ); - } - - public function testAccountCreation() { - $user = \User::newFromName( 'foo' ); - $user->setEmail( 'email' ); - $user->setRealName( 'realname' ); - - $req = new PasswordAuthenticationRequest(); - $req->action = AuthManager::ACTION_CREATE; - $reqs = [ PasswordAuthenticationRequest::class => $req ]; - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->any() )->method( 'canCreateAccounts' ) - ->will( $this->returnValue( false ) ); - $plugin->expects( $this->never() )->method( 'addUser' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - try { - $provider->beginPrimaryAccountCreation( $user, $user, [] ); - $this->fail( 'Expected exception was not thrown' ); - } catch ( \BadMethodCallException $ex ) { - $this->assertSame( - 'Shouldn\'t call this when accountCreationType() is NONE', $ex->getMessage() - ); - } - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->any() )->method( 'canCreateAccounts' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->never() )->method( 'addUser' ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAccountCreation( $user, $user, [] ) - ); - - $req->username = 'foo'; - $req->password = null; - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAccountCreation( $user, $user, $reqs ) - ); - - $req->username = null; - $req->password = 'bar'; - $this->assertEquals( - AuthenticationResponse::newAbstain(), - $provider->beginPrimaryAccountCreation( $user, $user, $reqs ) - ); - - $req->username = 'foo'; - $req->password = 'bar'; - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->any() )->method( 'canCreateAccounts' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'addUser' ) - ->with( - $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), - $this->equalTo( 'bar' ), - $this->equalTo( 'email' ), - $this->equalTo( 'realname' ) - ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $this->assertEquals( - AuthenticationResponse::newPass(), - $provider->beginPrimaryAccountCreation( $user, $user, $reqs ) - ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] ); - $plugin->expects( $this->any() )->method( 'canCreateAccounts' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->once() )->method( 'addUser' ) - ->with( - $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), - $this->equalTo( 'bar' ), - $this->equalTo( 'email' ), - $this->equalTo( 'realname' ) - ) - ->will( $this->returnValue( false ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - $ret = $provider->beginPrimaryAccountCreation( $user, $user, $reqs ); - $this->assertSame( AuthenticationResponse::FAIL, $ret->status ); - $this->assertSame( 'authmanager-authplugin-create-fail', $ret->message->getKey() ); - - $plugin = $this->createMock( \AuthPlugin::class ); - $plugin->expects( $this->any() )->method( 'canCreateAccounts' ) - ->will( $this->returnValue( true ) ); - $plugin->expects( $this->any() )->method( 'domainList' ) - ->will( $this->returnValue( [ 'Domain1', 'Domain2' ] ) ); - $plugin->expects( $this->any() )->method( 'validDomain' ) - ->will( $this->returnCallback( function ( $domain ) { - return in_array( $domain, [ 'Domain1', 'Domain2' ] ); - } ) ); - $plugin->expects( $this->once() )->method( 'setDomain' ) - ->with( $this->equalTo( 'Domain2' ) ); - $plugin->expects( $this->once() )->method( 'addUser' ) - ->with( $this->callback( function ( $u ) { - return $u instanceof \User && $u->getName() === 'Foo'; - } ), $this->equalTo( 'bar' ) ) - ->will( $this->returnValue( true ) ); - $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin ); - list( $req ) = $provider->getAuthenticationRequests( AuthManager::ACTION_CREATE, [] ); - $req->username = 'foo'; - $req->password = 'bar'; - $req->domain = 'Domain2'; - $provider->beginPrimaryAccountCreation( $user, $user, [ $req ] ); - } - -} -- 2.20.1