MediaWiki
REL1_21
|
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 $result = array(); 00051 00052 // Init session if necessary 00053 if ( session_id() == '' ) { 00054 wfSetupSession(); 00055 } 00056 00057 if( $params['mailpassword'] && !$params['email'] ) { 00058 $this->dieUsageMsg( 'noemail' ); 00059 } 00060 00061 $context = new DerivativeContext( $this->getContext() ); 00062 $context->setRequest( new DerivativeRequest( 00063 $this->getContext()->getRequest(), 00064 array( 00065 'type' => 'signup', 00066 'uselang' => $params['language'], 00067 'wpName' => $params['name'], 00068 'wpPassword' => $params['password'], 00069 'wpRetype' => $params['password'], 00070 'wpDomain' => $params['domain'], 00071 'wpEmail' => $params['email'], 00072 'wpRealName' => $params['realname'], 00073 'wpCreateaccountToken' => $params['token'], 00074 'wpCreateaccount' => $params['mailpassword'] ? null : '1', 00075 'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null 00076 ) 00077 ) ); 00078 00079 $loginForm = new LoginForm(); 00080 $loginForm->setContext( $context ); 00081 $loginForm->load(); 00082 00083 $status = $loginForm->addNewaccountInternal(); 00084 $result = array(); 00085 if( $status->isGood() ) { 00086 // Success! 00087 $user = $status->getValue(); 00088 00089 // If we showed up language selection links, and one was in use, be 00090 // smart (and sensible) and save that language as the user's preference 00091 global $wgLoginLanguageSelector, $wgEmailAuthentication; 00092 if( $wgLoginLanguageSelector && $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 // Cannot use dieUsageMsg() directly because extensions 00136 // might return custom error messages. 00137 $errors = $status->getErrorsArray(); 00138 if( $errors[0] instanceof Message ) { 00139 $code = 'aborted'; 00140 $desc = $errors[0]; 00141 } else { 00142 $code = array_shift( $errors[0] ); 00143 $desc = wfMessage( $code, $errors[0] ); 00144 } 00145 $this->dieUsage( $desc, $code ); 00146 } elseif( !$status->isGood() ) { 00147 // Status is not good, but OK. This means warnings. 00148 $result['result'] = 'warning'; 00149 00150 // Add any warnings to the result 00151 $warnings = $status->getErrorsByType( 'warning' ); 00152 if( $warnings ) { 00153 foreach( $warnings as &$warning ) { 00154 $apiResult->setIndexedTagName( $warning['params'], 'param' ); 00155 } 00156 $apiResult->setIndexedTagName( $warnings, 'warning' ); 00157 $result['warnings'] = $warnings; 00158 } 00159 } else { 00160 // Everything was fine. 00161 $result['result'] = 'success'; 00162 } 00163 00164 $apiResult->addValue( null, 'createaccount', $result ); 00165 } 00166 00167 public function getDescription() { 00168 return 'Create a new user account.'; 00169 } 00170 00171 public function mustBePosted() { 00172 return true; 00173 } 00174 00175 public function isReadMode() { 00176 return false; 00177 } 00178 00179 public function isWriteMode() { 00180 return true; 00181 } 00182 00183 public function getAllowedParams() { 00184 global $wgEmailConfirmToEdit; 00185 return array( 00186 'name' => array( 00187 ApiBase::PARAM_TYPE => 'user', 00188 ApiBase::PARAM_REQUIRED => true 00189 ), 00190 'password' => null, 00191 'domain' => null, 00192 'token' => null, 00193 'email' => array( 00194 ApiBase::PARAM_TYPE => 'string', 00195 ApiBase::PARAM_REQUIRED => $wgEmailConfirmToEdit 00196 ), 00197 'realname' => null, 00198 'mailpassword' => array( 00199 ApiBase::PARAM_TYPE => 'boolean', 00200 ApiBase::PARAM_DFLT => false 00201 ), 00202 'reason' => null, 00203 'language' => null 00204 ); 00205 } 00206 00207 public function getParamDescription() { 00208 $p = $this->getModulePrefix(); 00209 return array( 00210 'name' => 'Username', 00211 'password' => "Password (ignored if {$p}mailpassword is set)", 00212 'domain' => 'Domain for external authentication (optional)', 00213 'token' => 'Account creation token obtained in first request', 00214 'email' => 'Email address of user (optional)', 00215 'realname' => 'Real name of user (optional)', 00216 'mailpassword' => 'If set to any value, a random password will be emailed to the user', 00217 'reason' => 'Optional reason for creating the account to be put in the logs', 00218 'language' => 'Language code to set as default for the user (optional, defaults to content language)' 00219 ); 00220 } 00221 00222 public function getResultProperties() { 00223 return array( 00224 'createaccount' => array( 00225 'result' => array( 00226 ApiBase::PROP_TYPE => array( 00227 'success', 00228 'warning', 00229 'needtoken' 00230 ) 00231 ), 00232 'username' => array( 00233 ApiBase::PROP_TYPE => 'string', 00234 ApiBase::PROP_NULLABLE => true 00235 ), 00236 'userid' => array( 00237 ApiBase::PROP_TYPE => 'int', 00238 ApiBase::PROP_NULLABLE => true 00239 ), 00240 'token' => array( 00241 ApiBase::PROP_TYPE => 'string', 00242 ApiBase::PROP_NULLABLE => true 00243 ), 00244 ) 00245 ); 00246 } 00247 00248 public function getPossibleErrors() { 00249 // Note the following errors aren't possible and don't need to be listed: 00250 // sessionfailure, nocookiesfornew, badretype 00251 $localErrors = array( 00252 'wrongpassword', // Actually caused by wrong domain field. Riddle me that... 00253 'sorbs_create_account_reason', 00254 'noname', 00255 'userexists', 00256 'password-name-match', // from User::getPasswordValidity 00257 'password-login-forbidden', // from User::getPasswordValidity 00258 'noemailtitle', 00259 'invalidemailaddress', 00260 'externaldberror', 00261 'acct_creation_throttle_hit', 00262 ); 00263 00264 $errors = parent::getPossibleErrors(); 00265 // All local errors are from LoginForm, which means they're actually message keys. 00266 foreach( $localErrors as $error ) { 00267 $errors[] = array( 'code' => $error, 'info' => wfMessage( $error )->parse() ); 00268 } 00269 00270 $errors[] = array( 00271 'code' => 'permdenied-createaccount', 00272 'info' => 'You do not have the right to create a new account' 00273 ); 00274 $errors[] = array( 00275 'code' => 'blocked', 00276 'info' => 'You cannot create a new account because you are blocked' 00277 ); 00278 $errors[] = array( 00279 'code' => 'aborted', 00280 'info' => 'Account creation aborted by hook (info may vary)' 00281 ); 00282 00283 // 'passwordtooshort' has parameters. :( 00284 global $wgMinimalPasswordLength; 00285 $errors[] = array( 00286 'code' => 'passwordtooshort', 00287 'info' => wfMessage( 'passwordtooshort', $wgMinimalPasswordLength )->parse() 00288 ); 00289 return $errors; 00290 } 00291 00292 public function getExamples() { 00293 return array( 00294 'api.php?action=createaccount&name=testuser&password=test123', 00295 'api.php?action=createaccount&name=testmailuser&mailpassword=true&reason=MyReason', 00296 ); 00297 } 00298 00299 public function getHelpUrls() { 00300 return 'https://www.mediawiki.org/wiki/API:Account_creation'; 00301 } 00302 }