From 32f6c88896c8daa94222bd39eea82eb79ed66eb6 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 19 Jun 2013 16:28:48 -0700 Subject: [PATCH] Add first-time-setup registration flow Summary: Ref T1536. Currently, when you install Phabricator you're dumped on the login screen and have to consult the documentation to learn about `bin/accountadmin`. Instead, detect that an install is running first-time setup: - It has no configured providers; and - it has no user accounts. We can safely deduce that such an install isn't configured yet, and let the user create an admin account from the web UI. After they login, we raise a setup issue and lead them to configure authentication. (This could probably use some UI and copy tweaks.) Test Plan: {F46738} {F46739} Reviewers: chad, btrahan Reviewed By: chad CC: aran Maniphest Tasks: T1536 Differential Revision: https://secure.phabricator.com/D6228 --- src/__phutil_library_map__.php | 2 + .../controller/PhabricatorAuthController.php | 22 ++++++ .../PhabricatorAuthRegisterController.php | 67 ++++++++++++++++--- .../PhabricatorAuthStartController.php | 7 ++ .../check/PhabricatorSetupCheckAuth.php | 27 ++++++++ 5 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 src/applications/config/check/PhabricatorSetupCheckAuth.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index e9872ea819..0d8f66607c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1456,6 +1456,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php', 'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', 'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php', + 'PhabricatorSetupCheckAuth' => 'applications/config/check/PhabricatorSetupCheckAuth.php', 'PhabricatorSetupCheckBaseURI' => 'applications/config/check/PhabricatorSetupCheckBaseURI.php', 'PhabricatorSetupCheckBinaries' => 'applications/config/check/PhabricatorSetupCheckBinaries.php', 'PhabricatorSetupCheckDatabase' => 'applications/config/check/PhabricatorSetupCheckDatabase.php', @@ -3324,6 +3325,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck', + 'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckBaseURI' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckBinaries' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckDatabase' => 'PhabricatorSetupCheck', diff --git a/src/applications/auth/controller/PhabricatorAuthController.php b/src/applications/auth/controller/PhabricatorAuthController.php index 182a210e4a..aa23034a4b 100644 --- a/src/applications/auth/controller/PhabricatorAuthController.php +++ b/src/applications/auth/controller/PhabricatorAuthController.php @@ -29,6 +29,28 @@ abstract class PhabricatorAuthController extends PhabricatorController { } + /** + * Returns true if this install is newly setup (i.e., there are no user + * accounts yet). In this case, we enter a special mode to permit creation + * of the first account form the web UI. + */ + protected function isFirstTimeSetup() { + // If there are any auth providers, this isn't first time setup, even if + // we don't have accounts. + if (PhabricatorAuthProvider::getAllEnabledProviders()) { + return false; + } + + // Otherwise, check if there are any user accounts. If not, we're in first + // time setup. + $any_users = id(new PhabricatorPeopleQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->setLimit(1) + ->execute(); + + return !$any_users; + } + /** * Log a user into a web session and return an @{class:AphrontResponse} which diff --git a/src/applications/auth/controller/PhabricatorAuthRegisterController.php b/src/applications/auth/controller/PhabricatorAuthRegisterController.php index 86c509576f..85324ae090 100644 --- a/src/applications/auth/controller/PhabricatorAuthRegisterController.php +++ b/src/applications/auth/controller/PhabricatorAuthRegisterController.php @@ -20,10 +20,15 @@ final class PhabricatorAuthRegisterController return $this->renderError(pht('You are already logged in.')); } + $is_setup = false; if (strlen($this->accountKey)) { $result = $this->loadAccountForRegistrationOrLinking($this->accountKey); list($account, $provider, $response) = $result; $is_default = false; + } else if ($this->isFirstTimeSetup()) { + list($account, $provider, $response) = $this->loadSetupAccount(); + $is_default = true; + $is_setup = true; } else { list($account, $provider, $response) = $this->loadDefaultAccount(); $is_default = true; @@ -213,6 +218,10 @@ final class PhabricatorAuthRegisterController $editor->changePassword($user, $envelope); } + if ($is_setup) { + $editor->makeAdminUser($user, true); + } + $account->setUserPHID($user->getPHID()); $provider->willRegisterAccount($account); $account->save(); @@ -319,24 +328,53 @@ final class PhabricatorAuthRegisterController ->setError($e_realname)); } - $form->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($this->getApplicationURI('start/')) - ->setValue(pht('Register Phabricator Account'))); + $submit = id(new AphrontFormSubmitControl()); - $title = pht('Phabricator Registration'); + if ($is_setup) { + $submit + ->setValue(pht('Create Admin Account')); + } else { + $submit + ->addCancelButton($this->getApplicationURI('start/')) + ->setValue(pht('Register Phabricator Account')); + } + + + $form->appendChild($submit); $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addCrumb( - id(new PhabricatorCrumbView()) - ->setName(pht('Register'))); - $crumbs->addCrumb( - id(new PhabricatorCrumbView()) - ->setName($provider->getProviderName())); + + if ($is_setup) { + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Setup Admin Account'))); + $title = pht('Welcome to Phabricator'); + } else { + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Register'))); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName($provider->getProviderName())); + $title = pht('Phabricator Registration'); + } + + $welcome_view = null; + if ($is_setup) { + $welcome_view = id(new AphrontErrorView()) + ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) + ->setTitle(pht('Welcome to Phabricator')) + ->appendChild( + pht( + 'Installation is complete. Register your administrator account '. + 'below to log in. You will be able to configure options and add '. + 'other authentication mechanisms (like LDAP or OAuth) later on.')); + } return $this->buildApplicationPage( array( $crumbs, + $welcome_view, $error_view, $form, ), @@ -381,6 +419,13 @@ final class PhabricatorAuthRegisterController return array($account, $provider, $response); } + private function loadSetupAccount() { + $provider = new PhabricatorAuthProviderPassword(); + $account = $provider->getDefaultExternalAccount(); + $response = null; + return array($account, $provider, $response); + } + private function loadProfilePicture(PhabricatorExternalAccount $account) { $phid = $account->getProfileImagePHID(); if (!$phid) { diff --git a/src/applications/auth/controller/PhabricatorAuthStartController.php b/src/applications/auth/controller/PhabricatorAuthStartController.php index 7e605174c1..d6cde983c1 100644 --- a/src/applications/auth/controller/PhabricatorAuthStartController.php +++ b/src/applications/auth/controller/PhabricatorAuthStartController.php @@ -44,6 +44,13 @@ final class PhabricatorAuthStartController } if (!$providers) { + if ($this->isFirstTimeSetup()) { + // If this is a fresh install, let the user register their admin + // account. + return id(new AphrontRedirectResponse()) + ->setURI($this->getApplicationURI('/register/')); + } + return $this->renderError( pht( "This Phabricator install is not configured with any enabled ". diff --git a/src/applications/config/check/PhabricatorSetupCheckAuth.php b/src/applications/config/check/PhabricatorSetupCheckAuth.php new file mode 100644 index 0000000000..9cc2348aa6 --- /dev/null +++ b/src/applications/config/check/PhabricatorSetupCheckAuth.php @@ -0,0 +1,27 @@ + '/auth/', + ), + pht('using the "Auth" application'))); + + $this + ->newIssue('auth.noproviders') + ->setShortName(pht('No Auth Providers')) + ->setName(pht('No Authentication Providers Configured')) + ->setMessage($message); + } + } +}