forked from phacility/phabricator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPhabricatorSettingsPanelPassword.php
187 lines (154 loc) · 5.49 KB
/
PhabricatorSettingsPanelPassword.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<?php
final class PhabricatorSettingsPanelPassword
extends PhabricatorSettingsPanel {
public function getPanelKey() {
return 'password';
}
public function getPanelName() {
return pht('Password');
}
public function getPanelGroup() {
return pht('Authentication');
}
public function isEnabled() {
// There's no sense in showing a change password panel if the user
// can't change their password...
if (!PhabricatorEnv::getEnvConfig('account.editable')) {
return false;
}
// ...or this install doesn't support password authentication at all.
if (!PhabricatorAuthProviderPassword::getPasswordProvider()) {
return false;
}
return true;
}
public function processRequest(AphrontRequest $request) {
$user = $request->getUser();
$token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
$user,
$request,
'/settings/');
$min_len = PhabricatorEnv::getEnvConfig('account.minimum-password-length');
$min_len = (int)$min_len;
// NOTE: To change your password, you need to prove you own the account,
// either by providing the old password or by carrying a token to
// the workflow from a password reset email.
$token = $request->getStr('token');
$valid_token = false;
if ($token) {
$email_address = $request->getStr('email');
$email = id(new PhabricatorUserEmail())->loadOneWhere(
'address = %s',
$email_address);
if ($email) {
$valid_token = $user->validateEmailToken($email, $token);
}
}
$e_old = true;
$e_new = true;
$e_conf = true;
$errors = array();
if ($request->isFormPost()) {
if (!$valid_token) {
$envelope = new PhutilOpaqueEnvelope($request->getStr('old_pw'));
if (!$user->comparePassword($envelope)) {
$errors[] = pht('The old password you entered is incorrect.');
$e_old = pht('Invalid');
}
}
$pass = $request->getStr('new_pw');
$conf = $request->getStr('conf_pw');
if (strlen($pass) < $min_len) {
$errors[] = pht('Your new password is too short.');
$e_new = pht('Too Short');
} else if ($pass !== $conf) {
$errors[] = pht('New password and confirmation do not match.');
$e_conf = pht('Invalid');
} else if (PhabricatorCommonPasswords::isCommonPassword($pass)) {
$e_new = pht('Very Weak');
$e_conf = pht('Very Weak');
$errors[] = pht(
'Your new password is very weak: it is one of the most common '.
'passwords in use. Choose a stronger password.');
}
if (!$errors) {
// This write is unguarded because the CSRF token has already
// been checked in the call to $request->isFormPost() and
// the CSRF token depends on the password hash, so when it
// is changed here the CSRF token check will fail.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$envelope = new PhutilOpaqueEnvelope($pass);
id(new PhabricatorUserEditor())
->setActor($user)
->changePassword($user, $envelope);
unset($unguarded);
if ($valid_token) {
// If this is a password set/reset, kick the user to the home page
// after we update their account.
$next = '/';
} else {
$next = $this->getPanelURI('?saved=true');
}
return id(new AphrontRedirectResponse())->setURI($next);
}
}
$hash_envelope = new PhutilOpaqueEnvelope($user->getPasswordHash());
if (strlen($hash_envelope->openEnvelope())) {
if (PhabricatorPasswordHasher::canUpgradeHash($hash_envelope)) {
$errors[] = pht(
'The strength of your stored password hash can be upgraded. '.
'To upgrade, either: log out and log in using your password; or '.
'change your password.');
}
}
$len_caption = null;
if ($min_len) {
$len_caption = pht('Minimum password length: %d characters.', $min_len);
}
$form = new AphrontFormView();
$form
->setUser($user)
->addHiddenInput('token', $token);
if (!$valid_token) {
$form->appendChild(
id(new AphrontFormPasswordControl())
->setLabel(pht('Old Password'))
->setError($e_old)
->setName('old_pw'));
}
$form
->appendChild(
id(new AphrontFormPasswordControl())
->setLabel(pht('New Password'))
->setError($e_new)
->setName('new_pw'));
$form
->appendChild(
id(new AphrontFormPasswordControl())
->setLabel(pht('Confirm Password'))
->setCaption($len_caption)
->setError($e_conf)
->setName('conf_pw'));
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Change Password')));
$form->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Current Algorithm'))
->setValue(PhabricatorPasswordHasher::getCurrentAlgorithmName(
new PhutilOpaqueEnvelope($user->getPasswordHash()))));
$form->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Best Available Algorithm'))
->setValue(PhabricatorPasswordHasher::getBestAlgorithmName()));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Change Password'))
->setFormSaved($request->getStr('saved'))
->setFormErrors($errors)
->setForm($form);
return array(
$form_box,
);
}
}