Merge "Bypass login page if no user input is required."
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 24 Nov 2016 22:59:42 +0000 (22:59 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 24 Nov 2016 22:59:42 +0000 (22:59 +0000)
1  2 
includes/specialpage/LoginSignupSpecialPage.php

@@@ -156,7 -156,7 +156,7 @@@ abstract class LoginSignupSpecialPage e
                        [
                                'returnto' => $this->mReturnTo,
                                'returntoquery' => $this->mReturnToQuery,
 -                              'uselang' => $this->mLanguage,
 +                              'uselang' => $this->mLanguage ?: null,
                                'fromhttp' => $wgSecureLogin && $this->mFromHTTP ? '1' : null,
                        ]
                );
                        return;
                }
  
+               if ( $this->canBypassForm( $button_name ) ) {
+                       $this->setRequest( [], true );
+                       $this->getRequest()->setVal( $this->getTokenName(), $this->getToken() );
+                       if ( $button_name ) {
+                               $this->getRequest()->setVal( $button_name, true );
+                       }
+               }
                $status = $this->trySubmit();
  
                if ( !$status || !$status->isGood() ) {
                }
        }
  
+       /**
+        * Determine if the login form can be bypassed. This will be the case when no more than one
+        * button is present and no other user input fields that are not marked as 'skippable' are
+        * present. If the login form were not bypassed, the user would be presented with a
+        * superfluous page on which they must press the single button to proceed with login.
+        * Not only does this cause an additional mouse click and page load, it confuses users,
+        * especially since there are a help link and forgotten password link that are
+        * provided on the login page that do not apply to this situation.
+        *
+        * @param string|null &$button_name if the form has a single button, returns
+        *   the name of the button; otherwise, returns null
+        * @return bool
+        */
+       private function canBypassForm( &$button_name ) {
+               $button_name = null;
+               if ( $this->isContinued() ) {
+                       return false;
+               }
+               $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
+               foreach ( $fields as $fieldname => $field ) {
+                       if ( !isset( $field['type'] ) ) {
+                               return false;
+                       }
+                       if ( !empty( $field['skippable'] ) ) {
+                               continue;
+                       }
+                       if ( $field['type'] === 'button' ) {
+                               if ( $button_name !== null ) {
+                                       $button_name = null;
+                                       return false;
+                               } else {
+                                       $button_name = $fieldname;
+                               }
+                       } elseif ( $field['type'] !== 'null' ) {
+                               return false;
+                       }
+               }
+               return true;
+       }
        /**
         * Show the success page.
         *
                }
  
                // warning header for non-standard workflows (e.g. security reauthentication)
 -              if ( !$this->isSignup() && $this->getUser()->isLoggedIn() ) {
 +              if (
 +                      !$this->isSignup() &&
 +                      $this->getUser()->isLoggedIn() &&
 +                      $this->authAction !== AuthManager::ACTION_LOGIN_CONTINUE
 +              ) {
                        $reauthMessage = $this->securityLevel ? 'userlogin-reauth' : 'userlogin-loggedin';
                        $submitStatus->warning( $reauthMessage, $this->getUser()->getName() );
                }
                $form = HTMLForm::factory( 'vform', $formDescriptor, $context );
  
                $form->addHiddenField( 'authAction', $this->authAction );
 -              if ( $wgLoginLanguageSelector ) {
 +              if ( $wgLoginLanguageSelector && $this->mLanguage ) {
                        $form->addHiddenField( 'uselang', $this->mLanguage );
                }
                $form->addHiddenField( 'force', $this->securityLevel );
                // make a best effort to get the value of fields which used to be fixed in the old login
                // template but now might or might not exist depending on what providers are used
                $request = $this->getRequest();
 -              $data = (object) [
 +              $data = (object)[
                        'mUsername' => $request->getText( 'wpName' ),
                        'mPassword' => $request->getText( 'wpPassword' ),
                        'mRetype' => $request->getText( 'wpRetype' ),
                $wgAuth->modifyUITemplate( $template, $action );
  
                $oldTemplate = $template;
 -              $hookName = $this->isSignup() ? 'UserCreateForm' : 'UserLoginForm';
 -              Hooks::run( $hookName, [ &$template ] );
 -              if ( $oldTemplate !== $template ) {
 -                      wfDeprecated( "reference in $hookName hook", '1.27' );
 +
 +              // Both Hooks::run are explicit here to make findHooks.php happy
 +              if ( $this->isSignup() ) {
 +                      Hooks::run( 'UserCreateForm', [ &$template ] );
 +                      if ( $oldTemplate !== $template ) {
 +                              wfDeprecated( "reference in UserCreateForm hook", '1.27' );
 +                      }
 +              } else {
 +                      Hooks::run( 'UserLoginForm', [ &$template ] );
 +                      if ( $oldTemplate !== $template ) {
 +                              wfDeprecated( "reference in UserLoginForm hook", '1.27' );
 +                      }
                }
  
                return $template;
 -
        }
  
        public function onAuthChangeFormFields(
                }
                if ( !$this->isSignup() && $this->showExtraInformation() ) {
                        $passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
 -                      if ( $passwordReset->isAllowed( $this->getUser() ) ) {
 +                      if ( $passwordReset->isAllowed( $this->getUser() )->isGood() ) {
                                $fieldDefinitions['passwordReset'] = [
                                        'type' => 'info',
                                        'raw' => true,