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 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)); }
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(); $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)); }
private function loadProvider() { $provider = PhabricatorAuthProvider::getEnabledProviderByKey($this->providerKey); if (!$provider) { return $this->renderError(pht('The account you are attempting to login with uses a nonexistent ' . 'or disabled authentication provider (with key "%s"). An ' . 'administrator may have recently disabled this provider.', $this->providerKey)); } $this->provider = $provider; return null; }
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)); }