@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Give ExternalAccount a providerConfigPHID, tying it to a particular provider

Summary:
Depends on D20111. Ref T6703. Currently, each ExternalAccount row is tied to a provider by `providerType` + `providerDomain`. This effectively prevents multiple providers of the same type, since, e.g., two LDAP providers may be on different ports on the same domain. The `domain` also isn't really a useful idea anyway because you can move which hostname an LDAP server is on, and LDAP actually uses the value `self` in all cases. Yeah, yikes.

Instead, just bind each account to a particular provider. Then we can have an LDAP "alice" on seven different servers on different ports on the same machine and they can all move around and we'll still have a consistent, cohesive view of the world.

(On its own, this creates some issues with the link/unlink/refresh flows. Those will be updated in followups, and doing this change in a way with no intermediate breaks would require fixing them to use IDs to reference providerType/providerDomain, then fixing this, then undoing the first fix most of the way.)

Test Plan: Ran migrations, sanity-checked database. See followup changes for more comprehensive testing.

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T6703

Differential Revision: https://secure.phabricator.com/D20112

+85 -25
+2
resources/sql/autopatches/20190206.external.03.providerphid.sql
··· 1 + ALTER TABLE {$NAMESPACE}_user.user_externalaccount 2 + ADD providerConfigPHID VARBINARY(64) NOT NULL;
+36
resources/sql/autopatches/20190206.external.04.providerlink.php
··· 1 + <?php 2 + 3 + $account_table = new PhabricatorExternalAccount(); 4 + $account_conn = $account_table->establishConnection('w'); 5 + $table_name = $account_table->getTableName(); 6 + 7 + $config_table = new PhabricatorAuthProviderConfig(); 8 + $config_conn = $config_table->establishConnection('w'); 9 + 10 + foreach (new LiskRawMigrationIterator($account_conn, $table_name) as $row) { 11 + if (strlen($row['providerConfigPHID'])) { 12 + continue; 13 + } 14 + 15 + $config_row = queryfx_one( 16 + $config_conn, 17 + 'SELECT phid 18 + FROM %R 19 + WHERE providerType = %s AND providerDomain = %s 20 + LIMIT 1', 21 + $config_table, 22 + $row['accountType'], 23 + $row['accountDomain']); 24 + if (!$config_row) { 25 + continue; 26 + } 27 + 28 + queryfx( 29 + $account_conn, 30 + 'UPDATE %R 31 + SET providerConfigPHID = %s 32 + WHERE id = %d', 33 + $account_table, 34 + $config_row['phid'], 35 + $row['id']); 36 + }
+1 -1
src/applications/auth/controller/PhabricatorAuthRegisterController.php
··· 671 671 } 672 672 673 673 $provider = head($providers); 674 - $account = $provider->getDefaultExternalAccount(); 674 + $account = $provider->newDefaultExternalAccount(); 675 675 676 676 return array($account, $provider, $response); 677 677 }
+13 -5
src/applications/auth/provider/PhabricatorAuthProvider.php
··· 220 220 $adapter->getAdapterDomain(), 221 221 $account_id); 222 222 if (!$account) { 223 - $account = id(new PhabricatorExternalAccount()) 224 - ->setAccountType($adapter->getAdapterType()) 225 - ->setAccountDomain($adapter->getAdapterDomain()) 223 + $account = $this->newExternalAccount() 226 224 ->setAccountID($account_id); 227 225 } 228 226 ··· 299 297 return false; 300 298 } 301 299 302 - public function getDefaultExternalAccount() { 303 - throw new PhutilMethodNotImplementedException(); 300 + public function newDefaultExternalAccount() { 301 + return $this->newExternalAccount(); 302 + } 303 + 304 + protected function newExternalAccount() { 305 + $config = $this->getProviderConfig(); 306 + $adapter = $this->getAdapter(); 307 + 308 + return id(new PhabricatorExternalAccount()) 309 + ->setAccountType($adapter->getAdapterType()) 310 + ->setAccountDomain($adapter->getAdapterDomain()) 311 + ->setProviderConfigPHID($config->getPHID()); 304 312 } 305 313 306 314 public function getLoginOrder() {
-8
src/applications/auth/provider/PhabricatorPasswordAuthProvider.php
··· 359 359 return true; 360 360 } 361 361 362 - public function getDefaultExternalAccount() { 363 - $adapter = $this->getAdapter(); 364 - 365 - return id(new PhabricatorExternalAccount()) 366 - ->setAccountType($adapter->getAdapterType()) 367 - ->setAccountDomain($adapter->getAdapterDomain()); 368 - } 369 - 370 362 protected function willSaveAccount(PhabricatorExternalAccount $account) { 371 363 parent::willSaveAccount($account); 372 364 $account->setUserPHID($account->getAccountID());
+20
src/applications/auth/query/PhabricatorExternalAccountQuery.php
··· 71 71 } 72 72 73 73 protected function willFilterPage(array $accounts) { 74 + $viewer = $this->getViewer(); 75 + 76 + $configs = id(new PhabricatorAuthProviderConfigQuery()) 77 + ->setViewer($viewer) 78 + ->withPHIDs(mpull($accounts, 'getProviderConfigPHID')) 79 + ->execute(); 80 + $configs = mpull($configs, null, 'getPHID'); 81 + 82 + foreach ($accounts as $key => $account) { 83 + $config_phid = $account->getProviderConfigPHID(); 84 + $config = idx($configs, $config_phid); 85 + 86 + if (!$config) { 87 + unset($accounts[$key]); 88 + continue; 89 + } 90 + 91 + $account->attachProviderConfig($config); 92 + } 93 + 74 94 if ($this->needImages) { 75 95 $file_phids = mpull($accounts, 'getProfileImagePHID'); 76 96 $file_phids = array_filter($file_phids);
+13 -11
src/applications/people/storage/PhabricatorExternalAccount.php
··· 16 16 protected $accountURI; 17 17 protected $profileImagePHID; 18 18 protected $properties = array(); 19 + protected $providerConfigPHID; 19 20 20 21 private $profileImageFile = self::ATTACHABLE; 22 + private $providerConfig = self::ATTACHABLE; 21 23 22 24 public function getProfileImageFile() { 23 25 return $this->assertAttached($this->profileImageFile); ··· 65 67 ) + parent::getConfiguration(); 66 68 } 67 69 68 - public function getPhabricatorUser() { 69 - $tmp_usr = id(new PhabricatorUser()) 70 - ->makeEphemeral() 71 - ->setPHID($this->getPHID()); 72 - return $tmp_usr; 73 - } 74 - 75 70 public function getProviderKey() { 76 71 return $this->getAccountType().':'.$this->getAccountDomain(); 77 72 } ··· 93 88 } 94 89 95 90 public function isUsableForLogin() { 96 - $key = $this->getProviderKey(); 97 - $provider = PhabricatorAuthProvider::getEnabledProviderByKey($key); 98 - 99 - if (!$provider) { 91 + $config = $this->getProviderConfig(); 92 + if (!$config->getIsEnabled()) { 100 93 return false; 101 94 } 102 95 96 + $provider = $config->getProvider(); 103 97 if (!$provider->shouldAllowLogin()) { 104 98 return false; 105 99 } ··· 125 119 return idx($map, $type, pht('"%s" User', $type)); 126 120 } 127 121 122 + public function attachProviderConfig(PhabricatorAuthProviderConfig $config) { 123 + $this->providerConfig = $config; 124 + return $this; 125 + } 126 + 127 + public function getProviderConfig() { 128 + return $this->assertAttached($this->providerConfig); 129 + } 128 130 129 131 130 132 /* -( PhabricatorPolicyInterface )----------------------------------------- */