~ubuntu-branches/ubuntu/wily/phabricator/wily

« back to all changes in this revision

Viewing changes to phabricator/src/applications/settings/panel/PhabricatorPasswordSettingsPanel.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2015-01-29 00:15:58 UTC
  • mfrom: (0.14.1) (0.13.1) (0.10.2) (2.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20150129001558-7qklhtcc043y9mog
Tags: 0~git20150129-1
* New snapshot release
* restricted access to local config file (closes: #775479)
* moved local config file to /var/lib/phabricator (closes: #775478)
* switched mysql-server dependency to recommends (closes: #773536)
* use /run instead of /var/run (closes: #775803)
* prevent package reinstall from overwritting local changes (closes: #776288)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
final class PhabricatorPasswordSettingsPanel extends PhabricatorSettingsPanel {
 
4
 
 
5
  public function getPanelKey() {
 
6
    return 'password';
 
7
  }
 
8
 
 
9
  public function getPanelName() {
 
10
    return pht('Password');
 
11
  }
 
12
 
 
13
  public function getPanelGroup() {
 
14
    return pht('Authentication');
 
15
  }
 
16
 
 
17
  public function isEnabled() {
 
18
    // There's no sense in showing a change password panel if this install
 
19
    // doesn't support password authentication.
 
20
    if (!PhabricatorPasswordAuthProvider::getPasswordProvider()) {
 
21
      return false;
 
22
    }
 
23
 
 
24
    return true;
 
25
  }
 
26
 
 
27
  public function processRequest(AphrontRequest $request) {
 
28
    $user = $request->getUser();
 
29
 
 
30
    $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
 
31
      $user,
 
32
      $request,
 
33
      '/settings/');
 
34
 
 
35
    $min_len = PhabricatorEnv::getEnvConfig('account.minimum-password-length');
 
36
    $min_len = (int)$min_len;
 
37
 
 
38
    // NOTE: To change your password, you need to prove you own the account,
 
39
    // either by providing the old password or by carrying a token to
 
40
    // the workflow from a password reset email.
 
41
 
 
42
    $key = $request->getStr('key');
 
43
    $token = null;
 
44
    if ($key) {
 
45
      $token = id(new PhabricatorAuthTemporaryTokenQuery())
 
46
        ->setViewer($user)
 
47
        ->withObjectPHIDs(array($user->getPHID()))
 
48
        ->withTokenTypes(
 
49
          array(PhabricatorAuthSessionEngine::PASSWORD_TEMPORARY_TOKEN_TYPE))
 
50
        ->withTokenCodes(array(PhabricatorHash::digest($key)))
 
51
        ->withExpired(false)
 
52
        ->executeOne();
 
53
    }
 
54
 
 
55
    $e_old = true;
 
56
    $e_new = true;
 
57
    $e_conf = true;
 
58
 
 
59
    $errors = array();
 
60
    if ($request->isFormPost()) {
 
61
      if (!$token) {
 
62
        $envelope = new PhutilOpaqueEnvelope($request->getStr('old_pw'));
 
63
        if (!$user->comparePassword($envelope)) {
 
64
          $errors[] = pht('The old password you entered is incorrect.');
 
65
          $e_old = pht('Invalid');
 
66
        }
 
67
      }
 
68
 
 
69
      $pass = $request->getStr('new_pw');
 
70
      $conf = $request->getStr('conf_pw');
 
71
 
 
72
      if (strlen($pass) < $min_len) {
 
73
        $errors[] = pht('Your new password is too short.');
 
74
        $e_new = pht('Too Short');
 
75
      } else if ($pass !== $conf) {
 
76
        $errors[] = pht('New password and confirmation do not match.');
 
77
        $e_conf = pht('Invalid');
 
78
      } else if (PhabricatorCommonPasswords::isCommonPassword($pass)) {
 
79
        $e_new = pht('Very Weak');
 
80
        $e_conf = pht('Very Weak');
 
81
        $errors[] = pht(
 
82
          'Your new password is very weak: it is one of the most common '.
 
83
          'passwords in use. Choose a stronger password.');
 
84
      }
 
85
 
 
86
      if (!$errors) {
 
87
        // This write is unguarded because the CSRF token has already
 
88
        // been checked in the call to $request->isFormPost() and
 
89
        // the CSRF token depends on the password hash, so when it
 
90
        // is changed here the CSRF token check will fail.
 
91
        $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
 
92
 
 
93
          $envelope = new PhutilOpaqueEnvelope($pass);
 
94
          id(new PhabricatorUserEditor())
 
95
            ->setActor($user)
 
96
            ->changePassword($user, $envelope);
 
97
 
 
98
        unset($unguarded);
 
99
 
 
100
        if ($token) {
 
101
          // Destroy the token.
 
102
          $token->delete();
 
103
 
 
104
          // If this is a password set/reset, kick the user to the home page
 
105
          // after we update their account.
 
106
          $next = '/';
 
107
        } else {
 
108
          $next = $this->getPanelURI('?saved=true');
 
109
        }
 
110
 
 
111
        id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
 
112
          $user,
 
113
          $request->getCookie(PhabricatorCookies::COOKIE_SESSION));
 
114
 
 
115
        return id(new AphrontRedirectResponse())->setURI($next);
 
116
      }
 
117
    }
 
118
 
 
119
    $hash_envelope = new PhutilOpaqueEnvelope($user->getPasswordHash());
 
120
    if (strlen($hash_envelope->openEnvelope())) {
 
121
      try {
 
122
        $can_upgrade = PhabricatorPasswordHasher::canUpgradeHash(
 
123
          $hash_envelope);
 
124
      } catch (PhabricatorPasswordHasherUnavailableException $ex) {
 
125
        $can_upgrade = false;
 
126
 
 
127
        // Only show this stuff if we aren't on the reset workflow. We can
 
128
        // do resets regardless of the old hasher's availability.
 
129
        if (!$token) {
 
130
          $errors[] = pht(
 
131
            'Your password is currently hashed using an algorithm which is '.
 
132
            'no longer available on this install.');
 
133
          $errors[] = pht(
 
134
            'Because the algorithm implementation is missing, your password '.
 
135
            'can not be used or updated.');
 
136
          $errors[] = pht(
 
137
            'To set a new password, request a password reset link from the '.
 
138
            'login screen and then follow the instructions.');
 
139
        }
 
140
      }
 
141
 
 
142
      if ($can_upgrade) {
 
143
        $errors[] = pht(
 
144
          'The strength of your stored password hash can be upgraded. '.
 
145
          'To upgrade, either: log out and log in using your password; or '.
 
146
          'change your password.');
 
147
      }
 
148
    }
 
149
 
 
150
    $len_caption = null;
 
151
    if ($min_len) {
 
152
      $len_caption = pht('Minimum password length: %d characters.', $min_len);
 
153
    }
 
154
 
 
155
    $form = new AphrontFormView();
 
156
    $form
 
157
      ->setUser($user)
 
158
      ->addHiddenInput('key', $key);
 
159
 
 
160
    if (!$token) {
 
161
      $form->appendChild(
 
162
        id(new AphrontFormPasswordControl())
 
163
          ->setLabel(pht('Old Password'))
 
164
          ->setError($e_old)
 
165
          ->setName('old_pw'));
 
166
    }
 
167
 
 
168
    $form
 
169
      ->appendChild(
 
170
        id(new AphrontFormPasswordControl())
 
171
          ->setDisableAutocomplete(true)
 
172
          ->setLabel(pht('New Password'))
 
173
          ->setError($e_new)
 
174
          ->setName('new_pw'));
 
175
    $form
 
176
      ->appendChild(
 
177
        id(new AphrontFormPasswordControl())
 
178
          ->setDisableAutocomplete(true)
 
179
          ->setLabel(pht('Confirm Password'))
 
180
          ->setCaption($len_caption)
 
181
          ->setError($e_conf)
 
182
          ->setName('conf_pw'));
 
183
    $form
 
184
      ->appendChild(
 
185
        id(new AphrontFormSubmitControl())
 
186
          ->setValue(pht('Change Password')));
 
187
 
 
188
    $form->appendChild(
 
189
      id(new AphrontFormStaticControl())
 
190
        ->setLabel(pht('Current Algorithm'))
 
191
        ->setValue(PhabricatorPasswordHasher::getCurrentAlgorithmName(
 
192
          new PhutilOpaqueEnvelope($user->getPasswordHash()))));
 
193
 
 
194
    $form->appendChild(
 
195
      id(new AphrontFormStaticControl())
 
196
        ->setLabel(pht('Best Available Algorithm'))
 
197
        ->setValue(PhabricatorPasswordHasher::getBestAlgorithmName()));
 
198
 
 
199
    $form->appendRemarkupInstructions(
 
200
      pht(
 
201
        'NOTE: Changing your password will terminate any other outstanding '.
 
202
        'login sessions.'));
 
203
 
 
204
    $form_box = id(new PHUIObjectBoxView())
 
205
      ->setHeaderText(pht('Change Password'))
 
206
      ->setFormSaved($request->getStr('saved'))
 
207
      ->setFormErrors($errors)
 
208
      ->setForm($form);
 
209
 
 
210
    return array(
 
211
      $form_box,
 
212
    );
 
213
  }
 
214
 
 
215
 
 
216
}