Changed LoginForm::addNewaccountInternal() to return Status.

Rather than calling mainLoginForm() and returning false,
the addNewaccountInternal() function now returns a Status
on failure. mainLoginForm() is then called in addNewAccount()
and addNewAccountMailPassword() instead. This allows for
processing of the account creation form without submitting
anything to $wgOut.

Change-Id: I402c6bebcfe276233cc1f9e16efbe55a034b2181
This commit is contained in:
parent5446 2012-08-07 10:46:31 -04:00 committed by Gerrit Code Review
parent 91f2c1e40e
commit 69ea440003
3 changed files with 96 additions and 83 deletions

View file

@ -196,6 +196,7 @@ $wgAutoloadLocalClasses = array(
'ProtectionForm' => 'includes/ProtectionForm.php',
'QueryPage' => 'includes/QueryPage.php',
'QuickTemplate' => 'includes/SkinTemplate.php',
'RawMessage' => 'includes/Message.php',
'RCCacheEntry' => 'includes/ChangesList.php',
'RdfMetaData' => 'includes/Metadata.php',
'ReadOnlyError' => 'includes/Exception.php',

View file

@ -674,3 +674,45 @@ class Message {
}
}
/**
* Variant of the Message class.
*
* Rather than treating the message key as a lookup
* value (which is passed to the MessageCache and
* translated as necessary), a RawMessage key is
* treated as the actual message.
*
* All other functionality (parsing, escaping, etc.)
* is preserved.
*
* @since 1.21
*/
class RawMessage extends Message {
/**
* Call the parent constructor, then store the key as
* the message.
*
* @param $key Message to use
* @param $params Parameters for the message
* @see Message::__construct
*/
public function __construct( $key, $params = array() ) {
parent::__construct( $key, $params );
// The key is the message.
$this->message = $key;
}
/**
* Fetch the message (in this case, the key).
*
* @return string
*/
public function fetchMessage() {
// Just in case the message is unset somewhere.
if( !isset( $this->message ) ) {
$this->message = $this->key;
}
return $this->message;
}
}

View file

