public function handleRequest(AphrontRequest $request)
 {
     $this->requireApplicationCapability(AuthManageProvidersCapability::CAPABILITY);
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $providers = PhabricatorAuthProvider::getAllBaseProviders();
     $e_provider = null;
     $errors = array();
     if ($request->isFormPost()) {
         $provider_string = $request->getStr('provider');
         if (!strlen($provider_string)) {
             $e_provider = pht('Required');
             $errors[] = pht('You must select an authentication provider.');
         } else {
             $found = false;
             foreach ($providers as $provider) {
                 if (get_class($provider) === $provider_string) {
                     $found = true;
                     break;
                 }
             }
             if (!$found) {
                 $e_provider = pht('Invalid');
                 $errors[] = pht('You must select a valid provider.');
             }
         }
         if (!$errors) {
             return id(new AphrontRedirectResponse())->setURI($this->getApplicationURI('/config/new/' . $provider_string . '/'));
         }
     }
     $options = id(new AphrontFormRadioButtonControl())->setLabel(pht('Provider'))->setName('provider')->setError($e_provider);
     $configured = PhabricatorAuthProvider::getAllProviders();
     $configured_classes = array();
     foreach ($configured as $configured_provider) {
         $configured_classes[get_class($configured_provider)] = true;
     }
     // Sort providers by login order, and move disabled providers to the
     // bottom.
     $providers = msort($providers, 'getLoginOrder');
     $providers = array_diff_key($providers, $configured_classes) + $providers;
     foreach ($providers as $provider) {
         if (isset($configured_classes[get_class($provider)])) {
             $disabled = true;
             $description = pht('This provider is already configured.');
         } else {
             $disabled = false;
             $description = $provider->getDescriptionForCreate();
         }
         $options->addButton(get_class($provider), $provider->getNameForCreate(), $description, $disabled ? 'disabled' : null, $disabled);
     }
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild($options)->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Continue')));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Provider'))->setFormErrors($errors)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Add Provider'));
     $crumbs->setBorder(true);
     $title = pht('Add Auth Provider');
     $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon('fa-plus-square');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($form_box));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public static function getFacebookApplicationID()
 {
     $providers = PhabricatorAuthProvider::getAllProviders();
     $fb_provider = idx($providers, 'facebook:facebook.com');
     if (!$fb_provider) {
         return null;
     }
     return $fb_provider->getProviderConfig()->getProperty(self::PROPERTY_APP_ID);
 }
 public function isUsableForLogin()
 {
     $key = $this->getProviderKey();
     $provider = PhabricatorAuthProvider::getEnabledProviderByKey($key);
     if (!$provider) {
         return false;
     }
     if (!$provider->shouldAllowLogin()) {
         return false;
     }
     return true;
 }
 private function init($viewer, $repository)
 {
     $repo_uri = $repository->getRemoteURIObject();
     $repo_domain = $repo_uri->getDomain();
     $this->account = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->withAccountTypes(array('github'))->withAccountDomains(array($repo_domain))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$this->account) {
         throw new Exception(pht('No matching GitHub account found for %s.', $repo_domain));
     }
     $this->provider = PhabricatorAuthProvider::getEnabledProviderByKey($this->account->getProviderKey());
     if (!$this->provider) {
         throw new Exception(pht('GitHub provider for %s is not enabled.', $repo_domain));
     }
 }
 private function renderConfirmDialog()
 {
     $provider_key = $this->providerKey;
     $provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
     if ($provider) {
         $title = pht('Unlink "%s" Account?', $provider->getProviderName());
         $body = pht('You will no longer be able to use your %s account to ' . 'log in to Phabricator.', $provider->getProviderName());
     } else {
         $title = pht('Unlink Account?');
         $body = pht('You will no longer be able to use this account to log in ' . 'to Phabricator.');
     }
     $dialog = id(new AphrontDialogView())->setUser($this->getRequest()->getUser())->setTitle($title)->appendParagraph($body)->appendParagraph(pht('Note: Unlinking an authentication provider will terminate any ' . 'other active login sessions.'))->addSubmitButton(pht('Unlink Account'))->addCancelButton($this->getDoneURI());
     return id(new AphrontDialogResponse())->setDialog($dialog);
 }
 public function getProvider()
 {
     if (!$this->provider) {
         $base = PhabricatorAuthProvider::getAllBaseProviders();
         $found = null;
         foreach ($base as $provider) {
             if (get_class($provider) == $this->providerClass) {
                 $found = $provider;
                 break;
             }
         }
         if ($found) {
             $this->provider = id(clone $found)->attachProviderConfig($this);
         }
     }
     return $this->provider;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     if ($viewer->isLoggedIn()) {
         // Kick the user home if they are already logged in.
         return id(new AphrontRedirectResponse())->setURI('/');
     }
     if ($request->isAjax()) {
         return $this->processAjaxRequest();
     }
     if ($request->isConduit()) {
         return $this->processConduitRequest();
     }
     // If the user gets this far, they aren't logged in, so if they have a
     // user session token we can conclude that it's invalid: if it was valid,
     // they'd have been logged in above and never made it here. Try to clear
     // it and warn the user they may need to nuke their cookies.
     $session_token = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
     if (strlen($session_token)) {
         $kind = PhabricatorAuthSessionEngine::getSessionKindFromToken($session_token);
         switch ($kind) {
             case PhabricatorAuthSessionEngine::KIND_ANONYMOUS:
                 // If this is an anonymous session. It's expected that they won't
                 // be logged in, so we can just continue.
                 break;
             default:
                 // The session cookie is invalid, so clear it.
                 $request->clearCookie(PhabricatorCookies::COOKIE_USERNAME);
                 $request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
                 return $this->renderError(pht('Your login session is invalid. Try reloading the page and ' . 'logging in again. If that does not work, clear your browser ' . 'cookies.'));
         }
     }
     $providers = PhabricatorAuthProvider::getAllEnabledProviders();
     foreach ($providers as $key => $provider) {
         if (!$provider->shouldAllowLogin()) {
             unset($providers[$key]);
         }
     }
     if (!$providers) {
         if ($this->isFirstTimeSetup()) {
             // If this is a fresh install, let the user register their admin
             // account.
             return id(new AphrontRedirectResponse())->setURI($this->getApplicationURI('/register/'));
         }
         return $this->renderError(pht('This Phabricator install is not configured with any enabled ' . 'authentication providers which can be used to log in. If you ' . 'have accidentally locked yourself out by disabling all providers, ' . 'you can use `%s` to recover access to an administrative account.', 'phabricator/bin/auth recover <username>'));
     }
     $next_uri = $request->getStr('next');
     if (!strlen($next_uri)) {
         if ($this->getDelegatingController()) {
             // Only set a next URI from the request path if this controller was
             // delegated to, which happens when a user tries to view a page which
             // requires them to login.
             // If this controller handled the request directly, we're on the main
             // login page, and never want to redirect the user back here after they
             // login.
             $next_uri = (string) $this->getRequest()->getRequestURI();
         }
     }
     if (!$request->isFormPost()) {
         if (strlen($next_uri)) {
             PhabricatorCookies::setNextURICookie($request, $next_uri);
         }
         PhabricatorCookies::setClientIDCookie($request);
     }
     if (!$request->getURIData('loggedout') && count($providers) == 1) {
         $auto_login_provider = head($providers);
         $auto_login_config = $auto_login_provider->getProviderConfig();
         if ($auto_login_provider instanceof PhabricatorPhabricatorAuthProvider && $auto_login_config->getShouldAutoLogin()) {
             $auto_login_adapter = $provider->getAdapter();
             $auto_login_adapter->setState($provider->getAuthCSRFCode($request));
             return id(new AphrontRedirectResponse())->setIsExternal(true)->setURI($provider->getAdapter()->getAuthenticateURI());
         }
     }
     $invite = $this->loadInvite();
     $not_buttons = array();
     $are_buttons = array();
     $providers = msort($providers, 'getLoginOrder');
     foreach ($providers as $provider) {
         if ($invite) {
             $form = $provider->buildInviteForm($this);
         } else {
             $form = $provider->buildLoginForm($this);
         }
         if ($provider->isLoginFormAButton()) {
             $are_buttons[] = $form;
         } else {
             $not_buttons[] = $form;
         }
     }
     $out = array();
     $out[] = $not_buttons;
     if ($are_buttons) {
         require_celerity_resource('auth-css');
         foreach ($are_buttons as $key => $button) {
             $are_buttons[$key] = phutil_tag('div', array('class' => 'phabricator-login-button mmb'), $button);
         }
         // If we only have one button, add a second pretend button so that we
         // always have two columns. This makes it easier to get the alignments
         // looking reasonable.
         if (count($are_buttons) == 1) {
             $are_buttons[] = null;
         }
         $button_columns = id(new AphrontMultiColumnView())->setFluidLayout(true);
         $are_buttons = array_chunk($are_buttons, ceil(count($are_buttons) / 2));
         foreach ($are_buttons as $column) {
             $button_columns->addColumn($column);
         }
         $out[] = phutil_tag('div', array('class' => 'phabricator-login-buttons'), $button_columns);
     }
     $login_message = PhabricatorEnv::getEnvConfig('auth.login-message');
     $login_message = phutil_safe_html($login_message);
     $invite_message = null;
     if ($invite) {
         $invite_message = $this->renderInviteHeader($invite);
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Login'));
     $crumbs->setBorder(true);
     return $this->buildApplicationPage(array($crumbs, $login_message, $invite_message, $out), array('title' => pht('Login to Phabricator')));
 }
 private function loadDefaultAccount()
 {
     $providers = PhabricatorAuthProvider::getAllEnabledProviders();
     $account = null;
     $provider = null;
     $response = null;
     foreach ($providers as $key => $candidate_provider) {
         if (!$candidate_provider->shouldAllowRegistration()) {
             unset($providers[$key]);
             continue;
         }
         if (!$candidate_provider->isDefaultRegistrationProvider()) {
             unset($providers[$key]);
         }
     }
     if (!$providers) {
         $response = $this->renderError(pht('There are no configured default registration providers.'));
         return array($account, $provider, $response);
     } else {
         if (count($providers) > 1) {
             $response = $this->renderError(pht('There are too many configured default registration providers.'));
             return array($account, $provider, $response);
         }
     }
     $provider = head($providers);
     $account = $provider->getDefaultExternalAccount();
     return array($account, $provider, $response);
 }
 public function renderConfigPropertyTransactionTitle(PhabricatorAuthProviderConfigTransaction $xaction)
 {
     $author_phid = $xaction->getAuthorPHID();
     $old = $xaction->getOldValue();
     $new = $xaction->getNewValue();
     $key = $xaction->getMetadataValue(PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
     $labels = $this->getPropertyLabels();
     if (isset($labels[$key])) {
         $label = $labels[$key];
         $mask = false;
         switch ($key) {
             case self::KEY_ANONYMOUS_PASSWORD:
                 $mask = true;
                 break;
         }
         if ($mask) {
             return pht('%s updated the "%s" value.', $xaction->renderHandleLink($author_phid), $label);
         }
         if ($old === null || $old === '') {
             return pht('%s set the "%s" value to "%s".', $xaction->renderHandleLink($author_phid), $label, $new);
         } else {
             return pht('%s changed the "%s" value from "%s" to "%s".', $xaction->renderHandleLink($author_phid), $label, $old, $new);
         }
     }
     return parent::renderConfigPropertyTransactionTitle($xaction);
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $viewer = $this->getViewer();
     $query = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT));
     $username = $args->getArg('user');
     if (strlen($username)) {
         $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withUsernames(array($username))->executeOne();
         if ($user) {
             $query->withUserPHIDs(array($user->getPHID()));
         } else {
             throw new PhutilArgumentUsageException(pht('No such user "%s"!', $username));
         }
     }
     $type = $args->getArg('type');
     if (strlen($type)) {
         $query->withAccountTypes(array($type));
     }
     $domain = $args->getArg('domain');
     if (strlen($domain)) {
         $query->withAccountDomains(array($domain));
     }
     $accounts = $query->execute();
     if (!$accounts) {
         throw new PhutilArgumentUsageException(pht('No accounts match the arguments!'));
     } else {
         $console->writeOut("%s\n", pht('Found %s account(s) to refresh.', phutil_count($accounts)));
     }
     $providers = PhabricatorAuthProvider::getAllEnabledProviders();
     foreach ($accounts as $account) {
         $console->writeOut("%s\n", pht('Refreshing account #%d (%s/%s).', $account->getID(), $account->getAccountType(), $account->getAccountDomain()));
         $key = $account->getProviderKey();
         if (empty($providers[$key])) {
             $console->writeOut("> %s\n", pht('Skipping, provider is not enabled or does not exist.'));
             continue;
         }
         $provider = $providers[$key];
         if (!$provider instanceof PhabricatorOAuth2AuthProvider) {
             $console->writeOut("> %s\n", pht('Skipping, provider is not an OAuth2 provider.'));
             continue;
         }
         $adapter = $provider->getAdapter();
         if (!$adapter->supportsTokenRefresh()) {
             $console->writeOut("> %s\n", pht('Skipping, provider does not support token refresh.'));
             continue;
         }
         $refresh_token = $account->getProperty('oauth.token.refresh');
         if (!$refresh_token) {
             $console->writeOut("> %s\n", pht('Skipping, provider has no stored refresh token.'));
             continue;
         }
         $console->writeOut("+ %s\n", pht('Refreshing token, current token expires in %s seconds.', new PhutilNumber($account->getProperty('oauth.token.access.expires') - time())));
         $token = $provider->getOAuthAccessToken($account, $force_refresh = true);
         if (!$token) {
             $console->writeOut("* %s\n", pht('Unable to refresh token!'));
             continue;
         }
         $console->writeOut("+ %s\n", pht('Refreshed token, new token expires in %s seconds.', new PhutilNumber($account->getProperty('oauth.token.access.expires') - time())));
     }
     $console->writeOut("%s\n", pht('Done.'));
     return 0;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withIDs(array($this->id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     $profile_uri = '/p/' . $user->getUsername() . '/';
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $phid = $request->getStr('phid');
         $is_default = false;
         if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
             $phid = null;
             $is_default = true;
         } else {
             if ($phid) {
                 $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             } else {
                 if ($request->getFileExists('picture')) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['picture'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
                 } else {
                     $e_file = pht('Required');
                     $errors[] = pht('You must choose a file when uploading a new profile picture.');
                 }
             }
         }
         if (!$errors && !$is_default) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             } else {
                 $xformer = new PhabricatorImageTransformer();
                 $xformed = $xformer->executeProfileTransform($file, $width = 50, $min_height = 50, $max_height = 50);
             }
         }
         if (!$errors) {
             if ($is_default) {
                 $user->setProfileImagePHID(null);
             } else {
                 $user->setProfileImagePHID($xformed->getPHID());
                 $xformed->attachToObject($user->getPHID());
             }
             $user->save();
             return id(new AphrontRedirectResponse())->setURI($profile_uri);
         }
     }
     $title = pht('Edit Profile Picture');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($user->getUsername(), $profile_uri);
     $crumbs->addTextCrumb($title);
     $form = id(new PHUIFormLayoutView())->setUser($viewer);
     $default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png');
     $images = array();
     $current = $user->getProfileImagePHID();
     $has_current = false;
     if ($current) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($current))->execute();
         if ($files) {
             $file = head($files);
             if ($file->isTransformableImage()) {
                 $has_current = true;
                 $images[$current] = array('uri' => $file->getBestURI(), 'tip' => pht('Current Picture'));
             }
         }
     }
     // Try to add external account images for any associated external accounts.
     $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($user->getPHID()))->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     foreach ($accounts as $account) {
         $file = $account->getProfileImageFile();
         if ($account->getProfileImagePHID() != $file->getPHID()) {
             // This is a default image, just skip it.
             continue;
         }
         $provider = PhabricatorAuthProvider::getEnabledProviderByKey($account->getProviderKey());
         if ($provider) {
             $tip = pht('Picture From %s', $provider->getProviderName());
         } else {
             $tip = pht('Picture From External Account');
         }
         if ($file->isTransformableImage()) {
             $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => $tip);
         }
     }
     // Try to add Gravatar images for any email addresses associated with the
     // account.
     if (PhabricatorEnv::getEnvConfig('security.allow-outbound-http')) {
         $emails = id(new PhabricatorUserEmail())->loadAllWhere('userPHID = %s ORDER BY address', $user->getPHID());
         $futures = array();
         foreach ($emails as $email_object) {
             $email = $email_object->getAddress();
             $hash = md5(strtolower(trim($email)));
             $uri = id(new PhutilURI("https://secure.gravatar.com/avatar/{$hash}"))->setQueryParams(array('size' => 200, 'default' => '404', 'rating' => 'x'));
             $futures[$email] = new HTTPSFuture($uri);
         }
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         foreach (Futures($futures) as $email => $future) {
             try {
                 list($body) = $future->resolvex();
                 $file = PhabricatorFile::newFromFileData($body, array('name' => 'profile-gravatar', 'ttl' => 60 * 60 * 4));
                 if ($file->isTransformableImage()) {
                     $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => pht('Gravatar for %s', $email));
                 }
             } catch (Exception $ex) {
                 // Just continue.
             }
         }
         unset($unguarded);
     }
     $images[PhabricatorPHIDConstants::PHID_VOID] = array('uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'));
     require_celerity_resource('people-profile-css');
     Javelin::initBehavior('phabricator-tooltips', array());
     $buttons = array();
     foreach ($images as $phid => $spec) {
         $button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => $spec['tip'], 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $spec['uri'])));
         $button = array(phutil_tag('input', array('type' => 'hidden', 'name' => 'phid', 'value' => $phid)), $button);
         $button = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), $button);
         $buttons[] = $button;
     }
     if ($has_current) {
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Current Picture'))->setValue(array_shift($buttons)));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Use Picture'))->setValue($buttons));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('picture')->setLabel(pht('Upload Picture'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($profile_uri)->setValue(pht('Upload Picture')));
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Picture'))->setForm($upload_form);
     return $this->buildApplicationPage(array($crumbs, $form_box, $upload_box), array('title' => $title));
 }
 public function buildProviderErrorResponse(PhabricatorAuthProvider $provider, $message)
 {
     $message = pht('Authentication provider ("%s") encountered an error during login. %s', $provider->getProviderName(), $message);
     return $this->renderError($message);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     if ($viewer->isLoggedIn()) {
         // Kick the user home if they are already logged in.
         return id(new AphrontRedirectResponse())->setURI('/');
     }
     if ($request->isAjax()) {
         return $this->processAjaxRequest();
     }
     if ($request->isConduit()) {
         return $this->processConduitRequest();
     }
     // If the user gets this far, they aren't logged in, so if they have a
     // user session token we can conclude that it's invalid: if it was valid,
     // they'd have been logged in above and never made it here. Try to clear
     // it and warn the user they may need to nuke their cookies.
     $session_token = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
     $did_clear = $request->getStr('cleared');
     if (strlen($session_token)) {
         $kind = PhabricatorAuthSessionEngine::getSessionKindFromToken($session_token);
         switch ($kind) {
             case PhabricatorAuthSessionEngine::KIND_ANONYMOUS:
                 // If this is an anonymous session. It's expected that they won't
                 // be logged in, so we can just continue.
                 break;
             default:
                 // The session cookie is invalid, so try to clear it.
                 $request->clearCookie(PhabricatorCookies::COOKIE_USERNAME);
                 $request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
                 // We've previously tried to clear the cookie but we ended up back
                 // here, so it didn't work. Hard fatal instead of trying again.
                 if ($did_clear) {
                     return $this->renderError(pht('Your login session is invalid, and clearing the session ' . 'cookie was unsuccessful. Try clearing your browser cookies.'));
                 }
                 $redirect_uri = $request->getRequestURI();
                 $redirect_uri->setQueryParam('cleared', 1);
                 return id(new AphrontRedirectResponse())->setURI($redirect_uri);
         }
     }
     // If we just cleared the session cookie and it worked, clean up after
     // ourselves by redirecting to get rid of the "cleared" parameter. The
     // the workflow will continue normally.
     if ($did_clear) {
         $redirect_uri = $request->getRequestURI();
         $redirect_uri->setQueryParam('cleared', null);
         return id(new AphrontRedirectResponse())->setURI($redirect_uri);
     }
     $providers = PhabricatorAuthProvider::getAllEnabledProviders();
     foreach ($providers as $key => $provider) {
         if (!$provider->shouldAllowLogin()) {
             unset($providers[$key]);
         }
     }
     if (!$providers) {
         if ($this->isFirstTimeSetup()) {
             // If this is a fresh install, let the user register their admin
             // account.
             return id(new AphrontRedirectResponse())->setURI($this->getApplicationURI('/register/'));
         }
         return $this->renderError(pht('This Phabricator install is not configured with any enabled ' . 'authentication providers which can be used to log in. If you ' . 'have accidentally locked yourself out by disabling all providers, ' . 'you can use `%s` to recover access to an administrative account.', 'phabricator/bin/auth recover <username>'));
     }
     $next_uri = $request->getStr('next');
     if (!strlen($next_uri)) {
         if ($this->getDelegatingController()) {
             // Only set a next URI from the request path if this controller was
             // delegated to, which happens when a user tries to view a page which
             // requires them to login.
             // If this controller handled the request directly, we're on the main
             // login page, and never want to redirect the user back here after they
             // login.
             $next_uri = (string) $this->getRequest()->getRequestURI();
         }
     }
     if (!$request->isFormPost()) {
         if (strlen($next_uri)) {
             PhabricatorCookies::setNextURICookie($request, $next_uri);
         }
         PhabricatorCookies::setClientIDCookie($request);
     }
     $auto_response = $this->tryAutoLogin($providers);
     if ($auto_response) {
         return $auto_response;
     }
     $invite = $this->loadInvite();
     $not_buttons = array();
     $are_buttons = array();
     $providers = msort($providers, 'getLoginOrder');
     foreach ($providers as $provider) {
         if ($invite) {
             $form = $provider->buildInviteForm($this);
         } else {
             $form = $provider->buildLoginForm($this);
         }
         if ($provider->isLoginFormAButton()) {
             $are_buttons[] = $form;
         } else {
             $not_buttons[] = $form;
         }
     }
     $out = array();
     $out[] = $not_buttons;
     if ($are_buttons) {
         require_celerity_resource('auth-css');
         foreach ($are_buttons as $key => $button) {
             $are_buttons[$key] = phutil_tag('div', array('class' => 'phabricator-login-button mmb'), $button);
         }
         // If we only have one button, add a second pretend button so that we
         // always have two columns. This makes it easier to get the alignments
         // looking reasonable.
         if (count($are_buttons) == 1) {
             $are_buttons[] = null;
         }
         $button_columns = id(new AphrontMultiColumnView())->setFluidLayout(true);
         $are_buttons = array_chunk($are_buttons, ceil(count($are_buttons) / 2));
         foreach ($are_buttons as $column) {
             $button_columns->addColumn($column);
         }
         $out[] = phutil_tag('div', array('class' => 'phabricator-login-buttons'), $button_columns);
     }
     $handlers = PhabricatorAuthLoginHandler::getAllHandlers();
     $delegating_controller = $this->getDelegatingController();
     $header = array();
     foreach ($handlers as $handler) {
         $handler = clone $handler;
         $handler->setRequest($request);
         if ($delegating_controller) {
             $handler->setDelegatingController($delegating_controller);
         }
         $header[] = $handler->getAuthLoginHeaderContent();
     }
     $invite_message = null;
     if ($invite) {
         $invite_message = $this->renderInviteHeader($invite);
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Login'));
     $crumbs->setBorder(true);
     $title = pht('Login to Phabricator');
     $view = array($header, $invite_message, $out);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function willRegisterAccount(PhabricatorExternalAccount $account)
 {
     parent::willRegisterAccount($account);
     $account->setAccountID($account->getUserPHID());
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     if ($this->configID) {
         $config = id(new PhabricatorAuthProviderConfigQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($this->configID))->executeOne();
         if (!$config) {
             return new Aphront404Response();
         }
         $provider = $config->getProvider();
         if (!$provider) {
             return new Aphront404Response();
         }
         $is_new = false;
     } else {
         $providers = PhabricatorAuthProvider::getAllBaseProviders();
         foreach ($providers as $candidate_provider) {
             if (get_class($candidate_provider) === $this->providerClass) {
                 $provider = $candidate_provider;
                 break;
             }
         }
         if (!$provider) {
             return new Aphront404Response();
         }
         // TODO: When we have multi-auth providers, support them here.
         $configs = id(new PhabricatorAuthProviderConfigQuery())->setViewer($viewer)->withProviderClasses(array(get_class($provider)))->execute();
         if ($configs) {
             $id = head($configs)->getID();
             $dialog = id(new AphrontDialogView())->setUser($viewer)->setMethod('GET')->setSubmitURI($this->getApplicationURI('config/edit/' . $id . '/'))->setTitle(pht('Provider Already Configured'))->appendChild(pht('This provider ("%s") already exists, and you can not add more ' . 'than one instance of it. You can edit the existing provider, ' . 'or you can choose a different provider.', $provider->getProviderName()))->addCancelButton($this->getApplicationURI('config/new/'))->addSubmitButton(pht('Edit Existing Provider'));
             return id(new AphrontDialogResponse())->setDialog($dialog);
         }
         $config = $provider->getDefaultProviderConfig();
         $provider->attachProviderConfig($config);
         $is_new = true;
     }
     $errors = array();
     $v_registration = $config->getShouldAllowRegistration();
     $v_link = $config->getShouldAllowLink();
     $v_unlink = $config->getShouldAllowUnlink();
     $v_trust_email = $config->getShouldTrustEmails();
     if ($request->isFormPost()) {
         $properties = $provider->readFormValuesFromRequest($request);
         list($errors, $issues, $properties) = $provider->processEditForm($request, $properties);
         $xactions = array();
         if (!$errors) {
             if ($is_new) {
                 if (!strlen($config->getProviderType())) {
                     $config->setProviderType($provider->getProviderType());
                 }
                 if (!strlen($config->getProviderDomain())) {
                     $config->setProviderDomain($provider->getProviderDomain());
                 }
             }
             $xactions[] = id(new PhabricatorAuthProviderConfigTransaction())->setTransactionType(PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION)->setNewValue($request->getInt('allowRegistration', 0));
             $xactions[] = id(new PhabricatorAuthProviderConfigTransaction())->setTransactionType(PhabricatorAuthProviderConfigTransaction::TYPE_LINK)->setNewValue($request->getInt('allowLink', 0));
             $xactions[] = id(new PhabricatorAuthProviderConfigTransaction())->setTransactionType(PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK)->setNewValue($request->getInt('allowUnlink', 0));
             $xactions[] = id(new PhabricatorAuthProviderConfigTransaction())->setTransactionType(PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS)->setNewValue($request->getInt('trustEmails', 0));
             foreach ($properties as $key => $value) {
                 $xactions[] = id(new PhabricatorAuthProviderConfigTransaction())->setTransactionType(PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY)->setMetadataValue('auth:property', $key)->setNewValue($value);
             }
             if ($is_new) {
                 $config->save();
             }
             $editor = id(new PhabricatorAuthProviderConfigEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->applyTransactions($config, $xactions);
             if ($provider->hasSetupStep() && $is_new) {
                 $id = $config->getID();
                 $next_uri = $this->getApplicationURI('config/edit/' . $id . '/');
             } else {
                 $next_uri = $this->getApplicationURI();
             }
             return id(new AphrontRedirectResponse())->setURI($next_uri);
         }
     } else {
         $properties = $provider->readFormValuesFromProvider();
         $issues = array();
     }
     if ($is_new) {
         $button = pht('Add Provider');
         $crumb = pht('Add Provider');
         $title = pht('Add Authentication Provider');
         $cancel_uri = $this->getApplicationURI('/config/new/');
     } else {
         $button = pht('Save');
         $crumb = pht('Edit Provider');
         $title = pht('Edit Authentication Provider');
         $cancel_uri = $this->getApplicationURI();
     }
     $config_name = 'auth.email-domains';
     $config_href = '/config/edit/' . $config_name . '/';
     $email_domains = PhabricatorEnv::getEnvConfig($config_name);
     if ($email_domains) {
         $registration_warning = pht('Users will only be able to register with a verified email address ' . 'at one of the configured [[ %s | %s ]] domains: **%s**', $config_href, $config_name, implode(', ', $email_domains));
     } else {
         $registration_warning = pht("NOTE: Any user who can browse to this install's login page will be " . "able to register a Phabricator account. To restrict who can register " . "an account, configure [[ %s | %s ]].", $config_href, $config_name);
     }
     $str_registration = array(phutil_tag('strong', array(), pht('Allow Registration:')), ' ', pht('Allow users to register new Phabricator accounts using this ' . 'provider. If you disable registration, users can still use this ' . 'provider to log in to existing accounts, but will not be able to ' . 'create new accounts.'));
     $str_link = hsprintf('<strong>%s:</strong> %s', pht('Allow Linking Accounts'), pht('Allow users to link account credentials for this provider to ' . 'existing Phabricator accounts. There is normally no reason to ' . 'disable this unless you are trying to move away from a provider ' . 'and want to stop users from creating new account links.'));
     $str_unlink = hsprintf('<strong>%s:</strong> %s', pht('Allow Unlinking Accounts'), pht('Allow users to unlink account credentials for this provider from ' . 'existing Phabricator accounts. If you disable this, Phabricator ' . 'accounts will be permanently bound to provider accounts.'));
     $str_trusted_email = hsprintf('<strong>%s:</strong> %s', pht('Trust Email Addresses'), pht('Phabricator will skip email verification for accounts registered ' . 'through this provider.'));
     $status_tag = id(new PHUITagView())->setType(PHUITagView::TYPE_STATE);
     if ($is_new) {
         $status_tag->setName(pht('New Provider'))->setBackgroundColor('blue');
     } else {
         if ($config->getIsEnabled()) {
             $status_tag->setName(pht('Enabled'))->setBackgroundColor('green');
         } else {
             $status_tag->setName(pht('Disabled'))->setBackgroundColor('red');
         }
     }
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Provider'))->setValue($provider->getProviderName()))->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Status'))->setValue($status_tag))->appendChild(id(new AphrontFormCheckboxControl())->setLabel(pht('Allow'))->addCheckbox('allowRegistration', 1, $str_registration, $v_registration))->appendRemarkupInstructions($registration_warning)->appendChild(id(new AphrontFormCheckboxControl())->addCheckbox('allowLink', 1, $str_link, $v_link))->appendChild(id(new AphrontFormCheckboxControl())->addCheckbox('allowUnlink', 1, $str_unlink, $v_unlink));
     if ($provider->shouldAllowEmailTrustConfiguration()) {
         $form->appendChild(id(new AphrontFormCheckboxControl())->addCheckbox('trustEmails', 1, $str_trusted_email, $v_trust_email));
     }
     $provider->extendEditForm($request, $form, $properties, $issues);
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($button));
     $help = $provider->getConfigurationHelp();
     if ($help) {
         $form->appendChild(id(new PHUIFormDividerControl()));
         $form->appendRemarkupInstructions($help);
     }
     $footer = $provider->renderConfigurationFooter();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($crumb);
     $xaction_view = null;
     if (!$is_new) {
         $xactions = id(new PhabricatorAuthProviderConfigTransactionQuery())->withObjectPHIDs(array($config->getPHID()))->setViewer($viewer)->execute();
         foreach ($xactions as $xaction) {
             $xaction->setProvider($provider);
         }
         $xaction_view = id(new PhabricatorApplicationTransactionView())->setUser($viewer)->setObjectPHID($config->getPHID())->setTransactions($xactions);
     }
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box, $footer, $xaction_view), array('title' => $title));
 }
 protected function loadAccountForRegistrationOrLinking($account_key)
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $account = null;
     $provider = null;
     $response = null;
     if (!$account_key) {
         $response = $this->renderError(pht('Request did not include account key.'));
         return array($account, $provider, $response);
     }
     // NOTE: We're using the omnipotent user because the actual user may not
     // be logged in yet, and because we want to tailor an error message to
     // distinguish between "not usable" and "does not exist". We do explicit
     // checks later on to make sure this account is valid for the intended
     // operation. This requires edit permission for completeness and consistency
     // but it won't actually be meaningfully checked because we're using the
     // ominpotent user.
     $account = id(new PhabricatorExternalAccountQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withAccountSecrets(array($account_key))->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$account) {
         $response = $this->renderError(pht('No valid linkable account.'));
         return array($account, $provider, $response);
     }
     if ($account->getUserPHID()) {
         if ($account->getUserPHID() != $viewer->getPHID()) {
             $response = $this->renderError(pht('The account you are attempting to register or link is already ' . 'linked to another user.'));
         } else {
             $response = $this->renderError(pht('The account you are attempting to link is already linked ' . 'to your account.'));
         }
         return array($account, $provider, $response);
     }
     $registration_key = $request->getCookie(PhabricatorCookies::COOKIE_REGISTRATION);
     // NOTE: This registration key check is not strictly necessary, because
     // we're only creating new accounts, not linking existing accounts. It
     // might be more hassle than it is worth, especially for email.
     //
     // The attack this prevents is getting to the registration screen, then
     // copy/pasting the URL and getting someone else to click it and complete
     // the process. They end up with an account bound to credentials you
     // control. This doesn't really let you do anything meaningful, though,
     // since you could have simply completed the process yourself.
     if (!$registration_key) {
         $response = $this->renderError(pht('Your browser did not submit a registration key with the request. ' . 'You must use the same browser to begin and complete registration. ' . 'Check that cookies are enabled and try again.'));
         return array($account, $provider, $response);
     }
     // We store the digest of the key rather than the key itself to prevent a
     // theoretical attacker with read-only access to the database from
     // hijacking registration sessions.
     $actual = $account->getProperty('registrationKey');
     $expect = PhabricatorHash::digest($registration_key);
     if ($actual !== $expect) {
         $response = $this->renderError(pht('Your browser submitted a different registration key than the one ' . 'associated with this account. You may need to clear your cookies.'));
         return array($account, $provider, $response);
     }
     $other_account = id(new PhabricatorExternalAccount())->loadAllWhere('accountType = %s AND accountDomain = %s AND accountID = %s
     AND id != %d', $account->getAccountType(), $account->getAccountDomain(), $account->getAccountID(), $account->getID());
     if ($other_account) {
         $response = $this->renderError(pht('The account you are attempting to register with already belongs ' . 'to another user.'));
         return array($account, $provider, $response);
     }
     $provider = PhabricatorAuthProvider::getEnabledProviderByKey($account->getProviderKey());
     if (!$provider) {
         $response = $this->renderError(pht('The account you are attempting to register with uses a nonexistent ' . 'or disabled authentication provider (with key "%s"). An ' . 'administrator may have recently disabled this provider.', $account->getProviderKey()));
         return array($account, $provider, $response);
     }
     return array($account, $provider, null);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withIDs(array($id))->needProfileImage(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     $this->setUser($user);
     $done_uri = $this->getApplicationURI("manage/{$id}/");
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
     $e_file = true;
     $errors = array();
     if ($request->isFormPost()) {
         $phid = $request->getStr('phid');
         $is_default = false;
         if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
             $phid = null;
             $is_default = true;
         } else {
             if ($phid) {
                 $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             } else {
                 if ($request->getFileExists('picture')) {
                     $file = PhabricatorFile::newFromPHPUpload($_FILES['picture'], array('authorPHID' => $viewer->getPHID(), 'canCDN' => true));
                 } else {
                     $e_file = pht('Required');
                     $errors[] = pht('You must choose a file when uploading a new profile picture.');
                 }
             }
         }
         if (!$errors && !$is_default) {
             if (!$file->isTransformableImage()) {
                 $e_file = pht('Not Supported');
                 $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats));
             } else {
                 $xform = PhabricatorFileTransform::getTransformByKey(PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE);
                 $xformed = $xform->executeTransform($file);
             }
         }
         if (!$errors) {
             if ($is_default) {
                 $user->setProfileImagePHID(null);
             } else {
                 $user->setProfileImagePHID($xformed->getPHID());
                 $xformed->attachToObject($user->getPHID());
             }
             $user->save();
             return id(new AphrontRedirectResponse())->setURI($done_uri);
         }
     }
     $title = pht('Edit Profile Picture');
     $form = id(new PHUIFormLayoutView())->setUser($viewer);
     $default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png');
     $images = array();
     $current = $user->getProfileImagePHID();
     $has_current = false;
     if ($current) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($current))->execute();
         if ($files) {
             $file = head($files);
             if ($file->isTransformableImage()) {
                 $has_current = true;
                 $images[$current] = array('uri' => $file->getBestURI(), 'tip' => pht('Current Picture'));
             }
         }
     }
     $builtins = array('user1.png', 'user2.png', 'user3.png', 'user4.png', 'user5.png', 'user6.png', 'user7.png', 'user8.png', 'user9.png');
     foreach ($builtins as $builtin) {
         $file = PhabricatorFile::loadBuiltin($viewer, $builtin);
         $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => pht('Builtin Image'));
     }
     // Try to add external account images for any associated external accounts.
     $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($user->getPHID()))->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     foreach ($accounts as $account) {
         $file = $account->getProfileImageFile();
         if ($account->getProfileImagePHID() != $file->getPHID()) {
             // This is a default image, just skip it.
             continue;
         }
         $provider = PhabricatorAuthProvider::getEnabledProviderByKey($account->getProviderKey());
         if ($provider) {
             $tip = pht('Picture From %s', $provider->getProviderName());
         } else {
             $tip = pht('Picture From External Account');
         }
         if ($file->isTransformableImage()) {
             $images[$file->getPHID()] = array('uri' => $file->getBestURI(), 'tip' => $tip);
         }
     }
     $images[PhabricatorPHIDConstants::PHID_VOID] = array('uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'));
     require_celerity_resource('people-profile-css');
     Javelin::initBehavior('phabricator-tooltips', array());
     $buttons = array();
     foreach ($images as $phid => $spec) {
         $button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => $spec['tip'], 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $spec['uri'])));
         $button = array(phutil_tag('input', array('type' => 'hidden', 'name' => 'phid', 'value' => $phid)), $button);
         $button = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST'), $button);
         $buttons[] = $button;
     }
     if ($has_current) {
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Current Picture'))->setValue(array_shift($buttons)));
     }
     $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Use Picture'))->setValue($buttons));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     $upload_form = id(new AphrontFormView())->setUser($viewer)->setEncType('multipart/form-data')->appendChild(id(new AphrontFormFileControl())->setName('picture')->setLabel(pht('Upload Picture'))->setError($e_file)->setCaption(pht('Supported formats: %s', implode(', ', $supported_formats))))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($done_uri)->setValue(pht('Upload Picture')));
     $upload_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New Picture'))->setForm($upload_form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Edit Profile Picture'));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($form_box, $upload_box));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $action = $request->getURIData('action');
     $provider_key = $request->getURIData('pkey');
     $provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
     if (!$provider) {
         return new Aphront404Response();
     }
     switch ($action) {
         case 'link':
             if (!$provider->shouldAllowAccountLink()) {
                 return $this->renderErrorPage(pht('Account Not Linkable'), array(pht('This provider is not configured to allow linking.')));
             }
             break;
         case 'refresh':
             if (!$provider->shouldAllowAccountRefresh()) {
                 return $this->renderErrorPage(pht('Account Not Refreshable'), array(pht('This provider does not allow refreshing.')));
             }
             break;
         default:
             return new Aphront400Response();
     }
     $account = id(new PhabricatorExternalAccount())->loadOneWhere('accountType = %s AND accountDomain = %s AND userPHID = %s', $provider->getProviderType(), $provider->getProviderDomain(), $viewer->getPHID());
     switch ($action) {
         case 'link':
             if ($account) {
                 return $this->renderErrorPage(pht('Account Already Linked'), array(pht('Your Phabricator account is already linked to an external ' . 'account for this provider.')));
             }
             break;
         case 'refresh':
             if (!$account) {
                 return $this->renderErrorPage(pht('No Account Linked'), array(pht('You do not have a linked account on this provider, and thus ' . 'can not refresh it.')));
             }
             break;
         default:
             return new Aphront400Response();
     }
     $panel_uri = '/settings/panel/external/';
     PhabricatorCookies::setClientIDCookie($request);
     switch ($action) {
         case 'link':
             id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession($viewer, $request, $panel_uri);
             $form = $provider->buildLinkForm($this);
             break;
         case 'refresh':
             $form = $provider->buildRefreshForm($this);
             break;
         default:
             return new Aphront400Response();
     }
     if ($provider->isLoginFormAButton()) {
         require_celerity_resource('auth-css');
         $form = phutil_tag('div', array('class' => 'phabricator-link-button pl'), $form);
     }
     switch ($action) {
         case 'link':
             $name = pht('Link Account');
             $title = pht('Link %s Account', $provider->getProviderName());
             break;
         case 'refresh':
             $name = pht('Refresh Account');
             $title = pht('Refresh %s Account', $provider->getProviderName());
             break;
         default:
             return new Aphront400Response();
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Link Account'), $panel_uri);
     $crumbs->addTextCrumb($provider->getProviderName($name));
     return $this->buildApplicationPage(array($crumbs, $form), array('title' => $title));
 }
 public function processRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     $providers = PhabricatorAuthProvider::getAllProviders();
     $accounts = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     $linked_head = id(new PHUIHeaderView())->setHeader(pht('Linked Accounts and Authentication'));
     $linked = id(new PHUIObjectItemListView())->setUser($viewer)->setFlush(true)->setNoDataString(pht('You have no linked accounts.'));
     $login_accounts = 0;
     foreach ($accounts as $account) {
         if ($account->isUsableForLogin()) {
             $login_accounts++;
         }
     }
     foreach ($accounts as $account) {
         $item = id(new PHUIObjectItemView());
         $provider = idx($providers, $account->getProviderKey());
         if ($provider) {
             $item->setHeader($provider->getProviderName());
             $can_unlink = $provider->shouldAllowAccountUnlink();
             if (!$can_unlink) {
                 $item->addAttribute(pht('Permanently Linked'));
             }
         } else {
             $item->setHeader(pht('Unknown Account ("%s")', $account->getProviderKey()));
             $can_unlink = true;
         }
         $can_login = $account->isUsableForLogin();
         if (!$can_login) {
             $item->addAttribute(pht('Disabled (an administrator has disabled login for this ' . 'account provider).'));
         }
         $can_unlink = $can_unlink && (!$can_login || $login_accounts > 1);
         $can_refresh = $provider && $provider->shouldAllowAccountRefresh();
         if ($can_refresh) {
             $item->addAction(id(new PHUIListItemView())->setIcon('fa-refresh')->setHref('/auth/refresh/' . $account->getProviderKey() . '/'));
         }
         $item->addAction(id(new PHUIListItemView())->setIcon('fa-times')->setWorkflow(true)->setDisabled(!$can_unlink)->setHref('/auth/unlink/' . $account->getProviderKey() . '/'));
         if ($provider) {
             $provider->willRenderLinkedAccount($viewer, $item, $account);
         }
         $linked->addItem($item);
     }
     $linkable_head = id(new PHUIHeaderView())->setHeader(pht('Add External Account'));
     $linkable = id(new PHUIObjectItemListView())->setUser($viewer)->setFlush(true)->setNoDataString(pht('Your account is linked with all available providers.'));
     $accounts = mpull($accounts, null, 'getProviderKey');
     $providers = PhabricatorAuthProvider::getAllEnabledProviders();
     $providers = msort($providers, 'getProviderName');
     foreach ($providers as $key => $provider) {
         if (isset($accounts[$key])) {
             continue;
         }
         if (!$provider->shouldAllowAccountLink()) {
             continue;
         }
         $link_uri = '/auth/link/' . $provider->getProviderKey() . '/';
         $item = id(new PHUIObjectItemView());
         $item->setHeader($provider->getProviderName());
         $item->setHref($link_uri);
         $item->addAction(id(new PHUIListItemView())->setIcon('fa-link')->setHref($link_uri));
         $linkable->addItem($item);
     }
     $linked_box = id(new PHUIObjectBoxView())->setHeader($linked_head)->setObjectList($linked);
     $linkable_box = id(new PHUIObjectBoxView())->setHeader($linkable_head)->setObjectList($linkable);
     return array($linked_box, $linkable_box);
 }
 protected function willSaveAccount(PhabricatorExternalAccount $account)
 {
     parent::willSaveAccount($account);
     $this->synchronizeOAuthAccount($account);
 }