Index: branches/happy-melon/phase3/includes/ExternalUser.php |
— | — | @@ -285,4 +285,22 @@ |
286 | 286 | 'eu_external_id' => $this->getId() ), |
287 | 287 | __METHOD__ ); |
288 | 288 | } |
| 289 | + |
| 290 | + /** |
| 291 | + * Check whether this external user id is already linked with |
| 292 | + * a local user. |
| 293 | + * @return Mixed User if the account is linked, Null otherwise. |
| 294 | + */ |
| 295 | + public final function getLocalUser(){ |
| 296 | + $dbr = wfGetDb( DB_SLAVE ); |
| 297 | + $row = $dbr->selectRow( |
| 298 | + 'external_user', |
| 299 | + '*', |
| 300 | + array( 'eu_external_id' => $this->getId() ) |
| 301 | + ); |
| 302 | + return $row |
| 303 | + ? User::newFromId( $row->eu_wiki_id ) |
| 304 | + : null; |
| 305 | + } |
| 306 | + |
289 | 307 | } |
Index: branches/happy-melon/phase3/includes/Login.php |
— | — | @@ -147,6 +147,7 @@ |
148 | 148 | return self::NOT_EXISTS; |
149 | 149 | } |
150 | 150 | if( !$this->mExtUser->authenticate( $this->mPassword ) ) { |
| 151 | + $this->mLoginResult = 'wrongpassword'; |
151 | 152 | return self::WRONG_PLUGIN_PASS; |
152 | 153 | } |
153 | 154 | } else { |
— | — | @@ -160,6 +161,7 @@ |
161 | 162 | } |
162 | 163 | if( !$wgAuth->authenticate( $this->mUser->getName(), $this->mPassword ) ) { |
163 | 164 | wfDebug( __METHOD__.": \$wgAuth->authenticate() returned false, aborting\n" ); |
| 165 | + $this->mLoginResult = 'wrongpassword'; |
164 | 166 | return self::WRONG_PLUGIN_PASS; |
165 | 167 | } |
166 | 168 | } |
— | — | @@ -178,6 +180,7 @@ |
179 | 181 | global $wgUser, $wgAuth; |
180 | 182 | |
181 | 183 | if ( '' == $this->mName ) { |
| 184 | + $this->mLoginResult = 'noname'; |
182 | 185 | return self::NO_NAME; |
183 | 186 | } |
184 | 187 | |
— | — | @@ -195,6 +198,7 @@ |
196 | 199 | } else if ( $throttleCount < $count ) { |
197 | 200 | $wgMemc->incr($throttleKey); |
198 | 201 | } else if ( $throttleCount >= $count ) { |
| 202 | + $this->mLoginResult = 'login-throttled'; |
199 | 203 | return self::THROTTLED; |
200 | 204 | } |
201 | 205 | } |
— | — | @@ -211,6 +215,16 @@ |
212 | 216 | } |
213 | 217 | |
214 | 218 | $this->mExtUser = ExternalUser::newFromName( $this->mName ); |
| 219 | + |
| 220 | + # If the given username produces a valid ExternalUser, which is |
| 221 | + # linked to an existing local user, use that, regardless of |
| 222 | + # whether the username matches up. |
| 223 | + if( $this->mExtUser ){ |
| 224 | + $user = $this->mExtUser->getLocalUser(); |
| 225 | + if( $user instanceof User ){ |
| 226 | + $this->mUser = $user; |
| 227 | + } |
| 228 | + } |
215 | 229 | |
216 | 230 | # TODO: Allow some magic here for invalid external names, e.g., let the |
217 | 231 | # user choose a different wiki name. |
— | — | @@ -219,12 +233,15 @@ |
220 | 234 | } |
221 | 235 | |
222 | 236 | # If the user doesn't exist in the local database, our only chance |
223 | | - # is for an external auth plugin to autocreate the local user. |
| 237 | + # is for an external auth plugin to autocreate the local user first. |
224 | 238 | if ( $this->mUser->getID() == 0 ) { |
225 | 239 | if ( $this->canAutoCreate() == self::SUCCESS ) { |
226 | 240 | $isAutoCreated = true; |
227 | 241 | wfDebug( __METHOD__.": creating account\n" ); |
228 | | - $this->initUser( true ); |
| 242 | + $result = $this->initUser( true ); |
| 243 | + if( $result !== self::SUCCESS ){ |
| 244 | + return $result; |
| 245 | + }; |
229 | 246 | } else { |
230 | 247 | return $this->canAutoCreate(); |
231 | 248 | } |
— | — | @@ -234,9 +251,8 @@ |
235 | 252 | } |
236 | 253 | |
237 | 254 | # Give general extensions, such as a captcha, a chance to abort logins |
238 | | - $abort = self::ABORTED; |
239 | | - if( !wfRunHooks( 'AbortLogin', array( $this->mUser, $this->mPassword, &$abort ) ) ) { |
240 | | - return $abort; |
| 255 | + if( !wfRunHooks( 'AbortLogin', array( $this->mUser, $this->mPassword, &$this->mLoginResult ) ) ) { |
| 256 | + return self::ABORTED; |
241 | 257 | } |
242 | 258 | |
243 | 259 | if( !$this->mUser->checkPassword( $this->mPassword ) ) { |
— | — | @@ -266,7 +282,13 @@ |
267 | 283 | # etc will probably just fail cleanly here. |
268 | 284 | $retval = self::RESET_PASS; |
269 | 285 | } else { |
270 | | - $retval = ( $this->mPassword === '' ) ? self::EMPTY_PASS : self::WRONG_PASS; |
| 286 | + if( $this->mPassword === '' ){ |
| 287 | + $retval = self::EMPTY_PASS; |
| 288 | + $this->mLoginResult = 'wrongpasswordempty'; |
| 289 | + } else { |
| 290 | + $retval = self::WRONG_PASS; |
| 291 | + $this->mLoginResult = 'wrongpassword'; |
| 292 | + } |
271 | 293 | } |
272 | 294 | } else { |
273 | 295 | $wgAuth->updateUser( $this->mUser ); |
— | — | @@ -296,15 +318,20 @@ |
297 | 319 | * authentication database? |
298 | 320 | * @param $byEmail Bool is this request going to be handled by sending |
299 | 321 | * the password by email? |
300 | | - * @return Bool whether creation was successful (should only fail for |
301 | | - * Db errors etc). |
| 322 | + * @return Class constant status code. |
302 | 323 | */ |
303 | 324 | protected function initUser( $autocreate=false, $byEmail=false ) { |
304 | 325 | global $wgAuth; |
| 326 | + |
| 327 | + if( !wfRunHooks( 'AbortNewAccount', array( $this->mUser, &$this->mCreateResult, $autocreate, $byEmail ) ) ) { |
| 328 | + # Hook point to add extra creation throttles and blocks |
| 329 | + wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" ); |
| 330 | + return self::ABORTED; |
| 331 | + } |
305 | 332 | |
306 | 333 | $fields = array( |
307 | 334 | 'name' => $this->mName, |
308 | | - 'password' => $byEmail ? null : $this->mPassword, |
| 335 | + 'password' => $byEmail ? null : User::crypt( $this->mPassword ), |
309 | 336 | 'email' => $this->mEmail, |
310 | 337 | 'options' => array( |
311 | 338 | 'rememberpassword' => $this->mRemember ? 1 : 0, |
— | — | @@ -314,7 +341,7 @@ |
315 | 342 | $this->mUser = User::createNew( $this->mName, $fields ); |
316 | 343 | |
317 | 344 | if( $this->mUser === null ){ |
318 | | - return null; |
| 345 | + return self::FAILED; |
319 | 346 | } |
320 | 347 | |
321 | 348 | # Let old AuthPlugins play with the user |
— | — | @@ -338,9 +365,10 @@ |
339 | 366 | $this->mUser->addNewUserLogEntry( $byEmail ); |
340 | 367 | |
341 | 368 | # Run hooks |
342 | | - wfRunHooks( 'AddNewAccount', array( $this->mUser ) ); |
| 369 | + wfRunHooks( 'AddNewAccount', array( $this->mUser, $autocreate, $byEmail ) ); |
343 | 370 | |
344 | | - return true; |
| 371 | + $this->mUser->saveSettings(); |
| 372 | + return self::SUCCESS; |
345 | 373 | } |
346 | 374 | |
347 | 375 | /** |
— | — | @@ -431,12 +459,6 @@ |
432 | 460 | $this->mUser->setEmail( $this->mEmail ); |
433 | 461 | $this->mUser->setRealName( $this->mRealName ); |
434 | 462 | |
435 | | - if( !wfRunHooks( 'AbortNewAccount', array( $this->mUser, &$this->mCreateResult ) ) ) { |
436 | | - # Hook point to add extra creation throttles and blocks |
437 | | - wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" ); |
438 | | - return self::ABORTED; |
439 | | - } |
440 | | - |
441 | 463 | if ( $wgAccountCreationThrottle && $wgUser->isPingLimitable() ) { |
442 | 464 | $key = wfMemcKey( 'acctcreate', 'ip', $ip ); |
443 | 465 | $value = $wgMemc->get( $key ); |
— | — | @@ -457,11 +479,8 @@ |
458 | 480 | } |
459 | 481 | |
460 | 482 | $result = $this->initUser( false, $byEmail ); |
461 | | - if( $result === null ) |
462 | | - # It's unlikely we'd get here without some exception |
463 | | - # being thrown, but it's probably possible... |
464 | | - return self::FAILED; |
465 | | - |
| 483 | + if( $result !== self::SUCCESS ) |
| 484 | + return $result; |
466 | 485 | |
467 | 486 | # Send out an email message if needed |
468 | 487 | if( $byEmail ){ |
Index: branches/happy-melon/phase3/includes/specials/SpecialUserlogin.php |
— | — | @@ -451,11 +451,13 @@ |
452 | 452 | |
453 | 453 | case Login::NO_NAME: |
454 | 454 | case Login::ILLEGAL: |
455 | | - $this->mainLoginForm( wfMsg( 'noname' ) ); |
456 | | - break; |
457 | 455 | case Login::WRONG_PLUGIN_PASS: |
458 | | - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); |
| 456 | + case Login::WRONG_PASS: |
| 457 | + case Login::EMPTY_PASS: |
| 458 | + case Login::THROTTLED: |
| 459 | + $this->mainLoginForm( wfMsg( $this->mLogin->mLoginResult ) ); |
459 | 460 | break; |
| 461 | + |
460 | 462 | case Login::NOT_EXISTS: |
461 | 463 | if( $wgUser->isAllowed( 'createaccount' ) ){ |
462 | 464 | $this->mainLoginForm( wfMsgWikiHtml( 'nosuchuser', htmlspecialchars( $this->mName ) ) ); |
— | — | @@ -463,12 +465,7 @@ |
464 | 466 | $this->mainLoginForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->mName ) ) ); |
465 | 467 | } |
466 | 468 | break; |
467 | | - case Login::WRONG_PASS: |
468 | | - $this->mainLoginForm( wfMsg( 'wrongpassword' ) ); |
469 | | - break; |
470 | | - case Login::EMPTY_PASS: |
471 | | - $this->mainLoginForm( wfMsg( 'wrongpasswordempty' ) ); |
472 | | - break; |
| 469 | + |
473 | 470 | case Login::RESET_PASS: |
474 | 471 | # 'Shell out' to Special:ResetPass to get the user to |
475 | 472 | # set a new permanent password from a temporary one. |
— | — | @@ -477,14 +474,18 @@ |
478 | 475 | $reset->mHeaderMsgType = 'success'; |
479 | 476 | $reset->execute( null ); |
480 | 477 | break; |
| 478 | + |
481 | 479 | case Login::CREATE_BLOCKED: |
482 | 480 | $this->userBlockedMessage(); |
483 | 481 | break; |
484 | | - case Login::THROTTLED: |
485 | | - $this->mainLoginForm( wfMsg( 'login-throttled' ) ); |
| 482 | + |
| 483 | + case Login::ABORTED: |
| 484 | + $msg = $this->mLogin->mLoginResult ? $this->mLogin->mLoginResult : $this->mLogin->mCreateResult; |
| 485 | + $this->mainLoginForm( wfMsg( $msg ) ); |
486 | 486 | break; |
| 487 | + |
487 | 488 | default: |
488 | | - throw new MWException( "Unhandled case value" ); |
| 489 | + throw new MWException( "Unhandled case value: $result" ); |
489 | 490 | } |
490 | 491 | } |
491 | 492 | |
Index: branches/happy-melon/phase3/includes/specials/SpecialCreateAccount.php |
— | — | @@ -183,10 +183,10 @@ |
184 | 184 | case Login::CREATE_BADNAME: |
185 | 185 | case Login::WRONG_PLUGIN_PASS: |
186 | 186 | case Login::ABORTED: |
187 | | - return $this->showMainForm( wfMsg( $this->mLogin->mCreateResult ) ); |
| 187 | + return $this->showMainForm( wfMsgExt( $this->mLogin->mCreateResult, array('parseinline') ) ); |
188 | 188 | |
189 | 189 | case Login::CREATE_SORBS: |
190 | | - return $this->showMainForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . wfGetIP() . ')' ); |
| 190 | + return $this->showMainForm( wfMsgExt( 'sorbs_create_account_reason' ) . ' (' . wfGetIP() . ')', array('parseinline') ); |
191 | 191 | |
192 | 192 | case Login::CREATE_BLOCKED: |
193 | 193 | return $this->userBlockedMessage(); |