Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/auth/provider/PhabricatorAuthProvider.php b/src/applications/auth/provider/PhabricatorAuthProvider.php
index b02594f068..32fb052b4b 100644
--- a/src/applications/auth/provider/PhabricatorAuthProvider.php
+++ b/src/applications/auth/provider/PhabricatorAuthProvider.php
@@ -1,363 +1,439 @@
<?php
abstract class PhabricatorAuthProvider {
private $providerConfig;
public function attachProviderConfig(PhabricatorAuthProviderConfig $config) {
$this->providerConfig = $config;
return $this;
}
public function hasProviderConfig() {
return (bool)$this->providerConfig;
}
public function getProviderConfig() {
if ($this->providerConfig === null) {
throw new Exception(
"Call attachProviderConfig() before getProviderConfig()!");
}
return $this->providerConfig;
}
public function getConfigurationHelp() {
return null;
}
public function getDefaultProviderConfig() {
return id(new PhabricatorAuthProviderConfig())
->setProviderClass(get_class($this))
->setIsEnabled(1)
->setShouldAllowLogin(1)
->setShouldAllowRegistration(1)
->setShouldAllowLink(1)
->setShouldAllowUnlink(1);
}
public function getNameForCreate() {
return $this->getProviderName();
}
public function getDescriptionForCreate() {
return null;
}
public function getProviderKey() {
return $this->getAdapter()->getAdapterKey();
}
public function getProviderType() {
return $this->getAdapter()->getAdapterType();
}
public function getProviderDomain() {
return $this->getAdapter()->getAdapterDomain();
}
public static function getAllBaseProviders() {
static $providers;
if ($providers === null) {
$objects = id(new PhutilSymbolLoader())
->setAncestorClass(__CLASS__)
->loadObjects();
$providers = $objects;
}
return $providers;
}
public static function getAllProviders() {
static $providers;
if ($providers === null) {
$objects = self::getAllBaseProviders();
$configs = id(new PhabricatorAuthProviderConfigQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->execute();
$providers = array();
foreach ($configs as $config) {
if (!isset($objects[$config->getProviderClass()])) {
// This configuration is for a provider which is not installed.
continue;
}
$object = clone $objects[$config->getProviderClass()];
$object->attachProviderConfig($config);
$key = $object->getProviderKey();
if (isset($providers[$key])) {
throw new Exception(
pht(
"Two authentication providers use the same provider key ".
"('%s'). Each provider must be identified by a unique ".
"key.",
$key));
}
$providers[$key] = $object;
}
}
return $providers;
}
public static function getAllEnabledProviders() {
$providers = self::getAllProviders();
foreach ($providers as $key => $provider) {
if (!$provider->isEnabled()) {
unset($providers[$key]);
}
}
return $providers;
}
public static function getEnabledProviderByKey($provider_key) {
return idx(self::getAllEnabledProviders(), $provider_key);
}
abstract public function getProviderName();
abstract public function getAdapter();
public function isEnabled() {
return $this->getProviderConfig()->getIsEnabled();
}
public function shouldAllowLogin() {
return $this->getProviderConfig()->getShouldAllowLogin();
}
public function shouldAllowRegistration() {
return $this->getProviderConfig()->getShouldAllowRegistration();
}
public function shouldAllowAccountLink() {
return $this->getProviderConfig()->getShouldAllowLink();
}
public function shouldAllowAccountUnlink() {
return $this->getProviderConfig()->getShouldAllowUnlink();
}
public function buildLoginForm(
PhabricatorAuthStartController $controller) {
return $this->renderLoginForm($controller->getRequest(), $mode = 'start');
}
abstract public function processLoginRequest(
PhabricatorAuthLoginController $controller);
public function buildLinkForm(
PhabricatorAuthLinkController $controller) {
return $this->renderLoginForm($controller->getRequest(), $mode = 'link');
}
public function shouldAllowAccountRefresh() {
return true;
}
public function buildRefreshForm(
PhabricatorAuthLinkController $controller) {
return $this->renderLoginForm($controller->getRequest(), $mode = 'refresh');
}
protected function renderLoginForm(
AphrontRequest $request,
$mode) {
throw new Exception("Not implemented!");
}
public function createProviders() {
return array($this);
}
protected function willSaveAccount(PhabricatorExternalAccount $account) {
return;
}
public function willRegisterAccount(PhabricatorExternalAccount $account) {
return;
}
protected function loadOrCreateAccount($account_id) {
if (!strlen($account_id)) {
throw new Exception(
"loadOrCreateAccount(...): empty account ID!");
}
$adapter = $this->getAdapter();
$adapter_class = get_class($adapter);
if (!strlen($adapter->getAdapterType())) {
throw new Exception(
"AuthAdapter (of class '{$adapter_class}') has an invalid ".
"implementation: no adapter type.");
}
if (!strlen($adapter->getAdapterDomain())) {
throw new Exception(
"AuthAdapter (of class '{$adapter_class}') has an invalid ".
"implementation: no adapter domain.");
}
$account = id(new PhabricatorExternalAccount())->loadOneWhere(
'accountType = %s AND accountDomain = %s AND accountID = %s',
$adapter->getAdapterType(),
$adapter->getAdapterDomain(),
$account_id);
if (!$account) {
$account = id(new PhabricatorExternalAccount())
->setAccountType($adapter->getAdapterType())
->setAccountDomain($adapter->getAdapterDomain())
->setAccountID($account_id);
}
$account->setUsername($adapter->getAccountName());
$account->setRealName($adapter->getAccountRealName());
$account->setEmail($adapter->getAccountEmail());
$account->setAccountURI($adapter->getAccountURI());
$account->setProfileImagePHID(null);
$image_uri = $adapter->getAccountImageURI();
if ($image_uri) {
try {
$name = PhabricatorSlug::normalize($this->getProviderName());
$name = $name.'-profile.jpg';
// TODO: If the image has not changed, we do not need to make a new
// file entry for it, but there's no convenient way to do this with
// PhabricatorFile right now. The storage will get shared, so the impact
// here is negligible.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$image_file = PhabricatorFile::newFromFileDownload(
$image_uri,
array(
'name' => $name,
));
unset($unguarded);
if ($image_file) {
$account->setProfileImagePHID($image_file->getPHID());
}
} catch (Exception $ex) {
// Log this but proceed, it's not especially important that we
// be able to pull profile images.
phlog($ex);
}
}
$this->willSaveAccount($account);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$account->save();
unset($unguarded);
return $account;
}
public function getLoginURI() {
$app = PhabricatorApplication::getByClass('PhabricatorApplicationAuth');
$uri = $app->getApplicationURI('/login/'.$this->getProviderKey().'/');
return PhabricatorEnv::getURI($uri);
}
public function getSettingsURI() {
return '/settings/panel/external/';
}
public function getStartURI() {
$app = PhabricatorApplication::getByClass('PhabricatorApplicationAuth');
$uri = $app->getApplicationURI('/start/');
return $uri;
}
public function isDefaultRegistrationProvider() {
return false;
}
public function shouldRequireRegistrationPassword() {
return false;
}
public function getDefaultExternalAccount() {
throw new Exception("Not implemented!");
}
public function getLoginOrder() {
return '500-'.$this->getProviderName();
}
protected function getLoginIcon() {
return 'Generic';
}
public function isLoginFormAButton() {
return false;
}
public function renderConfigPropertyTransactionTitle(
PhabricatorAuthProviderConfigTransaction $xaction) {
return null;
}
public function readFormValuesFromProvider() {
return array();
}
public function readFormValuesFromRequest(AphrontRequest $request) {
return array();
}
public function processEditForm(
AphrontRequest $request,
array $values) {
$errors = array();
$issues = array();
return array($errors, $issues, $values);
}
public function extendEditForm(
AphrontRequest $request,
AphrontFormView $form,
array $values,
array $issues) {
return;
}
public function willRenderLinkedAccount(
PhabricatorUser $viewer,
PhabricatorObjectItemView $item,
PhabricatorExternalAccount $account) {
$account_view = id(new PhabricatorAuthAccountView())
->setExternalAccount($account)
->setAuthProvider($this);
$item->appendChild(
phutil_tag(
'div',
array(
'class' => 'mmr mml mst mmb',
),
$account_view));
}
/**
* Return true to use a two-step configuration (setup, configure) instead of
* the default single-step configuration. In practice, this means that
* creating a new provider instance will redirect back to the edit page
* instead of the provider list.
*
* @return bool True if this provider uses two-step configuration.
*/
public function hasSetupStep() {
return false;
}
+
+ /**
+ * Render a standard login/register button element.
+ *
+ * The `$attributes` parameter takes these keys:
+ *
+ * - `uri`: URI the button should take the user to when clicked.
+ * - `method`: Optional HTTP method the button should use, defaults to GET.
+ *
+ * @param AphrontRequest HTTP request.
+ * @param string Request mode string.
+ * @param map Additional parameters, see above.
+ * @return wild Login button.
+ */
+ protected function renderStandardLoginButton(
+ AphrontRequest $request,
+ $mode,
+ array $attributes = array()) {
+
+ PhutilTypeSpec::checkMap(
+ $attributes,
+ array(
+ 'method' => 'optional string',
+ 'uri' => 'string',
+ ));
+
+ $viewer = $request->getUser();
+ $adapter = $this->getAdapter();
+
+ if ($mode == 'link') {
+ $button_text = pht('Link External Account');
+ } else if ($mode == 'refresh') {
+ $button_text = pht('Refresh Account Link');
+ } else if ($this->shouldAllowRegistration()) {
+ $button_text = pht('Login or Register');
+ } else {
+ $button_text = pht('Login');
+ }
+
+ $icon = id(new PHUIIconView())
+ ->setSpriteSheet(PHUIIconView::SPRITE_LOGIN)
+ ->setSpriteIcon($this->getLoginIcon());
+
+ $button = id(new PHUIButtonView())
+ ->setSize(PHUIButtonView::BIG)
+ ->setColor(PHUIButtonView::GREY)
+ ->setIcon($icon)
+ ->setText($button_text)
+ ->setSubtext($this->getProviderName());
+
+ $uri = $attributes['uri'];
+ $uri = new PhutilURI($uri);
+ $params = $uri->getQueryParams();
+ $uri->setQueryParams(array());
+
+ $content = array($button);
+
+ foreach ($params as $key => $value) {
+ $content[] = phutil_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => $key,
+ 'value' => $value,
+ ));
+ }
+
+ return phabricator_form(
+ $viewer,
+ array(
+ 'method' => idx($attributes, 'method', 'GET'),
+ 'action' => (string)$uri,
+ ),
+ $content);
+ }
+
}
diff --git a/src/applications/auth/provider/PhabricatorAuthProviderOAuth.php b/src/applications/auth/provider/PhabricatorAuthProviderOAuth.php
index 88d1b60369..9578e3e2f4 100644
--- a/src/applications/auth/provider/PhabricatorAuthProviderOAuth.php
+++ b/src/applications/auth/provider/PhabricatorAuthProviderOAuth.php
@@ -1,380 +1,341 @@
<?php
abstract class PhabricatorAuthProviderOAuth extends PhabricatorAuthProvider {
protected $adapter;
abstract protected function newOAuthAdapter();
public function getDescriptionForCreate() {
return pht('Configure %s OAuth.', $this->getProviderName());
}
public function getAdapter() {
if (!$this->adapter) {
$adapter = $this->newOAuthAdapter();
$this->adapter = $adapter;
$this->configureAdapter($adapter);
}
return $this->adapter;
}
protected function configureAdapter(PhutilAuthAdapterOAuth $adapter) {
$config = $this->getProviderConfig();
$adapter->setClientID($config->getProperty(self::PROPERTY_APP_ID));
$adapter->setClientSecret(
new PhutilOpaqueEnvelope(
$config->getProperty(self::PROPERTY_APP_SECRET)));
$adapter->setRedirectURI($this->getLoginURI());
return $adapter;
}
public function isLoginFormAButton() {
return true;
}
protected function renderLoginForm(AphrontRequest $request, $mode) {
- $viewer = $request->getUser();
-
- if ($mode == 'link') {
- $button_text = pht('Link External Account');
- } else if ($mode == 'refresh') {
- $button_text = pht('Refresh Account Link');
- } else if ($this->shouldAllowRegistration()) {
- $button_text = pht('Login or Register');
- } else {
- $button_text = pht('Login');
- }
-
- $icon = id(new PHUIIconView())
- ->setSpriteSheet(PHUIIconView::SPRITE_LOGIN)
- ->setSpriteIcon($this->getLoginIcon());
-
- $button = id(new PHUIButtonView())
- ->setSize(PHUIButtonView::BIG)
- ->setColor(PHUIButtonView::GREY)
- ->setIcon($icon)
- ->setText($button_text)
- ->setSubtext($this->getProviderName());
-
$adapter = $this->getAdapter();
$adapter->setState(PhabricatorHash::digest($request->getCookie('phcid')));
- $uri = new PhutilURI($adapter->getAuthenticateURI());
- $params = $uri->getQueryParams();
- $uri->setQueryParams(array());
-
- $content = array($button);
-
- foreach ($params as $key => $value) {
- $content[] = phutil_tag(
- 'input',
- array(
- 'type' => 'hidden',
- 'name' => $key,
- 'value' => $value,
- ));
- }
+ $attributes = array(
+ 'method' => 'GET',
+ 'uri' => $adapter->getAuthenticateURI(),
+ );
- return phabricator_form(
- $viewer,
- array(
- 'method' => 'GET',
- 'action' => (string)$uri,
- ),
- $content);
+ return $this->renderStandardLoginButton($request, $mode, $attributes);
}
+
public function processLoginRequest(
PhabricatorAuthLoginController $controller) {
$request = $controller->getRequest();
$adapter = $this->getAdapter();
$account = null;
$response = null;
$error = $request->getStr('error');
if ($error) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'The OAuth provider returned an error: %s',
$error));
return array($account, $response);
}
$code = $request->getStr('code');
if (!strlen($code)) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'The OAuth provider did not return a "code" parameter in its '.
'response.'));
return array($account, $response);
}
if ($adapter->supportsStateParameter()) {
$phcid = $request->getCookie('phcid');
if (!strlen($phcid)) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'Your browser did not submit a "phcid" cookie with OAuth state '.
'information in the request. Check that cookies are enabled. '.
'If this problem persists, you may need to clear your cookies.'));
}
$state = $request->getStr('state');
$expect = PhabricatorHash::digest($phcid);
if ($state !== $expect) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'The OAuth provider did not return the correct "state" parameter '.
'in its response. If this problem persists, you may need to clear '.
'your cookies.'));
}
}
$adapter->setCode($code);
// NOTE: As a side effect, this will cause the OAuth adapter to request
// an access token.
try {
$account_id = $adapter->getAccountID();
} catch (Exception $ex) {
// TODO: Handle this in a more user-friendly way.
throw $ex;
}
if (!strlen($account_id)) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'The OAuth provider failed to retrieve an account ID.'));
return array($account, $response);
}
return array($this->loadOrCreateAccount($account_id), $response);
}
const PROPERTY_APP_ID = 'oauth:app:id';
const PROPERTY_APP_SECRET = 'oauth:app:secret';
public function readFormValuesFromProvider() {
$config = $this->getProviderConfig();
$id = $config->getProperty(self::PROPERTY_APP_ID);
$secret = $config->getProperty(self::PROPERTY_APP_SECRET);
return array(
self::PROPERTY_APP_ID => $id,
self::PROPERTY_APP_SECRET => $secret,
);
}
public function readFormValuesFromRequest(AphrontRequest $request) {
return array(
self::PROPERTY_APP_ID => $request->getStr(self::PROPERTY_APP_ID),
self::PROPERTY_APP_SECRET => $request->getStr(self::PROPERTY_APP_SECRET),
);
}
public function processEditForm(
AphrontRequest $request,
array $values) {
$errors = array();
$issues = array();
$key_id = self::PROPERTY_APP_ID;
$key_secret = self::PROPERTY_APP_SECRET;
if (!strlen($values[$key_id])) {
$errors[] = pht('Application ID is required.');
$issues[$key_id] = pht('Required');
}
if (!strlen($values[$key_secret])) {
$errors[] = pht('Application secret is required.');
$issues[$key_secret] = pht('Required');
}
// If the user has not changed the secret, don't update it (that is,
// don't cause a bunch of "****" to be written to the database).
if (preg_match('/^[*]+$/', $values[$key_secret])) {
unset($values[$key_secret]);
}
return array($errors, $issues, $values);
}
public function extendEditForm(
AphrontRequest $request,
AphrontFormView $form,
array $values,
array $issues) {
$key_id = self::PROPERTY_APP_ID;
$key_secret = self::PROPERTY_APP_SECRET;
$v_id = $values[$key_id];
$v_secret = $values[$key_secret];
if ($v_secret) {
$v_secret = str_repeat('*', strlen($v_secret));
}
$e_id = idx($issues, $key_id, $request->isFormPost() ? null : true);
$e_secret = idx($issues, $key_secret, $request->isFormPost() ? null : true);
$form
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('OAuth App ID'))
->setName($key_id)
->setValue($v_id)
->setError($e_id))
->appendChild(
id(new AphrontFormPasswordControl())
->setLabel(pht('OAuth App Secret'))
->setName($key_secret)
->setValue($v_secret)
->setError($e_secret));
}
public function renderConfigPropertyTransactionTitle(
PhabricatorAuthProviderConfigTransaction $xaction) {
$author_phid = $xaction->getAuthorPHID();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$key = $xaction->getMetadataValue(
PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
switch ($key) {
case self::PROPERTY_APP_ID:
if (strlen($old)) {
return pht(
'%s updated the OAuth application ID for this provider from '.
'"%s" to "%s".',
$xaction->renderHandleLink($author_phid),
$old,
$new);
} else {
return pht(
'%s set the OAuth application ID for this provider to '.
'"%s".',
$xaction->renderHandleLink($author_phid),
$new);
}
case self::PROPERTY_APP_SECRET:
if (strlen($old)) {
return pht(
'%s updated the OAuth application secret for this provider.',
$xaction->renderHandleLink($author_phid));
} else {
return pht(
'%s set the OAuth application seceret for this provider.',
$xaction->renderHandleLink($author_phid));
}
}
return parent::renderConfigPropertyTransactionTitle($xaction);
}
protected function willSaveAccount(PhabricatorExternalAccount $account) {
parent::willSaveAccount($account);
$this->synchronizeOAuthAccount($account);
}
protected function synchronizeOAuthAccount(
PhabricatorExternalAccount $account) {
$adapter = $this->getAdapter();
$oauth_token = $adapter->getAccessToken();
$account->setProperty('oauth.token.access', $oauth_token);
if ($adapter->supportsTokenRefresh()) {
$refresh_token = $adapter->getRefreshToken();
$account->setProperty('oauth.token.refresh', $refresh_token);
} else {
$account->setProperty('oauth.token.refresh', null);
}
$expires = $adapter->getAccessTokenExpires();
$account->setProperty('oauth.token.access.expires', $expires);
}
public function getOAuthAccessToken(
PhabricatorExternalAccount $account,
$force_refresh = false) {
if ($account->getProviderKey() !== $this->getProviderKey()) {
throw new Exception("Account does not match provider!");
}
if (!$force_refresh) {
$access_expires = $account->getProperty('oauth.token.access.expires');
$access_token = $account->getProperty('oauth.token.access');
// Don't return a token with fewer than this many seconds remaining until
// it expires.
$shortest_token = 60;
if ($access_token) {
if ($access_expires > (time() + $shortest_token)) {
return $access_token;
}
}
}
$refresh_token = $account->getProperty('oauth.token.refresh');
if ($refresh_token) {
$adapter = $this->getAdapter();
if ($adapter->supportsTokenRefresh()) {
$adapter->refreshAccessToken($refresh_token);
$this->synchronizeOAuthAccount($account);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$account->save();
unset($unguarded);
return $account->getProperty('oauth.token.access');
}
}
return null;
}
public function willRenderLinkedAccount(
PhabricatorUser $viewer,
PhabricatorObjectItemView $item,
PhabricatorExternalAccount $account) {
// Get a valid token, possibly refreshing it.
$oauth_token = $this->getOAuthAccessToken($account);
$item->addAttribute(pht('OAuth2 Account'));
if ($oauth_token) {
$oauth_expires = $account->getProperty('oauth.token.access.expires');
if ($oauth_expires) {
$item->addAttribute(
pht(
'Active OAuth Token (Expires: %s)',
phabricator_datetime($oauth_expires, $viewer)));
} else {
$item->addAttribute(
pht(
'Active OAuth Token'));
}
} else {
$item->addAttribute(pht('No OAuth Access Token'));
}
parent::willRenderLinkedAccount($viewer, $item, $account);
}
}
diff --git a/src/applications/auth/provider/PhabricatorAuthProviderOAuth1.php b/src/applications/auth/provider/PhabricatorAuthProviderOAuth1.php
index c5931cacd0..96cc5d7c1e 100644
--- a/src/applications/auth/provider/PhabricatorAuthProviderOAuth1.php
+++ b/src/applications/auth/provider/PhabricatorAuthProviderOAuth1.php
@@ -1,300 +1,257 @@
<?php
abstract class PhabricatorAuthProviderOAuth1 extends PhabricatorAuthProvider {
protected $adapter;
const PROPERTY_CONSUMER_KEY = 'oauth1:consumer:key';
const PROPERTY_CONSUMER_SECRET = 'oauth1:consumer:secret';
const PROPERTY_PRIVATE_KEY = 'oauth1:private:key';
abstract protected function newOAuthAdapter();
public function getDescriptionForCreate() {
return pht('Configure %s OAuth.', $this->getProviderName());
}
public function getAdapter() {
if (!$this->adapter) {
$adapter = $this->newOAuthAdapter();
$this->adapter = $adapter;
$this->configureAdapter($adapter);
}
return $this->adapter;
}
protected function configureAdapter(PhutilAuthAdapterOAuth1 $adapter) {
$config = $this->getProviderConfig();
$adapter->setConsumerKey($config->getProperty(self::PROPERTY_CONSUMER_KEY));
$secret = $config->getProperty(self::PROPERTY_CONSUMER_SECRET);
if (strlen($secret)) {
$adapter->setConsumerSecret(new PhutilOpaqueEnvelope($secret));
}
$adapter->setCallbackURI($this->getLoginURI());
return $adapter;
}
public function isLoginFormAButton() {
return true;
}
protected function renderLoginForm(AphrontRequest $request, $mode) {
- $viewer = $request->getUser();
-
- if ($mode == 'link') {
- $button_text = pht('Link External Account');
- } else if ($mode == 'refresh') {
- $button_text = pht('Refresh Account Link');
- } else if ($this->shouldAllowRegistration()) {
- $button_text = pht('Login or Register');
- } else {
- $button_text = pht('Login');
- }
-
- $icon = id(new PHUIIconView())
- ->setSpriteSheet(PHUIIconView::SPRITE_LOGIN)
- ->setSpriteIcon($this->getLoginIcon());
-
- $button = id(new PHUIButtonView())
- ->setSize(PHUIButtonView::BIG)
- ->setColor(PHUIButtonView::GREY)
- ->setIcon($icon)
- ->setText($button_text)
- ->setSubtext($this->getProviderName());
-
- $adapter = $this->getAdapter();
-
- $uri = new PhutilURI($this->getLoginURI());
- $params = $uri->getQueryParams();
- $uri->setQueryParams(array());
-
- $content = array($button);
-
- foreach ($params as $key => $value) {
- $content[] = phutil_tag(
- 'input',
- array(
- 'type' => 'hidden',
- 'name' => $key,
- 'value' => $value,
- ));
- }
-
- return phabricator_form(
- $viewer,
- array(
- 'method' => 'POST',
- 'action' => (string)$uri,
- ),
- $content);
+ $attributes = array(
+ 'method' => 'POST',
+ 'uri' => $this->getLoginURI(),
+ );
+ return $this->renderStandardLoginButton($request, $mode, $attributes);
}
public function processLoginRequest(
PhabricatorAuthLoginController $controller) {
$request = $controller->getRequest();
$adapter = $this->getAdapter();
$account = null;
$response = null;
if ($request->isHTTPPost()) {
$uri = $adapter->getClientRedirectURI();
$response = id(new AphrontRedirectResponse())->setURI($uri);
return array($account, $response);
}
$denied = $request->getStr('denied');
if (strlen($denied)) {
// Twitter indicates that the user cancelled the login attempt by
// returning "denied" as a parameter.
throw new PhutilAuthUserAbortedException();
}
// NOTE: You can get here via GET, this should probably be a bit more
// user friendly.
$token = $request->getStr('oauth_token');
$verifier = $request->getStr('oauth_verifier');
if (!$token) {
throw new Exception("Expected 'oauth_token' in request!");
}
if (!$verifier) {
throw new Exception("Expected 'oauth_verifier' in request!");
}
$adapter->setToken($token);
$adapter->setVerifier($verifier);
// NOTE: As a side effect, this will cause the OAuth adapter to request
// an access token.
try {
$account_id = $adapter->getAccountID();
} catch (Exception $ex) {
// TODO: Handle this in a more user-friendly way.
throw $ex;
}
if (!strlen($account_id)) {
$response = $controller->buildProviderErrorResponse(
$this,
pht(
'The OAuth provider failed to retrieve an account ID.'));
return array($account, $response);
}
return array($this->loadOrCreateAccount($account_id), $response);
}
public function readFormValuesFromProvider() {
$config = $this->getProviderConfig();
$id = $config->getProperty(self::PROPERTY_CONSUMER_KEY);
$secret = $config->getProperty(self::PROPERTY_CONSUMER_SECRET);
return array(
self::PROPERTY_CONSUMER_KEY => $id,
self::PROPERTY_CONSUMER_SECRET => $secret,
);
}
public function readFormValuesFromRequest(AphrontRequest $request) {
return array(
self::PROPERTY_CONSUMER_KEY
=> $request->getStr(self::PROPERTY_CONSUMER_KEY),
self::PROPERTY_CONSUMER_SECRET
=> $request->getStr(self::PROPERTY_CONSUMER_SECRET),
);
}
public function processEditForm(
AphrontRequest $request,
array $values) {
$errors = array();
$issues = array();
$key_ckey = self::PROPERTY_CONSUMER_KEY;
$key_csecret = self::PROPERTY_CONSUMER_SECRET;
if (!strlen($values[$key_ckey])) {
$errors[] = pht('Consumer key is required.');
$issues[$key_ckey] = pht('Required');
}
if (!strlen($values[$key_csecret])) {
$errors[] = pht('Consumer secret is required.');
$issues[$key_csecret] = pht('Required');
}
// If the user has not changed the secret, don't update it (that is,
// don't cause a bunch of "****" to be written to the database).
if (preg_match('/^[*]+$/', $values[$key_csecret])) {
unset($values[$key_csecret]);
}
return array($errors, $issues, $values);
}
public function extendEditForm(
AphrontRequest $request,
AphrontFormView $form,
array $values,
array $issues) {
$key_id = self::PROPERTY_CONSUMER_KEY;
$key_secret = self::PROPERTY_CONSUMER_SECRET;
$v_id = $values[$key_id];
$v_secret = $values[$key_secret];
if ($v_secret) {
$v_secret = str_repeat('*', strlen($v_secret));
}
$e_id = idx($issues, $key_id, $request->isFormPost() ? null : true);
$e_secret = idx($issues, $key_secret, $request->isFormPost() ? null : true);
$form
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('OAuth Consumer Key'))
->setName($key_id)
->setValue($v_id)
->setError($e_id))
->appendChild(
id(new AphrontFormPasswordControl())
->setLabel(pht('OAuth Consumer Secret'))
->setName($key_secret)
->setValue($v_secret)
->setError($e_secret));
}
public function renderConfigPropertyTransactionTitle(
PhabricatorAuthProviderConfigTransaction $xaction) {
$author_phid = $xaction->getAuthorPHID();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$key = $xaction->getMetadataValue(
PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
switch ($key) {
case self::PROPERTY_CONSUMER_KEY:
if (strlen($old)) {
return pht(
'%s updated the OAuth consumer key for this provider from '.
'"%s" to "%s".',
$xaction->renderHandleLink($author_phid),
$old,
$new);
} else {
return pht(
'%s set the OAuth consumer key for this provider to '.
'"%s".',
$xaction->renderHandleLink($author_phid),
$new);
}
case self::PROPERTY_CONSUMER_SECRET:
if (strlen($old)) {
return pht(
'%s updated the OAuth consumer secret for this provider.',
$xaction->renderHandleLink($author_phid));
} else {
return pht(
'%s set the OAuth consumer secret for this provider.',
$xaction->renderHandleLink($author_phid));
}
}
return parent::renderConfigPropertyTransactionTitle($xaction);
}
protected function willSaveAccount(PhabricatorExternalAccount $account) {
parent::willSaveAccount($account);
$this->synchronizeOAuthAccount($account);
}
protected function synchronizeOAuthAccount(
PhabricatorExternalAccount $account) {
$adapter = $this->getAdapter();
$oauth_token = $adapter->getToken();
$oauth_token_secret = $adapter->getTokenSecret();
$account->setProperty('oauth1.token', $oauth_token);
$account->setProperty('oauth1.token.secret', $oauth_token_secret);
}
public function willRenderLinkedAccount(
PhabricatorUser $viewer,
PhabricatorObjectItemView $item,
PhabricatorExternalAccount $account) {
$item->addAttribute(pht('OAuth1 Account'));
parent::willRenderLinkedAccount($viewer, $item, $account);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 18:33 (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127461
Default Alt Text
(33 KB)

Event Timeline