Remove $wgDisableAuthManager
Change-Id: I2b2c9693a275fcc026916bd97f303e7a5c8df341
This commit is contained in:
parent
c6532a11a8
commit
854a462dc0
50 changed files with 153 additions and 5193 deletions
10
autoload.php
10
autoload.php
|
|
@ -28,7 +28,6 @@ $wgAutoloadLocalClasses = [
|
|||
'ApiClientLogin' => __DIR__ . '/includes/api/ApiClientLogin.php',
|
||||
'ApiComparePages' => __DIR__ . '/includes/api/ApiComparePages.php',
|
||||
'ApiContinuationManager' => __DIR__ . '/includes/api/ApiContinuationManager.php',
|
||||
'ApiCreateAccount' => __DIR__ . '/includes/api/ApiCreateAccount.php',
|
||||
'ApiDelete' => __DIR__ . '/includes/api/ApiDelete.php',
|
||||
'ApiDisabled' => __DIR__ . '/includes/api/ApiDisabled.php',
|
||||
'ApiEditPage' => __DIR__ . '/includes/api/ApiEditPage.php',
|
||||
|
|
@ -748,8 +747,6 @@ $wgAutoloadLocalClasses = [
|
|||
'LoggedOutEditToken' => __DIR__ . '/includes/user/LoggedOutEditToken.php',
|
||||
'LoggedUpdateMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
|
||||
'LoginForm' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
|
||||
'LoginFormAuthManager' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
|
||||
'LoginFormPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialUserlogin.php',
|
||||
'LoginHelper' => __DIR__ . '/includes/specials/helpers/LoginHelper.php',
|
||||
'LoginSignupSpecialPage' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
|
||||
'LonelyPagesPage' => __DIR__ . '/includes/specials/SpecialLonelypages.php',
|
||||
|
|
@ -1281,13 +1278,10 @@ $wgAutoloadLocalClasses = [
|
|||
'SpecialChangeContentModel' => __DIR__ . '/includes/specials/SpecialChangeContentModel.php',
|
||||
'SpecialChangeCredentials' => __DIR__ . '/includes/specials/SpecialChangeCredentials.php',
|
||||
'SpecialChangeEmail' => __DIR__ . '/includes/specials/SpecialChangeEmail.php',
|
||||
'SpecialChangeEmailPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialChangeEmail.php',
|
||||
'SpecialChangePassword' => __DIR__ . '/includes/specials/SpecialChangePassword.php',
|
||||
'SpecialChangePasswordPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialChangePassword.php',
|
||||
'SpecialComparePages' => __DIR__ . '/includes/specials/SpecialComparePages.php',
|
||||
'SpecialContributions' => __DIR__ . '/includes/specials/SpecialContributions.php',
|
||||
'SpecialCreateAccount' => __DIR__ . '/includes/specials/SpecialCreateAccount.php',
|
||||
'SpecialCreateAccountPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialCreateAccount.php',
|
||||
'SpecialDiff' => __DIR__ . '/includes/specials/SpecialDiff.php',
|
||||
'SpecialEditTags' => __DIR__ . '/includes/specials/SpecialEditTags.php',
|
||||
'SpecialEditWatchlist' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
|
||||
|
|
@ -1320,7 +1314,6 @@ $wgAutoloadLocalClasses = [
|
|||
'SpecialPageLanguage' => __DIR__ . '/includes/specials/SpecialPageLanguage.php',
|
||||
'SpecialPagesWithProp' => __DIR__ . '/includes/specials/SpecialPagesWithProp.php',
|
||||
'SpecialPasswordReset' => __DIR__ . '/includes/specials/SpecialPasswordReset.php',
|
||||
'SpecialPasswordResetPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialPasswordReset.php',
|
||||
'SpecialPermanentLink' => __DIR__ . '/includes/specials/SpecialPermanentLink.php',
|
||||
'SpecialPreferences' => __DIR__ . '/includes/specials/SpecialPreferences.php',
|
||||
'SpecialPrefixindex' => __DIR__ . '/includes/specials/SpecialPrefixindex.php',
|
||||
|
|
@ -1351,7 +1344,6 @@ $wgAutoloadLocalClasses = [
|
|||
'SpecialUploadStashTooLargeException' => __DIR__ . '/includes/specials/SpecialUploadStash.php',
|
||||
'SpecialUserLogin' => __DIR__ . '/includes/specials/SpecialUserLogin.php',
|
||||
'SpecialUserLogout' => __DIR__ . '/includes/specials/SpecialUserLogout.php',
|
||||
'SpecialUserlogoutPreAuthManager' => __DIR__ . '/includes/specials/pre-authmanager/SpecialUserlogout.php',
|
||||
'SpecialVersion' => __DIR__ . '/includes/specials/SpecialVersion.php',
|
||||
'SpecialWatchlist' => __DIR__ . '/includes/specials/SpecialWatchlist.php',
|
||||
'SpecialWhatLinksHere' => __DIR__ . '/includes/specials/SpecialWhatlinkshere.php',
|
||||
|
|
@ -1487,8 +1479,6 @@ $wgAutoloadLocalClasses = [
|
|||
'UserOptions' => __DIR__ . '/maintenance/userOptions.inc',
|
||||
'UserPasswordPolicy' => __DIR__ . '/includes/password/UserPasswordPolicy.php',
|
||||
'UserRightsProxy' => __DIR__ . '/includes/user/UserRightsProxy.php',
|
||||
'UsercreateTemplate' => __DIR__ . '/includes/templates/Usercreate.php',
|
||||
'UserloginTemplate' => __DIR__ . '/includes/templates/Userlogin.php',
|
||||
'UserrightsPage' => __DIR__ . '/includes/specials/SpecialUserrights.php',
|
||||
'UsersPager' => __DIR__ . '/includes/specials/pagers/UsersPager.php',
|
||||
'UtfNormal' => __DIR__ . '/includes/compat/normal/UtfNormal.php',
|
||||
|
|
|
|||
|
|
@ -4447,13 +4447,6 @@ $wgPasswordPolicy = [
|
|||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Disable AuthManager
|
||||
* @since 1.27
|
||||
* @deprecated since 1.27, for use during development only
|
||||
*/
|
||||
$wgDisableAuthManager = false;
|
||||
|
||||
/**
|
||||
* Configure AuthManager
|
||||
*
|
||||
|
|
@ -8173,13 +8166,6 @@ $wgTextModelsToParse = [
|
|||
CONTENT_MODEL_CSS, // Make categories etc work, people put them into comments.
|
||||
];
|
||||
|
||||
/**
|
||||
* Whether the user must enter their password to change their e-mail address
|
||||
*
|
||||
* @since 1.20
|
||||
*/
|
||||
$wgRequirePasswordforEmailChange = true;
|
||||
|
||||
/**
|
||||
* Register handlers for specific types of sites.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -207,8 +207,9 @@ class Preferences {
|
|||
* @return void
|
||||
*/
|
||||
static function profilePreferences( $user, IContextSource $context, &$defaultPreferences ) {
|
||||
global $wgAuth, $wgContLang, $wgParser, $wgDisableAuthManager;
|
||||
global $wgContLang, $wgParser;
|
||||
|
||||
$authManager = AuthManager::singleton();
|
||||
$config = $context->getConfig();
|
||||
// retrieving user name for GENDER and misc.
|
||||
$userName = $user->getName();
|
||||
|
|
@ -283,21 +284,19 @@ class Preferences {
|
|||
$canEditPrivateInfo = $user->isAllowed( 'editmyprivateinfo' );
|
||||
|
||||
// Actually changeable stuff
|
||||
$realnameChangeAllowed = $wgDisableAuthManager ? $wgAuth->allowPropChange( 'realname' )
|
||||
: AuthManager::singleton()->allowsPropertyChange( 'realname' );
|
||||
$defaultPreferences['realname'] = [
|
||||
// (not really "private", but still shouldn't be edited without permission)
|
||||
'type' => $canEditPrivateInfo && $realnameChangeAllowed ? 'text' : 'info',
|
||||
'type' => $canEditPrivateInfo && $authManager->allowsPropertyChange( 'realname' )
|
||||
? 'text' : 'info',
|
||||
'default' => $user->getRealName(),
|
||||
'section' => 'personal/info',
|
||||
'label-message' => 'yourrealname',
|
||||
'help-message' => 'prefs-help-realname',
|
||||
];
|
||||
|
||||
$allowPasswordChange = $wgDisableAuthManager ? $wgAuth->allowPasswordChange()
|
||||
: AuthManager::singleton()->allowsAuthenticationDataChange(
|
||||
new PasswordAuthenticationRequest(), false )->isGood();
|
||||
if ( $canEditPrivateInfo && $allowPasswordChange ) {
|
||||
if ( $canEditPrivateInfo && $authManager->allowsAuthenticationDataChange(
|
||||
new PasswordAuthenticationRequest(), false )->isGood()
|
||||
) {
|
||||
$link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ),
|
||||
$context->msg( 'prefs-resetpass' )->escaped(), [],
|
||||
[ 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ] );
|
||||
|
|
@ -418,10 +417,8 @@ class Preferences {
|
|||
'default' => $oldsigHTML,
|
||||
'section' => 'personal/signature',
|
||||
];
|
||||
$nicknameChangeAllowed = $wgDisableAuthManager ? $wgAuth->allowPropChange( 'nickname' )
|
||||
: AuthManager::singleton()->allowsPropertyChange( 'nickname' );
|
||||
$defaultPreferences['nickname'] = [
|
||||
'type' => $nicknameChangeAllowed ? 'text' : 'info',
|
||||
'type' => $authManager->allowsPropertyChange( 'nickname' ) ? 'text' : 'info',
|
||||
'maxlength' => $config->get( 'MaxSigChars' ),
|
||||
'label-message' => 'yournick',
|
||||
'validation-callback' => [ 'Preferences', 'validateSignature' ],
|
||||
|
|
@ -450,9 +447,7 @@ class Preferences {
|
|||
}
|
||||
|
||||
$emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : '';
|
||||
$emailChangeAllowed = $wgDisableAuthManager ? $wgAuth->allowPropChange( 'emailaddress' )
|
||||
: AuthManager::singleton()->allowsPropertyChange( 'emailaddress' );
|
||||
if ( $canEditPrivateInfo && $emailChangeAllowed ) {
|
||||
if ( $canEditPrivateInfo && $authManager->allowsPropertyChange( 'emailaddress' ) ) {
|
||||
$link = Linker::link(
|
||||
SpecialPage::getTitleFor( 'ChangeEmail' ),
|
||||
$context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(),
|
||||
|
|
|
|||
|
|
@ -452,22 +452,6 @@ if ( $wgProfileOnly ) {
|
|||
$wgDebugLogFile = '';
|
||||
}
|
||||
|
||||
// Disable AuthManager API modules if $wgDisableAuthManager
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$wgAPIModules += [
|
||||
'clientlogin' => 'ApiDisabled',
|
||||
'createaccount' => 'ApiCreateAccount', // Use the non-AuthManager version
|
||||
'linkaccount' => 'ApiDisabled',
|
||||
'unlinkaccount' => 'ApiDisabled',
|
||||
'changeauthenticationdata' => 'ApiDisabled',
|
||||
'removeauthenticationdata' => 'ApiDisabled',
|
||||
'resetpassword' => 'ApiDisabled',
|
||||
];
|
||||
$wgAPIMetaModules += [
|
||||
'authmanagerinfo' => 'ApiQueryDisabled',
|
||||
];
|
||||
}
|
||||
|
||||
// Backwards compatibility with old password limits
|
||||
if ( $wgMinimalPasswordLength !== false ) {
|
||||
$wgPasswordPolicy['policies']['default']['MinimalPasswordLength'] = $wgMinimalPasswordLength;
|
||||
|
|
@ -711,12 +695,10 @@ $wgContLang->initContLang();
|
|||
$wgRequest->interpolateTitle();
|
||||
|
||||
if ( !is_object( $wgAuth ) ) {
|
||||
$wgAuth = $wgDisableAuthManager ? new AuthPlugin : new MediaWiki\Auth\AuthManagerAuthPlugin;
|
||||
$wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin;
|
||||
Hooks::run( 'AuthPluginSetup', [ &$wgAuth ] );
|
||||
}
|
||||
if ( !$wgDisableAuthManager &&
|
||||
$wgAuth && !$wgAuth instanceof MediaWiki\Auth\AuthManagerAuthPlugin
|
||||
) {
|
||||
if ( $wgAuth && !$wgAuth instanceof MediaWiki\Auth\AuthManagerAuthPlugin ) {
|
||||
MediaWiki\Auth\AuthManager::singleton()->forcePrimaryAuthenticationProviders( [
|
||||
new MediaWiki\Auth\TemporaryPasswordPrimaryAuthenticationProvider( [
|
||||
'authoritative' => false,
|
||||
|
|
@ -852,15 +834,11 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
|
|||
$sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser();
|
||||
if ( $sessionUser->getId() === 0 && User::isValidUserName( $sessionUser->getName() ) ) {
|
||||
$ps_autocreate = Profiler::instance()->scopedProfileIn( $fname . '-autocreate' );
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$res = MediaWiki\Session\SessionManager::autoCreateUser( $sessionUser );
|
||||
} else {
|
||||
$res = MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
|
||||
$sessionUser,
|
||||
MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
$res = MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
|
||||
$sessionUser,
|
||||
MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
|
||||
true
|
||||
);
|
||||
Profiler::instance()->scopedProfileOut( $ps_autocreate );
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authmanager' )->info( 'Autocreation attempt', [
|
||||
'event' => 'autocreate',
|
||||
|
|
|
|||
|
|
@ -1,238 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Created on August 7, 2012
|
||||
*
|
||||
* Copyright © 2012 Tyler Romeo <tylerromeo@gmail.com>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
|
||||
/**
|
||||
* Unit to authenticate account registration attempts to the current wiki.
|
||||
*
|
||||
* @ingroup API
|
||||
* @deprecated since 1.27, only used when $wgDisableAuthManager is true
|
||||
*/
|
||||
class ApiCreateAccount extends ApiBase {
|
||||
public function execute() {
|
||||
// If we're in a mode that breaks the same-origin policy, no tokens can
|
||||
// be obtained
|
||||
if ( $this->lacksSameOriginSecurity() ) {
|
||||
$this->dieUsage(
|
||||
'Cannot create account when the same-origin policy is not applied', 'aborted'
|
||||
);
|
||||
}
|
||||
|
||||
// $loginForm->addNewaccountInternal will throw exceptions
|
||||
// if wiki is read only (already handled by api), user is blocked or does not have rights.
|
||||
// Use userCan in order to hit GlobalBlock checks (according to Special:userlogin)
|
||||
$loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
|
||||
if ( !$loginTitle->userCan( 'createaccount', $this->getUser() ) ) {
|
||||
$this->dieUsage(
|
||||
'You do not have the right to create a new account',
|
||||
'permdenied-createaccount'
|
||||
);
|
||||
}
|
||||
if ( $this->getUser()->isBlockedFromCreateAccount() ) {
|
||||
$this->dieUsage(
|
||||
'You cannot create a new account because you are blocked',
|
||||
'blocked',
|
||||
0,
|
||||
[ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $this->getUser()->getBlock() ) ]
|
||||
);
|
||||
}
|
||||
|
||||
$params = $this->extractRequestParams();
|
||||
|
||||
// Make sure session is persisted
|
||||
MediaWiki\Session\SessionManager::getGlobalSession()->persist();
|
||||
|
||||
if ( $params['mailpassword'] && !$params['email'] ) {
|
||||
$this->dieUsageMsg( 'noemail' );
|
||||
}
|
||||
|
||||
if ( $params['language'] && !Language::isSupportedLanguage( $params['language'] ) ) {
|
||||
$this->dieUsage( 'Invalid language parameter', 'langinvalid' );
|
||||
}
|
||||
|
||||
$context = new DerivativeContext( $this->getContext() );
|
||||
$context->setRequest( new DerivativeRequest(
|
||||
$this->getContext()->getRequest(),
|
||||
[
|
||||
'type' => 'signup',
|
||||
'uselang' => $params['language'],
|
||||
'wpName' => $params['name'],
|
||||
'wpPassword' => $params['password'],
|
||||
'wpRetype' => $params['password'],
|
||||
'wpDomain' => $params['domain'],
|
||||
'wpEmail' => $params['email'],
|
||||
'wpRealName' => $params['realname'],
|
||||
'wpCreateaccountToken' => $params['token'],
|
||||
'wpCreateaccount' => $params['mailpassword'] ? null : '1',
|
||||
'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null
|
||||
]
|
||||
) );
|
||||
|
||||
$loginForm = new LoginForm();
|
||||
$loginForm->setContext( $context );
|
||||
Hooks::run( 'AddNewAccountApiForm', [ $this, $loginForm ] );
|
||||
$loginForm->load();
|
||||
|
||||
$status = $loginForm->addNewAccountInternal();
|
||||
LoggerFactory::getInstance( 'authmanager' )->info( 'Account creation attempt via API', [
|
||||
'event' => 'accountcreation',
|
||||
'status' => $status,
|
||||
] );
|
||||
$result = [];
|
||||
if ( $status->isGood() ) {
|
||||
// Success!
|
||||
$user = $status->getValue();
|
||||
|
||||
if ( $params['language'] ) {
|
||||
$user->setOption( 'language', $params['language'] );
|
||||
}
|
||||
|
||||
if ( $params['mailpassword'] ) {
|
||||
// If mailpassword was set, disable the password and send an email.
|
||||
$user->setPassword( null );
|
||||
$status->merge( $loginForm->mailPasswordInternal(
|
||||
$user,
|
||||
false,
|
||||
'createaccount-title',
|
||||
'createaccount-text'
|
||||
) );
|
||||
} elseif ( $this->getConfig()->get( 'EmailAuthentication' ) &&
|
||||
Sanitizer::validateEmail( $user->getEmail() )
|
||||
) {
|
||||
// Send out an email authentication message if needed
|
||||
$status->merge( $user->sendConfirmationMail() );
|
||||
}
|
||||
|
||||
// Save settings (including confirmation token)
|
||||
$user->saveSettings();
|
||||
|
||||
Hooks::run( 'AddNewAccount', [ $user, $params['mailpassword'] ] );
|
||||
|
||||
if ( $params['mailpassword'] ) {
|
||||
$logAction = 'byemail';
|
||||
} elseif ( $this->getUser()->isLoggedIn() ) {
|
||||
$logAction = 'create2';
|
||||
} else {
|
||||
$logAction = 'create';
|
||||
}
|
||||
$user->addNewUserLogEntry( $logAction, (string)$params['reason'] );
|
||||
|
||||
// Add username, id, and token to result.
|
||||
$result['username'] = $user->getName();
|
||||
$result['userid'] = $user->getId();
|
||||
$result['token'] = $user->getToken();
|
||||
}
|
||||
|
||||
$apiResult = $this->getResult();
|
||||
|
||||
if ( $status->hasMessage( 'sessionfailure' ) || $status->hasMessage( 'nocookiesfornew' ) ) {
|
||||
// Token was incorrect, so add it to result, but don't throw an exception
|
||||
// since not having the correct token is part of the normal
|
||||
// flow of events.
|
||||
$result['token'] = LoginForm::getCreateaccountToken()->toString();
|
||||
$result['result'] = 'NeedToken';
|
||||
$this->setWarning( 'Fetching a token via action=createaccount is deprecated. ' .
|
||||
'Use action=query&meta=tokens&type=createaccount instead.' );
|
||||
$this->logFeatureUsage( 'action=createaccount&!token' );
|
||||
} elseif ( !$status->isOK() ) {
|
||||
// There was an error. Die now.
|
||||
$this->dieStatus( $status );
|
||||
} elseif ( !$status->isGood() ) {
|
||||
// Status is not good, but OK. This means warnings.
|
||||
$result['result'] = 'Warning';
|
||||
|
||||
// Add any warnings to the result
|
||||
$warnings = $status->getErrorsByType( 'warning' );
|
||||
if ( $warnings ) {
|
||||
foreach ( $warnings as &$warning ) {
|
||||
ApiResult::setIndexedTagName( $warning['params'], 'param' );
|
||||
}
|
||||
ApiResult::setIndexedTagName( $warnings, 'warning' );
|
||||
$result['warnings'] = $warnings;
|
||||
}
|
||||
} else {
|
||||
// Everything was fine.
|
||||
$result['result'] = 'Success';
|
||||
}
|
||||
|
||||
// Give extensions a chance to modify the API result data
|
||||
Hooks::run( 'AddNewAccountApiResult', [ $this, $loginForm, &$result ] );
|
||||
|
||||
$apiResult->addValue( null, 'createaccount', $result );
|
||||
}
|
||||
|
||||
public function mustBePosted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isReadMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isWriteMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAllowedParams() {
|
||||
return [
|
||||
'name' => [
|
||||
ApiBase::PARAM_TYPE => 'user',
|
||||
ApiBase::PARAM_REQUIRED => true
|
||||
],
|
||||
'password' => [
|
||||
ApiBase::PARAM_TYPE => 'password',
|
||||
],
|
||||
'domain' => null,
|
||||
'token' => [
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => false, // for BC
|
||||
ApiBase::PARAM_HELP_MSG => [ 'api-help-param-token', 'createaccount' ],
|
||||
],
|
||||
'email' => [
|
||||
ApiBase::PARAM_TYPE => 'string',
|
||||
ApiBase::PARAM_REQUIRED => $this->getConfig()->get( 'EmailConfirmToEdit' ),
|
||||
],
|
||||
'realname' => null,
|
||||
'mailpassword' => [
|
||||
ApiBase::PARAM_TYPE => 'boolean',
|
||||
ApiBase::PARAM_DFLT => false
|
||||
],
|
||||
'reason' => null,
|
||||
'language' => null
|
||||
];
|
||||
}
|
||||
|
||||
protected function getExamplesMessages() {
|
||||
return [
|
||||
'action=createaccount&name=testuser&password=test123'
|
||||
=> 'apihelp-createaccount-example-pass',
|
||||
'action=createaccount&name=testmailuser&mailpassword=true&reason=MyReason'
|
||||
=> 'apihelp-createaccount-example-mail',
|
||||
];
|
||||
}
|
||||
|
||||
public function getHelpUrls() {
|
||||
return 'https://www.mediawiki.org/wiki/API:Account_creation';
|
||||
}
|
||||
}
|
||||
|
|
@ -42,9 +42,7 @@ class ApiLogin extends ApiBase {
|
|||
}
|
||||
|
||||
protected function getDescriptionMessage() {
|
||||
if ( $this->getConfig()->get( 'DisableAuthManager' ) ) {
|
||||
return 'apihelp-login-description-nonauthmanager';
|
||||
} elseif ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
|
||||
if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
|
||||
return 'apihelp-login-description';
|
||||
} else {
|
||||
return 'apihelp-login-description-nobotpasswords';
|
||||
|
|
@ -124,85 +122,52 @@ class ApiLogin extends ApiBase {
|
|||
}
|
||||
|
||||
if ( $authRes === false ) {
|
||||
if ( $this->getConfig()->get( 'DisableAuthManager' ) ) {
|
||||
// Non-AuthManager login
|
||||
$context->setRequest( new DerivativeRequest(
|
||||
$this->getContext()->getRequest(),
|
||||
[
|
||||
'wpName' => $params['name'],
|
||||
'wpPassword' => $params['password'],
|
||||
'wpDomain' => $params['domain'],
|
||||
'wpLoginToken' => $params['token'],
|
||||
'wpRemember' => ''
|
||||
]
|
||||
) );
|
||||
$loginForm = new LoginForm();
|
||||
$loginForm->setContext( $context );
|
||||
$authRes = $loginForm->authenticateUserData();
|
||||
$loginType = 'LoginForm';
|
||||
// Simplified AuthManager login, for backwards compatibility
|
||||
$manager = AuthManager::singleton();
|
||||
$reqs = AuthenticationRequest::loadRequestsFromSubmission(
|
||||
$manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN, $this->getUser() ),
|
||||
[
|
||||
'username' => $params['name'],
|
||||
'password' => $params['password'],
|
||||
'domain' => $params['domain'],
|
||||
'rememberMe' => true,
|
||||
]
|
||||
);
|
||||
$res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
|
||||
switch ( $res->status ) {
|
||||
case AuthenticationResponse::PASS:
|
||||
if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
|
||||
$warn = 'Main-account login via action=login is deprecated and may stop working ' .
|
||||
'without warning.';
|
||||
$warn .= ' To continue login with action=login, see [[Special:BotPasswords]].';
|
||||
$warn .= ' To safely continue using main-account login, see action=clientlogin.';
|
||||
} else {
|
||||
$warn = 'Login via action=login is deprecated and may stop working without warning.';
|
||||
$warn .= ' To safely log in, see action=clientlogin.';
|
||||
}
|
||||
$this->setWarning( $warn );
|
||||
$authRes = 'Success';
|
||||
$loginType = 'AuthManager';
|
||||
break;
|
||||
|
||||
switch ( $authRes ) {
|
||||
case LoginForm::SUCCESS:
|
||||
$authRes = 'Success';
|
||||
break;
|
||||
case LoginForm::NEED_TOKEN:
|
||||
$authRes = 'NeedToken';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Simplified AuthManager login, for backwards compatibility
|
||||
$manager = AuthManager::singleton();
|
||||
$reqs = AuthenticationRequest::loadRequestsFromSubmission(
|
||||
$manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN, $this->getUser() ),
|
||||
[
|
||||
'username' => $params['name'],
|
||||
'password' => $params['password'],
|
||||
'domain' => $params['domain'],
|
||||
'rememberMe' => true,
|
||||
]
|
||||
);
|
||||
$res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
|
||||
switch ( $res->status ) {
|
||||
case AuthenticationResponse::PASS:
|
||||
if ( $this->getConfig()->get( 'EnableBotPasswords' ) ) {
|
||||
$warn = 'Main-account login via action=login is deprecated and may stop working ' .
|
||||
'without warning.';
|
||||
$warn .= ' To continue login with action=login, see [[Special:BotPasswords]].';
|
||||
$warn .= ' To safely continue using main-account login, see action=clientlogin.';
|
||||
} else {
|
||||
$warn = 'Login via action=login is deprecated and may stop working without warning.';
|
||||
$warn .= ' To safely log in, see action=clientlogin.';
|
||||
}
|
||||
$this->setWarning( $warn );
|
||||
$authRes = 'Success';
|
||||
$loginType = 'AuthManager';
|
||||
break;
|
||||
case AuthenticationResponse::FAIL:
|
||||
// Hope it's not a PreAuthenticationProvider that failed...
|
||||
$authRes = 'Failed';
|
||||
$message = $res->message;
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
|
||||
->info( __METHOD__ . ': Authentication failed: ' . $message->plain() );
|
||||
break;
|
||||
|
||||
case AuthenticationResponse::FAIL:
|
||||
// Hope it's not a PreAuthenticationProvider that failed...
|
||||
$authRes = 'Failed';
|
||||
$message = $res->message;
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
|
||||
->info( __METHOD__ . ': Authentication failed: ' . $message->plain() );
|
||||
break;
|
||||
|
||||
default:
|
||||
$authRes = 'Aborted';
|
||||
break;
|
||||
}
|
||||
default:
|
||||
$authRes = 'Aborted';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$result['result'] = $authRes;
|
||||
switch ( $authRes ) {
|
||||
case 'Success':
|
||||
if ( $this->getConfig()->get( 'DisableAuthManager' ) ) {
|
||||
$user = $context->getUser();
|
||||
$this->getContext()->setUser( $user );
|
||||
$user->setCookies( $this->getRequest(), null, true );
|
||||
} else {
|
||||
$user = $session->getUser();
|
||||
}
|
||||
$user = $session->getUser();
|
||||
|
||||
ApiQueryInfo::resetTokenCache();
|
||||
|
||||
|
|
@ -252,65 +217,6 @@ class ApiLogin extends ApiBase {
|
|||
}
|
||||
break;
|
||||
|
||||
// Results from LoginForm for when $wgDisableAuthManager is true
|
||||
case LoginForm::WRONG_TOKEN:
|
||||
$result['result'] = 'WrongToken';
|
||||
break;
|
||||
|
||||
case LoginForm::NO_NAME:
|
||||
$result['result'] = 'NoName';
|
||||
break;
|
||||
|
||||
case LoginForm::ILLEGAL:
|
||||
$result['result'] = 'Illegal';
|
||||
break;
|
||||
|
||||
case LoginForm::WRONG_PLUGIN_PASS:
|
||||
$result['result'] = 'WrongPluginPass';
|
||||
break;
|
||||
|
||||
case LoginForm::NOT_EXISTS:
|
||||
$result['result'] = 'NotExists';
|
||||
break;
|
||||
|
||||
// bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
|
||||
// The e-mailed temporary password should not be used for actual logins.
|
||||
case LoginForm::RESET_PASS:
|
||||
case LoginForm::WRONG_PASS:
|
||||
$result['result'] = 'WrongPass';
|
||||
break;
|
||||
|
||||
case LoginForm::EMPTY_PASS:
|
||||
$result['result'] = 'EmptyPass';
|
||||
break;
|
||||
|
||||
case LoginForm::CREATE_BLOCKED:
|
||||
$result['result'] = 'CreateBlocked';
|
||||
$result['details'] = 'Your IP address is blocked from account creation';
|
||||
$block = $context->getUser()->getBlock();
|
||||
if ( $block ) {
|
||||
$result = array_merge( $result, ApiQueryUserInfo::getBlockInfo( $block ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case LoginForm::THROTTLED:
|
||||
$result['result'] = 'Throttled';
|
||||
$result['wait'] = intval( $loginForm->mThrottleWait );
|
||||
break;
|
||||
|
||||
case LoginForm::USER_BLOCKED:
|
||||
$result['result'] = 'Blocked';
|
||||
$block = User::newFromName( $params['name'] )->getBlock();
|
||||
if ( $block ) {
|
||||
$result = array_merge( $result, ApiQueryUserInfo::getBlockInfo( $block ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case LoginForm::ABORTED:
|
||||
$result['result'] = 'Aborted';
|
||||
$result['reason'] = $loginForm->mAbortLoginErrorMsg;
|
||||
break;
|
||||
|
||||
default:
|
||||
ApiBase::dieDebug( __METHOD__, "Unhandled case value: {$authRes}" );
|
||||
}
|
||||
|
|
@ -329,8 +235,7 @@ class ApiLogin extends ApiBase {
|
|||
}
|
||||
|
||||
public function isDeprecated() {
|
||||
return !$this->getConfig()->get( 'DisableAuthManager' ) &&
|
||||
!$this->getConfig()->get( 'EnableBotPasswords' );
|
||||
return !$this->getConfig()->get( 'EnableBotPasswords' );
|
||||
}
|
||||
|
||||
public function mustBePosted() {
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ class ApiQueryUsers extends ApiQueryBase {
|
|||
}
|
||||
} else {
|
||||
$data[$u]['missing'] = true;
|
||||
if ( isset( $this->prop['cancreate'] ) && !$this->getConfig()->get( 'DisableAuthManager' ) ) {
|
||||
if ( isset( $this->prop['cancreate'] ) ) {
|
||||
$status = MediaWiki\Auth\AuthManager::singleton()->canCreateAccount( $u );
|
||||
$data[$u]['cancreate'] = $status->isGood();
|
||||
if ( !$status->isGood() ) {
|
||||
|
|
@ -307,7 +307,7 @@ class ApiQueryUsers extends ApiQueryBase {
|
|||
}
|
||||
|
||||
public function getAllowedParams() {
|
||||
$ret = [
|
||||
return [
|
||||
'prop' => [
|
||||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_TYPE => [
|
||||
|
|
@ -320,6 +320,7 @@ class ApiQueryUsers extends ApiQueryBase {
|
|||
'emailable',
|
||||
'gender',
|
||||
'centralids',
|
||||
'cancreate',
|
||||
// When adding a prop, consider whether it should be added
|
||||
// to self::$publicProps
|
||||
],
|
||||
|
|
@ -336,10 +337,6 @@ class ApiQueryUsers extends ApiQueryBase {
|
|||
ApiBase::PARAM_ISMULTI => true
|
||||
],
|
||||
];
|
||||
if ( !$this->getConfig()->get( 'DisableAuthManager' ) ) {
|
||||
$ret['prop'][ApiBase::PARAM_TYPE][] = 'cancreate';
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
protected function getExamplesMessages() {
|
||||
|
|
|
|||
|
|
@ -231,7 +231,6 @@
|
|||
|
||||
"apihelp-login-description": "Log in and get authentication cookies.\n\nThis action should only be used in combination with [[Special:BotPasswords]]; use for main-account login is deprecated and may fail without warning. To safely log in to the main account, use <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
|
||||
"apihelp-login-description-nobotpasswords": "Log in and get authentication cookies.\n\nThis action is deprecated and may fail without warning. To safely log in, use <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
|
||||
"apihelp-login-description-nonauthmanager": "Log in and get authentication cookies.\n\nIn the event of a successful log-in, the needed cookies will be included in the HTTP response headers. In the event of a failed log-in, further attempts may be throttled to limit automated password guessing attacks.",
|
||||
"apihelp-login-param-name": "User name.",
|
||||
"apihelp-login-param-password": "Password.",
|
||||
"apihelp-login-param-domain": "Domain (optional).",
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@
|
|||
"apihelp-linkaccount-example-link": "{{doc-apihelp-example|linkaccount}}",
|
||||
"apihelp-login-description": "{{doc-apihelp-description|login|info=This message is used when <code>$wgEnableBotPasswords</code> is true.|seealso=* {{msg-mw|apihelp-login-description-nobotpasswords}}}}",
|
||||
"apihelp-login-description-nobotpasswords": "{{doc-apihelp-description|login|info=This message is used when <code>$wgEnableBotPasswords</code> is false.|seealso=* {{msg-mw|apihelp-login-description}}}}",
|
||||
"apihelp-login-description-nonauthmanager": "{{doc-apihelp-description|login|info=This message is used when <code>$wgDisableAuthManager</code> is true.|seealso=* {{msg-mw|apihelp-login-description}}}}",
|
||||
"apihelp-login-param-name": "{{doc-apihelp-param|login|name}}\n{{Identical|Username}}",
|
||||
"apihelp-login-param-password": "{{doc-apihelp-param|login|password}}\n{{Identical|Password}}",
|
||||
"apihelp-login-param-domain": "{{doc-apihelp-param|login|domain}}",
|
||||
|
|
|
|||
|
|
@ -105,12 +105,6 @@ class AuthManager implements LoggerAwareInterface {
|
|||
* @return AuthManager
|
||||
*/
|
||||
public static function singleton() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
throw new \BadMethodCallException( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
|
||||
if ( self::$instance === null ) {
|
||||
self::$instance = new self(
|
||||
\RequestContext::getMain()->getRequest(),
|
||||
|
|
|
|||
|
|
@ -374,202 +374,15 @@ final class SessionManager implements SessionManagerInterface {
|
|||
* @deprecated since 1.27, use MediaWiki\Auth\AuthManager::autoCreateUser instead
|
||||
* @param User $user User to auto-create
|
||||
* @return bool Success
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function autoCreateUser( User $user ) {
|
||||
global $wgAuth, $wgDisableAuthManager;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ( !$wgDisableAuthManager ) {
|
||||
wfDeprecated( __METHOD__, '1.27' );
|
||||
return \MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
|
||||
$user,
|
||||
\MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
|
||||
false
|
||||
)->isGood();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$logger = self::singleton()->logger;
|
||||
|
||||
// Much of this code is based on that in CentralAuth
|
||||
|
||||
// Try the local user from the slave DB
|
||||
$localId = User::idFromName( $user->getName() );
|
||||
$flags = 0;
|
||||
|
||||
// Fetch the user ID from the master, so that we don't try to create the user
|
||||
// when they already exist, due to replication lag
|
||||
// @codeCoverageIgnoreStart
|
||||
if ( !$localId && wfGetLB()->getReaderIndex() != 0 ) {
|
||||
$localId = User::idFromName( $user->getName(), User::READ_LATEST );
|
||||
$flags = User::READ_LATEST;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
if ( $localId ) {
|
||||
// User exists after all.
|
||||
$user->setId( $localId );
|
||||
$user->loadFromId( $flags );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Denied by AuthPlugin? But ignore AuthPlugin itself.
|
||||
if ( get_class( $wgAuth ) !== 'AuthPlugin' && !$wgAuth->autoCreate() ) {
|
||||
$logger->debug( __METHOD__ . ': denied by AuthPlugin' );
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wiki is read-only?
|
||||
if ( wfReadOnly() ) {
|
||||
$logger->debug( __METHOD__ . ': denied by wfReadOnly()' );
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
$userName = $user->getName();
|
||||
|
||||
// Check the session, if we tried to create this user already there's
|
||||
// no point in retrying.
|
||||
$session = self::getGlobalSession();
|
||||
$reason = $session->get( 'MWSession::AutoCreateBlacklist' );
|
||||
if ( $reason ) {
|
||||
$logger->debug( __METHOD__ . ": blacklisted in session ($reason)" );
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the IP user able to create accounts?
|
||||
$anon = new User;
|
||||
if ( !$anon->isAllowedAny( 'createaccount', 'autocreateaccount' )
|
||||
|| $anon->isBlockedFromCreateAccount()
|
||||
) {
|
||||
// Blacklist the user to avoid repeated DB queries subsequently
|
||||
$logger->debug( __METHOD__ . ': user is blocked from this wiki, blacklisting' );
|
||||
$session->set( 'MWSession::AutoCreateBlacklist', 'blocked', 600 );
|
||||
$session->persist();
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for validity of username
|
||||
if ( !User::isCreatableName( $userName ) ) {
|
||||
$logger->debug( __METHOD__ . ': Invalid username, blacklisting' );
|
||||
$session->set( 'MWSession::AutoCreateBlacklist', 'invalid username', 600 );
|
||||
$session->persist();
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Give other extensions a chance to stop auto creation.
|
||||
$user->loadDefaults( $userName );
|
||||
$abortMessage = '';
|
||||
if ( !\Hooks::run( 'AbortAutoAccount', [ $user, &$abortMessage ] ) ) {
|
||||
// In this case we have no way to return the message to the user,
|
||||
// but we can log it.
|
||||
$logger->debug( __METHOD__ . ": denied by hook: $abortMessage" );
|
||||
$session->set( 'MWSession::AutoCreateBlacklist', "hook aborted: $abortMessage", 600 );
|
||||
$session->persist();
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the name has not been changed
|
||||
if ( $user->getName() !== $userName ) {
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
throw new \UnexpectedValueException(
|
||||
'AbortAutoAccount hook tried to change the user name'
|
||||
);
|
||||
}
|
||||
|
||||
// Ignore warnings about master connections/writes...hard to avoid here
|
||||
\Profiler::instance()->getTransactionProfiler()->resetExpectations();
|
||||
|
||||
$cache = \ObjectCache::getLocalClusterInstance();
|
||||
$backoffKey = wfMemcKey( 'MWSession', 'autocreate-failed', md5( $userName ) );
|
||||
if ( $cache->get( $backoffKey ) ) {
|
||||
$logger->debug( __METHOD__ . ': denied by prior creation attempt failures' );
|
||||
$user->setId( 0 );
|
||||
$user->loadFromId();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks passed, create the user...
|
||||
$from = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : 'CLI';
|
||||
$logger->info( __METHOD__ . ': creating new user ({username}) - from: {url}',
|
||||
[
|
||||
'username' => $userName,
|
||||
'url' => $from,
|
||||
] );
|
||||
|
||||
try {
|
||||
// Insert the user into the local DB master
|
||||
$status = $user->addToDatabase();
|
||||
if ( !$status->isOK() ) {
|
||||
// @codeCoverageIgnoreStart
|
||||
// double-check for a race condition (T70012)
|
||||
$id = User::idFromName( $user->getName(), User::READ_LATEST );
|
||||
if ( $id ) {
|
||||
$logger->info( __METHOD__ . ': tried to autocreate existing user',
|
||||
[
|
||||
'username' => $userName,
|
||||
] );
|
||||
} else {
|
||||
$logger->error(
|
||||
__METHOD__ . ': failed with message ' . $status->getWikiText( false, false, 'en' ),
|
||||
[
|
||||
'username' => $userName,
|
||||
]
|
||||
);
|
||||
}
|
||||
$user->setId( $id );
|
||||
$user->loadFromId( User::READ_LATEST );
|
||||
return false;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
} catch ( \Exception $ex ) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$logger->error( __METHOD__ . ': failed with exception {exception}', [
|
||||
'exception' => $ex,
|
||||
'username' => $userName,
|
||||
] );
|
||||
// Do not keep throwing errors for a while
|
||||
$cache->set( $backoffKey, 1, 600 );
|
||||
// Bubble up error; which should normally trigger DB rollbacks
|
||||
throw $ex;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
# Notify AuthPlugin
|
||||
// @codeCoverageIgnoreStart
|
||||
$tmpUser = $user;
|
||||
$wgAuth->initUser( $tmpUser, true );
|
||||
if ( $tmpUser !== $user ) {
|
||||
$logger->warning( __METHOD__ . ': ' .
|
||||
get_class( $wgAuth ) . '::initUser() replaced the user object' );
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
# Notify hooks (e.g. Newuserlog)
|
||||
\Hooks::run( 'AuthPluginAutoCreate', [ $user ] );
|
||||
\Hooks::run( 'LocalUserCreated', [ $user, true ] );
|
||||
|
||||
$user->saveSettings();
|
||||
|
||||
# Update user count
|
||||
\DeferredUpdates::addUpdate( new \SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
|
||||
|
||||
# Watch user's userpage and talk page
|
||||
$user->addWatch( $user->getUserPage(), User::IGNORE_USER_RIGHTS );
|
||||
|
||||
return true;
|
||||
wfDeprecated( __METHOD__, '1.27' );
|
||||
return \MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
|
||||
$user,
|
||||
\MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION,
|
||||
false
|
||||
)->isGood();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -665,34 +665,17 @@ class SkinTemplate extends Skin {
|
|||
? 'nav-login-createaccount'
|
||||
: 'pt-login';
|
||||
|
||||
// TODO remove this after AuthManager is stable
|
||||
global $wgDisableAuthManager;
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$is_signup = $request->getText( 'type' ) == 'signup';
|
||||
$login_url = [
|
||||
'text' => $this->msg( $loginlink )->text(),
|
||||
'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
|
||||
'active' => $title->isSpecial( 'Userlogin' )
|
||||
&& ( $loginlink == 'nav-login-createaccount' || !$is_signup ),
|
||||
];
|
||||
$createaccount_url = [
|
||||
'text' => $this->msg( 'pt-createaccount' )->text(),
|
||||
'href' => self::makeSpecialUrl( 'Userlogin', "$returnto&type=signup" ),
|
||||
'active' => $title->isSpecial( 'Userlogin' ) && $is_signup,
|
||||
];
|
||||
} else {
|
||||
$login_url = [
|
||||
'text' => $this->msg( $loginlink )->text(),
|
||||
'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
|
||||
'active' => $title->isSpecial( 'Userlogin' ) ||
|
||||
$title->isSpecial( 'CreateAccount' ) && $useCombinedLoginLink,
|
||||
];
|
||||
$createaccount_url = [
|
||||
'text' => $this->msg( 'pt-createaccount' )->text(),
|
||||
'href' => self::makeSpecialUrl( 'CreateAccount', $returnto ),
|
||||
'active' => $title->isSpecial( 'CreateAccount' ),
|
||||
];
|
||||
}
|
||||
$login_url = [
|
||||
'text' => $this->msg( $loginlink )->text(),
|
||||
'href' => self::makeSpecialUrl( 'Userlogin', $returnto ),
|
||||
'active' => $title->isSpecial( 'Userlogin' )
|
||||
|| $title->isSpecial( 'CreateAccount' ) && $useCombinedLoginLink,
|
||||
];
|
||||
$createaccount_url = [
|
||||
'text' => $this->msg( 'pt-createaccount' )->text(),
|
||||
'href' => self::makeSpecialUrl( 'CreateAccount', $returnto ),
|
||||
'active' => $title->isSpecial( 'CreateAccount' ),
|
||||
];
|
||||
|
||||
// No need to show Talk and Contributions to anons if they can't contribute!
|
||||
if ( User::groupHasPermission( '*', 'edit' ) ) {
|
||||
|
|
|
|||
|
|
@ -1342,196 +1342,12 @@ class FakeAuthTemplate extends BaseTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A horrible hack to handle AuthManager's feature flag. For other special pages this is done in
|
||||
* SpecialPageFactory, but LoginForm is used directly by some extensions. Will be killed as soon
|
||||
* as AuthManager is stable.
|
||||
*/
|
||||
class LoginForm extends SpecialPage {
|
||||
private $realLoginForm;
|
||||
|
||||
public function __construct( $request = null ) {
|
||||
global $wgDisableAuthManager;
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->realLoginForm = new LoginFormPreAuthManager( $request );
|
||||
} else {
|
||||
$this->realLoginForm = new LoginFormAuthManager( $request );
|
||||
}
|
||||
}
|
||||
|
||||
// proxy everything
|
||||
|
||||
public function __get( $name ) {
|
||||
return $this->realLoginForm->$name;
|
||||
}
|
||||
|
||||
public function __set( $name, $value ) {
|
||||
$this->realLoginForm->$name = $value;
|
||||
}
|
||||
|
||||
public function __call( $name, $args ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, $name ], $args );
|
||||
}
|
||||
|
||||
public static function __callStatic( $name, $args ) {
|
||||
global $wgDisableAuthManager;
|
||||
return call_user_func_array( [ $wgDisableAuthManager ? LoginFormPreAuthManager::class
|
||||
: LoginFormAuthManager::class, $name ], $args );
|
||||
}
|
||||
|
||||
// all public SpecialPage methods need to be proxied explicitly
|
||||
|
||||
public function getName() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getRestriction() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function isListed() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function setListed( $listed ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function listed( $x = null ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function isIncludable() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function including( $x = null ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getLocalName() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function isExpensive() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function isCached() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function isRestricted() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function userCanExecute( User $user ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function displayRestrictionError() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function checkPermissions() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function checkReadOnly() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function requireLogin(
|
||||
$reasonMsg = 'exception-nologin-text', $titleMsg = 'exception-nologin'
|
||||
) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function prefixSearchSubpages( $search, $limit, $offset ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function execute( $subPage ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getDescription() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
function getTitle( $subpage = false ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
function getPageTitle( $subpage = false ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function setContext( $context ) {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getContext() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getRequest() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getOutput() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getUser() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getSkin() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getLanguage() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getConfig() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getFullTitle() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function getFinalGroupName() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
public function doesWrites() {
|
||||
return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
|
||||
}
|
||||
|
||||
// no way to proxy constants and static properties
|
||||
|
||||
const SUCCESS = 0;
|
||||
const NO_NAME = 1;
|
||||
const ILLEGAL = 2;
|
||||
const WRONG_PLUGIN_PASS = 3;
|
||||
const NOT_EXISTS = 4;
|
||||
const WRONG_PASS = 5;
|
||||
const EMPTY_PASS = 6;
|
||||
const RESET_PASS = 7;
|
||||
const ABORTED = 8;
|
||||
const CREATE_BLOCKED = 9;
|
||||
const THROTTLED = 10;
|
||||
const USER_BLOCKED = 11;
|
||||
const NEED_TOKEN = 12;
|
||||
const WRONG_TOKEN = 13;
|
||||
const USER_MIGRATED = 14;
|
||||
|
||||
public static $statusCodes = [
|
||||
self::SUCCESS => 'success',
|
||||
self::NO_NAME => 'no_name',
|
||||
self::ILLEGAL => 'illegal',
|
||||
self::WRONG_PLUGIN_PASS => 'wrong_plugin_pass',
|
||||
self::NOT_EXISTS => 'not_exists',
|
||||
self::WRONG_PASS => 'wrong_pass',
|
||||
self::EMPTY_PASS => 'empty_pass',
|
||||
self::RESET_PASS => 'reset_pass',
|
||||
self::ABORTED => 'aborted',
|
||||
self::CREATE_BLOCKED => 'create_blocked',
|
||||
self::THROTTLED => 'throttled',
|
||||
self::USER_BLOCKED => 'user_blocked',
|
||||
self::NEED_TOKEN => 'need_token',
|
||||
self::WRONG_TOKEN => 'wrong_token',
|
||||
self::USER_MIGRATED => 'user_migrated',
|
||||
];
|
||||
|
||||
public static $validErrorMessages = [
|
||||
'exception-nologin-text',
|
||||
'watchlistanontext',
|
||||
'changeemail-no-info',
|
||||
'resetpass-no-info',
|
||||
'confirmemail_needlogin',
|
||||
'prefsnologintext2',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* LoginForm as a special page has been replaced by SpecialUserLogin and SpecialCreateAccount,
|
||||
* but some extensions called its public methods directly, so the class is retained as a
|
||||
* B/C wrapper. Anything that used it before should use AuthManager instead.
|
||||
*/
|
||||
class LoginFormAuthManager extends SpecialPage {
|
||||
class LoginForm extends SpecialPage {
|
||||
const SUCCESS = 0;
|
||||
const NO_NAME = 1;
|
||||
const ILLEGAL = 2;
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ class SpecialPageFactory {
|
|||
|
||||
// Authentication
|
||||
'Userlogin' => 'SpecialUserLogin',
|
||||
'Userlogout' => 'SpecialUserlogoutPreAuthManager',
|
||||
'CreateAccount' => 'SpecialCreateAccountPreAuthManager',
|
||||
'Userlogout' => 'SpecialUserLogout',
|
||||
'CreateAccount' => 'SpecialCreateAccount',
|
||||
'LinkAccounts' => 'SpecialLinkAccounts',
|
||||
'UnlinkAccounts' => 'SpecialUnlinkAccounts',
|
||||
'ChangeCredentials' => 'SpecialChangeCredentials',
|
||||
|
|
@ -96,9 +96,9 @@ class SpecialPageFactory {
|
|||
'Block' => 'SpecialBlock',
|
||||
'Unblock' => 'SpecialUnblock',
|
||||
'BlockList' => 'SpecialBlockList',
|
||||
'ChangePassword' => 'SpecialChangePasswordPreAuthManager',
|
||||
'ChangePassword' => 'SpecialChangePassword',
|
||||
'BotPasswords' => 'SpecialBotPasswords',
|
||||
'PasswordReset' => 'SpecialPasswordResetPreAuthManager',
|
||||
'PasswordReset' => 'SpecialPasswordReset',
|
||||
'DeletedContributions' => 'DeletedContributionsPage',
|
||||
'Preferences' => 'SpecialPreferences',
|
||||
'ResetTokens' => 'SpecialResetTokens',
|
||||
|
|
@ -231,7 +231,6 @@ class SpecialPageFactory {
|
|||
global $wgDisableInternalSearch, $wgEmailAuthentication;
|
||||
global $wgEnableEmail, $wgEnableJavaScriptTest;
|
||||
global $wgPageLanguageUseDB, $wgContentHandlerUseDB;
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
if ( !is_array( self::$list ) ) {
|
||||
|
||||
|
|
@ -247,7 +246,7 @@ class SpecialPageFactory {
|
|||
}
|
||||
|
||||
if ( $wgEnableEmail ) {
|
||||
self::$list['ChangeEmail'] = 'SpecialChangeEmailPreAuthManager';
|
||||
self::$list['ChangeEmail'] = 'SpecialChangeEmail';
|
||||
}
|
||||
|
||||
if ( $wgEnableJavaScriptTest ) {
|
||||
|
|
@ -261,20 +260,6 @@ class SpecialPageFactory {
|
|||
self::$list['ChangeContentModel'] = 'SpecialChangeContentModel';
|
||||
}
|
||||
|
||||
// horrible hack to allow selection between old and new classes via a feature flag - T110756
|
||||
// will be removed once AuthManager is stable
|
||||
if ( !$wgDisableAuthManager ) {
|
||||
self::$list = array_map( function ( $class ) {
|
||||
return preg_replace( '/PreAuthManager$/', '', $class );
|
||||
}, self::$list );
|
||||
self::$list['Userlogout'] = 'SpecialUserLogout'; // case matters
|
||||
} else {
|
||||
self::$list['Userlogin'] = 'LoginForm';
|
||||
self::$list = array_diff_key( self::$list, array_fill_keys( [
|
||||
'LinkAccounts', 'UnlinkAccounts', 'ChangeCredentials', 'RemoveCredentials',
|
||||
], true ) );
|
||||
}
|
||||
|
||||
// Add extension special pages
|
||||
self::$list = array_merge( self::$list, $wgSpecialPages );
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
This directory temporarily hosts pre-AuthManager code as a way of feature-flagging.
|
||||
Class names are postfixed with 'PreAuthManager' and SpecialPageFactory adds/removes
|
||||
that postfix based on the feature flag.
|
||||
|
||||
This is a horrible hack that will only be in place for a few weeks, to allow instant
|
||||
rollback while AuthManager is tested in WMF production and major problems are ironed
|
||||
out. In the past such issues have been handled via deployment branches, but that
|
||||
meant blocking the work of all WMF developers from being deployed. This is hoped
|
||||
to be a less disruptive method.
|
||||
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implements Special:ChangeEmail
|
||||
*
|
||||
* 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
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* Let users change their email address.
|
||||
*
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialChangeEmailPreAuthManager extends FormSpecialPage {
|
||||
/**
|
||||
* @var Status
|
||||
*/
|
||||
private $status;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
|
||||
}
|
||||
|
||||
public function doesWrites() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isListed() {
|
||||
global $wgAuth;
|
||||
|
||||
return $wgAuth->allowPropChange( 'emailaddress' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution point
|
||||
* @param string $par
|
||||
*/
|
||||
function execute( $par ) {
|
||||
$out = $this->getOutput();
|
||||
$out->disallowUserJs();
|
||||
|
||||
parent::execute( $par );
|
||||
}
|
||||
|
||||
protected function checkExecutePermissions( User $user ) {
|
||||
global $wgAuth;
|
||||
|
||||
if ( !$wgAuth->allowPropChange( 'emailaddress' ) ) {
|
||||
throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
|
||||
}
|
||||
|
||||
$this->requireLogin( 'changeemail-no-info' );
|
||||
|
||||
// This could also let someone check the current email address, so
|
||||
// require both permissions.
|
||||
if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
|
||||
throw new PermissionsError( 'viewmyprivateinfo' );
|
||||
}
|
||||
|
||||
parent::checkExecutePermissions( $user );
|
||||
}
|
||||
|
||||
protected function getFormFields() {
|
||||
$user = $this->getUser();
|
||||
|
||||
$fields = [
|
||||
'Name' => [
|
||||
'type' => 'info',
|
||||
'label-message' => 'username',
|
||||
'default' => $user->getName(),
|
||||
],
|
||||
'OldEmail' => [
|
||||
'type' => 'info',
|
||||
'label-message' => 'changeemail-oldemail',
|
||||
'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
|
||||
],
|
||||
'NewEmail' => [
|
||||
'type' => 'email',
|
||||
'label-message' => 'changeemail-newemail',
|
||||
'autofocus' => true,
|
||||
'help-message' => 'changeemail-newemail-help',
|
||||
],
|
||||
];
|
||||
|
||||
if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' ) ) {
|
||||
$fields['Password'] = [
|
||||
'type' => 'password',
|
||||
'label-message' => 'changeemail-password'
|
||||
];
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
protected function getDisplayFormat() {
|
||||
return 'ooui';
|
||||
}
|
||||
|
||||
protected function alterForm( HTMLForm $form ) {
|
||||
$form->setId( 'mw-changeemail-form' );
|
||||
$form->setTableId( 'mw-changeemail-table' );
|
||||
$form->setSubmitTextMsg( 'changeemail-submit' );
|
||||
$form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
|
||||
|
||||
$form->addHeaderText( $this->msg( 'changeemail-header' )->parseAsBlock() );
|
||||
if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' ) ) {
|
||||
$form->addHeaderText( $this->msg( 'changeemail-passwordrequired' )->parseAsBlock() );
|
||||
}
|
||||
}
|
||||
|
||||
public function onSubmit( array $data ) {
|
||||
$password = isset( $data['Password'] ) ? $data['Password'] : null;
|
||||
$status = $this->attemptChange( $this->getUser(), $password, $data['NewEmail'] );
|
||||
|
||||
$this->status = $status;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function onSuccess() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$returnto = $request->getVal( 'returnto' );
|
||||
$titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
|
||||
if ( !$titleObj instanceof Title ) {
|
||||
$titleObj = Title::newMainPage();
|
||||
}
|
||||
$query = $request->getVal( 'returntoquery' );
|
||||
|
||||
if ( $this->status->value === true ) {
|
||||
$this->getOutput()->redirect( $titleObj->getFullURL( $query ) );
|
||||
} elseif ( $this->status->value === 'eauth' ) {
|
||||
# Notify user that a confirmation email has been sent...
|
||||
$this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
|
||||
'eauthentsent', $this->getUser()->getName() );
|
||||
// just show the link to go back
|
||||
$this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param string $pass
|
||||
* @param string $newaddr
|
||||
* @return Status
|
||||
*/
|
||||
private function attemptChange( User $user, $pass, $newaddr ) {
|
||||
global $wgAuth;
|
||||
|
||||
if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
|
||||
return Status::newFatal( 'invalidemailaddress' );
|
||||
}
|
||||
|
||||
if ( $newaddr === $user->getEmail() ) {
|
||||
return Status::newFatal( 'changeemail-nochange' );
|
||||
}
|
||||
|
||||
$throttleInfo = LoginForm::incrementLoginThrottle( $user->getName() );
|
||||
if ( $throttleInfo ) {
|
||||
$lang = $this->getLanguage();
|
||||
return Status::newFatal(
|
||||
'changeemail-throttled',
|
||||
$lang->formatDuration( $throttleInfo['wait'] )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $this->getConfig()->get( 'RequirePasswordforEmailChange' )
|
||||
&& !$user->checkTemporaryPassword( $pass )
|
||||
&& !$user->checkPassword( $pass )
|
||||
) {
|
||||
return Status::newFatal( 'wrongpassword' );
|
||||
}
|
||||
|
||||
LoginForm::clearLoginThrottle( $user->getName() );
|
||||
|
||||
$oldaddr = $user->getEmail();
|
||||
$status = $user->setEmailWithConfirmation( $newaddr );
|
||||
if ( !$status->isGood() ) {
|
||||
return $status;
|
||||
}
|
||||
|
||||
Hooks::run( 'PrefsEmailAudit', [ $user, $oldaddr, $newaddr ] );
|
||||
|
||||
$user->saveSettings();
|
||||
|
||||
$wgAuth->updateExternalDB( $user );
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function requiresUnblock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getGroupName() {
|
||||
return 'users';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,343 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implements Special:ChangePassword
|
||||
*
|
||||
* 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
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* Let users recover their password.
|
||||
*
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialChangePasswordPreAuthManager extends FormSpecialPage {
|
||||
protected $mUserName;
|
||||
protected $mDomain;
|
||||
|
||||
// Optional Wikitext Message to show above the password change form
|
||||
protected $mPreTextMessage = null;
|
||||
|
||||
// label for old password input
|
||||
protected $mOldPassMsg = null;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( 'ChangePassword', 'editmyprivateinfo' );
|
||||
$this->listed( false );
|
||||
}
|
||||
|
||||
public function doesWrites() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution point
|
||||
* @param string|null $par
|
||||
*/
|
||||
function execute( $par ) {
|
||||
$this->getOutput()->disallowUserJs();
|
||||
|
||||
parent::execute( $par );
|
||||
}
|
||||
|
||||
protected function checkExecutePermissions( User $user ) {
|
||||
parent::checkExecutePermissions( $user );
|
||||
|
||||
if ( !$this->getRequest()->wasPosted() ) {
|
||||
$this->requireLogin( 'resetpass-no-info' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a message at the top of the Change Password form
|
||||
* @since 1.23
|
||||
* @param Message $msg Message to parse and add to the form header
|
||||
*/
|
||||
public function setChangeMessage( Message $msg ) {
|
||||
$this->mPreTextMessage = $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a message at the top of the Change Password form
|
||||
* @since 1.23
|
||||
* @param string $msg Message label for old/temp password field
|
||||
*/
|
||||
public function setOldPasswordMessage( $msg ) {
|
||||
$this->mOldPassMsg = $msg;
|
||||
}
|
||||
|
||||
protected function getFormFields() {
|
||||
$user = $this->getUser();
|
||||
$request = $this->getRequest();
|
||||
|
||||
$oldpassMsg = $this->mOldPassMsg;
|
||||
if ( $oldpassMsg === null ) {
|
||||
$oldpassMsg = $user->isLoggedIn() ? 'oldpassword' : 'resetpass-temp-password';
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'Name' => [
|
||||
'type' => 'info',
|
||||
'label-message' => 'username',
|
||||
'default' => $request->getVal( 'wpName', $user->getName() ),
|
||||
],
|
||||
'Password' => [
|
||||
'type' => 'password',
|
||||
'label-message' => $oldpassMsg,
|
||||
],
|
||||
'NewPassword' => [
|
||||
'type' => 'password',
|
||||
'label-message' => 'newpassword',
|
||||
],
|
||||
'Retype' => [
|
||||
'type' => 'password',
|
||||
'label-message' => 'retypenew',
|
||||
],
|
||||
];
|
||||
|
||||
if ( !$this->getUser()->isLoggedIn() ) {
|
||||
$fields['LoginOnChangeToken'] = [
|
||||
'type' => 'hidden',
|
||||
'label' => 'Change Password Token',
|
||||
'default' => LoginForm::getLoginToken()->toString(),
|
||||
];
|
||||
}
|
||||
|
||||
$extraFields = [];
|
||||
Hooks::run( 'ChangePasswordForm', [ &$extraFields ] );
|
||||
foreach ( $extraFields as $extra ) {
|
||||
list( $name, $label, $type, $default ) = $extra;
|
||||
$fields[$name] = [
|
||||
'type' => $type,
|
||||
'name' => $name,
|
||||
'label-message' => $label,
|
||||
'default' => $default,
|
||||
];
|
||||
}
|
||||
|
||||
if ( !$user->isLoggedIn() ) {
|
||||
$fields['Remember'] = [
|
||||
'type' => 'check',
|
||||
'label' => $this->msg( 'remembermypassword' )
|
||||
->numParams(
|
||||
ceil( $this->getConfig()->get( 'CookieExpiration' ) / ( 3600 * 24 ) )
|
||||
)->text(),
|
||||
'default' => $request->getVal( 'wpRemember' ),
|
||||
];
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
protected function alterForm( HTMLForm $form ) {
|
||||
$form->setId( 'mw-resetpass-form' );
|
||||
$form->setTableId( 'mw-resetpass-table' );
|
||||
$form->setWrapperLegendMsg( 'resetpass_header' );
|
||||
$form->setSubmitTextMsg(
|
||||
$this->getUser()->isLoggedIn()
|
||||
? 'resetpass-submit-loggedin'
|
||||
: 'resetpass_submit'
|
||||
);
|
||||
$form->addButton( [
|
||||
'name' => 'wpCancel',
|
||||
'value' => $this->msg( 'resetpass-submit-cancel' )->text()
|
||||
] );
|
||||
$form->setHeaderText( $this->msg( 'resetpass_text' )->parseAsBlock() );
|
||||
if ( $this->mPreTextMessage instanceof Message ) {
|
||||
$form->addPreText( $this->mPreTextMessage->parseAsBlock() );
|
||||
}
|
||||
$form->addHiddenFields(
|
||||
$this->getRequest()->getValues( 'wpName', 'wpDomain', 'returnto', 'returntoquery' ) );
|
||||
}
|
||||
|
||||
public function onSubmit( array $data ) {
|
||||
global $wgAuth;
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
if ( $request->getCheck( 'wpLoginToken' ) ) {
|
||||
// This comes from Special:Userlogin when logging in with a temporary password
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !$this->getUser()->isLoggedIn()
|
||||
&& !LoginForm::getLoginToken()->match( $request->getVal( 'wpLoginOnChangeToken' ) )
|
||||
) {
|
||||
// Potential CSRF (bug 62497)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $request->getCheck( 'wpCancel' ) ) {
|
||||
$returnto = $request->getVal( 'returnto' );
|
||||
$titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
|
||||
if ( !$titleObj instanceof Title ) {
|
||||
$titleObj = Title::newMainPage();
|
||||
}
|
||||
$query = $request->getVal( 'returntoquery' );
|
||||
$this->getOutput()->redirect( $titleObj->getFullURL( $query ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->mUserName = $request->getVal( 'wpName', $this->getUser()->getName() );
|
||||
$this->mDomain = $wgAuth->getDomain();
|
||||
|
||||
if ( !$wgAuth->allowPasswordChange() ) {
|
||||
throw new ErrorPageError( 'changepassword', 'resetpass_forbidden' );
|
||||
}
|
||||
|
||||
$status = $this->attemptReset( $data['Password'], $data['NewPassword'], $data['Retype'] );
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function onSuccess() {
|
||||
if ( $this->getUser()->isLoggedIn() ) {
|
||||
$this->getOutput()->wrapWikiMsg(
|
||||
"<div class=\"successbox\">\n$1\n</div>",
|
||||
'changepassword-success'
|
||||
);
|
||||
$this->getOutput()->returnToMain();
|
||||
} else {
|
||||
$request = $this->getRequest();
|
||||
LoginForm::clearLoginToken();
|
||||
$token = LoginForm::getLoginToken()->toString();
|
||||
$data = [
|
||||
'action' => 'submitlogin',
|
||||
'wpName' => $this->mUserName,
|
||||
'wpDomain' => $this->mDomain,
|
||||
'wpLoginToken' => $token,
|
||||
'wpPassword' => $request->getVal( 'wpNewPassword' ),
|
||||
] + $request->getValues( 'wpRemember', 'returnto', 'returntoquery' );
|
||||
$login = new LoginForm( new DerivativeRequest( $request, $data, true ) );
|
||||
$login->setContext( $this->getContext() );
|
||||
$login->execute( null );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the new password if it meets the requirements for passwords and set
|
||||
* it as a current password, otherwise set the passed Status object to fatal
|
||||
* and doesn't change anything
|
||||
*
|
||||
* @param string $oldpass The current (temporary) password.
|
||||
* @param string $newpass The password to set.
|
||||
* @param string $retype The string of the retype password field to check with newpass
|
||||
* @return Status
|
||||
*/
|
||||
protected function attemptReset( $oldpass, $newpass, $retype ) {
|
||||
$isSelf = ( $this->mUserName === $this->getUser()->getName() );
|
||||
if ( $isSelf ) {
|
||||
$user = $this->getUser();
|
||||
} else {
|
||||
$user = User::newFromName( $this->mUserName );
|
||||
}
|
||||
|
||||
if ( !$user || $user->isAnon() ) {
|
||||
return Status::newFatal( $this->msg( 'nosuchusershort', $this->mUserName ) );
|
||||
}
|
||||
|
||||
if ( $newpass !== $retype ) {
|
||||
Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'badretype' ] );
|
||||
return Status::newFatal( $this->msg( 'badretype' ) );
|
||||
}
|
||||
|
||||
$throttleInfo = LoginForm::incrementLoginThrottle( $this->mUserName );
|
||||
if ( $throttleInfo ) {
|
||||
return Status::newFatal( $this->msg( 'changepassword-throttled' )
|
||||
->durationParams( $throttleInfo['wait'] )
|
||||
);
|
||||
}
|
||||
|
||||
// @todo Make these separate messages, since the message is written for both cases
|
||||
if ( !$user->checkTemporaryPassword( $oldpass ) && !$user->checkPassword( $oldpass ) ) {
|
||||
Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'wrongpassword' ] );
|
||||
return Status::newFatal( $this->msg( 'resetpass-wrong-oldpass' ) );
|
||||
}
|
||||
|
||||
// User is resetting their password to their old password
|
||||
if ( $oldpass === $newpass ) {
|
||||
return Status::newFatal( $this->msg( 'resetpass-recycled' ) );
|
||||
}
|
||||
|
||||
// Do AbortChangePassword after checking mOldpass, so we don't leak information
|
||||
// by possibly aborting a new password before verifying the old password.
|
||||
$abortMsg = 'resetpass-abort-generic';
|
||||
if ( !Hooks::run( 'AbortChangePassword', [ $user, $oldpass, $newpass, &$abortMsg ] ) ) {
|
||||
Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'abortreset' ] );
|
||||
return Status::newFatal( $this->msg( $abortMsg ) );
|
||||
}
|
||||
|
||||
// Please reset throttle for successful logins, thanks!
|
||||
LoginForm::clearLoginThrottle( $this->mUserName );
|
||||
|
||||
try {
|
||||
$user->setPassword( $newpass );
|
||||
Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'success' ] );
|
||||
} catch ( PasswordError $e ) {
|
||||
Hooks::run( 'PrefsPasswordAudit', [ $user, $newpass, 'error' ] );
|
||||
return Status::newFatal( new RawMessage( $e->getMessage() ) );
|
||||
}
|
||||
|
||||
if ( $isSelf ) {
|
||||
// This is needed to keep the user connected since
|
||||
// changing the password also modifies the user's token.
|
||||
$remember = $this->getRequest()->getCookie( 'Token' ) !== null;
|
||||
$user->setCookies( null, null, $remember );
|
||||
}
|
||||
$user->saveSettings();
|
||||
$this->resetPasswordExpiration( $user );
|
||||
return Status::newGood();
|
||||
}
|
||||
|
||||
public function requiresUnblock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getGroupName() {
|
||||
return 'users';
|
||||
}
|
||||
|
||||
/**
|
||||
* For resetting user password expiration, until AuthManager comes along
|
||||
* @param User $user
|
||||
*/
|
||||
private function resetPasswordExpiration( User $user ) {
|
||||
global $wgPasswordExpirationDays;
|
||||
$newExpire = null;
|
||||
if ( $wgPasswordExpirationDays ) {
|
||||
$newExpire = wfTimestamp(
|
||||
TS_MW,
|
||||
time() + ( $wgPasswordExpirationDays * 24 * 3600 )
|
||||
);
|
||||
}
|
||||
// Give extensions a chance to force an expiration
|
||||
Hooks::run( 'ResetPasswordExpiration', [ $this, &$newExpire ] );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->update(
|
||||
'user',
|
||||
[ 'user_password_expires' => $dbw->timestampOrNull( $newExpire ) ],
|
||||
[ 'user_id' => $user->getId() ],
|
||||
__METHOD__
|
||||
);
|
||||
}
|
||||
|
||||
protected function getDisplayFormat() {
|
||||
return 'ooui';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Redirect page: Special:CreateAccount --> Special:UserLogin/signup.
|
||||
*
|
||||
* 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
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* Redirect page: Special:CreateAccount --> Special:UserLogin/signup.
|
||||
* @todo FIXME: This (and the rest of the login frontend) needs to die a horrible painful death
|
||||
*
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialCreateAccountPreAuthManager extends SpecialRedirectToSpecial {
|
||||
function __construct() {
|
||||
parent::__construct(
|
||||
'CreateAccount',
|
||||
'Userlogin',
|
||||
'signup',
|
||||
[ 'returnto', 'returntoquery', 'uselang' ]
|
||||
);
|
||||
}
|
||||
|
||||
public function doesWrites() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// No reason to hide this link on Special:Specialpages
|
||||
public function isListed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isRestricted() {
|
||||
return !User::groupHasPermission( '*', 'createaccount' );
|
||||
}
|
||||
|
||||
public function userCanExecute( User $user ) {
|
||||
return $user->isAllowed( 'createaccount' );
|
||||
}
|
||||
|
||||
protected function getGroupName() {
|
||||
return 'login';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,378 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implements Special:PasswordReset
|
||||
*
|
||||
* 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
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* Special page for requesting a password reset email
|
||||
*
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialPasswordResetPreAuthManager extends FormSpecialPage {
|
||||
/**
|
||||
* @var Message
|
||||
*/
|
||||
private $email;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $firstUser;
|
||||
|
||||
/**
|
||||
* @var Status
|
||||
*/
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* @var string $method Identifies which password reset field was specified by the user.
|
||||
*/
|
||||
private $method;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( 'PasswordReset', 'editmyprivateinfo' );
|
||||
}
|
||||
|
||||
public function doesWrites() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function userCanExecute( User $user ) {
|
||||
return $this->canChangePassword( $user ) === true && parent::userCanExecute( $user );
|
||||
}
|
||||
|
||||
public function checkExecutePermissions( User $user ) {
|
||||
$error = $this->canChangePassword( $user );
|
||||
if ( is_string( $error ) ) {
|
||||
throw new ErrorPageError( 'internalerror', $error );
|
||||
} elseif ( !$error ) {
|
||||
throw new ErrorPageError( 'internalerror', 'resetpass_forbidden' );
|
||||
}
|
||||
|
||||
parent::checkExecutePermissions( $user );
|
||||
}
|
||||
|
||||
protected function getFormFields() {
|
||||
global $wgAuth;
|
||||
$resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
|
||||
$a = [];
|
||||
if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
|
||||
$a['Username'] = [
|
||||
'type' => 'text',
|
||||
'label-message' => 'passwordreset-username',
|
||||
];
|
||||
|
||||
if ( $this->getUser()->isLoggedIn() ) {
|
||||
$a['Username']['default'] = $this->getUser()->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
|
||||
$a['Email'] = [
|
||||
'type' => 'email',
|
||||
'label-message' => 'passwordreset-email',
|
||||
];
|
||||
}
|
||||
|
||||
if ( isset( $resetRoutes['domain'] ) && $resetRoutes['domain'] ) {
|
||||
$domains = $wgAuth->domainList();
|
||||
$a['Domain'] = [
|
||||
'type' => 'select',
|
||||
'options' => $domains,
|
||||
'label-message' => 'passwordreset-domain',
|
||||
];
|
||||
}
|
||||
|
||||
if ( $this->getUser()->isAllowed( 'passwordreset' ) ) {
|
||||
$a['Capture'] = [
|
||||
'type' => 'check',
|
||||
'label-message' => 'passwordreset-capture',
|
||||
'help-message' => 'passwordreset-capture-help',
|
||||
];
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
protected function getDisplayFormat() {
|
||||
return 'ooui';
|
||||
}
|
||||
|
||||
public function alterForm( HTMLForm $form ) {
|
||||
$resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
|
||||
|
||||
$form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
|
||||
|
||||
$i = 0;
|
||||
if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
|
||||
$i++;
|
||||
}
|
||||
if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
|
||||
$i++;
|
||||
}
|
||||
if ( isset( $resetRoutes['domain'] ) && $resetRoutes['domain'] ) {
|
||||
$i++;
|
||||
}
|
||||
|
||||
$message = ( $i > 1 ) ? 'passwordreset-text-many' : 'passwordreset-text-one';
|
||||
|
||||
$form->setHeaderText( $this->msg( $message, $i )->parseAsBlock() );
|
||||
$form->setSubmitTextMsg( 'mailmypassword' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the form. At this point we know that the user passes all the criteria in
|
||||
* userCanExecute(), and if the data array contains 'Username', etc, then Username
|
||||
* resets are allowed.
|
||||
* @param array $data
|
||||
* @throws MWException
|
||||
* @throws ThrottledError|PermissionsError
|
||||
* @return bool|array
|
||||
*/
|
||||
public function onSubmit( array $data ) {
|
||||
global $wgAuth, $wgMinimalPasswordLength;
|
||||
|
||||
if ( isset( $data['Domain'] ) ) {
|
||||
if ( $wgAuth->validDomain( $data['Domain'] ) ) {
|
||||
$wgAuth->setDomain( $data['Domain'] );
|
||||
} else {
|
||||
$wgAuth->setDomain( 'invaliddomain' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ) {
|
||||
// The user knows they don't have the passwordreset permission,
|
||||
// but they tried to spoof the form. That's naughty
|
||||
throw new PermissionsError( 'passwordreset' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @var $firstUser User
|
||||
* @var $users User[]
|
||||
*/
|
||||
|
||||
if ( isset( $data['Username'] ) && $data['Username'] !== '' ) {
|
||||
$method = 'username';
|
||||
$users = [ User::newFromName( $data['Username'] ) ];
|
||||
} elseif ( isset( $data['Email'] )
|
||||
&& $data['Email'] !== ''
|
||||
&& Sanitizer::validateEmail( $data['Email'] )
|
||||
) {
|
||||
$method = 'email';
|
||||
$res = wfGetDB( DB_SLAVE )->select(
|
||||
'user',
|
||||
User::selectFields(),
|
||||
[ 'user_email' => $data['Email'] ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
if ( $res ) {
|
||||
$users = [];
|
||||
|
||||
foreach ( $res as $row ) {
|
||||
$users[] = User::newFromRow( $row );
|
||||
}
|
||||
} else {
|
||||
// Some sort of database error, probably unreachable
|
||||
throw new MWException( 'Unknown database error in ' . __METHOD__ );
|
||||
}
|
||||
} else {
|
||||
// The user didn't supply any data
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for hooks (captcha etc), and allow them to modify the users list
|
||||
$error = [];
|
||||
if ( !Hooks::run( 'SpecialPasswordResetOnSubmit', [ &$users, $data, &$error ] ) ) {
|
||||
return [ $error ];
|
||||
}
|
||||
|
||||
$this->method = $method;
|
||||
|
||||
if ( count( $users ) == 0 ) {
|
||||
if ( $method == 'email' ) {
|
||||
// Don't reveal whether or not an email address is in use
|
||||
return true;
|
||||
} else {
|
||||
return [ 'noname' ];
|
||||
}
|
||||
}
|
||||
|
||||
$firstUser = $users[0];
|
||||
|
||||
if ( !$firstUser instanceof User || !$firstUser->getId() ) {
|
||||
// Don't parse username as wikitext (bug 65501)
|
||||
return [ [ 'nosuchuser', wfEscapeWikiText( $data['Username'] ) ] ];
|
||||
}
|
||||
|
||||
// Check against the rate limiter
|
||||
if ( $this->getUser()->pingLimiter( 'mailpassword' ) ) {
|
||||
throw new ThrottledError;
|
||||
}
|
||||
|
||||
// Check against password throttle
|
||||
foreach ( $users as $user ) {
|
||||
if ( $user->isPasswordReminderThrottled() ) {
|
||||
|
||||
# Round the time in hours to 3 d.p., in case someone is specifying
|
||||
# minutes or seconds.
|
||||
return [ [
|
||||
'throttled-mailpassword',
|
||||
round( $this->getConfig()->get( 'PasswordReminderResendTime' ), 3 )
|
||||
] ];
|
||||
}
|
||||
}
|
||||
|
||||
// All the users will have the same email address
|
||||
if ( $firstUser->getEmail() == '' ) {
|
||||
// This won't be reachable from the email route, so safe to expose the username
|
||||
return [ [ 'noemail', wfEscapeWikiText( $firstUser->getName() ) ] ];
|
||||
}
|
||||
|
||||
// We need to have a valid IP address for the hook, but per bug 18347, we should
|
||||
// send the user's name if they're logged in.
|
||||
$ip = $this->getRequest()->getIP();
|
||||
if ( !$ip ) {
|
||||
return [ 'badipaddress' ];
|
||||
}
|
||||
$caller = $this->getUser();
|
||||
Hooks::run( 'User::mailPasswordInternal', [ &$caller, &$ip, &$firstUser ] );
|
||||
$username = $caller->getName();
|
||||
$msg = IP::isValid( $username )
|
||||
? 'passwordreset-emailtext-ip'
|
||||
: 'passwordreset-emailtext-user';
|
||||
|
||||
// Send in the user's language; which should hopefully be the same
|
||||
$userLanguage = $firstUser->getOption( 'language' );
|
||||
|
||||
$passwords = [];
|
||||
foreach ( $users as $user ) {
|
||||
$password = PasswordFactory::generateRandomPasswordString( $wgMinimalPasswordLength );
|
||||
$user->setNewpassword( $password );
|
||||
$user->saveSettings();
|
||||
$passwords[] = $this->msg( 'passwordreset-emailelement', $user->getName(), $password )
|
||||
->inLanguage( $userLanguage )->text(); // We'll escape the whole thing later
|
||||
}
|
||||
$passwordBlock = implode( "\n\n", $passwords );
|
||||
|
||||
$this->email = $this->msg( $msg )->inLanguage( $userLanguage );
|
||||
$this->email->params(
|
||||
$username,
|
||||
$passwordBlock,
|
||||
count( $passwords ),
|
||||
'<' . Title::newMainPage()->getCanonicalURL() . '>',
|
||||
round( $this->getConfig()->get( 'NewPasswordExpiry' ) / 86400 )
|
||||
);
|
||||
|
||||
$title = $this->msg( 'passwordreset-emailtitle' )->inLanguage( $userLanguage );
|
||||
|
||||
$this->result = $firstUser->sendMail( $title->text(), $this->email->text() );
|
||||
|
||||
if ( isset( $data['Capture'] ) && $data['Capture'] ) {
|
||||
// Save the user, will be used if an error occurs when sending the email
|
||||
$this->firstUser = $firstUser;
|
||||
} else {
|
||||
// Blank the email if the user is not supposed to see it
|
||||
$this->email = null;
|
||||
}
|
||||
|
||||
if ( $this->result->isGood() ) {
|
||||
return true;
|
||||
} elseif ( isset( $data['Capture'] ) && $data['Capture'] ) {
|
||||
// The email didn't send, but maybe they knew that and that's why they captured it
|
||||
return true;
|
||||
} else {
|
||||
// @todo FIXME: The email wasn't sent, but we have already set
|
||||
// the password throttle timestamp, so they won't be able to try
|
||||
// again until it expires... :(
|
||||
return [ [ 'mailerror', $this->result->getMessage() ] ];
|
||||
}
|
||||
}
|
||||
|
||||
public function onSuccess() {
|
||||
if ( $this->getUser()->isAllowed( 'passwordreset' ) && $this->email != null ) {
|
||||
// @todo Logging
|
||||
|
||||
if ( $this->result->isGood() ) {
|
||||
$this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture' );
|
||||
} else {
|
||||
$this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture',
|
||||
$this->result->getMessage(), $this->firstUser->getName() );
|
||||
}
|
||||
|
||||
$this->getOutput()->addHTML( Html::rawElement( 'pre', [], $this->email->escaped() ) );
|
||||
}
|
||||
|
||||
if ( $this->method === 'email' ) {
|
||||
$this->getOutput()->addWikiMsg( 'passwordreset-emailsentemail' );
|
||||
} else {
|
||||
$this->getOutput()->addWikiMsg( 'passwordreset-emailsentusername' );
|
||||
}
|
||||
|
||||
$this->getOutput()->returnToMain();
|
||||
}
|
||||
|
||||
protected function canChangePassword( User $user ) {
|
||||
global $wgAuth;
|
||||
$resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
|
||||
|
||||
// Maybe password resets are disabled, or there are no allowable routes
|
||||
if ( !is_array( $resetRoutes ) ||
|
||||
!in_array( true, array_values( $resetRoutes ) )
|
||||
) {
|
||||
return 'passwordreset-disabled';
|
||||
}
|
||||
|
||||
// Maybe the external auth plugin won't allow local password changes
|
||||
if ( !$wgAuth->allowPasswordChange() ) {
|
||||
return 'resetpass_forbidden';
|
||||
}
|
||||
|
||||
// Maybe email features have been disabled
|
||||
if ( !$this->getConfig()->get( 'EnableEmail' ) ) {
|
||||
return 'passwordreset-emaildisabled';
|
||||
}
|
||||
|
||||
// Maybe the user is blocked (check this here rather than relying on the parent
|
||||
// method as we have a more specific error message to use here
|
||||
if ( $user->isBlocked() ) {
|
||||
return 'blocked-mailpassword';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the password reset page if resets are disabled.
|
||||
* @return bool
|
||||
*/
|
||||
function isListed() {
|
||||
if ( $this->canChangePassword( $this->getUser() ) === true ) {
|
||||
return parent::isListed();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getGroupName() {
|
||||
return 'users';
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,84 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Implements Special:Userlogout
|
||||
*
|
||||
* 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
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements Special:Userlogout
|
||||
*
|
||||
* @ingroup SpecialPage
|
||||
*/
|
||||
class SpecialUserlogoutPreAuthManager extends UnlistedSpecialPage {
|
||||
function __construct() {
|
||||
parent::__construct( 'Userlogout' );
|
||||
}
|
||||
|
||||
public function doesWrites() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function execute( $par ) {
|
||||
/**
|
||||
* Some satellite ISPs use broken precaching schemes that log people out straight after
|
||||
* they're logged in (bug 17790). Luckily, there's a way to detect such requests.
|
||||
*/
|
||||
if ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '&' ) !== false ) {
|
||||
wfDebug( "Special:Userlogout request {$_SERVER['REQUEST_URI']} looks suspicious, denying.\n" );
|
||||
throw new HttpError( 400, $this->msg( 'suspicious-userlogout' ), $this->msg( 'loginerror' ) );
|
||||
}
|
||||
|
||||
$this->setHeaders();
|
||||
$this->outputHeader();
|
||||
|
||||
// Make sure it's possible to log out
|
||||
$session = MediaWiki\Session\SessionManager::getGlobalSession();
|
||||
if ( !$session->canSetUser() ) {
|
||||
throw new ErrorPageError(
|
||||
'cannotlogoutnow-title',
|
||||
'cannotlogoutnow-text',
|
||||
[
|
||||
$session->getProvider()->describe( RequestContext::getMain()->getLanguage() )
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
$oldName = $user->getName();
|
||||
$user->logout();
|
||||
|
||||
$loginURL = SpecialPage::getTitleFor( 'Userlogin' )->getFullURL(
|
||||
$this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
|
||||
|
||||
$out = $this->getOutput();
|
||||
$out->addWikiMsg( 'logouttext', $loginURL );
|
||||
|
||||
// Hook.
|
||||
$injected_html = '';
|
||||
Hooks::run( 'UserLogoutComplete', [ &$user, &$injected_html, $oldName ] );
|
||||
$out->addHTML( $injected_html );
|
||||
|
||||
$out->returnToMain();
|
||||
}
|
||||
|
||||
protected function getGroupName() {
|
||||
return 'login';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,308 +0,0 @@
|
|||
<?php
|
||||
// @codingStandardsIgnoreFile
|
||||
/**
|
||||
* Html form for account creation (since 1.22 with VForm appearance).
|
||||
*
|
||||
* 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
|
||||
* @ingroup Templates
|
||||
* @deprecated Will be removed when AuthManager lands.
|
||||
* The signup form will be generated via HTMLForm.
|
||||
*/
|
||||
|
||||
class UsercreateTemplate extends BaseTemplate {
|
||||
/**
|
||||
* Extensions (AntiSpoof and TitleBlacklist) call this in response to
|
||||
* UserCreateForm hook to add checkboxes to the create account form.
|
||||
*/
|
||||
function addInputItem( $name, $value, $type, $msg, $helptext = false ) {
|
||||
$this->data['extraInput'][] = [
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
'type' => $type,
|
||||
'msg' => $msg,
|
||||
'helptext' => $helptext,
|
||||
];
|
||||
}
|
||||
|
||||
function execute() {
|
||||
?>
|
||||
<div class="mw-ui-container">
|
||||
<?php if ( $this->haveData( 'languages' ) ) { ?>
|
||||
<div id="languagelinks">
|
||||
<p><?php $this->html( 'languages' ); ?></p>
|
||||
</div>
|
||||
<?php }
|
||||
if ( !wfMessage( 'signupstart' )->isDisabled() ) { ?>
|
||||
<div id="signupstart"><?php $this->msgWiki( 'signupstart' ); ?></div>
|
||||
<?php } ?>
|
||||
<div id="userloginForm">
|
||||
<form name="userlogin2" id="userlogin2" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
|
||||
<section class="mw-form-header">
|
||||
<?php $this->html( 'header' ); ?>
|
||||
</section>
|
||||
<!-- This element is used by the mediawiki.special.userlogin.signup.js module. -->
|
||||
<div
|
||||
id="mw-createacct-status-area"
|
||||
<?php if ( $this->data['message'] ) { ?>
|
||||
class="<?php echo $this->data['messagetype']; ?>box"
|
||||
<?php } else { ?>
|
||||
style="display: none;"
|
||||
<?php } ?>
|
||||
>
|
||||
<?php if ( $this->data['message'] ) { ?>
|
||||
<?php if ( $this->data['messagetype'] == 'error' ) { ?>
|
||||
<strong><?php $this->msg( 'createacct-error' ); ?></strong>
|
||||
<br />
|
||||
<?php } ?>
|
||||
<?php $this->html( 'message' ); ?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<?php if ( $this->data['formheader'] ) { ?>
|
||||
<div class="mw-form-formheader">
|
||||
<?php $this->html( 'formheader' ); /* extensions such as MobileFrontend add html here */ ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<div class="mw-ui-vform-field">
|
||||
<label for='wpName2'>
|
||||
<?php $this->msg( 'userlogin-yourname' ); ?>
|
||||
|
||||
<span class="mw-ui-flush-right"><?php echo $this->getMsg( 'createacct-helpusername' )->parse(); ?></span>
|
||||
</label>
|
||||
<?php
|
||||
echo Html::input( 'wpName', $this->data['name'], 'text', [
|
||||
'class' => 'mw-ui-input loginText',
|
||||
'id' => 'wpName2',
|
||||
'tabindex' => '1',
|
||||
'size' => '20',
|
||||
'required',
|
||||
'placeholder' => $this->getMsg( $this->data['loggedin'] ?
|
||||
'createacct-another-username-ph' : 'userlogin-yourname-ph' )->text(),
|
||||
] );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="mw-ui-vform-field">
|
||||
<?php if ( $this->data['createemail'] ) { ?>
|
||||
<div class="mw-ui-checkbox">
|
||||
<input name="wpCreateaccountMail" type="checkbox" value="1" id="wpCreateaccountMail" tabindex="2"
|
||||
<?php if ( $this->data['createemailset'] ) {
|
||||
echo 'checked="checked"';
|
||||
} ?>
|
||||
><label for="wpCreateaccountMail">
|
||||
<?php $this->msg( 'createaccountmail' ); ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<div class="mw-ui-vform-field mw-row-password">
|
||||
<label for='wpPassword2'><?php $this->msg( 'userlogin-yourpassword' ); ?></label>
|
||||
<?php
|
||||
echo Html::input( 'wpPassword', null, 'password', [
|
||||
'class' => 'mw-ui-input loginPassword',
|
||||
'id' => 'wpPassword2',
|
||||
'tabindex' => '3',
|
||||
'size' => '20',
|
||||
'required',
|
||||
'placeholder' => $this->getMsg( 'createacct-yourpassword-ph' )->text()
|
||||
] + User::passwordChangeInputAttribs() );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
if ( $this->data['usedomain'] ) {
|
||||
$select = new XmlSelect( 'wpDomain', false, $this->data['domain'] );
|
||||
$select->setAttribute( 'tabindex', 4 );
|
||||
foreach ( $this->data['domainnames'] as $dom ) {
|
||||
$select->addOption( $dom );
|
||||
}
|
||||
?>
|
||||
<div class="mw-ui-vform-field" id="mw-user-domain-section">
|
||||
<label for="wpDomain"><?php $this->msg( 'yourdomainname' ); ?></label>
|
||||
<div>
|
||||
<?php echo $select->getHTML(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<div class="mw-ui-vform-field mw-row-password">
|
||||
<label for='wpRetype'><?php $this->msg( 'createacct-yourpasswordagain' ); ?></label>
|
||||
<?php
|
||||
echo Html::input( 'wpRetype', null, 'password', [
|
||||
'class' => 'mw-ui-input loginPassword',
|
||||
'id' => 'wpRetype',
|
||||
'tabindex' => '5',
|
||||
'size' => '20',
|
||||
'required',
|
||||
'placeholder' => $this->getMsg( 'createacct-yourpasswordagain-ph' )->text()
|
||||
] + User::passwordChangeInputAttribs() );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="mw-ui-vform-field">
|
||||
<?php if ( $this->data['useemail'] ) { ?>
|
||||
<label for='wpEmail'>
|
||||
<?php
|
||||
$this->msg( $this->data['emailrequired'] ?
|
||||
'createacct-emailrequired' :
|
||||
'createacct-emailoptional'
|
||||
);
|
||||
?>
|
||||
</label>
|
||||
<?php
|
||||
echo Html::input( 'wpEmail', $this->data['email'], 'email', [
|
||||
'class' => 'mw-ui-input loginText',
|
||||
'id' => 'wpEmail',
|
||||
'tabindex' => '6',
|
||||
'size' => '20',
|
||||
'required' => $this->data['emailrequired'],
|
||||
'placeholder' => $this->getMsg( $this->data['loggedin'] ?
|
||||
'createacct-another-email-ph' : 'createacct-email-ph' )->text()
|
||||
] );
|
||||
?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<?php if ( $this->data['userealname'] ) { ?>
|
||||
<div class="mw-ui-vform-field">
|
||||
<label for='wpRealName'><?php $this->msg( 'createacct-realname' ); ?></label>
|
||||
<input type='text' class='mw-ui-input loginText' name="wpRealName" id="wpRealName"
|
||||
tabindex="7"
|
||||
value="<?php $this->text( 'realname' ); ?>" size='20' />
|
||||
<div class="prefsectiontip">
|
||||
<?php $this->msgWiki( $this->data['loggedin'] ? 'createacct-another-realname-tip' : 'prefs-help-realname' ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ( $this->data['usereason'] ) { ?>
|
||||
<div class="mw-ui-vform-field">
|
||||
<label for='wpReason'><?php $this->msg( 'createacct-reason' ); ?></label>
|
||||
<?php echo Html::input( 'wpReason', $this->data['reason'], 'text', [
|
||||
'class' => 'mw-ui-input loginText',
|
||||
'id' => 'wpReason',
|
||||
'tabindex' => '8',
|
||||
'size' => '20',
|
||||
'placeholder' => $this->getMsg( 'createacct-reason-ph' )->text()
|
||||
] ); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php
|
||||
$tabIndex = 9;
|
||||
if ( isset( $this->data['extraInput'] ) && is_array( $this->data['extraInput'] ) ) {
|
||||
foreach ( $this->data['extraInput'] as $inputItem ) { ?>
|
||||
<div class="mw-ui-vform-field">
|
||||
<?php
|
||||
// If it's a checkbox, output the whole thing (assume it has a msg).
|
||||
if ( $inputItem['type'] == 'checkbox' ) {
|
||||
?>
|
||||
<div class="mw-ui-checkbox">
|
||||
<input
|
||||
name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
|
||||
id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
|
||||
type="checkbox" value="1"
|
||||
tabindex="<?php echo $tabIndex++; ?>"
|
||||
<?php if ( !empty( $inputItem['value'] ) ) {
|
||||
echo 'checked="checked"';
|
||||
} ?>
|
||||
><label for="<?php echo htmlspecialchars( $inputItem['name'] ); ?>">
|
||||
<?php $this->msg( $inputItem['msg'] ); ?>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
// Not a checkbox.
|
||||
// TODO (bug 31909) support other input types, e.g. select boxes.
|
||||
?>
|
||||
<?php if ( !empty( $inputItem['msg'] ) ) { ?>
|
||||
<label for="<?php echo htmlspecialchars( $inputItem['name'] ); ?>">
|
||||
<?php $this->msgWiki( $inputItem['msg'] ); ?>
|
||||
</label>
|
||||
<?php } ?>
|
||||
<input
|
||||
type="<?php echo htmlspecialchars( $inputItem['type'] ); ?>"
|
||||
class="mw-ui-input"
|
||||
name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
|
||||
tabindex="<?php echo $tabIndex++; ?>"
|
||||
value="<?php echo htmlspecialchars( $inputItem['value'] ); ?>"
|
||||
id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
|
||||
/>
|
||||
<?php } ?>
|
||||
<?php if ( $inputItem['helptext'] !== false ) { ?>
|
||||
<div class="prefsectiontip">
|
||||
<?php $this->msgWiki( $inputItem['helptext'] ); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
// A separate placeholder for any inserting any extrafields, e.g used by ConfirmEdit extension
|
||||
if ( $this->haveData( 'extrafields' ) ) {
|
||||
echo $this->data['extrafields'];
|
||||
}
|
||||
// skip one index.
|
||||
$tabIndex++;
|
||||
?>
|
||||
<div class="mw-ui-vform-field mw-submit">
|
||||
<?php
|
||||
echo Html::submitButton(
|
||||
$this->getMsg( $this->data['loggedin'] ? 'createacct-another-submit' : 'createacct-submit' ),
|
||||
[
|
||||
'id' => 'wpCreateaccount',
|
||||
'name' => 'wpCreateaccount',
|
||||
'tabindex' => $tabIndex++
|
||||
],
|
||||
[
|
||||
'mw-ui-block',
|
||||
'mw-ui-constructive',
|
||||
]
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php if ( $this->haveData( 'uselang' ) ) { ?><input type="hidden" name="uselang" value="<?php $this->text( 'uselang' ); ?>" /><?php } ?>
|
||||
<?php if ( $this->haveData( 'token' ) ) { ?><input type="hidden" name="wpCreateaccountToken" value="<?php $this->text( 'token' ); ?>" /><?php } ?>
|
||||
</form>
|
||||
<?php if ( !wfMessage( 'signupend' )->isDisabled() ) { ?>
|
||||
<div id="signupend"><?php $this->html( 'signupend' ); ?></div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="mw-createacct-benefits-container">
|
||||
<h2><?php $this->msg( 'createacct-benefit-heading' ); ?></h2>
|
||||
<div class="mw-createacct-benefits-list">
|
||||
<?php
|
||||
for ( $benefitIdx = 1; $benefitIdx <= $this->data['benefitCount']; $benefitIdx++ ) {
|
||||
// Pass each benefit's head text (by default a number) as a parameter to the body's message for PLURAL handling.
|
||||
$headUnescaped = $this->getMsg( "createacct-benefit-head$benefitIdx" )->text();
|
||||
?>
|
||||
<div class="mw-number-text <?php $this->msg( "createacct-benefit-icon$benefitIdx" ); ?>">
|
||||
<h3><?php $this->msg( "createacct-benefit-head$benefitIdx" ); ?></h3>
|
||||
<p><?php echo $this->getMsg( "createacct-benefit-body$benefitIdx" )->params( $headUnescaped )->escaped(); ?></p>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
<?php
|
||||
// @codingStandardsIgnoreFile
|
||||
/**
|
||||
* HTML form for user login (since 1.22 with VForm appearance).
|
||||
*
|
||||
* 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
|
||||
* @ingroup Templates
|
||||
* @deprecated Will be removed when AuthManager lands.
|
||||
* The login form will be generated via HTMLForm.
|
||||
*/
|
||||
|
||||
class UserloginTemplate extends BaseTemplate {
|
||||
|
||||
function execute() {
|
||||
global $wgCookieExpiration;
|
||||
$expirationDays = ceil( $wgCookieExpiration / ( 3600 * 24 ) );
|
||||
?>
|
||||
<div class="mw-ui-container">
|
||||
<div id="userloginprompt"><?php $this->msgWiki('loginprompt') ?></div>
|
||||
<?php if ( $this->haveData( 'languages' ) ) { ?>
|
||||
<div id="languagelinks">
|
||||
<p><?php $this->html( 'languages' ); ?></p>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div id="userloginForm">
|
||||
<form name="userlogin" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
|
||||
<?php if ( $this->data['loggedin'] ) { ?>
|
||||
<div class="warningbox">
|
||||
<?php echo $this->getMsg( 'userlogin-loggedin' )->params( $this->data['loggedinuser'] )->parse(); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<section class="mw-form-header">
|
||||
<?php $this->html( 'header' ); /* extensions such as ConfirmEdit add form HTML here */ ?>
|
||||
</section>
|
||||
|
||||
<?php if ( $this->data['message'] ) { ?>
|
||||
<div class="<?php $this->text( 'messagetype' ); ?>box">
|
||||
<?php if ( $this->data['messagetype'] == 'error' ) { ?>
|
||||
<strong><?php $this->msg( 'loginerror' ); ?></strong>
|
||||
<br />
|
||||
<?php } ?>
|
||||
<?php $this->html( 'message' ); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ( $this->data['formheader'] ) { ?>
|
||||
<div class="mw-form-formheader">
|
||||
<?php $this->html( 'formheader' ); /* extensions such as MobileFrontend add HTML here */ ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="mw-ui-vform-field">
|
||||
<label for="wpName1">
|
||||
<?php
|
||||
$this->msg( 'userlogin-yourname' );
|
||||
|
||||
if ( $this->data['secureLoginUrl'] ) {
|
||||
echo Html::element( 'a', [
|
||||
'href' => $this->data['secureLoginUrl'],
|
||||
'class' => 'mw-ui-flush-right mw-secure',
|
||||
], $this->getMsg( 'userlogin-signwithsecure' )->text() );
|
||||
}
|
||||
?>
|
||||
</label>
|
||||
<?php
|
||||
echo Html::input( 'wpName', $this->data['name'], 'text', [
|
||||
'class' => 'loginText mw-ui-input',
|
||||
'id' => 'wpName1',
|
||||
'tabindex' => '1',
|
||||
// 'required' is blacklisted for now in Html.php due to browser issues.
|
||||
// Keeping here in case that changes.
|
||||
'required' => true,
|
||||
// Set focus to this field if it's blank.
|
||||
'autofocus' => !$this->data['name'],
|
||||
'placeholder' => $this->getMsg( 'userlogin-yourname-ph' )->text()
|
||||
] );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="mw-ui-vform-field">
|
||||
<label for="wpPassword1">
|
||||
<?php
|
||||
$this->msg( 'userlogin-yourpassword' );
|
||||
?>
|
||||
</label>
|
||||
<?php
|
||||
echo Html::input( 'wpPassword', null, 'password', [
|
||||
'class' => 'loginPassword mw-ui-input',
|
||||
'id' => 'wpPassword1',
|
||||
'tabindex' => '2',
|
||||
// Set focus to this field if username is filled in.
|
||||
'autofocus' => (bool)$this->data['name'],
|
||||
'placeholder' => $this->getMsg( 'userlogin-yourpassword-ph' )->text()
|
||||
] );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
if ( isset( $this->data['usedomain'] ) && $this->data['usedomain'] ) {
|
||||
$select = new XmlSelect( 'wpDomain', false, $this->data['domain'] );
|
||||
$select->setAttribute( 'tabindex', 3 );
|
||||
foreach ( $this->data['domainnames'] as $dom ) {
|
||||
$select->addOption( $dom );
|
||||
}
|
||||
?>
|
||||
<div class="mw-ui-vform-field" id="mw-user-domain-section">
|
||||
<label for="wpDomain"><?php $this->msg( 'yourdomainname' ); ?></label>
|
||||
<?php echo $select->getHTML(); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php
|
||||
if ( $this->haveData( 'extrafields' ) ) {
|
||||
echo $this->data['extrafields'];
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="mw-ui-vform-field">
|
||||
<?php if ( $this->data['canremember'] ) { ?>
|
||||
<div class="mw-ui-checkbox">
|
||||
<input name="wpRemember" type="checkbox" value="1" id="wpRemember" tabindex="4"
|
||||
<?php if ( $this->data['remember'] ) {
|
||||
echo 'checked="checked"';
|
||||
} ?>
|
||||
><label for="wpRemember">
|
||||
<?php echo $this->getMsg( 'userlogin-remembermypassword' )->numParams( $expirationDays )->escaped(); ?></label>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<div class="mw-ui-vform-field">
|
||||
<?php
|
||||
$attrs = [
|
||||
'id' => 'wpLoginAttempt',
|
||||
'name' => 'wpLoginAttempt',
|
||||
'tabindex' => '6',
|
||||
];
|
||||
$modifiers = [
|
||||
'mw-ui-progressive',
|
||||
];
|
||||
echo Html::submitButton( $this->getMsg( 'pt-login-button' )->text(), $attrs, $modifiers );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="mw-ui-vform-field mw-form-related-link-container" id="mw-userlogin-help">
|
||||
<?php
|
||||
echo Html::element(
|
||||
'a',
|
||||
[
|
||||
'href' => Skin::makeInternalOrExternalUrl(
|
||||
wfMessage( 'helplogin-url' )->inContentLanguage()->text()
|
||||
),
|
||||
],
|
||||
$this->getMsg( 'userlogin-helplink2' )->text()
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
if ( $this->data['useemail'] && $this->data['canreset'] && $this->data['resetlink'] === true ) {
|
||||
echo Html::rawElement(
|
||||
'div',
|
||||
[
|
||||
'class' => 'mw-ui-vform-field mw-form-related-link-container',
|
||||
],
|
||||
Linker::link(
|
||||
SpecialPage::getTitleFor( 'PasswordReset' ),
|
||||
$this->getMsg( 'userlogin-resetpassword-link' )->escaped()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( $this->haveData( 'createOrLoginHref' ) ) {
|
||||
if ( $this->data['loggedin'] ) { ?>
|
||||
<div class="mw-form-related-link-container mw-ui-vform-field">
|
||||
<a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7"><?php $this->msg( 'userlogin-createanother' ); ?></a>
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div id="mw-createaccount-cta" class="mw-ui-vform-field">
|
||||
<?php $this->msg( 'userlogin-noaccount' ); ?><a href="<?php $this->text( 'createOrLoginHref' ); ?>" id="mw-createaccount-join" tabindex="7" class="mw-ui-button"><?php $this->msg( 'userlogin-joinproject' ); ?></a>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
// Hidden fields
|
||||
$fields = '';
|
||||
if ( $this->haveData( 'uselang' ) ) {
|
||||
$fields .= Html::hidden( 'uselang', $this->data['uselang'] );
|
||||
}
|
||||
if ( $this->haveData( 'token' ) ) {
|
||||
$fields .= Html::hidden( 'wpLoginToken', $this->data['token'] );
|
||||
}
|
||||
if ( $this->data['cansecurelogin'] ) {
|
||||
$fields .= Html::hidden( 'wpForceHttps', $this->data['stickhttps'] );
|
||||
}
|
||||
if ( $this->data['cansecurelogin'] && $this->haveData( 'fromhttp' ) ) {
|
||||
$fields .= Html::hidden( 'wpFromhttp', $this->data['fromhttp'] );
|
||||
}
|
||||
echo $fields;
|
||||
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -648,8 +648,6 @@ class User implements IDBAccessObject {
|
|||
* @since 1.27
|
||||
*/
|
||||
public static function newSystemUser( $name, $options = [] ) {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
$options += [
|
||||
'validate' => 'valid',
|
||||
'create' => true,
|
||||
|
|
@ -662,9 +660,6 @@ class User implements IDBAccessObject {
|
|||
}
|
||||
|
||||
$fields = self::selectFields();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$fields = array_merge( $fields, [ 'user_password', 'user_newpassword' ] );
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$row = $dbw->selectRow(
|
||||
|
|
@ -681,49 +676,15 @@ class User implements IDBAccessObject {
|
|||
|
||||
// A user is considered to exist as a non-system user if it can
|
||||
// authenticate, or has an email set, or has a non-invalid token.
|
||||
if ( !$user->mEmail && $user->mToken === self::INVALID_TOKEN ) {
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$passwordFactory = new PasswordFactory();
|
||||
$passwordFactory->init( RequestContext::getMain()->getConfig() );
|
||||
try {
|
||||
$password = $passwordFactory->newFromCiphertext( $row->user_password );
|
||||
} catch ( PasswordError $e ) {
|
||||
wfDebug( 'Invalid password hash found in database.' );
|
||||
$password = PasswordFactory::newInvalidPassword();
|
||||
}
|
||||
try {
|
||||
$newpassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
|
||||
} catch ( PasswordError $e ) {
|
||||
wfDebug( 'Invalid password hash found in database.' );
|
||||
$newpassword = PasswordFactory::newInvalidPassword();
|
||||
}
|
||||
$canAuthenticate = !$password instanceof InvalidPassword ||
|
||||
!$newpassword instanceof InvalidPassword;
|
||||
} else {
|
||||
$canAuthenticate = AuthManager::singleton()->userCanAuthenticate( $name );
|
||||
}
|
||||
}
|
||||
if ( $user->mEmail || $user->mToken !== self::INVALID_TOKEN || $canAuthenticate ) {
|
||||
if ( $user->mEmail || $user->mToken !== self::INVALID_TOKEN ||
|
||||
AuthManager::singleton()->userCanAuthenticate( $name )
|
||||
) {
|
||||
// User exists. Steal it?
|
||||
if ( !$options['steal'] ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$nopass = PasswordFactory::newInvalidPassword()->toString();
|
||||
$dbw->update(
|
||||
'user',
|
||||
[
|
||||
'user_password' => $nopass,
|
||||
'user_newpassword' => $nopass,
|
||||
'user_newpass_time' => null,
|
||||
],
|
||||
[ 'user_id' => $user->getId() ],
|
||||
__METHOD__
|
||||
);
|
||||
} else {
|
||||
AuthManager::singleton()->revokeAccessForUser( $name );
|
||||
}
|
||||
AuthManager::singleton()->revokeAccessForUser( $name );
|
||||
|
||||
$user->invalidateEmail();
|
||||
$user->mToken = self::INVALID_TOKEN;
|
||||
|
|
@ -2508,31 +2469,7 @@ class User implements IDBAccessObject {
|
|||
* @return bool
|
||||
*/
|
||||
public function setPassword( $str ) {
|
||||
global $wgAuth, $wgDisableAuthManager;
|
||||
|
||||
if ( !$wgDisableAuthManager ) {
|
||||
return $this->setPasswordInternal( $str );
|
||||
}
|
||||
|
||||
if ( $str !== null ) {
|
||||
if ( !$wgAuth->allowPasswordChange() ) {
|
||||
throw new PasswordError( wfMessage( 'password-change-forbidden' )->text() );
|
||||
}
|
||||
|
||||
$status = $this->checkPasswordValidity( $str );
|
||||
if ( !$status->isGood() ) {
|
||||
throw new PasswordError( $status->getMessage()->text() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$wgAuth->setPassword( $this, $str ) ) {
|
||||
throw new PasswordError( wfMessage( 'externaldberror' )->text() );
|
||||
}
|
||||
|
||||
$this->setOption( 'watchlisttoken', false );
|
||||
$this->setPasswordInternal( $str );
|
||||
|
||||
return true;
|
||||
return $this->setPasswordInternal( $str );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2544,16 +2481,7 @@ class User implements IDBAccessObject {
|
|||
* through the web interface.
|
||||
*/
|
||||
public function setInternalPassword( $str ) {
|
||||
global $wgAuth, $wgDisableAuthManager;
|
||||
|
||||
if ( !$wgDisableAuthManager ) {
|
||||
$this->setPasswordInternal( $str );
|
||||
}
|
||||
|
||||
if ( $wgAuth->allowSetLocalPassword() ) {
|
||||
$this->setOption( 'watchlisttoken', false );
|
||||
$this->setPasswordInternal( $str );
|
||||
}
|
||||
$this->setPasswordInternal( $str );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2565,55 +2493,26 @@ class User implements IDBAccessObject {
|
|||
* @return bool Success
|
||||
*/
|
||||
private function setPasswordInternal( $str ) {
|
||||
global $wgDisableAuthManager;
|
||||
$manager = AuthManager::singleton();
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$id = self::idFromName( $this->getName(), self::READ_LATEST );
|
||||
if ( $id == 0 ) {
|
||||
throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
|
||||
}
|
||||
|
||||
$passwordFactory = new PasswordFactory();
|
||||
$passwordFactory->init( RequestContext::getMain()->getConfig() );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->update(
|
||||
'user',
|
||||
[
|
||||
'user_password' => $passwordFactory->newFromPlaintext( $str )->toString(),
|
||||
'user_newpassword' => PasswordFactory::newInvalidPassword()->toString(),
|
||||
'user_newpass_time' => $dbw->timestampOrNull( null ),
|
||||
],
|
||||
[
|
||||
'user_id' => $id,
|
||||
],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
// When the main password is changed, invalidate all bot passwords too
|
||||
BotPassword::invalidateAllPasswordsForUser( $this->getName() );
|
||||
} else {
|
||||
$manager = AuthManager::singleton();
|
||||
|
||||
// If the user doesn't exist yet, fail
|
||||
if ( !$manager->userExists( $this->getName() ) ) {
|
||||
throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
|
||||
}
|
||||
|
||||
$status = $this->changeAuthenticationData( [
|
||||
'username' => $this->getName(),
|
||||
'password' => $str,
|
||||
'retype' => $str,
|
||||
] );
|
||||
if ( !$status->isGood() ) {
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
|
||||
->info( __METHOD__ . ': Password change rejected: '
|
||||
. $status->getWikiText( null, null, 'en' ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setOption( 'watchlisttoken', false );
|
||||
// If the user doesn't exist yet, fail
|
||||
if ( !$manager->userExists( $this->getName() ) ) {
|
||||
throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
|
||||
}
|
||||
|
||||
$status = $this->changeAuthenticationData( [
|
||||
'username' => $this->getName(),
|
||||
'password' => $str,
|
||||
'retype' => $str,
|
||||
] );
|
||||
if ( !$status->isGood() ) {
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
|
||||
->info( __METHOD__ . ': Password change rejected: '
|
||||
. $status->getWikiText( null, null, 'en' ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setOption( 'watchlisttoken', false );
|
||||
SessionManager::singleton()->invalidateSessionsForUser( $this );
|
||||
|
||||
return true;
|
||||
|
|
@ -2632,12 +2531,6 @@ class User implements IDBAccessObject {
|
|||
* @since 1.27
|
||||
*/
|
||||
public function changeAuthenticationData( array $data ) {
|
||||
global $wgDisableAuthManager;
|
||||
if ( $wgDisableAuthManager ) {
|
||||
throw new LogicException( __METHOD__ . ' cannot be called when $wgDisableAuthManager '
|
||||
. 'is true' );
|
||||
}
|
||||
|
||||
$manager = AuthManager::singleton();
|
||||
$reqs = $manager->getAuthenticationRequests( AuthManager::ACTION_CHANGE, $this );
|
||||
$reqs = AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data );
|
||||
|
|
@ -2723,32 +2616,7 @@ class User implements IDBAccessObject {
|
|||
* @param bool $throttle If true, reset the throttle timestamp to the present
|
||||
*/
|
||||
public function setNewpassword( $str, $throttle = true ) {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$id = $this->getId();
|
||||
if ( $id == 0 ) {
|
||||
throw new LogicException( 'Cannot set new password for a user that is not in the database.' );
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
$passwordFactory = new PasswordFactory();
|
||||
$passwordFactory->init( RequestContext::getMain()->getConfig() );
|
||||
$update = [
|
||||
'user_newpassword' => $passwordFactory->newFromPlaintext( $str )->toString(),
|
||||
];
|
||||
|
||||
if ( $str === null ) {
|
||||
$update['user_newpass_time'] = null;
|
||||
} elseif ( $throttle ) {
|
||||
$update['user_newpass_time'] = $dbw->timestamp();
|
||||
}
|
||||
|
||||
$dbw->update( 'user', $update, [ 'user_id' => $id ], __METHOD__ );
|
||||
} else {
|
||||
throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
|
||||
}
|
||||
throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2758,33 +2626,7 @@ class User implements IDBAccessObject {
|
|||
* @return bool
|
||||
*/
|
||||
public function isPasswordReminderThrottled() {
|
||||
global $wgPasswordReminderResendTime, $wgDisableAuthManager;
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
if ( !$wgPasswordReminderResendTime ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->load();
|
||||
|
||||
$db = ( $this->queryFlagsUsed & self::READ_LATEST )
|
||||
? wfGetDB( DB_MASTER )
|
||||
: wfGetDB( DB_SLAVE );
|
||||
$newpassTime = $db->selectField(
|
||||
'user',
|
||||
'user_newpass_time',
|
||||
[ 'user_id' => $this->getId() ],
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
if ( $newpassTime === null ) {
|
||||
return false;
|
||||
}
|
||||
$expiry = wfTimestamp( TS_UNIX, $newpassTime ) + $wgPasswordReminderResendTime * 3600;
|
||||
return time() < $expiry;
|
||||
} else {
|
||||
throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
|
||||
}
|
||||
throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4280,87 +4122,27 @@ class User implements IDBAccessObject {
|
|||
* @return bool True if the given password is correct, otherwise False
|
||||
*/
|
||||
public function checkPassword( $password ) {
|
||||
global $wgAuth, $wgLegacyEncoding, $wgDisableAuthManager;
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->load();
|
||||
|
||||
// Some passwords will give a fatal Status, which means there is
|
||||
// some sort of technical or security reason for this password to
|
||||
// be completely invalid and should never be checked (e.g., T64685)
|
||||
if ( !$this->checkPasswordValidity( $password )->isOK() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Certain authentication plugins do NOT want to save
|
||||
// domain passwords in a mysql database, so we should
|
||||
// check this (in case $wgAuth->strict() is false).
|
||||
if ( $wgAuth->authenticate( $this->getName(), $password ) ) {
|
||||
$manager = AuthManager::singleton();
|
||||
$reqs = AuthenticationRequest::loadRequestsFromSubmission(
|
||||
$manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN ),
|
||||
[
|
||||
'username' => $this->getName(),
|
||||
'password' => $password,
|
||||
]
|
||||
);
|
||||
$res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
|
||||
switch ( $res->status ) {
|
||||
case AuthenticationResponse::PASS:
|
||||
return true;
|
||||
} elseif ( $wgAuth->strict() ) {
|
||||
// Auth plugin doesn't allow local authentication
|
||||
case AuthenticationResponse::FAIL:
|
||||
// Hope it's not a PreAuthenticationProvider that failed...
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
|
||||
->info( __METHOD__ . ': Authentication failed: ' . $res->message->plain() );
|
||||
return false;
|
||||
} elseif ( $wgAuth->strictUserAuth( $this->getName() ) ) {
|
||||
// Auth plugin doesn't allow local authentication for this user name
|
||||
return false;
|
||||
}
|
||||
|
||||
$passwordFactory = new PasswordFactory();
|
||||
$passwordFactory->init( RequestContext::getMain()->getConfig() );
|
||||
$db = ( $this->queryFlagsUsed & self::READ_LATEST )
|
||||
? wfGetDB( DB_MASTER )
|
||||
: wfGetDB( DB_SLAVE );
|
||||
|
||||
try {
|
||||
$mPassword = $passwordFactory->newFromCiphertext( $db->selectField(
|
||||
'user', 'user_password', [ 'user_id' => $this->getId() ], __METHOD__
|
||||
) );
|
||||
} catch ( PasswordError $e ) {
|
||||
wfDebug( 'Invalid password hash found in database.' );
|
||||
$mPassword = PasswordFactory::newInvalidPassword();
|
||||
}
|
||||
|
||||
if ( !$mPassword->equals( $password ) ) {
|
||||
if ( $wgLegacyEncoding ) {
|
||||
// Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
|
||||
// Check for this with iconv
|
||||
$cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password );
|
||||
if ( $cp1252Password === $password || !$mPassword->equals( $cp1252Password ) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $passwordFactory->needsUpdate( $mPassword ) && !wfReadOnly() ) {
|
||||
$this->setPasswordInternal( $password );
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
$manager = AuthManager::singleton();
|
||||
$reqs = AuthenticationRequest::loadRequestsFromSubmission(
|
||||
$manager->getAuthenticationRequests( AuthManager::ACTION_LOGIN ),
|
||||
[
|
||||
'username' => $this->getName(),
|
||||
'password' => $password,
|
||||
]
|
||||
);
|
||||
$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...
|
||||
\MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
|
||||
->info( __METHOD__ . ': Authentication failed: ' . $res->message->plain() );
|
||||
return false;
|
||||
default:
|
||||
throw new BadMethodCallException(
|
||||
'AuthManager returned a response unsupported by ' . __METHOD__
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new BadMethodCallException(
|
||||
'AuthManager returned a response unsupported by ' . __METHOD__
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4373,43 +4155,8 @@ class User implements IDBAccessObject {
|
|||
* @return bool True if matches, false otherwise
|
||||
*/
|
||||
public function checkTemporaryPassword( $plaintext ) {
|
||||
global $wgNewPasswordExpiry, $wgDisableAuthManager;
|
||||
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->load();
|
||||
|
||||
$passwordFactory = new PasswordFactory();
|
||||
$passwordFactory->init( RequestContext::getMain()->getConfig() );
|
||||
$db = ( $this->queryFlagsUsed & self::READ_LATEST )
|
||||
? wfGetDB( DB_MASTER )
|
||||
: wfGetDB( DB_SLAVE );
|
||||
|
||||
$row = $db->selectRow(
|
||||
'user',
|
||||
[ 'user_newpassword', 'user_newpass_time' ],
|
||||
[ 'user_id' => $this->getId() ],
|
||||
__METHOD__
|
||||
);
|
||||
try {
|
||||
$newPassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
|
||||
} catch ( PasswordError $e ) {
|
||||
wfDebug( 'Invalid password hash found in database.' );
|
||||
$newPassword = PasswordFactory::newInvalidPassword();
|
||||
}
|
||||
|
||||
if ( $newPassword->equals( $plaintext ) ) {
|
||||
if ( is_null( $row->user_newpass_time ) ) {
|
||||
return true;
|
||||
}
|
||||
$expiry = wfTimestamp( TS_UNIX, $row->user_newpass_time ) + $wgNewPasswordExpiry;
|
||||
return ( time() < $expiry );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Can't check the temporary password individually.
|
||||
return $this->checkPassword( $plaintext );
|
||||
}
|
||||
// Can't check the temporary password individually.
|
||||
return $this->checkPassword( $plaintext );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5286,45 +5033,10 @@ class User implements IDBAccessObject {
|
|||
* - false will be converted to 'create' if this object is the same as
|
||||
* $wgUser and to 'create2' otherwise
|
||||
* @param string $reason User supplied reason
|
||||
* @return int|bool True if not $wgNewUserLog or not $wgDisableAuthManager;
|
||||
* otherwise ID of log item or 0 on failure
|
||||
* @return bool true
|
||||
*/
|
||||
public function addNewUserLogEntry( $action = false, $reason = '' ) {
|
||||
global $wgUser, $wgNewUserLog, $wgDisableAuthManager;
|
||||
if ( !$wgDisableAuthManager || empty( $wgNewUserLog ) ) {
|
||||
return true; // disabled
|
||||
}
|
||||
|
||||
if ( $action === true ) {
|
||||
$action = 'byemail';
|
||||
} elseif ( $action === false ) {
|
||||
if ( $this->equals( $wgUser ) ) {
|
||||
$action = 'create';
|
||||
} else {
|
||||
$action = 'create2';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $action === 'create' || $action === 'autocreate' ) {
|
||||
$performer = $this;
|
||||
} else {
|
||||
$performer = $wgUser;
|
||||
}
|
||||
|
||||
$logEntry = new ManualLogEntry( 'newusers', $action );
|
||||
$logEntry->setPerformer( $performer );
|
||||
$logEntry->setTarget( $this->getUserPage() );
|
||||
$logEntry->setComment( $reason );
|
||||
$logEntry->setParameters( [
|
||||
'4::userid' => $this->getId(),
|
||||
] );
|
||||
$logid = $logEntry->insert();
|
||||
|
||||
if ( $action !== 'autocreate' ) {
|
||||
$logEntry->publish( $logid );
|
||||
}
|
||||
|
||||
return (int)$logid;
|
||||
return true; // disabled
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -605,8 +605,6 @@
|
|||
"passwordreset-emailelement": "Username:\n$1\n\nTemporary password:\n$2",
|
||||
"passwordreset-emailsentemail": "If this email address is associated with your account, then a password reset email will be sent.",
|
||||
"passwordreset-emailsentusername": "If there is an email address associated with this username, then a password reset email will be sent.",
|
||||
"passwordreset-emailsent-capture": "A password reset email has been sent, which is shown below.",
|
||||
"passwordreset-emailerror-capture": "A password reset email was generated, which is shown below, but sending it to the {{GENDER:$2|user}} failed: $1",
|
||||
"passwordreset-emailsent-capture2": "The password reset {{PLURAL:$1|email has|emails have}} been sent. The {{PLURAL:$1|username and password|list of usernames and passwords}} is shown below.",
|
||||
"passwordreset-emailerror-capture2": "Emailing the {{GENDER:$2|user}} failed: $1 The {{PLURAL:$3|username and password|list of usernames and passwords}} is shown below.",
|
||||
"passwordreset-nocaller": "A caller must be provided",
|
||||
|
|
@ -617,7 +615,6 @@
|
|||
"changeemail": "Change or remove email address",
|
||||
"changeemail-summary": "",
|
||||
"changeemail-header": "Complete this form to change your email address. If you would like to remove the association of any email address from your account, leave the new email address blank when submitting the form.",
|
||||
"changeemail-passwordrequired": "You will need to enter your password to confirm this change.",
|
||||
"changeemail-no-info": "You must be logged in to access this page directly.",
|
||||
"changeemail-oldemail": "Current email address:",
|
||||
"changeemail-newemail": "New email address:",
|
||||
|
|
@ -815,7 +812,6 @@
|
|||
"undo-nochange": "The edit appears to have already been undone.",
|
||||
"undo-summary": "Undo revision $1 by [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]])",
|
||||
"undo-summary-username-hidden": "Undo revision $1 by a hidden user",
|
||||
"cantcreateaccounttitle": "Cannot create account",
|
||||
"cantcreateaccount-text": "Account creation from this IP address (<strong>$1</strong>) has been blocked by [[User:$3|$3]].\n\nThe reason given by $3 is <em>$2</em>",
|
||||
"cantcreateaccount-range-text": "Account creation from IP addresses in the range <strong>$1</strong>, which includes your IP address (<strong>$4</strong>), has been blocked by [[User:$3|$3]].\n\nThe reason given by $3 is <em>$2</em>",
|
||||
"createaccount-hook-aborted": "$1",
|
||||
|
|
|
|||
|
|
@ -788,8 +788,6 @@
|
|||
"passwordreset-emailelement": "This is a body of a password reset email to allow them into the system with a new password. Parameters:\n* $1 - the user's login name. This parameter can be used for GENDER.\n* $2 - the temporary password given by the system",
|
||||
"passwordreset-emailsentemail": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
|
||||
"passwordreset-emailsentusername": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
|
||||
"passwordreset-emailsent-capture": "Used in [[Special:PasswordReset]].\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
|
||||
"passwordreset-emailerror-capture": "Error message displayed in [[Special:PasswordReset]] when sending an email fails. Parameters:\n* $1 - error message\n* $2 - username, used for GENDER\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailsent-capture}}",
|
||||
"passwordreset-emailsent-capture2": "Used in [[Special:PasswordReset]].\n\nParameters:\n* $1 - number of accounts notified\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
|
||||
"passwordreset-emailerror-capture2": "Error message displayed in [[Special:PasswordReset]] when sending an email fails. Parameters:\n* $1 - error message\n* $2 - username, used for GENDER\n* $3 - number of accounts notified\n\nSee also:\n* {{msg-mw|Passwordreset-emailsentemail}}\n* {{msg-mw|Passwordreset-emailsentusername}}\n* {{msg-mw|Passwordreset-emailsent-capture}}\n* {{msg-mw|Passwordreset-emailerror-capture}}",
|
||||
"passwordreset-nocaller": "Shown when a password reset was requested but the caller was not provided. This is an internal error.",
|
||||
|
|
@ -800,7 +798,6 @@
|
|||
"changeemail": "Title of [[Special:ChangeEmail|special page]]. This page also allows removing the user's email address.",
|
||||
"changeemail-summary": "{{ignored}}",
|
||||
"changeemail-header": "Text of [[Special:ChangeEmail]].",
|
||||
"changeemail-passwordrequired": "Shown on [[Special:ChangeEmail]] if users are required to enter their password to change their email address..",
|
||||
"changeemail-no-info": "Error message for [[Special:ChangeEmail]].\n\nParameters:\n* $1 (unused) - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",
|
||||
"changeemail-oldemail": "Label for e-mail address field in [[Special:ChangeEmail]].",
|
||||
"changeemail-newemail": "Label for e-mail address field in [[Special:ChangeEmail]]. See also {{msg-mw|changeemail-newemail-help}}",
|
||||
|
|
@ -998,8 +995,7 @@
|
|||
"undo-nochange": "Message appears if an attempt to revert an edit by clicking the \"undo\" link results in an edit making no change to the current version of the page.\n\nSee also:\n* {{msg-mw|Undo-failure}}\n* {{msg-mw|Undo-norev}}",
|
||||
"undo-summary": "Edit summary for an undo action. Parameters:\n* $1 - revision ID\n* $2 - username\n{{Identical|Undo}}",
|
||||
"undo-summary-username-hidden": "Edit summary for an undo action where the username of the old revision is hidden.\n\nParameters:\n* $1 - the revision ID being undone\nSee also:\n* {{msg-mw|Undo-summary}}",
|
||||
"cantcreateaccounttitle": "Used as title of the error message {{msg-mw|Cantcreateaccount-text}}.",
|
||||
"cantcreateaccount-text": "Used as error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP address\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\nSee also:\n* {{msg-mw|Cantcreateaccount-range-text}}",
|
||||
"cantcreateaccount-text": "Used as error message when account creation is prevented by an IP block.\n* $1 - target IP address\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\nSee also:\n* {{msg-mw|Cantcreateaccount-range-text}}",
|
||||
"cantcreateaccount-range-text": "Used instead of the {{msg-mw|Cantcreateaccount-text}} when the block is a range block.\n* $1 - target IP address range\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\n* $4 - current user's IP address",
|
||||
"createaccount-hook-aborted": "Placeholder message to return with API errors on account create; passes through the message from a hook {{notranslate}}",
|
||||
"viewpagelogs": "Link displayed in history of pages",
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ class ChangePassword extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
if ( $this->hasOption( "user" ) ) {
|
||||
$user = User::newFromName( $this->getOption( 'user' ) );
|
||||
} elseif ( $this->hasOption( "userid" ) ) {
|
||||
|
|
@ -55,17 +53,13 @@ class ChangePassword extends Maintenance {
|
|||
}
|
||||
$password = $this->getOption( 'password' );
|
||||
try {
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$user->setPassword( $password );
|
||||
} else {
|
||||
$status = $user->changeAuthenticationData( [
|
||||
'username' => $user->getName(),
|
||||
'password' => $password,
|
||||
'retype' => $password,
|
||||
] );
|
||||
if ( !$status->isGood() ) {
|
||||
throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
|
||||
}
|
||||
$status = $user->changeAuthenticationData( [
|
||||
'username' => $user->getName(),
|
||||
'password' => $password,
|
||||
'retype' => $password,
|
||||
] );
|
||||
if ( !$status->isGood() ) {
|
||||
throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
|
||||
}
|
||||
$user->saveSettings();
|
||||
$this->output( "Password set for " . $user->getName() . "\n" );
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ class CreateAndPromote extends Maintenance {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
$username = $this->getArg( 0 );
|
||||
$password = $this->getArg( 1 );
|
||||
$force = $this->hasOption( 'force' );
|
||||
|
|
@ -122,17 +120,13 @@ class CreateAndPromote extends Maintenance {
|
|||
if ( $password ) {
|
||||
# Try to set the password
|
||||
try {
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$user->setPassword( $password );
|
||||
} else {
|
||||
$status = $user->changeAuthenticationData( [
|
||||
'username' => $user->getName(),
|
||||
'password' => $password,
|
||||
'retype' => $password,
|
||||
] );
|
||||
if ( !$status->isGood() ) {
|
||||
throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
|
||||
}
|
||||
$status = $user->changeAuthenticationData( [
|
||||
'username' => $user->getName(),
|
||||
'password' => $password,
|
||||
'retype' => $password,
|
||||
] );
|
||||
if ( !$status->isGood() ) {
|
||||
throw new PasswordError( $status->getWikiText( null, null, 'en' ) );
|
||||
}
|
||||
if ( $exists ) {
|
||||
$this->output( "Password set.\n" );
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ class ApiLoginTest extends ApiTestCase {
|
|||
* Test result of attempted login with an empty username
|
||||
*/
|
||||
public function testApiLoginNoName() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
$session = [
|
||||
'wsTokenSecrets' => [ 'login' => 'foobar' ],
|
||||
];
|
||||
|
|
@ -22,11 +20,11 @@ class ApiLoginTest extends ApiTestCase {
|
|||
'lgname' => '', 'lgpassword' => self::$users['sysop']->getPassword(),
|
||||
'lgtoken' => (string)( new MediaWiki\Session\Token( 'foobar', '' ) )
|
||||
], $session );
|
||||
$this->assertEquals( $wgDisableAuthManager ? 'NoName' : 'Failed', $data[0]['login']['result'] );
|
||||
$this->assertEquals( 'Failed', $data[0]['login']['result'] );
|
||||
}
|
||||
|
||||
public function testApiLoginBadPass() {
|
||||
global $wgServer, $wgDisableAuthManager;
|
||||
global $wgServer;
|
||||
|
||||
$user = self::$users['sysop'];
|
||||
$userName = $user->getUser()->getName();
|
||||
|
|
@ -64,7 +62,7 @@ class ApiLoginTest extends ApiTestCase {
|
|||
$this->assertNotInternalType( "bool", $result );
|
||||
$a = $result["login"]["result"];
|
||||
|
||||
$this->assertEquals( $wgDisableAuthManager ? 'WrongPass' : 'Failed', $a );
|
||||
$this->assertEquals( 'Failed', $a );
|
||||
}
|
||||
|
||||
public function testApiLoginGoodPass() {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
|
|||
protected $apiContext;
|
||||
|
||||
protected function setUp() {
|
||||
global $wgServer, $wgDisableAuthManager;
|
||||
global $wgServer;
|
||||
|
||||
parent::setUp();
|
||||
self::$apiUrl = $wgServer . wfScript( 'api' );
|
||||
|
|
@ -22,7 +22,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
|
|||
];
|
||||
|
||||
$this->setMwGlobals( [
|
||||
'wgAuth' => $wgDisableAuthManager ? new AuthPlugin : new MediaWiki\Auth\AuthManagerAuthPlugin,
|
||||
'wgAuth' => new MediaWiki\Auth\AuthManagerAuthPlugin,
|
||||
'wgRequest' => new FauxRequest( [] ),
|
||||
'wgUser' => self::$users['sysop']->getUser(),
|
||||
] );
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AbstractAuthenticationProvider
|
||||
*/
|
||||
class AbstractAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testAbstractAuthenticationProvider() {
|
||||
$provider = $this->getMockForAbstractClass( AbstractAuthenticationProvider::class );
|
||||
$providerPriv = \TestingAccessWrapper::newFromObject( $provider );
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AbstractPasswordPrimaryAuthenticationProvider
|
||||
*/
|
||||
class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstructor() {
|
||||
$provider = $this->getMockForAbstractClass(
|
||||
AbstractPasswordPrimaryAuthenticationProvider::class
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AbstractPreAuthenticationProvider
|
||||
*/
|
||||
class AbstractPreAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testAbstractPreAuthenticationProvider() {
|
||||
$user = \User::newFromName( 'UTSysop' );
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AbstractPrimaryAuthenticationProvider
|
||||
*/
|
||||
class AbstractPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testAbstractPrimaryAuthenticationProvider() {
|
||||
$user = \User::newFromName( 'UTSysop' );
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AbstractSecondaryAuthenticationProvider
|
||||
*/
|
||||
class AbstractSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testAbstractSecondaryAuthenticationProvider() {
|
||||
$user = \User::newFromName( 'UTSysop' );
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,7 @@ class AuthManagerTest extends \MediaWikiTestCase {
|
|||
protected $managerPriv;
|
||||
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
|
||||
$this->setMwGlobals( [ 'wgAuth' => null ] );
|
||||
$this->stashMwGlobals( [ 'wgHooks' ] );
|
||||
|
|
@ -200,14 +195,6 @@ class AuthManagerTest extends \MediaWikiTestCase {
|
|||
\RequestContext::getMain()->getConfig(),
|
||||
\TestingAccessWrapper::newFromObject( $singleton )->config
|
||||
);
|
||||
|
||||
$this->setMwGlobals( [ 'wgDisableAuthManager' => true ] );
|
||||
try {
|
||||
AuthManager::singleton();
|
||||
$this->fail( 'Expected exception not thrown' );
|
||||
} catch ( \BadMethodCallException $ex ) {
|
||||
$this->assertSame( '$wgDisableAuthManager is set', $ex->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
public function testCanAuthenticateNow() {
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AuthPluginPrimaryAuthenticationProvider
|
||||
*/
|
||||
class AuthPluginPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstruction() {
|
||||
$plugin = new AuthManagerAuthPlugin();
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AuthenticationRequest
|
||||
*/
|
||||
class AuthenticationRequestTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testBasics() {
|
||||
$mock = $this->getMockForAbstractClass( AuthenticationRequest::class );
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,6 @@ namespace MediaWiki\Auth;
|
|||
* @group AuthManager
|
||||
*/
|
||||
abstract class AuthenticationRequestTestCase extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected function getInstance( array $args = [] );
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\AuthenticationResponse
|
||||
*/
|
||||
class AuthenticationResponseTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideConstructors
|
||||
* @param string $constructor
|
||||
|
|
|
|||
|
|
@ -8,15 +8,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\CheckBlocksSecondaryAuthenticationProvider
|
||||
*/
|
||||
class CheckBlocksSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstructor() {
|
||||
$provider = new CheckBlocksSecondaryAuthenticationProvider();
|
||||
$providerPriv = \TestingAccessWrapper::newFromObject( $provider );
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\ConfirmLinkSecondaryAuthenticationProvider
|
||||
*/
|
||||
class ConfirmLinkSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideGetAuthenticationRequests
|
||||
* @param string $action
|
||||
|
|
|
|||
|
|
@ -8,15 +8,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\LegacyHookPreAuthenticationProvider
|
||||
*/
|
||||
class LegacyHookPreAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the provider
|
||||
* @return LegacyHookPreAuthenticationProvider
|
||||
|
|
|
|||
|
|
@ -13,15 +13,6 @@ class LocalPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestCase
|
|||
private $config = null;
|
||||
private $validity = null;
|
||||
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the provider
|
||||
*
|
||||
|
|
|
|||
|
|
@ -7,15 +7,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\ResetPasswordSecondaryAuthenticationProvider
|
||||
*/
|
||||
class ResetPasswordSecondaryAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideGetAuthenticationRequests
|
||||
* @param string $action
|
||||
|
|
|
|||
|
|
@ -13,15 +13,6 @@ class TemporaryPasswordPrimaryAuthenticationProviderTest extends \MediaWikiTestC
|
|||
private $config = null;
|
||||
private $validity = null;
|
||||
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the provider
|
||||
*
|
||||
|
|
|
|||
|
|
@ -8,15 +8,6 @@ namespace MediaWiki\Auth;
|
|||
* @covers MediaWiki\Auth\ThrottlePreAuthenticationProvider
|
||||
*/
|
||||
class ThrottlePreAuthenticationProviderTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstructor() {
|
||||
$provider = new ThrottlePreAuthenticationProvider();
|
||||
$providerPriv = \TestingAccessWrapper::newFromObject( $provider );
|
||||
|
|
|
|||
|
|
@ -14,15 +14,6 @@ use Psr\Log\NullLogger;
|
|||
* @covers MediaWiki\Auth\Throttler
|
||||
*/
|
||||
class ThrottlerTest extends \MediaWikiTestCase {
|
||||
protected function setUp() {
|
||||
global $wgDisableAuthManager;
|
||||
|
||||
parent::setUp();
|
||||
if ( $wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( '$wgDisableAuthManager is set' );
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstructor() {
|
||||
$cache = new \HashBagOStuff();
|
||||
$logger = $this->getMockBuilder( AbstractLogger::class )
|
||||
|
|
|
|||
|
|
@ -867,303 +867,6 @@ class SessionManagerTest extends MediaWikiTestCase {
|
|||
$this->assertTrue( SessionManager::validateSessionId( $id ), "Generated ID: $id" );
|
||||
}
|
||||
|
||||
public function testAutoCreateUser() {
|
||||
global $wgGroupPermissions, $wgDisableAuthManager;
|
||||
|
||||
if ( !$wgDisableAuthManager ) {
|
||||
$this->markTestSkipped( 'AuthManager is not disabled' );
|
||||
}
|
||||
|
||||
\ObjectCache::$instances[__METHOD__] = new TestBagOStuff();
|
||||
$this->setMwGlobals( [ 'wgMainCacheType' => __METHOD__ ] );
|
||||
$this->setMwGlobals( [
|
||||
'wgAuth' => new AuthPlugin,
|
||||
] );
|
||||
|
||||
$this->stashMwGlobals( [ 'wgGroupPermissions' ] );
|
||||
$wgGroupPermissions['*']['createaccount'] = true;
|
||||
$wgGroupPermissions['*']['autocreateaccount'] = false;
|
||||
|
||||
// Replace the global singleton with one configured for testing
|
||||
$manager = $this->getManager();
|
||||
$reset = TestUtils::setSessionManagerSingleton( $manager );
|
||||
|
||||
$logger = new \TestLogger( true, function ( $m ) {
|
||||
if ( substr( $m, 0, 15 ) === 'SessionBackend ' ) {
|
||||
// Don't care.
|
||||
return null;
|
||||
}
|
||||
$m = str_replace( 'MediaWiki\Session\SessionManager::autoCreateUser: ', '', $m );
|
||||
return $m;
|
||||
} );
|
||||
$manager->setLogger( $logger );
|
||||
|
||||
$session = SessionManager::getGlobalSession();
|
||||
|
||||
// Can't create an already-existing user
|
||||
$user = User::newFromName( 'UTSysop' );
|
||||
$id = $user->getId();
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( $id, $user->getId() );
|
||||
$this->assertSame( 'UTSysop', $user->getName() );
|
||||
$this->assertSame( [], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Sanity check that creation works at all
|
||||
$user = User::newFromName( 'UTSessionAutoCreate1' );
|
||||
$this->assertSame( 0, $user->getId(), 'sanity check' );
|
||||
$this->assertTrue( $manager->autoCreateUser( $user ) );
|
||||
$this->assertNotEquals( 0, $user->getId() );
|
||||
$this->assertSame( 'UTSessionAutoCreate1', $user->getName() );
|
||||
$this->assertEquals(
|
||||
$user->getId(), User::idFromName( 'UTSessionAutoCreate1', User::READ_LATEST )
|
||||
);
|
||||
$this->assertSame( [
|
||||
[ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Check lack of permissions
|
||||
$wgGroupPermissions['*']['createaccount'] = false;
|
||||
$wgGroupPermissions['*']['autocreateaccount'] = false;
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[
|
||||
LogLevel::DEBUG,
|
||||
'user is blocked from this wiki, blacklisting',
|
||||
],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Check other permission
|
||||
$wgGroupPermissions['*']['createaccount'] = false;
|
||||
$wgGroupPermissions['*']['autocreateaccount'] = true;
|
||||
$user = User::newFromName( 'UTSessionAutoCreate2' );
|
||||
$this->assertSame( 0, $user->getId(), 'sanity check' );
|
||||
$this->assertTrue( $manager->autoCreateUser( $user ) );
|
||||
$this->assertNotEquals( 0, $user->getId() );
|
||||
$this->assertSame( 'UTSessionAutoCreate2', $user->getName() );
|
||||
$this->assertEquals(
|
||||
$user->getId(), User::idFromName( 'UTSessionAutoCreate2', User::READ_LATEST )
|
||||
);
|
||||
$this->assertSame( [
|
||||
[ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test account-creation block
|
||||
$anon = new User;
|
||||
$block = new \Block( [
|
||||
'address' => $anon->getName(),
|
||||
'user' => $id,
|
||||
'reason' => __METHOD__,
|
||||
'expiry' => time() + 100500,
|
||||
'createAccount' => true,
|
||||
] );
|
||||
$block->insert();
|
||||
$this->assertInstanceOf( 'Block', $anon->isBlockedFromCreateAccount(), 'sanity check' );
|
||||
$reset2 = new \ScopedCallback( [ $block, 'delete' ] );
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
\ScopedCallback::consume( $reset2 );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'user is blocked from this wiki, blacklisting' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Sanity check that creation still works
|
||||
$user = User::newFromName( 'UTSessionAutoCreate3' );
|
||||
$this->assertSame( 0, $user->getId(), 'sanity check' );
|
||||
$this->assertTrue( $manager->autoCreateUser( $user ) );
|
||||
$this->assertNotEquals( 0, $user->getId() );
|
||||
$this->assertSame( 'UTSessionAutoCreate3', $user->getName() );
|
||||
$this->assertEquals(
|
||||
$user->getId(), User::idFromName( 'UTSessionAutoCreate3', User::READ_LATEST )
|
||||
);
|
||||
$this->assertSame( [
|
||||
[ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test prevention by AuthPlugin
|
||||
global $wgAuth;
|
||||
$oldWgAuth = $wgAuth;
|
||||
$mockWgAuth = $this->getMock( 'AuthPlugin', [ 'autoCreate' ] );
|
||||
$mockWgAuth->expects( $this->once() )->method( 'autoCreate' )
|
||||
->will( $this->returnValue( false ) );
|
||||
$this->setMwGlobals( [
|
||||
'wgAuth' => $mockWgAuth,
|
||||
] );
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$this->setMwGlobals( [
|
||||
'wgAuth' => $oldWgAuth,
|
||||
] );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'denied by AuthPlugin' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test prevention by wfReadOnly()
|
||||
$this->setMwGlobals( [
|
||||
'wgReadOnly' => 'Because',
|
||||
] );
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$this->setMwGlobals( [
|
||||
'wgReadOnly' => false,
|
||||
] );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'denied by wfReadOnly()' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test prevention by a previous session
|
||||
$session->set( 'MWSession::AutoCreateBlacklist', 'test' );
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'blacklisted in session (test)' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test uncreatable name
|
||||
$user = User::newFromName( 'UTDoesNotExist@' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist@', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'Invalid username, blacklisting' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test AbortAutoAccount hook
|
||||
$mock = $this->getMock( __CLASS__, [ 'onAbortAutoAccount' ] );
|
||||
$mock->expects( $this->once() )->method( 'onAbortAutoAccount' )
|
||||
->will( $this->returnCallback( function ( User $user, &$msg ) {
|
||||
$msg = 'No way!';
|
||||
return false;
|
||||
} ) );
|
||||
$this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [ $mock ] ] );
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [] ] );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'denied by hook: No way!' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test AbortAutoAccount hook screwing up the name
|
||||
$mock = $this->getMock( 'stdClass', [ 'onAbortAutoAccount' ] );
|
||||
$mock->expects( $this->once() )->method( 'onAbortAutoAccount' )
|
||||
->will( $this->returnCallback( function ( User $user ) {
|
||||
$user->setName( 'UTDoesNotExistEither' );
|
||||
} ) );
|
||||
$this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [ $mock ] ] );
|
||||
try {
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$manager->autoCreateUser( $user );
|
||||
$this->fail( 'Expected exception not thrown' );
|
||||
} catch ( \UnexpectedValueException $ex ) {
|
||||
$this->assertSame(
|
||||
'AbortAutoAccount hook tried to change the user name',
|
||||
$ex->getMessage()
|
||||
);
|
||||
}
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertNotSame( 'UTDoesNotExistEither', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExistEither', User::READ_LATEST ) );
|
||||
$this->mergeMwGlobalArrayValue( 'wgHooks', [ 'AbortAutoAccount' => [] ] );
|
||||
$session->clear();
|
||||
$this->assertSame( [], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Test for "exception backoff"
|
||||
$user = User::newFromName( 'UTDoesNotExist' );
|
||||
$cache = \ObjectCache::getLocalClusterInstance();
|
||||
$backoffKey = wfMemcKey( 'MWSession', 'autocreate-failed', md5( $user->getName() ) );
|
||||
$cache->set( $backoffKey, 1, 60 * 10 );
|
||||
$this->assertFalse( $manager->autoCreateUser( $user ) );
|
||||
$this->assertSame( 0, $user->getId() );
|
||||
$this->assertNotSame( 'UTDoesNotExist', $user->getName() );
|
||||
$this->assertEquals( 0, User::idFromName( 'UTDoesNotExist', User::READ_LATEST ) );
|
||||
$cache->delete( $backoffKey );
|
||||
$session->clear();
|
||||
$this->assertSame( [
|
||||
[ LogLevel::DEBUG, 'denied by prior creation attempt failures' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
|
||||
// Sanity check that creation still works, and test completion hook
|
||||
$cb = $this->callback( function ( User $user ) {
|
||||
$this->assertNotEquals( 0, $user->getId() );
|
||||
$this->assertSame( 'UTSessionAutoCreate4', $user->getName() );
|
||||
$this->assertEquals(
|
||||
$user->getId(), User::idFromName( 'UTSessionAutoCreate4', User::READ_LATEST )
|
||||
);
|
||||
return true;
|
||||
} );
|
||||
$mock = $this->getMock( 'stdClass',
|
||||
[ 'onAuthPluginAutoCreate', 'onLocalUserCreated' ] );
|
||||
$mock->expects( $this->once() )->method( 'onAuthPluginAutoCreate' )
|
||||
->with( $cb );
|
||||
$mock->expects( $this->once() )->method( 'onLocalUserCreated' )
|
||||
->with( $cb, $this->identicalTo( true ) );
|
||||
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
||||
'AuthPluginAutoCreate' => [ $mock ],
|
||||
'LocalUserCreated' => [ $mock ],
|
||||
] );
|
||||
$user = User::newFromName( 'UTSessionAutoCreate4' );
|
||||
$this->assertSame( 0, $user->getId(), 'sanity check' );
|
||||
$this->assertTrue( $manager->autoCreateUser( $user ) );
|
||||
$this->assertNotEquals( 0, $user->getId() );
|
||||
$this->assertSame( 'UTSessionAutoCreate4', $user->getName() );
|
||||
$this->assertEquals(
|
||||
$user->getId(),
|
||||
User::idFromName( 'UTSessionAutoCreate4', User::READ_LATEST )
|
||||
);
|
||||
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
||||
'AuthPluginAutoCreate' => [],
|
||||
'LocalUserCreated' => [],
|
||||
] );
|
||||
$this->assertSame( [
|
||||
[ LogLevel::INFO, 'creating new user ({username}) - from: {url}' ],
|
||||
], $logger->getBuffer() );
|
||||
$logger->clearBuffer();
|
||||
}
|
||||
|
||||
public function onAbortAutoAccount( User $user, &$msg ) {
|
||||
}
|
||||
|
||||
public function testPreventSessionsForUser() {
|
||||
$manager = $this->getManager();
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class PHPUnitMaintClass extends Maintenance {
|
|||
global $wgDevelopmentWarnings;
|
||||
global $wgSessionProviders, $wgSessionPbkdf2Iterations;
|
||||
global $wgJobTypeConf;
|
||||
global $wgAuthManagerConfig, $wgAuth, $wgDisableAuthManager;
|
||||
global $wgAuthManagerConfig, $wgAuth;
|
||||
|
||||
// Inject test autoloader
|
||||
require_once __DIR__ . '/../TestsAutoLoader.php';
|
||||
|
|
@ -147,7 +147,7 @@ class PHPUnitMaintClass extends Maintenance {
|
|||
],
|
||||
'secondaryauth' => [],
|
||||
];
|
||||
$wgAuth = $wgDisableAuthManager ? new AuthPlugin : new MediaWiki\Auth\AuthManagerAuthPlugin();
|
||||
$wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin();
|
||||
|
||||
// Bug 44192 Do not attempt to send a real e-mail
|
||||
Hooks::clear( 'AlternateUserMailer' );
|
||||
|
|
|
|||
Loading…
Reference in a new issue