diff options
author | Stefan Giehl <stefan@matomo.org> | 2022-07-25 11:58:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-25 11:58:34 +0300 |
commit | 6cc723685d3c1c9b399b09e9b691b9f2dba80bce (patch) | |
tree | e694ce956c8c3358a428dd6c87f1ad07d86719b1 /core | |
parent | 064f6db3b8f8534e9aaaf881168017bac5fcb6cf (diff) |
Refactor and improve password confirmation in UI & API (#19525)
* Extract password confirmation into own vue component
* Require password confirmation for Anonymize data section
* Adjust tests
* Move password confirmation method to abstract class
* Use new password confirmation component also for setting super user access
* Use new password confirmation component also for changing user & 2FA reset
* Introduce new event Login.userRequiresPasswordConfirmation to allow plugins to disable the password confirmation for users
* adjust ui tests
* Use new password confirmation component also for user settings
* cleans up some vue code
* built vue files
* clean up php code
* improve 2fa tab & adjust tests
* add warning to event
Co-authored-by: sgiehl <sgiehl@users.noreply.github.com>
Diffstat (limited to 'core')
-rw-r--r-- | core/Piwik.php | 26 | ||||
-rw-r--r-- | core/Plugin/API.php | 36 | ||||
-rw-r--r-- | core/View.php | 2 |
3 files changed, 61 insertions, 3 deletions
diff --git a/core/Piwik.php b/core/Piwik.php index 1d8c547f45..e42a00adbe 100644 --- a/core/Piwik.php +++ b/core/Piwik.php @@ -283,6 +283,32 @@ class Piwik } /** + * Returns if the given user needs to confirm his password in UI and for certain API methods + * + * @param string $login + * @return bool + */ + public static function doesUserRequirePasswordConfirmation(string $login) + { + $requiresPasswordConfirmation = true; + + /** + * Triggered to check if a password confirmation for a user is required. + * + * This event can be used in custom login plugins to skip the password confirmation checks for certain users, + * where e.g. no password would be available. + * + * Attention: Use this event wisely. Disabling password confirmation decreases the security. + * + * @param bool $requiresPasswordConfirmation Indicates if the password should be checked or not + * @param string $login Login of a user the password should be confirmed for + */ + Piwik::postEvent('Login.userRequiresPasswordConfirmation', [&$requiresPasswordConfirmation, $login]); + + return $requiresPasswordConfirmation; + } + + /** * Check that the current user is either the specified user or the superuser. * * @param string $theUser A username. diff --git a/core/Plugin/API.php b/core/Plugin/API.php index 8618a63dd6..a5aa8d73ee 100644 --- a/core/Plugin/API.php +++ b/core/Plugin/API.php @@ -1,4 +1,5 @@ <?php + /** * Matomo - free/libre analytics platform * @@ -9,8 +10,12 @@ namespace Piwik\Plugin; +use Piwik\Common; use Piwik\Container\StaticContainer; +use Piwik\Piwik; +use Piwik\Plugins\Login\PasswordVerifier; use Psr\Log\LoggerInterface; +use Exception; /** * The base class of all API singletons. @@ -66,8 +71,8 @@ abstract class API $logger = $container->get('Psr\Log\LoggerInterface'); // BC with API defining a protected constructor - $logger->notice('The API class {class} defines a protected constructor which is deprecated, make the constructor public instead', array('class' => $class)); - self::$instances[$class] = new $class; + $logger->notice('The API class {class} defines a protected constructor which is deprecated, make the constructor public instead', ['class' => $class]); + self::$instances[$class] = new $class(); } } @@ -92,7 +97,7 @@ abstract class API */ public static function unsetAllInstances() { - self::$instances = array(); + self::$instances = []; } /** @@ -105,4 +110,29 @@ abstract class API $class = get_called_class(); self::$instances[$class] = $instance; } + + /** + * Verifies if the given password matches the current users password + * + * @param $passwordConfirmation + * @throws Exception + */ + protected function confirmCurrentUserPassword($passwordConfirmation) + { + $loginCurrentUser = Piwik::getCurrentUserLogin(); + + if (!Piwik::doesUserRequirePasswordConfirmation($loginCurrentUser)) { + return; // password confirmation disabled for user + } + + if (empty($passwordConfirmation)) { + throw new Exception(Piwik::translate('UsersManager_ConfirmWithPassword')); + } + + $passwordConfirmation = Common::unsanitizeInputValue($passwordConfirmation); + + if (!StaticContainer::get(PasswordVerifier::class)->isPasswordCorrect($loginCurrentUser, $passwordConfirmation)) { + throw new Exception(Piwik::translate('UsersManager_CurrentPasswordNotCorrect')); + } + } } diff --git a/core/View.php b/core/View.php index 99c94b8906..599791fa62 100644 --- a/core/View.php +++ b/core/View.php @@ -164,6 +164,8 @@ class View implements ViewInterface } catch (Exception $ex) { // pass (occurs when DB cannot be connected to, perhaps piwik URL cache should be stored in config file...) } + + $this->userRequiresPasswordConfirmation = Piwik::doesUserRequirePasswordConfirmation(Piwik::getCurrentUserLogin()); } /** |