Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/auth/controller/PhabricatorAuthUnlinkController.php b/src/applications/auth/controller/PhabricatorAuthUnlinkController.php
index e6e1493e5a..1e3023e5d2 100644
--- a/src/applications/auth/controller/PhabricatorAuthUnlinkController.php
+++ b/src/applications/auth/controller/PhabricatorAuthUnlinkController.php
@@ -1,146 +1,154 @@
<?php
final class PhabricatorAuthUnlinkController
extends PhabricatorAuthController {
private $providerKey;
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$this->providerKey = $request->getURIData('pkey');
list($type, $domain) = explode(':', $this->providerKey, 2);
// Check that this account link actually exists. We don't require the
// provider to exist because we want users to be able to delete links to
// dead accounts if they want.
$account = id(new PhabricatorExternalAccount())->loadOneWhere(
'accountType = %s AND accountDomain = %s AND userPHID = %s',
$type,
$domain,
$viewer->getPHID());
if (!$account) {
return $this->renderNoAccountErrorDialog();
}
// Check that the provider (if it exists) allows accounts to be unlinked.
$provider_key = $this->providerKey;
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
if ($provider) {
if (!$provider->shouldAllowAccountUnlink()) {
return $this->renderNotUnlinkableErrorDialog($provider);
}
}
- // Check that this account isn't the last account which can be used to
- // login. We prevent you from removing the last account.
+ $confirmations = $request->getStrList('confirmations');
+ $confirmations = array_fuse($confirmations);
+
+ if (!$request->isFormPost() || !isset($confirmations['unlink'])) {
+ return $this->renderConfirmDialog($confirmations);
+ }
+
+ // Check that this account isn't the only account which can be used to
+ // login. We warn you when you remove your only login account.
if ($account->isUsableForLogin()) {
$other_accounts = id(new PhabricatorExternalAccount())->loadAllWhere(
'userPHID = %s',
$viewer->getPHID());
$valid_accounts = 0;
foreach ($other_accounts as $other_account) {
if ($other_account->isUsableForLogin()) {
$valid_accounts++;
}
}
if ($valid_accounts < 2) {
- return $this->renderLastUsableAccountErrorDialog();
+ if (!isset($confirmations['only'])) {
+ return $this->renderOnlyUsableAccountConfirmDialog($confirmations);
+ }
}
}
- if ($request->isDialogFormPost()) {
- $account->delete();
-
- id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
- $viewer,
- new PhutilOpaqueEnvelope(
- $request->getCookie(PhabricatorCookies::COOKIE_SESSION)));
+ $account->delete();
- return id(new AphrontRedirectResponse())->setURI($this->getDoneURI());
- }
+ id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
+ $viewer,
+ new PhutilOpaqueEnvelope(
+ $request->getCookie(PhabricatorCookies::COOKIE_SESSION)));
- return $this->renderConfirmDialog();
+ return id(new AphrontRedirectResponse())->setURI($this->getDoneURI());
}
private function getDoneURI() {
return '/settings/panel/external/';
}
private function renderNoAccountErrorDialog() {
$dialog = id(new AphrontDialogView())
->setUser($this->getRequest()->getUser())
->setTitle(pht('No Such Account'))
->appendChild(
pht(
'You can not unlink this account because it is not linked.'))
->addCancelButton($this->getDoneURI());
return id(new AphrontDialogResponse())->setDialog($dialog);
}
private function renderNotUnlinkableErrorDialog(
PhabricatorAuthProvider $provider) {
$dialog = id(new AphrontDialogView())
->setUser($this->getRequest()->getUser())
->setTitle(pht('Permanent Account Link'))
->appendChild(
pht(
'You can not unlink this account because the administrator has '.
'configured Phabricator to make links to %s accounts permanent.',
$provider->getProviderName()))
->addCancelButton($this->getDoneURI());
return id(new AphrontDialogResponse())->setDialog($dialog);
}
- private function renderLastUsableAccountErrorDialog() {
- $dialog = id(new AphrontDialogView())
- ->setUser($this->getRequest()->getUser())
- ->setTitle(pht('Last Valid Account'))
- ->appendChild(
- pht(
- 'You can not unlink this account because you have no other '.
- 'valid login accounts. If you removed it, you would be unable '.
- 'to log in. Add another authentication method before removing '.
- 'this one.'))
- ->addCancelButton($this->getDoneURI());
+ private function renderOnlyUsableAccountConfirmDialog(array $confirmations) {
+ $confirmations[] = 'only';
- return id(new AphrontDialogResponse())->setDialog($dialog);
+ return $this->newDialog()
+ ->setTitle(pht('Unlink Your Only Login Account?'))
+ ->addHiddenInput('confirmations', implode(',', $confirmations))
+ ->appendParagraph(
+ pht(
+ 'This is the only external login account linked to your Phabicator '.
+ 'account. If you remove it, you may no longer be able to log in.'))
+ ->appendParagraph(
+ pht(
+ 'If you lose access to your account, you can recover access by '.
+ 'sending yourself an email login link from the login screen.'))
+ ->addCancelButton($this->getDoneURI())
+ ->addSubmitButton(pht('Unlink External Account'));
}
- private function renderConfirmDialog() {
+ private function renderConfirmDialog(array $confirmations) {
+ $confirmations[] = 'unlink';
+
$provider_key = $this->providerKey;
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
if ($provider) {
$title = pht('Unlink "%s" Account?', $provider->getProviderName());
$body = pht(
'You will no longer be able to use your %s account to '.
'log in to Phabricator.',
$provider->getProviderName());
} else {
$title = pht('Unlink Account?');
$body = pht(
'You will no longer be able to use this account to log in '.
'to Phabricator.');
}
- $dialog = id(new AphrontDialogView())
- ->setUser($this->getRequest()->getUser())
+ return $this->newDialog()
->setTitle($title)
+ ->addHiddenInput('confirmations', implode(',', $confirmations))
->appendParagraph($body)
->appendParagraph(
pht(
'Note: Unlinking an authentication provider will terminate any '.
'other active login sessions.'))
->addSubmitButton(pht('Unlink Account'))
->addCancelButton($this->getDoneURI());
-
- return id(new AphrontDialogResponse())->setDialog($dialog);
}
}
diff --git a/src/applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php b/src/applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php
index 9401cddbef..29ef9fa2c7 100644
--- a/src/applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php
+++ b/src/applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php
@@ -1,154 +1,145 @@
<?php
final class PhabricatorExternalAccountsSettingsPanel
extends PhabricatorSettingsPanel {
public function getPanelKey() {
return 'external';
}
public function getPanelName() {
return pht('External Accounts');
}
public function getPanelMenuIcon() {
return 'fa-users';
}
public function getPanelGroupKey() {
return PhabricatorSettingsAuthenticationPanelGroup::PANELGROUPKEY;
}
public function processRequest(AphrontRequest $request) {
$viewer = $request->getUser();
$providers = PhabricatorAuthProvider::getAllProviders();
$accounts = id(new PhabricatorExternalAccountQuery())
->setViewer($viewer)
->withUserPHIDs(array($viewer->getPHID()))
->needImages(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$linked_head = pht('Linked Accounts and Authentication');
$linked = id(new PHUIObjectItemListView())
->setUser($viewer)
->setNoDataString(pht('You have no linked accounts.'));
- $login_accounts = 0;
- foreach ($accounts as $account) {
- if ($account->isUsableForLogin()) {
- $login_accounts++;
- }
- }
-
foreach ($accounts as $account) {
$item = new PHUIObjectItemView();
$provider = idx($providers, $account->getProviderKey());
if ($provider) {
$item->setHeader($provider->getProviderName());
$can_unlink = $provider->shouldAllowAccountUnlink();
if (!$can_unlink) {
$item->addAttribute(pht('Permanently Linked'));
}
} else {
$item->setHeader(
pht('Unknown Account ("%s")', $account->getProviderKey()));
$can_unlink = true;
}
$can_login = $account->isUsableForLogin();
if (!$can_login) {
$item->addAttribute(
pht(
'Disabled (an administrator has disabled login for this '.
'account provider).'));
}
- $can_unlink = $can_unlink && (!$can_login || ($login_accounts > 1));
-
$can_refresh = $provider && $provider->shouldAllowAccountRefresh();
if ($can_refresh) {
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-refresh')
->setHref('/auth/refresh/'.$account->getProviderKey().'/'));
}
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-times')
->setWorkflow(true)
->setDisabled(!$can_unlink)
->setHref('/auth/unlink/'.$account->getProviderKey().'/'));
if ($provider) {
$provider->willRenderLinkedAccount($viewer, $item, $account);
}
$linked->addItem($item);
}
$linkable_head = pht('Add External Account');
$linkable = id(new PHUIObjectItemListView())
->setUser($viewer)
->setNoDataString(
pht('Your account is linked with all available providers.'));
$accounts = mpull($accounts, null, 'getProviderKey');
$configs = id(new PhabricatorAuthProviderConfigQuery())
->setViewer($viewer)
->withIsEnabled(true)
->execute();
$configs = msort($configs, 'getSortVector');
foreach ($configs as $config) {
$provider = $config->getProvider();
if (!$provider->shouldAllowAccountLink()) {
continue;
}
// Don't show the user providers they already have linked.
$provider_key = $config->getProvider()->getProviderKey();
if (isset($accounts[$provider_key])) {
continue;
}
$link_uri = '/auth/link/'.$provider->getProviderKey().'/';
$link_button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-link')
->setHref($link_uri)
->setColor(PHUIButtonView::GREY)
->setText(pht('Link External Account'));
$item = id(new PHUIObjectItemView())
->setHeader($config->getDisplayName())
->setHref($link_uri)
->setImageIcon($config->newIconView())
->setSideColumn($link_button);
$linkable->addItem($item);
}
$linked_box = $this->newBox($linked_head, $linked);
$linkable_box = $this->newBox($linkable_head, $linkable);
return array(
$linked_box,
$linkable_box,
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 14:53 (3 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1125693
Default Alt Text
(11 KB)

Event Timeline