@ -197,12 +197,15 @@ class LoginForm extends SpecialPage {
return;
}
$u = $this->addNewaccountInternal();
if ( $u == null ) {
return;
$status = $this->addNewaccountInternal();
if( !$status->isGood() ) {
$error = $this->getOutput()->parse( $status->getWikiText() );
$this->mainLoginForm( $error );
return false;
}
$u = $status->getValue();
// Wipe the initial password and mail a temporary one
$u->setPassword( null );
$u->saveSettings();
@ -230,11 +233,15 @@ class LoginForm extends SpecialPage {
global $wgUser, $wgEmailAuthentication, $wgLoginLanguageSelector;
# Create the account and abort if there's a problem doing so
$u = $this->addNewAccountInternal();
if( $u == null ) {
$status = $this->addNewAccountInternal();
if( !$status->isGood() ) {
$error = $this->getOutput()->parse( $status->getWikiText() );
$this->mainLoginForm( $error );
return false;
}
$u = $status->getValue();
# If we showed up language selection links, and one was in use, be
# smart (and sensible) and save that language as the user's preference
if( $wgLoginLanguageSelector && $this->mLanguage ) {
@ -285,18 +292,18 @@ class LoginForm extends SpecialPage {
}
/**
* Make a new user account using the loaded data.
* @private
* @throws PermissionsError|ReadOnlyError
* @return bool|User
* @return Status
*/
function addNewAccountInternal() {
public function addNewAccountInternal() {
global $wgAuth, $wgMemc, $wgAccountCreationThrottle,
$wgMinimalPasswordLength, $wgEmailConfirmToEdit;
// If the user passes an invalid domain, something is fishy
if( !$wgAuth->validDomain( $this->mDomain ) ) {
$this->mainLoginForm( $this->msg( 'wrongpassword' )->text() );
return false;
return Status::newFatal( 'wrongpassword' );
}
// If we are not allowing users to login locally, we should be checking
@ -305,10 +312,12 @@ class LoginForm extends SpecialPage {
// create a local account and login as any domain user). We only need
// to check this for domains that aren't local.
if( 'local' != $this->mDomain && $this->mDomain != '' ) {
if( !$wgAuth->canCreateAccounts() && ( !$wgAuth->userExists( $this->mUsername )
|| !$wgAuth->authenticate( $this->mUsername, $this->mPassword ) ) ) {
$this->mainLoginForm( $this->msg( 'wrongpassword' )->text() );
return false;
if(
!$wgAuth->canCreateAccounts() &&
( !$wgAuth->userExists( $this->mUsername ||
!$wgAuth->authenticate( $this->mUsername, $this->mPassword ) ) )
) {
return Status::newFatal( 'wrongpassword' );
}
}
@ -319,28 +328,28 @@ class LoginForm extends SpecialPage {
# Request forgery checks.
if ( !self::getCreateaccountToken() ) {
self::setCreateaccountToken();
$this->mainLoginForm( $this->msg( 'nocookiesfornew' )->parse() );
return false;
return Status::newFatal( 'sessionfailure' );
}
# The user didn't pass a createaccount token
if ( !$this->mToken ) {
$this->mainLoginForm( $this->msg( 'sessionfailure' )->text() );
return false;
return Status::newFatal( 'sessionfailure' );
}
# Validate the createaccount token
if ( $this->mToken !== self::getCreateaccountToken() ) {
$this->mainLoginForm( $this->msg( 'sessionfailure' )->text() );
return false;
return Status::newFatal( 'sessionfailure' );
}
# Check permissions
$currentUser = $this->getUser();
$creationBlock = $currentUser->isBlockedFromCreateAccount();
if ( !$currentUser->isAllowed( 'createaccount' ) ) {
throw new PermissionsError( 'createaccount' );
} elseif ( $currentUser->isBlockedFromCreateAccount() ) {
$this->userBlockedMessage( $currentUser->isBlockedFromCreateAccount() );
} elseif ( $creationBlock instanceof Block ) {
// Throws an ErrorPageError.
$this->userBlockedMessage( $creationBlock );
// This should never be reached.
return false;
}
@ -352,41 +361,28 @@ class LoginForm extends SpecialPage {
$ip = $this->getRequest()->getIP();
if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) {
$this->mainLoginForm( $this->msg( 'sorbs_create_account_reason' )->text() . ' ' . $this->msg( 'parentheses', $ip )->escaped() );
return false;
return Status::newFatal( 'sorbs_create_account_reason' );
}
# Now create a dummy user ($u) and check if it is valid
$name = trim( $this->mUsername );
$u = User::newFromName( $name, 'creatable' );
if ( !is_object( $u ) ) {
$this->mainLoginForm( $this->msg( 'noname' )->text() );
return false;
}
if ( 0 != $u->idForName() ) {
$this->mainLoginForm( $this->msg( 'userexists' )->text() );
return false;
}
if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
$this->mainLoginForm( $this->msg( 'badretype' )->text() );
return false;
return Status::newFatal( 'noname' );
} elseif ( 0 != $u->idForName() ) {
return Status::newFatal( 'userexists' );
} elseif ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
return Status::newFatal( 'badretype' );
}
# check for minimal password length
$valid = $u->getPasswordValidity( $this->mPassword );
if ( $valid !== true ) {
if ( !$this->mCreateaccountMail ) {
if ( is_array( $valid ) ) {
$message = array_shift( $valid );
$params = $valid;
} else {
$message = $valid;
$params = array( $wgMinimalPasswordLength );
if ( !is_array( $valid ) ) {
$valid = array( $valid, $wgMinimalPasswordLength );
}
$this->mainLoginForm( $this->msg( $message, $params )->text() );
return false;
return call_user_func_array( 'Status::newFatal', $valid );
} else {
# do not force a password for account creation by email
# set invalid password, it will be replaced later by a random generated password
@ -397,13 +393,11 @@ class LoginForm extends SpecialPage {
# if you need a confirmed email address to edit, then obviously you
# need an email address.
if ( $wgEmailConfirmToEdit && empty( $this->mEmail ) ) {
$this->mainLoginForm( $this->msg( 'noemailtitle' )->text() );
return false;
return Status::newFatal( 'noemailtitle' );
}
if( !empty( $this->mEmail ) && !Sanitizer::validateEmail( $this->mEmail ) ) {
$this->mainLoginForm( $this->msg( 'invalidemailaddress' )->text() );
return false;
return Status::newFatal( 'invalidemailaddress' );
}
# Set some additional data so the AbortNewAccount hook can be used for
@ -415,8 +409,7 @@ class LoginForm extends SpecialPage {
if( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError ) ) ) {
// Hook point to add extra creation throttles and blocks
wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
$this->mainLoginForm( $abortError );
return false;
return Status::newFatal( new RawMessage( $abortError ) );
}
// Hook point to check for exempt from account creation throttle
@ -430,26 +423,18 @@ class LoginForm extends SpecialPage {
$wgMemc->set( $key, 0, 86400 );
}
if ( $value >= $wgAccountCreationThrottle ) {
$this->throttleHit( $wgAccountCreationThrottle );
return false;
return Status::newFatal( 'acct_creation_throttle_hit', $wgAccountCreationThrottle );
}
$wgMemc->incr( $key );
}
}
if( !$wgAuth->addUser( $u, $this->mPassword, $this->mEmail, $this->mRealName ) ) {
$this->mainLoginForm( $this->msg( 'externaldberror' )->text() );
return false;
return Status::newFatal( 'externaldberror' );
}
self::clearCreateaccountToken();
$status = $this->initUser( $u, false );
if ( !$status->isOK() ) {
$this->mainLoginForm( $status->getHTML() );
return false;
}
return $status->value;
return $this->initUser( $u, false );
}
/**
@ -965,23 +950,15 @@ class LoginForm extends SpecialPage {
# haven't bothered to log out before trying to create an account to
# evade it, but we'll leave that to their guilty conscience to figure
# out.
$out = $this->getOutput();
$out->setPageTitle( $this->msg( 'cantcreateaccounttitle' ) );
$block_reason = $block->mReason;
if ( strval( $block_reason ) === '' ) {
$block_reason = $this->msg( 'blockednoreason' )->text();
}
$out->addWikiMsg(
throw new ErrorPageError(
'cantcreateaccounttitle',
'cantcreateaccount-text',
array(
$block->getTarget(),
$block_reason,
$block->mReason ? $block->mReason : $this->msg( 'blockednoreason' )->text(),
$block->getByName()
)
);
$this->executeReturnTo( 'error' );
}
/**
@ -1316,13 +1293,6 @@ class LoginForm extends SpecialPage {
}
}
/**
* @private
*/
function throttleHit( $limit ) {
$this->mainLoginForm( $this->msg( 'acct_creation_throttle_hit' )->numParams( $limit )->parse() );
}
/**
* Produce a bar of links which allow the user to select another language
* during login/registration but retain "returnto"