mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 05:50:55 +01:00
Allow users to unlink their last external account with a warning, instead of preventing the action
Summary: Depends on D20105. Fixes T7732. T7732 describes a case where a user had their Google credentials swapped and had trouble regaining access to their account. Since we now allow email login even if password auth is disabled, it's okay to let users unlink their final account, and it's even reasonable for users to unlink their final account if it is mis-linked. Just give them a warning that what they're doing is a little sketchy, rather than preventing the workflow. Test Plan: Unlinked my only login account, got a stern warning instead of a dead end. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T7732 Differential Revision: https://secure.phabricator.com/D20106
This commit is contained in:
parent
d6f691cf5d
commit
fc3b90e1d1
2 changed files with 38 additions and 39 deletions
|
@ -32,8 +32,15 @@ final class PhabricatorAuthUnlinkController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that this account isn't the last account which can be used to
|
$confirmations = $request->getStrList('confirmations');
|
||||||
// login. We prevent you from removing the last account.
|
$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()) {
|
if ($account->isUsableForLogin()) {
|
||||||
$other_accounts = id(new PhabricatorExternalAccount())->loadAllWhere(
|
$other_accounts = id(new PhabricatorExternalAccount())->loadAllWhere(
|
||||||
'userPHID = %s',
|
'userPHID = %s',
|
||||||
|
@ -47,11 +54,12 @@ final class PhabricatorAuthUnlinkController
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($valid_accounts < 2) {
|
if ($valid_accounts < 2) {
|
||||||
return $this->renderLastUsableAccountErrorDialog();
|
if (!isset($confirmations['only'])) {
|
||||||
|
return $this->renderOnlyUsableAccountConfirmDialog($confirmations);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->isDialogFormPost()) {
|
|
||||||
$account->delete();
|
$account->delete();
|
||||||
|
|
||||||
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
|
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
|
||||||
|
@ -62,9 +70,6 @@ final class PhabricatorAuthUnlinkController
|
||||||
return id(new AphrontRedirectResponse())->setURI($this->getDoneURI());
|
return id(new AphrontRedirectResponse())->setURI($this->getDoneURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->renderConfirmDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDoneURI() {
|
private function getDoneURI() {
|
||||||
return '/settings/panel/external/';
|
return '/settings/panel/external/';
|
||||||
}
|
}
|
||||||
|
@ -97,22 +102,27 @@ final class PhabricatorAuthUnlinkController
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderLastUsableAccountErrorDialog() {
|
private function renderOnlyUsableAccountConfirmDialog(array $confirmations) {
|
||||||
$dialog = id(new AphrontDialogView())
|
$confirmations[] = 'only';
|
||||||
->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());
|
|
||||||
|
|
||||||
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_key = $this->providerKey;
|
||||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
|
$provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key);
|
||||||
|
|
||||||
|
@ -129,9 +139,9 @@ final class PhabricatorAuthUnlinkController
|
||||||
'to Phabricator.');
|
'to Phabricator.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$dialog = id(new AphrontDialogView())
|
return $this->newDialog()
|
||||||
->setUser($this->getRequest()->getUser())
|
|
||||||
->setTitle($title)
|
->setTitle($title)
|
||||||
|
->addHiddenInput('confirmations', implode(',', $confirmations))
|
||||||
->appendParagraph($body)
|
->appendParagraph($body)
|
||||||
->appendParagraph(
|
->appendParagraph(
|
||||||
pht(
|
pht(
|
||||||
|
@ -139,8 +149,6 @@ final class PhabricatorAuthUnlinkController
|
||||||
'other active login sessions.'))
|
'other active login sessions.'))
|
||||||
->addSubmitButton(pht('Unlink Account'))
|
->addSubmitButton(pht('Unlink Account'))
|
||||||
->addCancelButton($this->getDoneURI());
|
->addCancelButton($this->getDoneURI());
|
||||||
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,6 @@ final class PhabricatorExternalAccountsSettingsPanel
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setNoDataString(pht('You have no linked accounts.'));
|
->setNoDataString(pht('You have no linked accounts.'));
|
||||||
|
|
||||||
$login_accounts = 0;
|
|
||||||
foreach ($accounts as $account) {
|
|
||||||
if ($account->isUsableForLogin()) {
|
|
||||||
$login_accounts++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$item = new PHUIObjectItemView();
|
$item = new PHUIObjectItemView();
|
||||||
|
|
||||||
|
@ -72,8 +65,6 @@ final class PhabricatorExternalAccountsSettingsPanel
|
||||||
'account provider).'));
|
'account provider).'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$can_unlink = $can_unlink && (!$can_login || ($login_accounts > 1));
|
|
||||||
|
|
||||||
$can_refresh = $provider && $provider->shouldAllowAccountRefresh();
|
$can_refresh = $provider && $provider->shouldAllowAccountRefresh();
|
||||||
if ($can_refresh) {
|
if ($can_refresh) {
|
||||||
$item->addAction(
|
$item->addAction(
|
||||||
|
|
Loading…
Reference in a new issue