Merge "ApiSandbox: Add text about limit's "max" value"
[lhc/web/wiklou.git] / includes / user / PasswordReset.php
index 889ec92..530580d 100644 (file)
@@ -22,6 +22,9 @@
 
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\Auth\TemporaryPasswordAuthenticationRequest;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use MediaWiki\Logger\LoggerFactory;
 
 /**
  * Helper class for the password reset functionality shared by the web UI and the API.
@@ -30,13 +33,16 @@ use MediaWiki\Auth\TemporaryPasswordAuthenticationRequest;
  * EmailNotificationSecondaryAuthenticationProvider (or something providing equivalent
  * functionality) to be enabled.
  */
-class PasswordReset {
+class PasswordReset implements LoggerAwareInterface {
        /** @var Config */
        protected $config;
 
        /** @var AuthManager */
        protected $authManager;
 
+       /** @var LoggerInterface */
+       protected $logger;
+
        /**
         * In-process cache for isAllowed lookups, by username. Contains pairs of StatusValue objects
         * (for false and true value of $displayPassword, respectively).
@@ -48,6 +54,17 @@ class PasswordReset {
                $this->config = $config;
                $this->authManager = $authManager;
                $this->permissionCache = new HashBagOStuff( [ 'maxKeys' => 1 ] );
+               $this->logger = LoggerFactory::getInstance( 'authentication' );
+       }
+
+       /**
+        * Set the logger instance to use.
+        *
+        * @param LoggerInterface $logger
+        * @since 1.29
+        */
+       public function setLogger( LoggerInterface $logger ) {
+               $this->logger = $logger;
        }
 
        /**
@@ -134,12 +151,14 @@ class PasswordReset {
                if ( $resetRoutes['username'] && $username ) {
                        $method = 'username';
                        $users = [ User::newFromName( $username ) ];
+                       $email = null;
                } elseif ( $resetRoutes['email'] && $email ) {
                        if ( !Sanitizer::validateEmail( $email ) ) {
                                return StatusValue::newFatal( 'passwordreset-invalidemail' );
                        }
                        $method = 'email';
                        $users = $this->getUsersByEmail( $email );
+                       $username = null;
                } else {
                        // The user didn't supply any data
                        return StatusValue::newFatal( 'passwordreset-nodata' );
@@ -214,7 +233,20 @@ class PasswordReset {
                        }
                }
 
+               $logContext = [
+                       'requestingIp' => $ip,
+                       'requestingUser' => $performingUser->getName(),
+                       'targetUsername' => $username,
+                       'targetEmail' => $email,
+                       'actualUser' => $firstUser->getName(),
+                       'capture' => $displayPassword,
+               ];
+
                if ( !$result->isGood() ) {
+                       $this->logger->info(
+                               "{requestingUser} attempted password reset of {actualUser} but failed",
+                               $logContext + [ 'errors' => $result->getErrors() ]
+                       );
                        return $result;
                }
 
@@ -227,6 +259,20 @@ class PasswordReset {
                        }
                }
 
+               if ( $displayPassword ) {
+                       // The password capture thing is scary, so log
+                       // at a higher warning level.
+                       $this->logger->warning(
+                               "{requestingUser} did password reset of {actualUser} with password capturing!",
+                               $logContext
+                       );
+               } else {
+                       $this->logger->info(
+                               "{requestingUser} did password reset of {actualUser}",
+                               $logContext
+                       );
+               }
+
                return StatusValue::newGood( $passwords );
        }