2013-11-01 16:34:11 +01:00
|
|
|
<?php
|
|
|
|
|
2015-01-03 14:46:28 +01:00
|
|
|
final class DiffusionSetPasswordSettingsPanel extends PhabricatorSettingsPanel {
|
2013-11-01 16:34:11 +01:00
|
|
|
|
2014-04-02 21:06:05 +02:00
|
|
|
public function isEditableByAdministrators() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-01 16:34:11 +01:00
|
|
|
public function getPanelKey() {
|
|
|
|
return 'vcspassword';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPanelName() {
|
|
|
|
return pht('VCS Password');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPanelGroup() {
|
|
|
|
return pht('Authentication');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isEnabled() {
|
|
|
|
return PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest(AphrontRequest $request) {
|
2014-04-02 21:06:05 +02:00
|
|
|
$viewer = $request->getUser();
|
|
|
|
$user = $this->getUser();
|
2013-11-01 16:34:11 +01:00
|
|
|
|
2014-05-01 02:44:59 +02:00
|
|
|
$token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
|
|
|
$viewer,
|
|
|
|
$request,
|
|
|
|
'/settings/');
|
|
|
|
|
2013-11-01 16:34:11 +01:00
|
|
|
$vcspassword = id(new PhabricatorRepositoryVCSPassword())
|
|
|
|
->loadOneWhere(
|
|
|
|
'userPHID = %s',
|
|
|
|
$user->getPHID());
|
|
|
|
if (!$vcspassword) {
|
|
|
|
$vcspassword = id(new PhabricatorRepositoryVCSPassword());
|
|
|
|
$vcspassword->setUserPHID($user->getPHID());
|
|
|
|
}
|
|
|
|
|
|
|
|
$panel_uri = $this->getPanelURI('?saved=true');
|
|
|
|
|
|
|
|
$errors = array();
|
|
|
|
|
|
|
|
$e_password = true;
|
|
|
|
$e_confirm = true;
|
|
|
|
|
|
|
|
if ($request->isFormPost()) {
|
|
|
|
if ($request->getBool('remove')) {
|
|
|
|
if ($vcspassword->getID()) {
|
|
|
|
$vcspassword->delete();
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($panel_uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$new_password = $request->getStr('password');
|
|
|
|
$confirm = $request->getStr('confirm');
|
|
|
|
if (!strlen($new_password)) {
|
|
|
|
$e_password = pht('Required');
|
|
|
|
$errors[] = pht('Password is required.');
|
|
|
|
} else {
|
|
|
|
$e_password = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strlen($confirm)) {
|
|
|
|
$e_confirm = pht('Required');
|
|
|
|
$errors[] = pht('You must confirm the new password.');
|
|
|
|
} else {
|
|
|
|
$e_confirm = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors) {
|
|
|
|
$envelope = new PhutilOpaqueEnvelope($new_password);
|
|
|
|
|
2014-08-21 20:30:05 +02:00
|
|
|
try {
|
|
|
|
// NOTE: This test is against $viewer (not $user), so that the error
|
|
|
|
// message below makes sense in the case that the two are different,
|
|
|
|
// and because an admin reusing their own password is bad, while
|
|
|
|
// system agents generally do not have passwords anyway.
|
|
|
|
|
|
|
|
$same_password = $viewer->comparePassword($envelope);
|
|
|
|
} catch (PhabricatorPasswordHasherUnavailableException $ex) {
|
|
|
|
// If we're missing the hasher, just let the user continue.
|
|
|
|
$same_password = false;
|
|
|
|
}
|
|
|
|
|
2013-11-01 16:34:11 +01:00
|
|
|
if ($new_password !== $confirm) {
|
|
|
|
$e_password = pht('Does Not Match');
|
|
|
|
$e_confirm = pht('Does Not Match');
|
|
|
|
$errors[] = pht('Password and confirmation do not match.');
|
2014-08-21 20:30:05 +02:00
|
|
|
} else if ($same_password) {
|
2013-11-01 16:34:11 +01:00
|
|
|
$e_password = pht('Not Unique');
|
|
|
|
$e_confirm = pht('Not Unique');
|
|
|
|
$errors[] = pht(
|
2014-01-23 23:01:18 +01:00
|
|
|
'This password is the same as another password associated '.
|
|
|
|
'with your account. You must use a unique password for '.
|
|
|
|
'VCS access.');
|
|
|
|
} else if (
|
|
|
|
PhabricatorCommonPasswords::isCommonPassword($new_password)) {
|
|
|
|
$e_password = pht('Very Weak');
|
|
|
|
$e_confirm = pht('Very Weak');
|
|
|
|
$errors[] = pht(
|
|
|
|
'This password is extremely weak: it is one of the most common '.
|
|
|
|
'passwords in use. Choose a stronger password.');
|
2013-11-01 16:34:11 +01:00
|
|
|
}
|
|
|
|
|
2014-01-23 23:01:18 +01:00
|
|
|
|
2013-11-01 16:34:11 +01:00
|
|
|
if (!$errors) {
|
|
|
|
$vcspassword->setPassword($envelope, $user);
|
|
|
|
$vcspassword->save();
|
|
|
|
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($panel_uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$title = pht('Set VCS Password');
|
|
|
|
|
|
|
|
$form = id(new AphrontFormView())
|
2014-04-02 21:06:05 +02:00
|
|
|
->setUser($viewer)
|
2013-11-01 16:34:11 +01:00
|
|
|
->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'To access repositories hosted by Phabricator over HTTP, you must '.
|
|
|
|
'set a version control password. This password should be unique.'.
|
|
|
|
"\n\n".
|
|
|
|
"This password applies to all repositories available over ".
|
|
|
|
"HTTP."));
|
|
|
|
|
|
|
|
if ($vcspassword->getID()) {
|
|
|
|
$form
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormPasswordControl())
|
2014-08-13 19:06:48 +02:00
|
|
|
->setDisableAutocomplete(true)
|
2013-11-01 16:34:11 +01:00
|
|
|
->setLabel(pht('Current Password'))
|
|
|
|
->setDisabled(true)
|
|
|
|
->setValue('********************'));
|
|
|
|
} else {
|
|
|
|
$form
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormMarkupControl())
|
|
|
|
->setLabel(pht('Current Password'))
|
|
|
|
->setValue(phutil_tag('em', array(), pht('No Password Set'))));
|
|
|
|
}
|
|
|
|
|
|
|
|
$form
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormPasswordControl())
|
2014-08-13 19:06:48 +02:00
|
|
|
->setDisableAutocomplete(true)
|
2013-11-01 16:34:11 +01:00
|
|
|
->setName('password')
|
|
|
|
->setLabel(pht('New VCS Password'))
|
|
|
|
->setError($e_password))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormPasswordControl())
|
2014-08-13 19:06:48 +02:00
|
|
|
->setDisableAutocomplete(true)
|
2013-11-01 16:34:11 +01:00
|
|
|
->setName('confirm')
|
|
|
|
->setLabel(pht('Confirm VCS Password'))
|
|
|
|
->setError($e_confirm))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->setValue(pht('Change Password')));
|
|
|
|
|
|
|
|
|
|
|
|
if (!$vcspassword->getID()) {
|
|
|
|
$is_serious = PhabricatorEnv::getEnvConfig(
|
|
|
|
'phabricator.serious-business');
|
|
|
|
|
|
|
|
$suggest = Filesystem::readRandomBytes(128);
|
|
|
|
$suggest = preg_replace('([^A-Za-z0-9/!().,;{}^&*%~])', '', $suggest);
|
|
|
|
$suggest = substr($suggest, 0, 20);
|
|
|
|
|
|
|
|
if ($is_serious) {
|
|
|
|
$form->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'Having trouble coming up with a good password? Try this randomly '.
|
|
|
|
'generated one, made by a computer:'.
|
|
|
|
"\n\n".
|
|
|
|
"`%s`",
|
|
|
|
$suggest));
|
|
|
|
} else {
|
|
|
|
$form->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'Having trouble coming up with a good password? Try this '.
|
|
|
|
'artisinal password, hand made in small batches by our expert '.
|
|
|
|
'craftspeople: '.
|
|
|
|
"\n\n".
|
|
|
|
"`%s`",
|
|
|
|
$suggest));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-18 21:18:04 +01:00
|
|
|
$hash_envelope = new PhutilOpaqueEnvelope($vcspassword->getPasswordHash());
|
|
|
|
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel(pht('Current Algorithm'))
|
|
|
|
->setValue(
|
|
|
|
PhabricatorPasswordHasher::getCurrentAlgorithmName($hash_envelope)));
|
|
|
|
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel(pht('Best Available Algorithm'))
|
|
|
|
->setValue(PhabricatorPasswordHasher::getBestAlgorithmName()));
|
|
|
|
|
2014-02-20 17:12:04 +01:00
|
|
|
if (strlen($hash_envelope->openEnvelope())) {
|
2014-08-21 20:30:05 +02:00
|
|
|
try {
|
|
|
|
$can_upgrade = PhabricatorPasswordHasher::canUpgradeHash(
|
|
|
|
$hash_envelope);
|
|
|
|
} catch (PhabricatorPasswordHasherUnavailableException $ex) {
|
|
|
|
$can_upgrade = false;
|
|
|
|
$errors[] = pht(
|
|
|
|
'Your VCS password is currently hashed using an algorithm which is '.
|
|
|
|
'no longer available on this install.');
|
|
|
|
$errors[] = pht(
|
|
|
|
'Because the algorithm implementation is missing, your password '.
|
|
|
|
'can not be used.');
|
|
|
|
$errors[] = pht(
|
|
|
|
'You can set a new password to replace the old password.');
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($can_upgrade) {
|
2014-02-20 17:12:04 +01:00
|
|
|
$errors[] = pht(
|
|
|
|
'The strength of your stored VCS password hash can be upgraded. '.
|
|
|
|
'To upgrade, either: use the password to authenticate with a '.
|
|
|
|
'repository; or change your password.');
|
|
|
|
}
|
2014-02-18 21:18:04 +01:00
|
|
|
}
|
|
|
|
|
2013-11-01 16:34:11 +01:00
|
|
|
$object_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeaderText($title)
|
|
|
|
->setForm($form)
|
2014-01-10 18:17:37 +01:00
|
|
|
->setFormErrors($errors);
|
2013-11-01 16:34:11 +01:00
|
|
|
|
|
|
|
$remove_form = id(new AphrontFormView())
|
2014-04-02 21:06:05 +02:00
|
|
|
->setUser($viewer);
|
2013-11-01 16:34:11 +01:00
|
|
|
|
|
|
|
if ($vcspassword->getID()) {
|
|
|
|
$remove_form
|
|
|
|
->addHiddenInput('remove', true)
|
|
|
|
->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'You can remove your VCS password, which will prevent your '.
|
|
|
|
'account from accessing repositories.'))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->setValue(pht('Remove Password')));
|
|
|
|
} else {
|
|
|
|
$remove_form->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'You do not currently have a VCS password set. If you set one, you '.
|
|
|
|
'can remove it here later.'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$remove_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeaderText(pht('Remove VCS Password'))
|
|
|
|
->setForm($remove_form);
|
|
|
|
|
|
|
|
$saved = null;
|
|
|
|
if ($request->getBool('saved')) {
|
|
|
|
$saved = id(new AphrontErrorView())
|
|
|
|
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
|
|
|
->setTitle(pht('Password Updated'))
|
|
|
|
->appendChild(pht('Your VCS password has been updated.'));
|
|
|
|
}
|
|
|
|
|
|
|
|
return array(
|
|
|
|
$saved,
|
|
|
|
$object_box,
|
|
|
|
$remove_box,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|