@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.

Make external account unlinking use account IDs, not "providerType + providerDomain" nonsense

Summary: Depends on D20112. Ref T6703. When you go to unlink an account, unlink it by ID. Crazy!

Test Plan: Unlinked and relinked Google accounts.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T6703

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

+50 -71
+1 -1
src/applications/auth/application/PhabricatorAuthApplication.php
··· 61 61 'start/' => 'PhabricatorAuthStartController', 62 62 'validate/' => 'PhabricatorAuthValidateController', 63 63 'finish/' => 'PhabricatorAuthFinishController', 64 - 'unlink/(?P<pkey>[^/]+)/' => 'PhabricatorAuthUnlinkController', 64 + 'unlink/(?P<id>\d+)/' => 'PhabricatorAuthUnlinkController', 65 65 '(?P<action>link|refresh)/(?P<pkey>[^/]+)/' 66 66 => 'PhabricatorAuthLinkController', 67 67 'confirmlink/(?P<akey>[^/]+)/'
+48 -69
src/applications/auth/controller/PhabricatorAuthUnlinkController.php
··· 3 3 final class PhabricatorAuthUnlinkController 4 4 extends PhabricatorAuthController { 5 5 6 - private $providerKey; 7 - 8 6 public function handleRequest(AphrontRequest $request) { 9 7 $viewer = $this->getViewer(); 10 - $this->providerKey = $request->getURIData('pkey'); 11 - 12 - list($type, $domain) = explode(':', $this->providerKey, 2); 8 + $id = $request->getURIData('id'); 13 9 14 - // Check that this account link actually exists. We don't require the 15 - // provider to exist because we want users to be able to delete links to 16 - // dead accounts if they want. 17 - $account = id(new PhabricatorExternalAccount())->loadOneWhere( 18 - 'accountType = %s AND accountDomain = %s AND userPHID = %s', 19 - $type, 20 - $domain, 21 - $viewer->getPHID()); 10 + $account = id(new PhabricatorExternalAccountQuery()) 11 + ->setViewer($viewer) 12 + ->withIDs(array($id)) 13 + ->requireCapabilities( 14 + array( 15 + PhabricatorPolicyCapability::CAN_VIEW, 16 + PhabricatorPolicyCapability::CAN_EDIT, 17 + )) 18 + ->executeOne(); 22 19 if (!$account) { 23 - return $this->renderNoAccountErrorDialog(); 20 + return new Aphront404Response(); 24 21 } 25 22 26 - // Check that the provider (if it exists) allows accounts to be unlinked. 27 - $provider_key = $this->providerKey; 28 - $provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key); 29 - if ($provider) { 30 - if (!$provider->shouldAllowAccountUnlink()) { 31 - return $this->renderNotUnlinkableErrorDialog($provider); 32 - } 23 + $done_uri = '/settings/panel/external/'; 24 + 25 + $config = $account->getProviderConfig(); 26 + $provider = $config->getProvider(); 27 + if (!$provider->shouldAllowAccountUnlink()) { 28 + return $this->renderNotUnlinkableErrorDialog($provider, $done_uri); 33 29 } 34 30 35 31 $confirmations = $request->getStrList('confirmations'); 36 32 $confirmations = array_fuse($confirmations); 37 33 38 34 if (!$request->isFormPost() || !isset($confirmations['unlink'])) { 39 - return $this->renderConfirmDialog($confirmations); 35 + return $this->renderConfirmDialog($confirmations, $config, $done_uri); 40 36 } 41 37 42 38 // Check that this account isn't the only account which can be used to 43 39 // login. We warn you when you remove your only login account. 44 40 if ($account->isUsableForLogin()) { 45 - $other_accounts = id(new PhabricatorExternalAccount())->loadAllWhere( 46 - 'userPHID = %s', 47 - $viewer->getPHID()); 41 + $other_accounts = id(new PhabricatorExternalAccountQuery()) 42 + ->setViewer($viewer) 43 + ->withUserPHIDs(array($viewer->getPHID())) 44 + ->execute(); 48 45 49 46 $valid_accounts = 0; 50 47 foreach ($other_accounts as $other_account) { ··· 55 52 56 53 if ($valid_accounts < 2) { 57 54 if (!isset($confirmations['only'])) { 58 - return $this->renderOnlyUsableAccountConfirmDialog($confirmations); 55 + return $this->renderOnlyUsableAccountConfirmDialog( 56 + $confirmations, 57 + $done_uri); 59 58 } 60 59 } 61 60 } ··· 67 66 new PhutilOpaqueEnvelope( 68 67 $request->getCookie(PhabricatorCookies::COOKIE_SESSION))); 69 68 70 - return id(new AphrontRedirectResponse())->setURI($this->getDoneURI()); 71 - } 72 - 73 - private function getDoneURI() { 74 - return '/settings/panel/external/'; 75 - } 76 - 77 - private function renderNoAccountErrorDialog() { 78 - $dialog = id(new AphrontDialogView()) 79 - ->setUser($this->getRequest()->getUser()) 80 - ->setTitle(pht('No Such Account')) 81 - ->appendChild( 82 - pht( 83 - 'You can not unlink this account because it is not linked.')) 84 - ->addCancelButton($this->getDoneURI()); 85 - 86 - return id(new AphrontDialogResponse())->setDialog($dialog); 69 + return id(new AphrontRedirectResponse())->setURI($done_uri); 87 70 } 88 71 89 72 private function renderNotUnlinkableErrorDialog( 90 - PhabricatorAuthProvider $provider) { 73 + PhabricatorAuthProvider $provider, 74 + $done_uri) { 91 75 92 - $dialog = id(new AphrontDialogView()) 93 - ->setUser($this->getRequest()->getUser()) 76 + return $this->newDialog() 94 77 ->setTitle(pht('Permanent Account Link')) 95 78 ->appendChild( 96 79 pht( 97 80 'You can not unlink this account because the administrator has '. 98 - 'configured Phabricator to make links to %s accounts permanent.', 81 + 'configured Phabricator to make links to "%s" accounts permanent.', 99 82 $provider->getProviderName())) 100 - ->addCancelButton($this->getDoneURI()); 101 - 102 - return id(new AphrontDialogResponse())->setDialog($dialog); 83 + ->addCancelButton($done_uri); 103 84 } 104 85 105 - private function renderOnlyUsableAccountConfirmDialog(array $confirmations) { 86 + private function renderOnlyUsableAccountConfirmDialog( 87 + array $confirmations, 88 + $done_uri) { 89 + 106 90 $confirmations[] = 'only'; 107 91 108 92 return $this->newDialog() ··· 116 100 pht( 117 101 'If you lose access to your account, you can recover access by '. 118 102 'sending yourself an email login link from the login screen.')) 119 - ->addCancelButton($this->getDoneURI()) 103 + ->addCancelButton($done_uri) 120 104 ->addSubmitButton(pht('Unlink External Account')); 121 105 } 122 106 123 - private function renderConfirmDialog(array $confirmations) { 107 + private function renderConfirmDialog( 108 + array $confirmations, 109 + PhabricatorAuthProviderConfig $config, 110 + $done_uri) { 111 + 124 112 $confirmations[] = 'unlink'; 113 + $provider = $config->getProvider(); 125 114 126 - $provider_key = $this->providerKey; 127 - $provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key); 128 - 129 - if ($provider) { 130 - $title = pht('Unlink "%s" Account?', $provider->getProviderName()); 131 - $body = pht( 132 - 'You will no longer be able to use your %s account to '. 133 - 'log in to Phabricator.', 134 - $provider->getProviderName()); 135 - } else { 136 - $title = pht('Unlink Account?'); 137 - $body = pht( 138 - 'You will no longer be able to use this account to log in '. 139 - 'to Phabricator.'); 140 - } 115 + $title = pht('Unlink "%s" Account?', $provider->getProviderName()); 116 + $body = pht( 117 + 'You will no longer be able to use your %s account to '. 118 + 'log in to Phabricator.', 119 + $provider->getProviderName()); 141 120 142 121 return $this->newDialog() 143 122 ->setTitle($title) ··· 148 127 'Note: Unlinking an authentication provider will terminate any '. 149 128 'other active login sessions.')) 150 129 ->addSubmitButton(pht('Unlink Account')) 151 - ->addCancelButton($this->getDoneURI()); 130 + ->addCancelButton($done_uri); 152 131 } 153 132 154 133 }
+1 -1
src/applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php
··· 78 78 ->setIcon('fa-times') 79 79 ->setWorkflow(true) 80 80 ->setDisabled(!$can_unlink) 81 - ->setHref('/auth/unlink/'.$account->getProviderKey().'/')); 81 + ->setHref('/auth/unlink/'.$account->getID().'/')); 82 82 83 83 if ($provider) { 84 84 $provider->willRenderLinkedAccount($viewer, $item, $account);