[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/settings/panel/ -> PhabricatorSettingsPanelPassword.php (source)

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


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1