[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/auth/controller/ -> PhabricatorAuthLoginController.php (source)

   1  <?php
   2  
   3  final class PhabricatorAuthLoginController
   4    extends PhabricatorAuthController {
   5  
   6    private $providerKey;
   7    private $extraURIData;
   8    private $provider;
   9  
  10    public function shouldRequireLogin() {
  11      return false;
  12    }
  13  
  14    public function shouldAllowRestrictedParameter($parameter_name) {
  15      // Whitelist the OAuth 'code' parameter.
  16  
  17      if ($parameter_name == 'code') {
  18        return true;
  19      }
  20      return parent::shouldAllowRestrictedParameter($parameter_name);
  21    }
  22  
  23    public function willProcessRequest(array $data) {
  24      $this->providerKey = $data['pkey'];
  25      $this->extraURIData = idx($data, 'extra');
  26    }
  27  
  28    public function getExtraURIData() {
  29      return $this->extraURIData;
  30    }
  31  
  32    public function processRequest() {
  33      $request = $this->getRequest();
  34      $viewer = $request->getUser();
  35  
  36      $response = $this->loadProvider();
  37      if ($response) {
  38        return $response;
  39      }
  40  
  41      $provider = $this->provider;
  42  
  43      try {
  44        list($account, $response) = $provider->processLoginRequest($this);
  45      } catch (PhutilAuthUserAbortedException $ex) {
  46        if ($viewer->isLoggedIn()) {
  47          // If a logged-in user cancels, take them back to the external accounts
  48          // panel.
  49          $next_uri = '/settings/panel/external/';
  50        } else {
  51          // If a logged-out user cancels, take them back to the auth start page.
  52          $next_uri = '/';
  53        }
  54  
  55        // User explicitly hit "Cancel".
  56        $dialog = id(new AphrontDialogView())
  57          ->setUser($viewer)
  58          ->setTitle(pht('Authentication Canceled'))
  59          ->appendChild(
  60            pht('You canceled authentication.'))
  61          ->addCancelButton($next_uri, pht('Continue'));
  62        return id(new AphrontDialogResponse())->setDialog($dialog);
  63      }
  64  
  65      if ($response) {
  66        return $response;
  67      }
  68  
  69      if (!$account) {
  70        throw new Exception(
  71          'Auth provider failed to load an account from processLoginRequest()!');
  72      }
  73  
  74      if ($account->getUserPHID()) {
  75        // The account is already attached to a Phabricator user, so this is
  76        // either a login or a bad account link request.
  77        if (!$viewer->isLoggedIn()) {
  78          if ($provider->shouldAllowLogin()) {
  79            return $this->processLoginUser($account);
  80          } else {
  81            return $this->renderError(
  82              pht(
  83                'The external account ("%s") you just authenticated with is '.
  84                'not configured to allow logins on this Phabricator install. '.
  85                'An administrator may have recently disabled it.',
  86                $provider->getProviderName()));
  87          }
  88        } else if ($viewer->getPHID() == $account->getUserPHID()) {
  89          // This is either an attempt to re-link an existing and already
  90          // linked account (which is silly) or a refresh of an external account
  91          // (e.g., an OAuth account).
  92          return id(new AphrontRedirectResponse())
  93            ->setURI('/settings/panel/external/');
  94        } else {
  95          return $this->renderError(
  96            pht(
  97              'The external account ("%s") you just used to login is already '.
  98              'associated with another Phabricator user account. Login to the '.
  99              'other Phabricator account and unlink the external account before '.
 100              'linking it to a new Phabricator account.',
 101              $provider->getProviderName()));
 102        }
 103      } else {
 104        // The account is not yet attached to a Phabricator user, so this is
 105        // either a registration or an account link request.
 106        if (!$viewer->isLoggedIn()) {
 107          if ($provider->shouldAllowRegistration()) {
 108            return $this->processRegisterUser($account);
 109          } else {
 110            return $this->renderError(
 111              pht(
 112                'The external account ("%s") you just authenticated with is '.
 113                'not configured to allow registration on this Phabricator '.
 114                'install. An administrator may have recently disabled it.',
 115                $provider->getProviderName()));
 116          }
 117        } else {
 118          if ($provider->shouldAllowAccountLink()) {
 119            return $this->processLinkUser($account);
 120          } else {
 121            return $this->renderError(
 122              pht(
 123                'The external account ("%s") you just authenticated with is '.
 124                'not configured to allow account linking on this Phabricator '.
 125                'install. An administrator may have recently disabled it.',
 126                $provider->getProviderName()));
 127          }
 128        }
 129      }
 130  
 131      // This should be unreachable, but fail explicitly if we get here somehow.
 132      return new Aphront400Response();
 133    }
 134  
 135    private function processLoginUser(PhabricatorExternalAccount $account) {
 136      $user = id(new PhabricatorUser())->loadOneWhere(
 137        'phid = %s',
 138        $account->getUserPHID());
 139  
 140      if (!$user) {
 141        return $this->renderError(
 142          pht(
 143            'The external account you just logged in with is not associated '.
 144            'with a valid Phabricator user.'));
 145      }
 146  
 147      return $this->loginUser($user);
 148    }
 149  
 150    private function processRegisterUser(PhabricatorExternalAccount $account) {
 151      $account_secret = $account->getAccountSecret();
 152      $register_uri = $this->getApplicationURI('register/'.$account_secret.'/');
 153      return $this->setAccountKeyAndContinue($account, $register_uri);
 154    }
 155  
 156    private function processLinkUser(PhabricatorExternalAccount $account) {
 157      $account_secret = $account->getAccountSecret();
 158      $confirm_uri = $this->getApplicationURI('confirmlink/'.$account_secret.'/');
 159      return $this->setAccountKeyAndContinue($account, $confirm_uri);
 160    }
 161  
 162    private function setAccountKeyAndContinue(
 163      PhabricatorExternalAccount $account,
 164      $next_uri) {
 165  
 166      if ($account->getUserPHID()) {
 167        throw new Exception('Account is already registered or linked.');
 168      }
 169  
 170      // Regenerate the registration secret key, set it on the external account,
 171      // set a cookie on the user's machine, and redirect them to registration.
 172      // See PhabricatorAuthRegisterController for discussion of the registration
 173      // key.
 174  
 175      $registration_key = Filesystem::readRandomCharacters(32);
 176      $account->setProperty(
 177        'registrationKey',
 178        PhabricatorHash::digest($registration_key));
 179  
 180      $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
 181        $account->save();
 182      unset($unguarded);
 183  
 184      $this->getRequest()->setTemporaryCookie(
 185        PhabricatorCookies::COOKIE_REGISTRATION,
 186        $registration_key);
 187  
 188      return id(new AphrontRedirectResponse())->setURI($next_uri);
 189    }
 190  
 191    private function loadProvider() {
 192      $provider = PhabricatorAuthProvider::getEnabledProviderByKey(
 193        $this->providerKey);
 194  
 195      if (!$provider) {
 196        return $this->renderError(
 197          pht(
 198            'The account you are attempting to login with uses a nonexistent '.
 199            'or disabled authentication provider (with key "%s"). An '.
 200            'administrator may have recently disabled this provider.',
 201            $this->providerKey));
 202      }
 203  
 204      $this->provider = $provider;
 205  
 206      return null;
 207    }
 208  
 209    protected function renderError($message) {
 210      return $this->renderErrorPage(
 211        pht('Login Failed'),
 212        array($message));
 213    }
 214  
 215    public function buildProviderPageResponse(
 216      PhabricatorAuthProvider $provider,
 217      $content) {
 218  
 219      $crumbs = $this->buildApplicationCrumbs();
 220  
 221      if ($this->getRequest()->getUser()->isLoggedIn()) {
 222        $crumbs->addTextCrumb(pht('Link Account'), $provider->getSettingsURI());
 223      } else {
 224        $crumbs->addTextCrumb(pht('Login'), $this->getApplicationURI('start/'));
 225      }
 226  
 227      $crumbs->addTextCrumb($provider->getProviderName());
 228  
 229      return $this->buildApplicationPage(
 230        array(
 231          $crumbs,
 232          $content,
 233        ),
 234        array(
 235          'title' => pht('Login'),
 236        ));
 237    }
 238  
 239    public function buildProviderErrorResponse(
 240      PhabricatorAuthProvider $provider,
 241      $message) {
 242  
 243      $message = pht(
 244        'Authentication provider ("%s") encountered an error during login. %s',
 245        $provider->getProviderName(),
 246        $message);
 247  
 248      return $this->renderError($message);
 249    }
 250  
 251  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1