MediaWiki  REL1_22
ApiCreateAccount.php
Go to the documentation of this file.
00001 <?php
00030 class ApiCreateAccount extends ApiBase {
00031     public function execute() {
00032         // If we're in JSON callback mode, no tokens can be obtained
00033         if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) {
00034             $this->dieUsage( 'Cannot create account when using a callback', 'aborted' );
00035         }
00036 
00037         // $loginForm->addNewaccountInternal will throw exceptions
00038         // if wiki is read only (already handled by api), user is blocked or does not have rights.
00039         // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin)
00040         $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
00041         if ( !$loginTitle->userCan( 'createaccount', $this->getUser() ) ) {
00042             $this->dieUsage( 'You do not have the right to create a new account', 'permdenied-createaccount' );
00043         }
00044         if ( $this->getUser()->isBlockedFromCreateAccount() ) {
00045             $this->dieUsage( 'You cannot create a new account because you are blocked', 'blocked' );
00046         }
00047 
00048         $params = $this->extractRequestParams();
00049 
00050         // Init session if necessary
00051         if ( session_id() == '' ) {
00052             wfSetupSession();
00053         }
00054 
00055         if ( $params['mailpassword'] && !$params['email'] ) {
00056             $this->dieUsageMsg( 'noemail' );
00057         }
00058 
00059         if ( $params['language'] && !Language::isSupportedLanguage( $params['language'] ) ) {
00060             $this->dieUsage( 'Invalid language parameter', 'langinvalid' );
00061         }
00062 
00063         $context = new DerivativeContext( $this->getContext() );
00064         $context->setRequest( new DerivativeRequest(
00065             $this->getContext()->getRequest(),
00066             array(
00067                 'type' => 'signup',
00068                 'uselang' => $params['language'],
00069                 'wpName' => $params['name'],
00070                 'wpPassword' => $params['password'],
00071                 'wpRetype' => $params['password'],
00072                 'wpDomain' => $params['domain'],
00073                 'wpEmail' => $params['email'],
00074                 'wpRealName' => $params['realname'],
00075                 'wpCreateaccountToken' => $params['token'],
00076                 'wpCreateaccount' => $params['mailpassword'] ? null : '1',
00077                 'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null
00078             )
00079         ) );
00080 
00081         $loginForm = new LoginForm();
00082         $loginForm->setContext( $context );
00083         $loginForm->load();
00084 
00085         $status = $loginForm->addNewaccountInternal();
00086         $result = array();
00087         if ( $status->isGood() ) {
00088             // Success!
00089             global $wgEmailAuthentication;
00090             $user = $status->getValue();
00091 
00092             if ( $params['language'] ) {
00093                 $user->setOption( 'language', $params['language'] );
00094             }
00095 
00096             if ( $params['mailpassword'] ) {
00097                 // If mailpassword was set, disable the password and send an email.
00098                 $user->setPassword( null );
00099                 $status->merge( $loginForm->mailPasswordInternal( $user, false, 'createaccount-title', 'createaccount-text' ) );
00100             } elseif ( $wgEmailAuthentication && Sanitizer::validateEmail( $user->getEmail() ) ) {
00101                 // Send out an email authentication message if needed
00102                 $status->merge( $user->sendConfirmationMail() );
00103             }
00104 
00105             // Save settings (including confirmation token)
00106             $user->saveSettings();
00107 
00108             wfRunHooks( 'AddNewAccount', array( $user, $params['mailpassword'] ) );
00109 
00110             if ( $params['mailpassword'] ) {
00111                 $logAction = 'byemail';
00112             } elseif ( $this->getUser()->isLoggedIn() ) {
00113                 $logAction = 'create2';
00114             } else {
00115                 $logAction = 'create';
00116             }
00117             $user->addNewUserLogEntry( $logAction, (string)$params['reason'] );
00118 
00119             // Add username, id, and token to result.
00120             $result['username'] = $user->getName();
00121             $result['userid'] = $user->getId();
00122             $result['token'] = $user->getToken();
00123         }
00124 
00125         $apiResult = $this->getResult();
00126 
00127         if ( $status->hasMessage( 'sessionfailure' ) || $status->hasMessage( 'nocookiesfornew' ) ) {
00128             // Token was incorrect, so add it to result, but don't throw an exception
00129             // since not having the correct token is part of the normal
00130             // flow of events.
00131             $result['token'] = LoginForm::getCreateaccountToken();
00132             $result['result'] = 'needtoken';
00133         } elseif ( !$status->isOK() ) {
00134             // There was an error. Die now.
00135             $this->dieStatus( $status );
00136         } elseif ( !$status->isGood() ) {
00137             // Status is not good, but OK. This means warnings.
00138             $result['result'] = 'warning';
00139 
00140             // Add any warnings to the result
00141             $warnings = $status->getErrorsByType( 'warning' );
00142             if ( $warnings ) {
00143                 foreach ( $warnings as &$warning ) {
00144                     $apiResult->setIndexedTagName( $warning['params'], 'param' );
00145                 }
00146                 $apiResult->setIndexedTagName( $warnings, 'warning' );
00147                 $result['warnings'] = $warnings;
00148             }
00149         } else {
00150             // Everything was fine.
00151             $result['result'] = 'success';
00152         }
00153 
00154         $apiResult->addValue( null, 'createaccount', $result );
00155     }
00156 
00157     public function getDescription() {
00158         return 'Create a new user account.';
00159     }
00160 
00161     public function mustBePosted() {
00162         return true;
00163     }
00164 
00165     public function isReadMode() {
00166         return false;
00167     }
00168 
00169     public function isWriteMode() {
00170         return true;
00171     }
00172 
00173     public function getAllowedParams() {
00174         global $wgEmailConfirmToEdit;
00175         return array(
00176             'name' => array(
00177                 ApiBase::PARAM_TYPE => 'user',
00178                 ApiBase::PARAM_REQUIRED => true
00179             ),
00180             'password' => null,
00181             'domain' => null,
00182             'token' => null,
00183             'email' => array(
00184                 ApiBase::PARAM_TYPE => 'string',
00185                 ApiBase::PARAM_REQUIRED => $wgEmailConfirmToEdit
00186             ),
00187             'realname' => null,
00188             'mailpassword' => array(
00189                 ApiBase::PARAM_TYPE => 'boolean',
00190                 ApiBase::PARAM_DFLT => false
00191             ),
00192             'reason' => null,
00193             'language' => null
00194         );
00195     }
00196 
00197     public function getParamDescription() {
00198         $p = $this->getModulePrefix();
00199         return array(
00200             'name' => 'Username',
00201             'password' => "Password (ignored if {$p}mailpassword is set)",
00202             'domain' => 'Domain for external authentication (optional)',
00203             'token' => 'Account creation token obtained in first request',
00204             'email' => 'Email address of user (optional)',
00205             'realname' => 'Real name of user (optional)',
00206             'mailpassword' => 'If set to any value, a random password will be emailed to the user',
00207             'reason' => 'Optional reason for creating the account to be put in the logs',
00208             'language' => 'Language code to set as default for the user (optional, defaults to content language)'
00209         );
00210     }
00211 
00212     public function getResultProperties() {
00213         return array(
00214             'createaccount' => array(
00215                 'result' => array(
00216                     ApiBase::PROP_TYPE => array(
00217                         'success',
00218                         'warning',
00219                         'needtoken'
00220                     )
00221                 ),
00222                 'username' => array(
00223                     ApiBase::PROP_TYPE => 'string',
00224                     ApiBase::PROP_NULLABLE => true
00225                 ),
00226                 'userid' => array(
00227                     ApiBase::PROP_TYPE => 'int',
00228                     ApiBase::PROP_NULLABLE => true
00229                 ),
00230                 'token' => array(
00231                     ApiBase::PROP_TYPE => 'string',
00232                     ApiBase::PROP_NULLABLE => true
00233                 ),
00234             )
00235         );
00236     }
00237 
00238     public function getPossibleErrors() {
00239         // Note the following errors aren't possible and don't need to be listed:
00240         // sessionfailure, nocookiesfornew, badretype
00241         $localErrors = array(
00242             'wrongpassword', // Actually caused by wrong domain field. Riddle me that...
00243             'sorbs_create_account_reason',
00244             'noname',
00245             'userexists',
00246             'password-name-match', // from User::getPasswordValidity
00247             'password-login-forbidden', // from User::getPasswordValidity
00248             'noemailtitle',
00249             'invalidemailaddress',
00250             'externaldberror',
00251             'acct_creation_throttle_hit',
00252         );
00253 
00254         $errors = parent::getPossibleErrors();
00255         // All local errors are from LoginForm, which means they're actually message keys.
00256         foreach ( $localErrors as $error ) {
00257             $errors[] = array( 'code' => $error, 'info' => wfMessage( $error )->inLanguage( 'en' )->useDatabase( false )->parse() );
00258         }
00259 
00260         $errors[] = array(
00261             'code' => 'permdenied-createaccount',
00262             'info' => 'You do not have the right to create a new account'
00263         );
00264         $errors[] = array(
00265             'code' => 'blocked',
00266             'info' => 'You cannot create a new account because you are blocked'
00267         );
00268         $errors[] = array(
00269             'code' => 'aborted',
00270             'info' => 'Account creation aborted by hook (info may vary)'
00271         );
00272         $errors[] = array(
00273             'code' => 'langinvalid',
00274             'info' => 'Invalid language parameter'
00275         );
00276 
00277         // 'passwordtooshort' has parameters. :(
00278         global $wgMinimalPasswordLength;
00279         $errors[] = array(
00280             'code' => 'passwordtooshort',
00281             'info' => wfMessage( 'passwordtooshort', $wgMinimalPasswordLength )->inLanguage( 'en' )->useDatabase( false )->parse()
00282         );
00283         return $errors;
00284     }
00285 
00286     public function getExamples() {
00287         return array(
00288             'api.php?action=createaccount&name=testuser&password=test123',
00289             'api.php?action=createaccount&name=testmailuser&mailpassword=true&reason=MyReason',
00290         );
00291     }
00292 
00293     public function getHelpUrls() {
00294         return 'https://www.mediawiki.org/wiki/API:Account_creation';
00295     }
00296 }