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