Page MenuHomePhabricator

D9203.id25104.diff
No OneTemporary

D9203.id25104.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -151,7 +151,7 @@
'rsrc/css/sprite-conpherence.css' => '3b4a0487',
'rsrc/css/sprite-docs.css' => '5f65d0da',
'rsrc/css/sprite-gradient.css' => '4bdb98a7',
- 'rsrc/css/sprite-login.css' => '878ee4d8',
+ 'rsrc/css/sprite-login.css' => '3c811008',
'rsrc/css/sprite-main-header.css' => '92720ee2',
'rsrc/css/sprite-menu.css' => '28281e16',
'rsrc/css/sprite-payments.css' => 'cc085d44',
@@ -817,7 +817,7 @@
'sprite-conpherence-css' => '3b4a0487',
'sprite-docs-css' => '5f65d0da',
'sprite-gradient-css' => '4bdb98a7',
- 'sprite-login-css' => '878ee4d8',
+ 'sprite-login-css' => '3c811008',
'sprite-main-header-css' => '92720ee2',
'sprite-menu-css' => '28281e16',
'sprite-payments-css' => 'cc085d44',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1721,6 +1721,7 @@
'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php',
'PhabricatorMarkupOneOff' => 'infrastructure/markup/PhabricatorMarkupOneOff.php',
'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php',
+ 'PhabricatorMediaWikiAuthProvider' => 'applications/auth/provider/PhabricatorMediaWikiAuthProvider.php',
'PhabricatorMemeRemarkupRule' => 'applications/macro/markup/PhabricatorMemeRemarkupRule.php',
'PhabricatorMentionRemarkupRule' => 'applications/people/markup/PhabricatorMentionRemarkupRule.php',
'PhabricatorMercurialGraphStream' => 'applications/repository/daemon/PhabricatorMercurialGraphStream.php',
@@ -4569,6 +4570,7 @@
'PhabricatorMarkupCache' => 'PhabricatorCacheDAO',
'PhabricatorMarkupOneOff' => 'PhabricatorMarkupInterface',
'PhabricatorMarkupPreviewController' => 'PhabricatorController',
+ 'PhabricatorMediaWikiAuthProvider' => 'PhabricatorOAuth1AuthProvider',
'PhabricatorMemeRemarkupRule' => 'PhutilRemarkupRule',
'PhabricatorMentionRemarkupRule' => 'PhutilRemarkupRule',
'PhabricatorMercurialGraphStream' => 'PhabricatorRepositoryGraphStream',
diff --git a/src/applications/auth/provider/PhabricatorMediaWikiAuthProvider.php b/src/applications/auth/provider/PhabricatorMediaWikiAuthProvider.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/provider/PhabricatorMediaWikiAuthProvider.php
@@ -0,0 +1,260 @@
+<?php
+
+final class PhabricatorMediaWikiAuthProvider
+ extends PhabricatorOAuth1AuthProvider {
+
+ 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');
+ }
+
+ public function getWikiURI() {
+ $config = $this->getProviderConfig();
+ $uri = $config->getProperty(self::PROPERTY_MEDIAWIKI_URI);
+ $uri = new PhutilURI($uri);
+ $normalized = $uri->getProtocol().'://'.$uri->getDomain();
+ if ($uri->getPort() != 80 && $uri->getPort() != 443) {
+ $normalized .= ':'.$uri->getPort();
+ }
+ if (strlen(($uri->getPath())) > 0 && $uri->getPath() !== '/') {
+ $normalized .= $uri->getPath();
+ }
+ if (substr($normalized, -1) == '/') {
+ $normalized = substr($normalized, 0, -1);
+ }
+ return $normalized;
+ }
+
+ protected function getProviderConfigurationHelp() {
+ $login_uri = PhabricatorEnv::getURI($this->getLoginURI());
+ if ($this->isSetup()) {
+ return pht(
+ "**Step 1 of 2**: Provide the name and URI for your MediaWiki install.\n\n".
+ "In the next step, you will create an auth consumer in MediaWiki to be used by Phabricator oauth.");
+ } else {
+ $wiki_uri = $this->getWikiURI();
+ return pht(
+ "**Step 2 of 2**: Create a MediaWiki auth consumer for this Phabricator instance.".
+ "\n\n".
+ "NOTE: Propose a consumer with the form at this url: %s".
+ "\n\n".
+ "Provide the following settings on the consumer registration:\n\n".
+ " - **Callback URL:** Set this to: `%s`\n".
+ " - **Grants:** `Basic Rights` is all that is needed for authentication.\n".
+ "\n\n".
+ "After you register the consumer, a **Consumer Key** and ".
+ "**Consumer Secret** will be provided to you by MediaWiki. ".
+ "To complete configuration of phabricator, copy the provided keys into ".
+ "the corresponding fields above.".
+ "\n\n".
+ "NOTE: Before Phabricator can successfully authenticate to your MediaWiki,".
+ " a wiki admin must approve the oauth consumer registration using the form".
+ " which can be found at the following url: %s",
+ $wiki_uri.'/index.php?title=Special:OAuthConsumerRegistration/propose',
+ $login_uri,
+ $wiki_uri.'/index.php?title=Special:OAuthManageConsumers/proposed');
+ }
+ }
+
+ protected function newOAuthAdapter() {
+ $config = $this->getProviderConfig();
+
+ return id(new PhutilMediaWikiAuthAdapter())
+ ->setAdapterDomain($config->getProviderDomain())
+ ->setMediaWikiBaseURI($this->getWikiURI());
+ }
+
+ protected function getLoginIcon() {
+ return 'MediaWiki';
+ }
+
+ private function isSetup() {
+ return !$this->getProviderConfig()->getID();
+ }
+
+ public function hasSetupStep() {
+ return true;
+ }
+
+ 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 (!$is_setup && !strlen($values[$key_secret])) {
+ $errors[] = pht('Consumer Secret is required');
+ $issues[$key_secret] = pht('Required');
+ }
+
+ if (!$is_setup && !strlen($values[$key_consumer])) {
+ $errors[] = pht('Consumer Key is required');
+ $issues[$key_consumer] = pht('Required');
+ }
+
+ if (!count($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]);
+ } else {
+ $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)
+ ->setName(self::PROPERTY_MEDIAWIKI_NAME));
+ }
+
+ $form
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('MediaWiki Base URI'))
+ ->setValue($v_uri)
+ ->setName(self::PROPERTY_MEDIAWIKI_URI)
+ ->setPlaceholder('https://www.mediawiki.org/w')
+ ->setCaption(pht('The full URL to your MediaWiki innstall, up to but not including "index.php"'))
+ ->setError($e_uri));
+
+ if (!$is_setup) {
+ if (!strlen($config->getProperty(self::PROPERTY_CONSUMER_KEY))) {
+ $form->appendRemarkupInstructions(
+ pht(
+ 'NOTE: Copy the keys generated by the MediaWiki OAuth'.
+ ' consumer registration and paste them here.'));
+ }
+
+ $form
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('Consumer Key'))
+ ->setName(self::PROPERTY_CONSUMER_KEY)
+ ->setValue($values[self::PROPERTY_CONSUMER_KEY]))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('Secret Key'))
+ ->setName(self::PROPERTY_CONSUMER_SECRET)
+ ->setValue($values[self::PROPERTY_CONSUMER_SECRET]));
+ }
+ }
+
+ public static function getMediaWikiProvider() {
+ $providers = self::getAllEnabledProviders();
+
+ foreach ($providers as $provider) {
+ if ($provider instanceof PhabricatorMediaWikiAuthProvider) {
+ return $provider;
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php b/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php
--- a/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php
+++ b/src/applications/auth/provider/PhabricatorOAuth1AuthProvider.php
@@ -52,9 +52,11 @@
$client_code = $this->getAuthCSRFCode($request);
- $callback_uri = $adapter->getCallbackURI();
- $callback_uri = $callback_uri.$client_code.'/';
- $adapter->setCallbackURI($callback_uri);
+ if ($adapter->shouldAddCSRFTokenToCallbackURI()) {
+ $callback_uri = $adapter->getCallbackURI();
+ $callback_uri = $callback_uri.$client_code.'/';
+ $adapter->setCallbackURI($callback_uri);
+ }
$uri = $adapter->getClientRedirectURI();
@@ -77,8 +79,9 @@
// NOTE: You can get here via GET, this should probably be a bit more
// user friendly.
-
- $this->verifyAuthCSRFCode($request, $controller->getExtraURIData());
+ if ($adapter->shouldAddCSRFTokenToCallbackURI()) {
+ $this->verifyAuthCSRFCode($request, $controller->getExtraURIData());
+ }
$token = $request->getStr('oauth_token');
$verifier = $request->getStr('oauth_verifier');

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 27, 5:34 AM (4 w, 8 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7649444
Default Alt Text
D9203.id25104.diff (12 KB)

Event Timeline