Page MenuHomePhabricator

D20170.id48155.diff
No OneTemporary

D20170.id48155.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -9,7 +9,7 @@
'names' => array(
'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf',
- 'core.pkg.css' => '7a73ffc5',
+ 'core.pkg.css' => 'da140bde',
'core.pkg.js' => '5c737607',
'differential.pkg.css' => 'b8df73d4',
'differential.pkg.js' => '67c9ea4c',
@@ -164,7 +164,7 @@
'rsrc/css/phui/phui-left-right.css' => '68513c34',
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
'rsrc/css/phui/phui-list.css' => '470b1adb',
- 'rsrc/css/phui/phui-object-box.css' => '9b58483d',
+ 'rsrc/css/phui/phui-object-box.css' => 'f434b6be',
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
'rsrc/css/phui/phui-property-list-view.css' => 'cad62236',
@@ -831,7 +831,7 @@
'phui-left-right-css' => '68513c34',
'phui-lightbox-css' => '4ebf22da',
'phui-list-view-css' => '470b1adb',
- 'phui-object-box-css' => '9b58483d',
+ 'phui-object-box-css' => 'f434b6be',
'phui-oi-big-ui-css' => '9e037c7a',
'phui-oi-color-css' => 'b517bfa0',
'phui-oi-drag-ui-css' => 'da15d3dc',
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
@@ -2270,6 +2270,7 @@
'PhabricatorAuthInviteVerifyException' => 'applications/auth/exception/PhabricatorAuthInviteVerifyException.php',
'PhabricatorAuthInviteWorker' => 'applications/auth/worker/PhabricatorAuthInviteWorker.php',
'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php',
+ 'PhabricatorAuthLinkMessageType' => 'applications/auth/message/PhabricatorAuthLinkMessageType.php',
'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php',
'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php',
'PhabricatorAuthLoginMessageType' => 'applications/auth/message/PhabricatorAuthLoginMessageType.php',
@@ -2368,6 +2369,7 @@
'PhabricatorAuthSessionPHIDType' => 'applications/auth/phid/PhabricatorAuthSessionPHIDType.php',
'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php',
'PhabricatorAuthSessionRevoker' => 'applications/auth/revoker/PhabricatorAuthSessionRevoker.php',
+ 'PhabricatorAuthSetExternalController' => 'applications/auth/controller/PhabricatorAuthSetExternalController.php',
'PhabricatorAuthSetPasswordController' => 'applications/auth/controller/PhabricatorAuthSetPasswordController.php',
'PhabricatorAuthSetupCheck' => 'applications/config/check/PhabricatorAuthSetupCheck.php',
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
@@ -8019,6 +8021,7 @@
'PhabricatorAuthInviteVerifyException' => 'PhabricatorAuthInviteDialogException',
'PhabricatorAuthInviteWorker' => 'PhabricatorWorker',
'PhabricatorAuthLinkController' => 'PhabricatorAuthController',
+ 'PhabricatorAuthLinkMessageType' => 'PhabricatorAuthMessageType',
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorAuthLoginMessageType' => 'PhabricatorAuthMessageType',
@@ -8138,6 +8141,7 @@
'PhabricatorAuthSessionPHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthSessionRevoker' => 'PhabricatorAuthRevoker',
+ 'PhabricatorAuthSetExternalController' => 'PhabricatorAuthController',
'PhabricatorAuthSetPasswordController' => 'PhabricatorAuthController',
'PhabricatorAuthSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
diff --git a/src/applications/auth/application/PhabricatorAuthApplication.php b/src/applications/auth/application/PhabricatorAuthApplication.php
--- a/src/applications/auth/application/PhabricatorAuthApplication.php
+++ b/src/applications/auth/application/PhabricatorAuthApplication.php
@@ -86,7 +86,9 @@
=> 'PhabricatorAuthSSHKeyRevokeController',
'view/(?P<id>\d+)/' => 'PhabricatorAuthSSHKeyViewController',
),
+
'password/' => 'PhabricatorAuthSetPasswordController',
+ 'external/' => 'PhabricatorAuthSetExternalController',
'mfa/' => array(
$this->getQueryRoutePattern() =>
diff --git a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php
--- a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php
+++ b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php
@@ -225,17 +225,45 @@
));
}
- $providers = id(new PhabricatorAuthProviderConfigQuery())
+ // Check if the user already has external accounts linked. If they do,
+ // it's not obvious why they aren't using them to log in, but assume they
+ // know what they're doing. We won't send them to the link workflow.
+ $accounts = id(new PhabricatorExternalAccountQuery())
+ ->setViewer($user)
+ ->withUserPHIDs(array($user->getPHID()))
+ ->execute();
+
+ $configs = id(new PhabricatorAuthProviderConfigQuery())
->setViewer($user)
->withIsEnabled(true)
->execute();
+ $linkable = array();
+ foreach ($configs as $config) {
+ if (!$config->getShouldAllowLink()) {
+ continue;
+ }
+
+ $provider = $config->getProvider();
+ if (!$provider->isLoginFormAButton()) {
+ continue;
+ }
+
+ $linkable[] = $provider;
+ }
+
+ // If there's at least one linkable provider, and the user doesn't already
+ // have accounts, send the user to the link workflow.
+ if (!$accounts && $linkable) {
+ return '/auth/external/';
+ }
+
// If there are no configured providers and the user is an administrator,
// send them to Auth to configure a provider. This is probably where they
// want to go. You can end up in this state by accidentally losing your
// first session during initial setup, or after restoring exported data
// from a hosted instance.
- if (!$providers && $user->getIsAdmin()) {
+ if (!$configs && $user->getIsAdmin()) {
return '/auth/';
}
diff --git a/src/applications/auth/controller/PhabricatorAuthSetExternalController.php b/src/applications/auth/controller/PhabricatorAuthSetExternalController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/controller/PhabricatorAuthSetExternalController.php
@@ -0,0 +1,110 @@
+<?php
+
+final class PhabricatorAuthSetExternalController
+ extends PhabricatorAuthController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+
+ $configs = id(new PhabricatorAuthProviderConfigQuery())
+ ->setViewer($viewer)
+ ->withIsEnabled(true)
+ ->execute();
+
+ $linkable = array();
+ foreach ($configs as $config) {
+ if (!$config->getShouldAllowLink()) {
+ continue;
+ }
+
+ // For now, only buttons get to appear here: for example, we can't
+ // reasonably embed an entire LDAP form into this UI.
+ $provider = $config->getProvider();
+ if (!$provider->isLoginFormAButton()) {
+ continue;
+ }
+
+ $linkable[] = $config;
+ }
+
+ if (!$linkable) {
+ return $this->newDialog()
+ ->setTitle(pht('No Linkable External Providers'))
+ ->appendParagraph(
+ pht(
+ 'Currently, there are no configured external auth providers '.
+ 'which you can link your account to.'))
+ ->addCancelButton('/');
+ }
+
+ $text = PhabricatorAuthMessage::loadMessageText(
+ $viewer,
+ PhabricatorAuthLinkMessageType::MESSAGEKEY);
+ if (!strlen($text)) {
+ $text = pht(
+ 'You can link your Phabricator account to an external account to '.
+ 'allow you to log in more easily in the future. To continue, choose '.
+ 'an account to link below. If you prefer not to link your account, '.
+ 'you can skip this step.');
+ }
+
+ $remarkup_view = new PHUIRemarkupView($viewer, $text);
+ $remarkup_view = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'phui-object-box-instructions',
+ ),
+ $remarkup_view);
+
+ PhabricatorCookies::setClientIDCookie($request);
+
+ $view = array();
+ foreach ($configs as $config) {
+ $provider = $config->getProvider();
+
+ $form = $provider->buildLinkForm($this);
+
+ if ($provider->isLoginFormAButton()) {
+ require_celerity_resource('auth-css');
+ $form = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'phabricator-link-button pl',
+ ),
+ $form);
+ }
+
+ $view[] = $form;
+ }
+
+ $form = id(new AphrontFormView())
+ ->setViewer($viewer)
+ ->appendControl(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton('/', pht('Skip This Step')));
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(pht('Link External Account'));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setViewer($viewer)
+ ->setHeader($header)
+ ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
+ ->appendChild($remarkup_view)
+ ->appendChild($view)
+ ->appendChild($form);
+
+ $main_view = id(new PHUITwoColumnView())
+ ->setFooter($box);
+
+ $crumbs = $this->buildApplicationCrumbs()
+ ->addTextCrumb(pht('Link External Account'))
+ ->setBorder(true);
+
+ return $this->newPage()
+ ->setTitle(pht('Link External Account'))
+ ->setCrumbs($crumbs)
+ ->appendChild($main_view);
+ }
+
+}
diff --git a/src/applications/auth/message/PhabricatorAuthLinkMessageType.php b/src/applications/auth/message/PhabricatorAuthLinkMessageType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/message/PhabricatorAuthLinkMessageType.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorAuthLinkMessageType
+ extends PhabricatorAuthMessageType {
+
+ const MESSAGEKEY = 'auth.link';
+
+ public function getDisplayName() {
+ return pht('Unlinked Account Instructions');
+ }
+
+ public function getShortDescription() {
+ return pht(
+ 'Guidance shown after a user logs in with an email link and is '.
+ 'prompted to link an external account.');
+ }
+
+}
diff --git a/src/applications/auth/provider/PhabricatorAuthProvider.php b/src/applications/auth/provider/PhabricatorAuthProvider.php
--- a/src/applications/auth/provider/PhabricatorAuthProvider.php
+++ b/src/applications/auth/provider/PhabricatorAuthProvider.php
@@ -161,7 +161,7 @@
abstract public function processLoginRequest(
PhabricatorAuthLoginController $controller);
- public function buildLinkForm(PhabricatorAuthLinkController $controller) {
+ public function buildLinkForm($controller) {
return $this->renderLoginForm($controller->getRequest(), $mode = 'link');
}
diff --git a/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php b/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php
--- a/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php
+++ b/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php
@@ -159,8 +159,7 @@
return $dialog;
}
- public function buildLinkForm(
- PhabricatorAuthLinkController $controller) {
+ public function buildLinkForm($controller) {
throw new Exception(pht("Password providers can't be linked."));
}
diff --git a/webroot/rsrc/css/phui/phui-object-box.css b/webroot/rsrc/css/phui/phui-object-box.css
--- a/webroot/rsrc/css/phui/phui-object-box.css
+++ b/webroot/rsrc/css/phui/phui-object-box.css
@@ -158,3 +158,8 @@
margin-top: 8px;
margin-bottom: 8px;
}
+
+.phui-object-box-instructions {
+ padding: 16px;
+ border-bottom: 1px solid {$thinblueborder};
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 9, 5:08 PM (4 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7738161
Default Alt Text
D20170.id48155.diff (11 KB)

Event Timeline