Page MenuHomePhabricator

D20120.id.diff
No OneTemporary

D20120.id.diff

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
@@ -14,11 +14,6 @@
$key = $request->getURIData('key');
$email_id = $request->getURIData('emailID');
- if ($request->getUser()->isLoggedIn()) {
- return $this->renderError(
- pht('You are already logged in.'));
- }
-
$target_user = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withIDs(array($id))
@@ -27,6 +22,19 @@
return new Aphront404Response();
}
+ // NOTE: We allow you to use a one-time login link for your own current
+ // login account. This supports the "Set Password" flow.
+
+ $is_logged_in = false;
+ if ($viewer->isLoggedIn()) {
+ if ($viewer->getPHID() !== $target_user->getPHID()) {
+ return $this->renderError(
+ pht('You are already logged in.'));
+ } else {
+ $is_logged_in = true;
+ }
+ }
+
// NOTE: As a convenience to users, these one-time login URIs may also
// be associated with an email address which will be verified when the
// URI is used.
@@ -100,7 +108,7 @@
->addCancelButton('/');
}
- if ($request->isFormPost()) {
+ if ($request->isFormPost() || $is_logged_in) {
// If we have an email bound into this URI, verify email so that clicking
// the link in the "Welcome" email is good enough, without requiring users
// to go through a second round of email verification.
@@ -121,6 +129,12 @@
$next_uri = $this->getNextStepURI($target_user);
+ // If the user is already logged in, we're just doing a "password set"
+ // flow. Skip directly to the next step.
+ if ($is_logged_in) {
+ return id(new AphrontRedirectResponse())->setURI($next_uri);
+ }
+
PhabricatorCookies::setNextURICookie($request, $next_uri, $force = true);
$force_full_session = false;
diff --git a/src/applications/auth/controller/PhabricatorEmailLoginController.php b/src/applications/auth/controller/PhabricatorEmailLoginController.php
--- a/src/applications/auth/controller/PhabricatorEmailLoginController.php
+++ b/src/applications/auth/controller/PhabricatorEmailLoginController.php
@@ -9,20 +9,38 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
+ $is_logged_in = $viewer->isLoggedIn();
$e_email = true;
$e_captcha = true;
$errors = array();
- $v_email = $request->getStr('email');
+ if ($is_logged_in) {
+ if (!$this->isPasswordAuthEnabled()) {
+ return $this->newDialog()
+ ->setTitle(pht('No Password Auth'))
+ ->appendParagraph(
+ pht(
+ 'Password authentication is not enabled and you are already '.
+ 'logged in. There is nothing for you here.'))
+ ->addCancelButton('/', pht('Continue'));
+ }
+
+ $v_email = $viewer->loadPrimaryEmailAddress();
+ } else {
+ $v_email = $request->getStr('email');
+ }
+
if ($request->isFormPost()) {
$e_email = null;
$e_captcha = pht('Again');
- $captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
- if (!$captcha_ok) {
- $errors[] = pht('Captcha response is incorrect, try again.');
- $e_captcha = pht('Invalid');
+ if (!$is_logged_in) {
+ $captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
+ if (!$captcha_ok) {
+ $errors[] = pht('Captcha response is incorrect, try again.');
+ $e_captcha = pht('Invalid');
+ }
}
if (!strlen($v_email)) {
@@ -76,10 +94,24 @@
}
if (!$errors) {
- $body = $this->newAccountLoginMailBody($target_user);
+ $body = $this->newAccountLoginMailBody(
+ $target_user,
+ $is_logged_in);
+
+ if ($is_logged_in) {
+ $subject = pht('[Phabricator] Account Password Link');
+ $instructions = pht(
+ 'An email has been sent containing a link you can use to set '.
+ 'a password for your account.');
+ } else {
+ $subject = pht('[Phabricator] Account Login Link');
+ $instructions = pht(
+ 'An email has been sent containing a link you can use to log '.
+ 'in to your account.');
+ }
$mail = id(new PhabricatorMetaMTAMail())
- ->setSubject(pht('[Phabricator] Account Login Link'))
+ ->setSubject($subject)
->setForceDelivery(true)
->addRawTos(array($target_email->getAddress()))
->setBody($body)
@@ -88,8 +120,7 @@
return $this->newDialog()
->setTitle(pht('Check Your Email'))
->setShortTitle(pht('Email Sent'))
- ->appendParagraph(
- pht('An email has been sent with a link you can use to log in.'))
+ ->appendParagraph($instructions)
->addCancelButton('/', pht('Done'));
}
}
@@ -99,33 +130,47 @@
->setViewer($viewer);
if ($this->isPasswordAuthEnabled()) {
- $form->appendRemarkupInstructions(
- pht(
- 'To reset your password, provide your email address. An email '.
- 'with a login link will be sent to you.'));
+ if ($is_logged_in) {
+ $title = pht('Set Password');
+ $form->appendRemarkupInstructions(
+ pht(
+ 'A password reset link will be sent to your primary email '.
+ 'address. Follow the link to set an account password.'));
+ } else {
+ $title = pht('Password Reset');
+ $form->appendRemarkupInstructions(
+ pht(
+ 'To reset your password, provide your email address. An email '.
+ 'with a login link will be sent to you.'));
+ }
} else {
+ $title = pht('Email Login');
$form->appendRemarkupInstructions(
pht(
'To access your account, provide your email address. An email '.
'with a login link will be sent to you.'));
}
+ if ($is_logged_in) {
+ $address_control = new AphrontFormStaticControl();
+ } else {
+ $address_control = id(new AphrontFormTextControl())
+ ->setName('email')
+ ->setError($e_email);
+ }
+
+ $address_control
+ ->setLabel(pht('Email Address'))
+ ->setValue($v_email);
+
$form
- ->appendControl(
- id(new AphrontFormTextControl())
- ->setLabel(pht('Email Address'))
- ->setName('email')
- ->setValue($v_email)
- ->setError($e_email))
- ->appendControl(
+ ->appendControl($address_control);
+
+ if (!$is_logged_in) {
+ $form->appendControl(
id(new AphrontFormRecaptchaControl())
->setLabel(pht('Captcha'))
->setError($e_captcha));
-
- if ($this->isPasswordAuthEnabled()) {
- $title = pht('Password Reset');
- } else {
- $title = pht('Email Login');
}
return $this->newDialog()
@@ -137,7 +182,10 @@
->addSubmitButton(pht('Send Email'));
}
- private function newAccountLoginMailBody(PhabricatorUser $user) {
+ private function newAccountLoginMailBody(
+ PhabricatorUser $user,
+ $is_logged_in) {
+
$engine = new PhabricatorAuthSessionEngine();
$uri = $engine->getOneTimeLoginURI(
$user,
@@ -148,7 +196,12 @@
$have_passwords = $this->isPasswordAuthEnabled();
if ($have_passwords) {
- if ($is_serious) {
+ if ($is_logged_in) {
+ $body = pht(
+ 'You can use this link to set a password on your account:'.
+ "\n\n %s\n",
+ $uri);
+ } else if ($is_serious) {
$body = pht(
"You can use this link to reset your Phabricator password:".
"\n\n %s\n",
diff --git a/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php b/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php
--- a/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php
+++ b/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php
@@ -34,11 +34,6 @@
$content_source = PhabricatorContentSource::newFromRequest($request);
- $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
- $viewer,
- $request,
- '/settings/');
-
$min_len = PhabricatorEnv::getEnvConfig('account.minimum-password-length');
$min_len = (int)$min_len;
@@ -55,20 +50,25 @@
->withPasswordTypes(array($account_type))
->withIsRevoked(false)
->execute();
- if ($password_objects) {
- $password_object = head($password_objects);
- } else {
- $password_object = PhabricatorAuthPassword::initializeNewPassword(
- $user,
- $account_type);
+ if (!$password_objects) {
+ return $this->newSetPasswordView($request);
}
+ $password_object = head($password_objects);
$e_old = true;
$e_new = true;
$e_conf = true;
$errors = array();
- if ($request->isFormPost()) {
+ if ($request->isFormOrHisecPost()) {
+ $workflow_key = sprintf(
+ 'password.change(%s)',
+ $user->getPHID());
+
+ $hisec_token = id(new PhabricatorAuthSessionEngine())
+ ->setWorkflowKey($workflow_key)
+ ->requireHighSecurityToken($viewer, $request, '/settings/');
+
// Rate limit guesses about the old password. This page requires MFA and
// session compromise already, so this is mostly just to stop researchers
// from reporting this as a vulnerability.
@@ -218,5 +218,27 @@
);
}
+ private function newSetPasswordView(AphrontRequest $request) {
+ $viewer = $request->getUser();
+ $user = $this->getUser();
+
+ $form = id(new AphrontFormView())
+ ->setViewer($viewer)
+ ->appendRemarkupInstructions(
+ pht(
+ 'Your account does not currently have a password set. You can '.
+ 'choose a password by performing a password reset.'))
+ ->appendControl(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton('/login/email/', pht('Reset Password')));
+
+ $form_box = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Set Password'))
+ ->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
+ ->setForm($form);
+
+ return $form_box;
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 16, 4:39 PM (2 d, 14 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7385717
Default Alt Text
D20120.id.diff (10 KB)

Event Timeline