Add "purpose" to password validity check
authorcsteipp <csteipp@wikimedia.org>
Tue, 14 Jul 2015 19:26:46 +0000 (12:26 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Tue, 14 Jul 2015 20:04:23 +0000 (20:04 +0000)
Allow callers to specify why they are checking a passwords validity, so
some checks can be modified. Only check the default policy on creation,
since the account doesn't exist it's not a member of any groups.

Bug: T104615
Change-Id: I56b66002562aaa1493d94a90309bc8e4ae3841c8

docs/hooks.txt
includes/User.php
includes/installer/WebInstallerPage.php
includes/password/UserPasswordPolicy.php
includes/specials/SpecialUserlogin.php

index 23df983..2fd815e 100644 (file)
@@ -2313,6 +2313,8 @@ that tests continue to run properly.
 'PasswordPoliciesForUser': Alter the effective password policy for a user.
 $user: User object whose policy you are modifying
 &$effectivePolicy: Array of policy statements that apply to this user
+$purpose: string indicating purpose of the check, one of 'login', 'create',
+  or 'reset'
 
 'PerformRetroactiveAutoblock': Called before a retroactive autoblock is applied
 to a user.
index 95ac0f1..7057af6 100644 (file)
@@ -838,10 +838,11 @@ class User implements IDBAccessObject {
         * able to set their password to this.
         *
         * @param string $password Desired password
+        * @param string $purpose one of 'login', 'create', 'reset'
         * @return Status
         * @since 1.23
         */
-       public function checkPasswordValidity( $password ) {
+       public function checkPasswordValidity( $password, $purpose = 'login' ) {
                global $wgPasswordPolicy;
 
                $upp = new UserPasswordPolicy(
@@ -858,7 +859,7 @@ class User implements IDBAccessObject {
                }
 
                if ( $result === false ) {
-                       $status->merge( $upp->checkUserPassword( $this, $password ) );
+                       $status->merge( $upp->checkUserPassword( $this, $password, $purpose ) );
                        return $status;
                } elseif ( $result === true ) {
                        return $status;
index 9aa6960..f7910ba 100644 (file)
@@ -911,16 +911,8 @@ class WebInstallerName extends WebInstallerPage {
                $pwd = $this->getVar( '_AdminPassword' );
                $user = User::newFromName( $cname );
                if ( $user ) {
-                       $upp = new UserPasswordPolicy(
-                               $wgPasswordPolicy['policies'],
-                               $wgPasswordPolicy['checks']
-                       );
-                       $status = $upp->checkUserPasswordForGroups(
-                               $user,
-                               $pwd,
-                               array( 'sysop', 'bureaucrat' )
-                       );
-                       $valid = $status->isGood();
+                       $status = $user->checkPasswordValidity( $pwd, 'create' );
+                       $valid = $status->isGood() ? true : $status->getMessage()->escaped();
                } else {
                        $valid = 'config-admin-name-invalid';
                }
index 70757ac..80dc669 100644 (file)
@@ -67,11 +67,12 @@ class UserPasswordPolicy {
         * Check if a passwords meets the effective password policy for a User.
         * @param User $user who's policy we are checking
         * @param string $password the password to check
+        * @param string $purpose one of 'login', 'create', 'reset'
         * @return Status error to indicate the password didn't meet the policy, or fatal to
         *      indicate the user shouldn't be allowed to login.
         */
-       public function checkUserPassword( User $user, $password ) {
-               $effectivePolicy = $this->getPoliciesForUser( $user );
+       public function checkUserPassword( User $user, $password, $purpose = 'login' ) {
+               $effectivePolicy = $this->getPoliciesForUser( $user, $purpose );
                return $this->checkPolicies(
                        $user,
                        $password,
@@ -126,16 +127,20 @@ class UserPasswordPolicy {
         * Get the policy for a user, based on their group membership. Public so
         * UI elements can access and inform the user.
         * @param User $user
+        * @param string $purpose one of 'login', 'create', 'reset'
         * @return array the effective policy for $user
         */
-       public function getPoliciesForUser( User $user ) {
-               $effectivePolicy = self::getPoliciesForGroups(
-                       $this->policies,
-                       $user->getEffectiveGroups(),
-                       $this->policies['default']
-               );
+       public function getPoliciesForUser( User $user, $purpose = 'login' ) {
+               $effectivePolicy = $this->policies['default'];
+               if ( $purpose !== 'create' ) {
+                       $effectivePolicy = self::getPoliciesForGroups(
+                               $this->policies,
+                               $user->getEffectiveGroups(),
+                               $this->policies['default']
+                       );
+               }
 
-               Hooks::run( 'PasswordPoliciesForUser', array( $user, &$effectivePolicy ) );
+               Hooks::run( 'PasswordPoliciesForUser', array( $user, &$effectivePolicy, $purpose ) );
 
                return $effectivePolicy;
        }
index aa51415..4ca07fe 100644 (file)
@@ -545,7 +545,7 @@ class LoginForm extends SpecialPage {
                        }
 
                        # check for password validity, return a fatal Status if invalid
-                       $validity = $u->checkPasswordValidity( $this->mPassword );
+                       $validity = $u->checkPasswordValidity( $this->mPassword, 'create' );
                        if ( !$validity->isGood() ) {
                                $validity->ok = false; // make sure this Status is fatal
                                return $validity;
@@ -948,7 +948,10 @@ class LoginForm extends SpecialPage {
                                        } elseif ( $wgInvalidPasswordReset
                                                && !$user->isValidPassword( $this->mPassword )
                                        ) {
-                                               $status = $user->checkPasswordValidity( $this->mPassword );
+                                               $status = $user->checkPasswordValidity(
+                                                       $this->mPassword,
+                                                       'login'
+                                               );
                                                $this->resetLoginForm(
                                                        $status->getMessage( 'resetpass-validity-soft' )
                                                );