Differential D9203 Diff 23378 src/applications/auth/provider/PhabricatorAuthProviderOAuth1MediaWiki.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/provider/PhabricatorAuthProviderOAuth1MediaWiki.php
- This file was added.
<?php | |||||
final class PhabricatorAuthProviderOAuth1MediaWiki | |||||
extends PhabricatorAuthProviderOAuth1 { | |||||
const PROPERTY_MEDIAWIKI_NAME = 'oauth1:mediawiki:name'; | |||||
const PROPERTY_MEDIAWIKI_URI = 'oauth1:mediawiki:uri'; | |||||
const PROPERTY_PRIVATE_KEY = 'oauth1:mediawiki:key:private'; | |||||
const PROPERTY_PUBLIC_KEY = 'oauth1:mediawiki:key:public'; | |||||
public function readFormValuesFromProvider() { | |||||
$config = $this->getProviderConfig(); | |||||
return array( | |||||
self::PROPERTY_MEDIAWIKI_NAME => | |||||
$this->getProviderDomain(), | |||||
self::PROPERTY_MEDIAWIKI_URI => | |||||
$config->getProperty(self::PROPERTY_MEDIAWIKI_URI), | |||||
self::PROPERTY_CONSUMER_KEY => | |||||
$config->getProperty(self::PROPERTY_CONSUMER_KEY), | |||||
self::PROPERTY_CONSUMER_SECRET => | |||||
$config->getProperty(self::PROPERTY_CONSUMER_SECRET), | |||||
); | |||||
} | |||||
public function readFormValuesFromRequest(AphrontRequest $request) { | |||||
$is_setup = $this->isSetup(); | |||||
if ($is_setup) { | |||||
$name = $request->getStr(self::PROPERTY_MEDIAWIKI_NAME); | |||||
} else { | |||||
$name = $this->getProviderDomain(); | |||||
} | |||||
return array( | |||||
self::PROPERTY_MEDIAWIKI_NAME => $name, | |||||
self::PROPERTY_MEDIAWIKI_URI => | |||||
$request->getStr(self::PROPERTY_MEDIAWIKI_URI), | |||||
self::PROPERTY_CONSUMER_KEY => | |||||
$request->getStr(self::PROPERTY_CONSUMER_KEY), | |||||
self::PROPERTY_CONSUMER_SECRET => | |||||
$request->getStr(self::PROPERTY_CONSUMER_SECRET), | |||||
); | |||||
} | |||||
public function getProviderName() { | |||||
return pht('MediaWiki'); | |||||
} | |||||
protected function getProviderConfigurationHelp() { | |||||
$login_uri = PhabricatorEnv::getURI($this->getLoginURI()); | |||||
return pht( | |||||
"To configure MediaWiki OAuth, create a new \"consumer\" here:". | |||||
"\n\n". | |||||
"https://www.mediawiki.org/wiki/". | |||||
"Special:OAuthConsumerRegistration/propose". | |||||
"\n\n". | |||||
epriestley: This URI should be generic. | |||||
"When creating your application, use these settings:". | |||||
"\n\n". | |||||
" - **Callback URL:** Set this to: `%s`". | |||||
"\n\n". | |||||
"After you register the consumer, a **Consumer Key** and ". | |||||
"**Consumer Secret** will be provided to you by MediaWiki. ". | |||||
"To complete the configuration, copy the provided keys into ". | |||||
"the corresponding fields above.", | |||||
$login_uri); | |||||
} | |||||
protected function newOAuthAdapter() { | |||||
$config = $this->getProviderConfig(); | |||||
return id(new PhutilAuthAdapterOAuthMediaWiki()) | |||||
->setAdapterDomain($config->getProviderDomain()) | |||||
->setMediaWikiBaseURI( | |||||
$config->getProperty(self::PROPERTY_MEDIAWIKI_URI)); | |||||
} | |||||
protected function getLoginIcon() { | |||||
return 'MediaWiki'; | |||||
} | |||||
private function isSetup() { | |||||
return !$this->getProviderConfig()->getID(); | |||||
} | |||||
public function processLoginRequest( | |||||
PhabricatorAuthLoginController $controller) { | |||||
Not Done Inline ActionsI want to genericize the cookie stuff so we don't need to duplicate this function. It's pretty much a direct copy/paste of the method in the parent class. epriestley: I want to genericize the cookie stuff so we don't need to duplicate this function. It's pretty… | |||||
$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); | |||||
} | |||||
// 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!"); | |||||
} | |||||
list ( $ctok, $csec ) = explode(':', $_COOKIE['mwoauth'], 2); | |||||
if ($ctok !== $token) { | |||||
throw new Exception("Token from callback does not ". | |||||
"match your cookie."); | |||||
} | |||||
$adapter->setToken($token); | |||||
$adapter->setTokenSecret($csec); | |||||
$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) { | |||||
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 processEditForm( | |||||
AphrontRequest $request, | |||||
array $values) { | |||||
$errors = array(); | |||||
$issues = array(); | |||||
$is_setup = $this->isSetup(); | |||||
$key_name = self::PROPERTY_MEDIAWIKI_NAME; | |||||
$key_uri = self::PROPERTY_MEDIAWIKI_URI; | |||||
$key_secret = self::PROPERTY_CONSUMER_SECRET; | |||||
$key_consumer = self::PROPERTY_CONSUMER_KEY; | |||||
if (!strlen($values[$key_uri])) { | |||||
$errors[] = pht('MediaWiki base URI is required.'); | |||||
$issues[$key_uri] = pht('Required'); | |||||
} else { | |||||
$uri = new PhutilURI($values[$key_uri]); | |||||
if (!$uri->getProtocol()) { | |||||
$errors[] = pht( | |||||
'MediaWiki base URI should include protocol ' | |||||
.'(like "https://").'); | |||||
$issues[$key_uri] = pht('Invalid'); | |||||
} | |||||
} | |||||
if (!$errors) { | |||||
$config = $this->getProviderConfig(); | |||||
if ($is_setup) { | |||||
$config->setProviderDomain($values[$key_name]); | |||||
$config->setProperty($key_name, $values[$key_name]); | |||||
} | |||||
$config->setProperty($key_uri, $values[$key_uri]); | |||||
$config->setProperty($key_secret, $values[$key_secret]); | |||||
$config->setProperty($key_consumer, $values[$key_consumer]); | |||||
} | |||||
return array($errors, $issues, $values); | |||||
} | |||||
public function extendEditForm( | |||||
AphrontRequest $request, | |||||
AphrontFormView $form, | |||||
array $values, | |||||
array $issues) { | |||||
$is_setup = $this->isSetup(); | |||||
$e_required = $request->isFormPost() ? null : true; | |||||
$v_name = $values[self::PROPERTY_MEDIAWIKI_NAME]; | |||||
if ($is_setup) { | |||||
$e_name = idx($issues, self::PROPERTY_MEDIAWIKI_NAME, $e_required); | |||||
} else { | |||||
$e_name = null; | |||||
} | |||||
$v_uri = $values[self::PROPERTY_MEDIAWIKI_URI]; | |||||
$e_uri = idx($issues, self::PROPERTY_MEDIAWIKI_URI, $e_required); | |||||
$config = $this->getProviderConfig(); | |||||
if ($is_setup) { | |||||
$form | |||||
->appendRemarkupInstructions( | |||||
pht( | |||||
"**MediaWiki Instance Name**\n\n". | |||||
"Choose a permanent name for this instance of MediaWiki.". | |||||
"Phabricator uses this name internally to keep track of ". | |||||
"this instance of MediaWiki, in case the URL changes later.". | |||||
"\n\n". | |||||
"Use lowercase letters, digits, and period. For example: ". | |||||
"\n\n`mediawiki`, `mediawiki.mycompany` ". | |||||
"or `mediawiki.engineering` are reasonable names.")) | |||||
->appendChild( | |||||
id(new AphrontFormTextControl()) | |||||
->setLabel(pht('MediaWiki Instance Name')) | |||||
->setValue($v_name) | |||||
->setName(self::PROPERTY_MEDIAWIKI_NAME) | |||||
->setError($e_name)); | |||||
} else { | |||||
$form | |||||
->appendChild( | |||||
id(new AphrontFormStaticControl()) | |||||
->setLabel(pht('MediaWiki Instance Name')) | |||||
->setValue($v_name)); | |||||
} | |||||
$form | |||||
->appendChild( | |||||
id(new AphrontFormTextControl()) | |||||
->setLabel(pht('MediaWiki Base URI')) | |||||
->setValue($v_uri) | |||||
->setName(self::PROPERTY_MEDIAWIKI_URI) | |||||
->setCaption(pht('The URI where MediaWiki is installed.')) | |||||
->setError($e_uri)) | |||||
->appendRemarkupInstructions( | |||||
pht( | |||||
'NOTE: Copy the keys generated by the MediaWiki OAuth'. | |||||
' consumer registration and paste them here.')) | |||||
->appendChild( | |||||
id(new AphrontFormTextControl()) | |||||
->setLabel(pht('Consumer Key')) | |||||
->setName(self::PROPERTY_CONSUMER_KEY) | |||||
->setValue( | |||||
$config->getProperty(self::PROPERTY_CONSUMER_KEY))) | |||||
->appendChild( | |||||
id(new AphrontFormTextControl()) | |||||
->setLabel(pht('Secret Key')) | |||||
->setName(self::PROPERTY_CONSUMER_SECRET) | |||||
->setValue( | |||||
$config->getProperty(self::PROPERTY_CONSUMER_SECRET))); | |||||
} | |||||
public static function getMediaWikiProvider() { | |||||
$providers = self::getAllEnabledProviders(); | |||||
foreach ($providers as $provider) { | |||||
if ($provider instanceof PhabricatorAuthProviderOAuth1MediaWiki) { | |||||
return $provider; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
Not Done Inline ActionsIf you don't plan to need this, just omit it. Some of the providers have a method like this because we use "is Phabricator connected to this thing?" to adjust other behavior (like turning on the "JIRA Issues" field in Differential). epriestley: If you don't plan to need this, just omit it. Some of the providers have a method like this… | |||||
} |
This URI should be generic.