diff options
Diffstat (limited to 'plugins/UsersManager/API.php')
-rw-r--r-- | plugins/UsersManager/API.php | 122 |
1 files changed, 104 insertions, 18 deletions
diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php index c1f5965f96..ae9189e653 100644 --- a/plugins/UsersManager/API.php +++ b/plugins/UsersManager/API.php @@ -10,12 +10,14 @@ namespace Piwik\Plugins\UsersManager; use Exception; use Piwik\Access; +use Piwik\Auth\Password; use Piwik\Common; use Piwik\Config; use Piwik\Container\StaticContainer; use Piwik\Date; use Piwik\Option; use Piwik\Piwik; +use Piwik\SettingsPiwik; use Piwik\Site; use Piwik\Tracker\Cache; @@ -41,6 +43,11 @@ class API extends \Piwik\Plugin\API private $model; /** + * @var Password + */ + private $password; + + /** * @var UserAccessFilter */ private $userFilter; @@ -50,10 +57,11 @@ class API extends \Piwik\Plugin\API private static $instance = null; - public function __construct(Model $model, UserAccessFilter $filter) + public function __construct(Model $model, UserAccessFilter $filter, Password $password) { $this->model = $model; $this->userFilter = $filter; + $this->password = $password; } /** @@ -208,6 +216,7 @@ class API extends \Piwik\Plugin\API $users = $this->model->getUsers($logins); $users = $this->userFilter->filterUsers($users); + $users = $this->enrichUsers($users); // Non Super user can only access login & alias if (!Piwik::hasUserSuperUserAccess()) { @@ -355,7 +364,10 @@ class API extends \Piwik\Plugin\API $user = $this->model->getUser($userLogin); - return $this->userFilter->filterUser($user); + $user = $this->userFilter->filterUser($user); + $user = $this->enrichUser($user); + + return $user; } /** @@ -372,7 +384,10 @@ class API extends \Piwik\Plugin\API $user = $this->model->getUserByEmail($userEmail); - return $this->userFilter->filterUser($user); + $user = $this->userFilter->filterUser($user); + $user = $this->enrichUser($user); + + return $user; } private function checkLogin($userLogin) @@ -436,9 +451,9 @@ class API extends \Piwik\Plugin\API $passwordTransformed = $password; } - $alias = $this->getCleanAlias($alias, $userLogin); - - $token_auth = $this->getTokenAuth($userLogin, $passwordTransformed); + $alias = $this->getCleanAlias($alias, $userLogin); + $passwordTransformed = $this->password->hash($passwordTransformed); + $token_auth = $this->createTokenAuth($userLogin); $this->model->addUser($userLogin, $passwordTransformed, $email, $alias, $token_auth, Date::now()->getDatetime()); @@ -500,11 +515,7 @@ class API extends \Piwik\Plugin\API Piwik::checkUserIsNotAnonymous(); $users = $this->model->getUsersHavingSuperUserAccess(); - - foreach($users as &$user) { - // remove token_auth in API response - unset($user['token_auth']); - } + $users = $this->enrichUsers($users); // we do not filter these users by access and return them all since we need to print this information in the // UI and they are allowed to see this. @@ -512,11 +523,52 @@ class API extends \Piwik\Plugin\API return $users; } + private function enrichUsers($users) + { + if (!empty($users)) { + foreach ($users as $index => $user) { + $users[$index] = $this->enrichUser($user); + } + } + return $users; + } + + private function enrichUser($user) + { + if (!empty($user)) { + unset($user['token_auth']); + } + + return $user; + } + + /** + * Regenerate the token_auth associated with a user. + * + * If the user currently logged in regenerates his own token, he will be logged out. + * His previous token will be rendered invalid. + * + * @param string $userLogin + * @throws Exception + */ + public function regenerateTokenAuth($userLogin) + { + $this->checkUserIsNotAnonymous($userLogin); + + Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin); + + $this->model->updateUserTokenAuth( + $userLogin, + $this->createTokenAuth($userLogin) + ); + } + /** * Updates a user in the database. * Only login and password are required (case when we update the password). - * When the password changes, the key token for this user will change, which could break - * its API calls. + * + * If the password changes and the user has an old token_auth (legacy MD5 format) associated, + * the token will be regenerated. This could break a user's API calls. * * @see addUser() for all the parameters */ @@ -525,18 +577,30 @@ class API extends \Piwik\Plugin\API { Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin); $this->checkUserIsNotAnonymous($userLogin); - $userInfo = $this->getUser($userLogin); + $this->checkUserExists($userLogin); + + $userInfo = $this->model->getUser($userLogin); + $token_auth = $userInfo['token_auth']; + $passwordHasBeenUpdated = false; if (empty($password)) { $password = $userInfo['password']; } else { $password = Common::unsanitizeInputValue($password); + if (!$_isPasswordHashed) { UsersManager::checkPassword($password); $password = UsersManager::getPasswordHash($password); } + $passwordInfo = $this->password->info($password); + + if (!isset($passwordInfo['algo']) || 0 >= $passwordInfo['algo']) { + // password may have already been fully hashed + $password = $this->password->hash($password); + } + $passwordHasBeenUpdated = true; } @@ -552,8 +616,7 @@ class API extends \Piwik\Plugin\API $this->checkEmail($email); } - $alias = $this->getCleanAlias($alias, $userLogin); - $token_auth = $this->getTokenAuth($userLogin, $password); + $alias = $this->getCleanAlias($alias, $userLogin); $this->model->updateUser($userLogin, $password, $email, $alias, $token_auth); @@ -780,7 +843,20 @@ class API extends \Piwik\Plugin\API } /** - * Generates a unique MD5 for the given login & password + * Generates a new random authentication token. + * + * @param string $userLogin Login + * @return string + */ + public function createTokenAuth($userLogin) + { + return md5($userLogin . microtime(true) . Common::generateUniqId() . SettingsPiwik::getSalt()); + } + + /** + * Returns the user's API token. + * + * If the username/password combination is incorrect an invalid token will be returned. * * @param string $userLogin Login * @param string $md5Password hashed string of the password (using current hash function; MD5-named for historical reasons) @@ -790,6 +866,16 @@ class API extends \Piwik\Plugin\API { UsersManager::checkPasswordHash($md5Password, Piwik::translate('UsersManager_ExceptionPasswordMD5HashExpected')); - return md5($userLogin . $md5Password); + $user = $this->model->getUser($userLogin); + + if (!$this->password->verify($md5Password, $user['password'])) { + return md5($userLogin . microtime(true) . Common::generateUniqId()); + } + + if ($this->password->needsRehash($user['password'])) { + $this->updateUser($userLogin, $this->password->hash($md5Password)); + } + + return $user['token_auth']; } } |