update Piwik to version 2.16 (fixes #91)

This commit is contained in:
oliver 2016-04-10 18:55:57 +02:00
commit 47263617c5
70 changed files with 418860 additions and 226988 deletions

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -12,6 +12,7 @@ use Exception;
use Piwik\Access;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\Option;
use Piwik\Piwik;
@ -28,23 +29,31 @@ use Piwik\Tracker\Cache;
* Existing Permissions are listed given a login via "getSitesAccessFromUser", or a website ID via "getUsersAccessFromSite",
* or you can list all users and websites for a given permission via "getUsersSitesFromAccess". Permissions are set and updated
* via the method "setUserAccess".
* See also the documentation about <a href='http://piwik.org/docs/manage-users/' target='_blank'>Managing Users</a> in Piwik.
* See also the documentation about <a href='http://piwik.org/docs/manage-users/' rel='noreferrer' target='_blank'>Managing Users</a> in Piwik.
*/
class API extends \Piwik\Plugin\API
{
const OPTION_NAME_PREFERENCE_SEPARATOR = '_';
/**
* @var Model
*/
private $model;
/**
* @var UserAccessFilter
*/
private $userFilter;
const PREFERENCE_DEFAULT_REPORT = 'defaultReport';
const PREFERENCE_DEFAULT_REPORT_DATE = 'defaultReportDate';
static private $instance = null;
private static $instance = null;
protected function __construct()
public function __construct(Model $model, UserAccessFilter $filter)
{
$this->model = new Model();
$this->model = $model;
$this->userFilter = $filter;
}
/**
@ -52,24 +61,26 @@ class API extends \Piwik\Plugin\API
* Example of how you would overwrite the UsersManager_API with your own class:
* Call the following in your plugin __construct() for example:
*
* Registry::set('UsersManager_API', \Piwik\Plugins\MyCustomUsersManager\API::getInstance());
* StaticContainer::getContainer()->set('UsersManager_API', \Piwik\Plugins\MyCustomUsersManager\API::getInstance());
*
* @throws Exception
* @return \Piwik\Plugins\UsersManager\API
*/
static public function getInstance()
public static function getInstance()
{
try {
$instance = \Piwik\Registry::get('UsersManager_API');
$instance = StaticContainer::get('UsersManager_API');
if (!($instance instanceof API)) {
// Exception is caught below and corrected
throw new Exception('UsersManager_API must inherit API');
}
self::$instance = $instance;
} catch (Exception $e) {
self::$instance = new self;
\Piwik\Registry::set('UsersManager_API', self::$instance);
self::$instance = StaticContainer::get('Piwik\Plugins\UsersManager\API');
StaticContainer::getContainer()->set('UsersManager_API', self::$instance);
}
return self::$instance;
}
@ -96,16 +107,72 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$optionValue = Option::get($this->getPreferenceId($userLogin, $preferenceName));
$optionValue = $this->getPreferenceValue($userLogin, $preferenceName);
if ($optionValue !== false) {
return $optionValue;
}
return $this->getDefaultUserPreference($preferenceName, $userLogin);
}
/**
* Sets a user preference in the DB using the preference's default value.
* @param string $userLogin
* @param string $preferenceName
* @ignore
*/
public function initUserPreferenceWithDefault($userLogin, $preferenceName)
{
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$optionValue = $this->getPreferenceValue($userLogin, $preferenceName);
if ($optionValue === false) {
$defaultValue = $this->getDefaultUserPreference($preferenceName, $userLogin);
if ($defaultValue !== false) {
$this->setUserPreference($userLogin, $preferenceName, $defaultValue);
}
}
}
/**
* Returns an array of Preferences
* @param $preferenceNames array of preference names
* @return array
* @ignore
*/
public function getAllUsersPreferences(array $preferenceNames)
{
Piwik::checkUserHasSuperUserAccess();
$userPreferences = array();
foreach($preferenceNames as $preferenceName) {
$optionNameMatchAllUsers = $this->getPreferenceId('%', $preferenceName);
$preferences = Option::getLike($optionNameMatchAllUsers);
foreach($preferences as $optionName => $optionValue) {
$lastUnderscore = strrpos($optionName, self::OPTION_NAME_PREFERENCE_SEPARATOR);
$userName = substr($optionName, 0, $lastUnderscore);
$preference = substr($optionName, $lastUnderscore + 1);
$userPreferences[$userName][$preference] = $optionValue;
}
}
return $userPreferences;
}
private function getPreferenceId($login, $preference)
{
return $login . '_' . $preference;
if(false !== strpos($preference, self::OPTION_NAME_PREFERENCE_SEPARATOR)) {
throw new Exception("Preference name cannot contain underscores.");
}
return $login . self::OPTION_NAME_PREFERENCE_SEPARATOR . $preference;
}
private function getPreferenceValue($userLogin, $preferenceName)
{
return Option::get($this->getPreferenceId($userLogin, $preferenceName));
}
private function getDefaultUserPreference($preferenceName, $login)
@ -113,7 +180,10 @@ class API extends \Piwik\Plugin\API
switch ($preferenceName) {
case self::PREFERENCE_DEFAULT_REPORT:
$viewableSiteIds = \Piwik\Plugins\SitesManager\API::getInstance()->getSitesIdWithAtLeastViewAccess($login);
return reset($viewableSiteIds);
if (!empty($viewableSiteIds)) {
return reset($viewableSiteIds);
}
return false;
case self::PREFERENCE_DEFAULT_REPORT_DATE:
return Config::getInstance()->General['default_day'];
default:
@ -137,6 +207,7 @@ class API extends \Piwik\Plugin\API
}
$users = $this->model->getUsers($logins);
$users = $this->userFilter->filterUsers($users);
// Non Super user can only access login & alias
if (!Piwik::hasUserSuperUserAccess()) {
@ -157,7 +228,10 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSomeAdminAccess();
return $this->model->getUsersLogin();
$logins = $this->model->getUsersLogin();
$logins = $this->userFilter->filterLogins($logins);
return $logins;
}
/**
@ -180,7 +254,10 @@ class API extends \Piwik\Plugin\API
$this->checkAccessType($access);
return $this->model->getUsersSitesFromAccess($access);
$userSites = $this->model->getUsersSitesFromAccess($access);
$userSites = $this->userFilter->filterLoginIndexedArray($userSites);
return $userSites;
}
/**
@ -202,7 +279,10 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasAdminAccess($idSite);
return $this->model->getUsersAccessFromSite($idSite);
$usersAccess = $this->model->getUsersAccessFromSite($idSite);
$usersAccess = $this->userFilter->filterLoginIndexedArray($usersAccess);
return $usersAccess;
}
public function getUsersWithSiteAccess($idSite, $access)
@ -216,7 +296,9 @@ class API extends \Piwik\Plugin\API
return array();
}
$logins = $this->userFilter->filterLogins($logins);
$logins = implode(',', $logins);
return $this->getUsers($logins);
}
@ -240,13 +322,27 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccess();
$this->checkUserExists($userLogin);
$this->checkUserHasNotSuperUserAccess($userLogin);
// Super users have 'admin' access for every site
if (Piwik::hasTheUserSuperUserAccess($userLogin)) {
$return = array();
$siteManagerModel = new \Piwik\Plugins\SitesManager\Model();
$sites = $siteManagerModel->getAllSites();
foreach ($sites as $site) {
$return[] = array(
'site' => $site['idsite'],
'access' => 'admin'
);
}
return $return;
}
return $this->model->getSitesAccessFromUser($userLogin);
}
/**
* Returns the user information (login, password md5, alias, email, date_registered, etc.)
* Returns the user information (login, password hash, alias, email, date_registered, etc.)
*
* @param string $userLogin the user login
*
@ -257,11 +353,13 @@ class API extends \Piwik\Plugin\API
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$this->checkUserExists($userLogin);
return $this->model->getUser($userLogin);
$user = $this->model->getUser($userLogin);
return $this->userFilter->filterUser($user);
}
/**
* Returns the user information (login, password md5, alias, email, date_registered, etc.)
* Returns the user information (login, password hash, alias, email, date_registered, etc.)
*
* @param string $userEmail the user email
*
@ -272,7 +370,9 @@ class API extends \Piwik\Plugin\API
Piwik::checkUserHasSuperUserAccess();
$this->checkUserEmailExists($userEmail);
return $this->model->getUserByEmail($userEmail);
$user = $this->model->getUserByEmail($userEmail);
return $this->userFilter->filterUser($user);
}
private function checkLogin($userLogin)
@ -300,6 +400,7 @@ class API extends \Piwik\Plugin\API
if (empty($alias)) {
$alias = $userLogin;
}
return $alias;
}
@ -318,7 +419,7 @@ class API extends \Piwik\Plugin\API
*
* @exception in case of an invalid parameter
*/
public function addUser($userLogin, $password, $email, $alias = false)
public function addUser($userLogin, $password, $email, $alias = false, $_isPasswordHashed = false)
{
Piwik::checkUserHasSuperUserAccess();
@ -326,10 +427,16 @@ class API extends \Piwik\Plugin\API
$this->checkEmail($email);
$password = Common::unsanitizeInputValue($password);
UsersManager::checkPassword($password);
if (!$_isPasswordHashed) {
UsersManager::checkPassword($password);
$passwordTransformed = UsersManager::getPasswordHash($password);
} else {
$passwordTransformed = $password;
}
$alias = $this->getCleanAlias($alias, $userLogin);
$passwordTransformed = UsersManager::getPasswordHash($password);
$token_auth = $this->getTokenAuth($userLogin, $passwordTransformed);
@ -341,10 +448,10 @@ class API extends \Piwik\Plugin\API
/**
* Triggered after a new user is created.
*
*
* @param string $userLogin The new user's login handle.
*/
Piwik::postEvent('UsersManager.addUser.end', array($userLogin));
Piwik::postEvent('UsersManager.addUser.end', array($userLogin, $email, $password, $alias));
}
/**
@ -392,7 +499,17 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserIsNotAnonymous();
return $this->model->getUsersHavingSuperUserAccess();
$users = $this->model->getUsersHavingSuperUserAccess();
foreach($users as &$user) {
// remove token_auth in API response
unset($user['token_auth']);
}
// 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.
return $users;
}
/**
@ -409,6 +526,7 @@ class API extends \Piwik\Plugin\API
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$this->checkUserIsNotAnonymous($userLogin);
$userInfo = $this->getUser($userLogin);
$passwordHasBeenUpdated = false;
if (empty($password)) {
$password = $userInfo['password'];
@ -418,6 +536,8 @@ class API extends \Piwik\Plugin\API
UsersManager::checkPassword($password);
$password = UsersManager::getPasswordHash($password);
}
$passwordHasBeenUpdated = true;
}
if (empty($alias)) {
@ -432,7 +552,7 @@ class API extends \Piwik\Plugin\API
$this->checkEmail($email);
}
$alias = $this->getCleanAlias($alias, $userLogin);
$alias = $this->getCleanAlias($alias, $userLogin);
$token_auth = $this->getTokenAuth($userLogin, $password);
$this->model->updateUser($userLogin, $password, $email, $alias, $token_auth);
@ -441,10 +561,12 @@ class API extends \Piwik\Plugin\API
/**
* Triggered after an existing user has been updated.
*
* Event notify about password change.
*
* @param string $userLogin The user's login handle.
* @param boolean $passwordHasBeenUpdated Flag containing information about password change.
*/
Piwik::postEvent('UsersManager.updateUser.end', array($userLogin));
Piwik::postEvent('UsersManager.updateUser.end', array($userLogin, $passwordHasBeenUpdated, $email, $password, $alias));
}
/**
@ -460,6 +582,7 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccess();
$this->checkUserIsNotAnonymous($userLogin);
if (!$this->userExists($userLogin)) {
throw new Exception(Piwik::translate("UsersManager_ExceptionDeleteDoesNotExist", $userLogin));
}
@ -508,10 +631,32 @@ class API extends \Piwik\Plugin\API
public function userEmailExists($userEmail)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasSomeViewAccess();
return $this->model->userEmailExists($userEmail);
}
/**
* Returns the first login name of an existing user that has the given email address. If no user can be found for
* this user an error will be returned.
*
* @param string $userEmail
* @return bool true if the user is known
*/
public function getUserLoginFromUserEmail($userEmail)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasSomeAdminAccess();
$this->checkUserEmailExists($userEmail);
$user = $this->model->getUserByEmail($userEmail);
// any user with some admin access is allowed to find any user by email, no need to filter by access here
return $user['login'];
}
/**
* Set an access level to a given user for a list of websites ID.
*
@ -562,6 +707,12 @@ class API extends \Piwik\Plugin\API
// when no access are specified
if ($access != 'noaccess') {
$this->model->addUserAccess($userLogin, $access, $idSites);
} else {
if (!empty($idSites) && !is_array($idSites)) {
$idSites = array($idSites);
}
Piwik::postEvent('UsersManager.removeSiteAccess', array($userLogin, $idSites));
}
// we reload the access list which doesn't yet take in consideration this new user access
@ -632,15 +783,13 @@ class API extends \Piwik\Plugin\API
* Generates a unique MD5 for the given login & password
*
* @param string $userLogin Login
* @param string $md5Password MD5ied string of the password
* @throws Exception
* @param string $md5Password hashed string of the password (using current hash function; MD5-named for historical reasons)
* @return string
*/
public function getTokenAuth($userLogin, $md5Password)
{
if (strlen($md5Password) != 32) {
throw new Exception(Piwik::translate('UsersManager_ExceptionPasswordMD5HashExpected'));
}
UsersManager::checkPasswordHash($md5Password, Piwik::translate('UsersManager_ExceptionPasswordMD5HashExpected'));
return md5($userLogin . $md5Password);
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -9,24 +9,39 @@
namespace Piwik\Plugins\UsersManager;
use Exception;
use Piwik\API\Request;
use Piwik\API\ResponseBuilder;
use Piwik\Common;
use Piwik\Container\StaticContainer;
use Piwik\Metrics\Formatter;
use Piwik\NoAccessException;
use Piwik\Piwik;
use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Plugins\UsersManager\API as APIUsersManager;
use Piwik\Plugin\ControllerAdmin;
use Piwik\Plugins\LanguagesManager\API as APILanguagesManager;
use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\Plugins\Login\SessionInitializer;
use Piwik\Plugins\UsersManager\API as APIUsersManager;
use Piwik\SettingsPiwik;
use Piwik\Site;
use Piwik\Tracker\IgnoreCookie;
use Piwik\Translation\Translator;
use Piwik\Url;
use Piwik\View;
use Piwik\MetricsFormatter;
/**
*
*/
class Controller extends \Piwik\Plugin\ControllerAdmin
class Controller extends ControllerAdmin
{
/**
* @var Translator
*/
private $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
parent::__construct();
}
static function orderByName($a, $b)
{
return strcmp($a['name'], $b['name']);
@ -38,10 +53,11 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
function index()
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasSomeAdminAccess();
$view = new View('@UsersManager/index');
$IdSitesAdmin = APISitesManager::getInstance()->getSitesIdWithAdminAccess();
$IdSitesAdmin = Request::processRequest('SitesManager.getSitesIdWithAdminAccess');
$idSiteSelected = 1;
if (count($IdSitesAdmin) > 0) {
@ -51,15 +67,25 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
if ($idSiteSelected === 'all') {
$usersAccessByWebsite = array();
$defaultReportSiteName = Piwik::translate('UsersManager_ApplyToAllWebsites');
$defaultReportSiteName = $this->translator->translate('UsersManager_ApplyToAllWebsites');
} else {
$usersAccessByWebsite = APIUsersManager::getInstance()->getUsersAccessFromSite($idSiteSelected);
if (!Piwik::isUserHasAdminAccess($idSiteSelected) && count($IdSitesAdmin) > 0) {
// make sure to show a website where user actually has admin access
$idSiteSelected = $IdSitesAdmin[0];
}
$defaultReportSiteName = Site::getNameFor($idSiteSelected);
try {
$usersAccessByWebsite = Request::processRequest('UsersManager.getUsersAccessFromSite', array('idSite' => $idSiteSelected));
} catch (NoAccessException $e) {
return $this->noAdminAccessToWebsite($idSiteSelected, $defaultReportSiteName, $e->getMessage());
}
}
// we dont want to display the user currently logged so that the user can't change his settings from admin to view...
$currentlyLogged = Piwik::getCurrentUserLogin();
$usersLogin = APIUsersManager::getInstance()->getUsersLogin();
$usersLogin = Request::processRequest('UsersManager.getUsersLogin');
foreach ($usersLogin as $login) {
if (!isset($usersAccessByWebsite[$login])) {
$usersAccessByWebsite[$login] = 'noaccess';
@ -81,16 +107,18 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$superUsers = array();
$usersAliasByLogin = array();
$formatter = new Formatter();
if (Piwik::isUserHasSomeAdminAccess()) {
$view->showLastSeen = true;
$users = APIUsersManager::getInstance()->getUsers();
$users = Request::processRequest('UsersManager.getUsers');
foreach ($users as $index => $user) {
$usersAliasByLogin[$user['login']] = $user['alias'];
$lastSeen = LastSeenTimeLogger::getLastSeenTimeForUser($user['login']);
$users[$index]['last_seen'] = $lastSeen == 0
? false : MetricsFormatter::getPrettyTimeFromSeconds(time() - $lastSeen);
? false : $formatter->getPrettyTimeFromSeconds(time() - $lastSeen);
}
if (Piwik::hasUserSuperUserAccess()) {
@ -102,6 +130,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
}
}
$view->hasOnlyAdminAccess = Piwik::isUserHasSomeAdminAccess() && !Piwik::hasUserSuperUserAccess();
$view->anonymousHasViewAccess = $this->hasAnonymousUserViewAccess($usersAccessByWebsite);
$view->idSiteSelected = $idSiteSelected;
$view->defaultReportSiteName = $defaultReportSiteName;
@ -110,7 +139,8 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$view->usersAliasByLogin = $usersAliasByLogin;
$view->usersCount = count($users) - 1;
$view->usersAccessByWebsite = $usersAccessByWebsite;
$websites = APISitesManager::getInstance()->getSitesWithAdminAccess();
$websites = Request::processRequest('SitesManager.getSitesWithAdminAccess');
uasort($websites, array('Piwik\Plugins\UsersManager\Controller', 'orderByName'));
$view->websites = $websites;
$this->setBasicVariablesView($view);
@ -121,6 +151,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
private function hasAnonymousUserViewAccess($usersAccessByWebsite)
{
$anonymousHasViewAccess = false;
foreach ($usersAccessByWebsite as $login => $access) {
if ($login == 'anonymous'
&& $access != 'noaccess'
@ -128,6 +159,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$anonymousHasViewAccess = true;
}
}
return $anonymousHasViewAccess;
}
@ -142,6 +174,59 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
return APIUsersManager::getInstance()->getUserPreference($user, APIUsersManager::PREFERENCE_DEFAULT_REPORT_DATE);
}
/**
* Returns the enabled dates that users can select,
* in their User Settings page "Report date to load by default"
*
* @throws
* @return array
*/
protected function getDefaultDates()
{
$dates = array(
'today' => $this->translator->translate('Intl_Today'),
'yesterday' => $this->translator->translate('Intl_Yesterday'),
'previous7' => $this->translator->translate('General_PreviousDays', 7),
'previous30' => $this->translator->translate('General_PreviousDays', 30),
'last7' => $this->translator->translate('General_LastDays', 7),
'last30' => $this->translator->translate('General_LastDays', 30),
'week' => $this->translator->translate('General_CurrentWeek'),
'month' => $this->translator->translate('General_CurrentMonth'),
'year' => $this->translator->translate('General_CurrentYear'),
);
$mappingDatesToPeriods = array(
'today' => 'day',
'yesterday' => 'day',
'previous7' => 'range',
'previous30' => 'range',
'last7' => 'range',
'last30' => 'range',
'week' => 'week',
'month' => 'month',
'year' => 'year',
);
// assertion
if (count($dates) != count($mappingDatesToPeriods)) {
throw new Exception("some metadata is missing in getDefaultDates()");
}
$allowedPeriods = self::getEnabledPeriodsInUI();
$allowedDates = array_intersect($mappingDatesToPeriods, $allowedPeriods);
$dates = array_intersect_key($dates, $allowedDates);
/**
* Triggered when the list of available dates is requested, for example for the
* User Settings > Report date to load by default.
*
* @param array &$dates Array of (date => translation)
*/
Piwik::postEvent('UsersManager.getDefaultDates', array(&$dates));
return $dates;
}
/**
* The "User Settings" admin UI screen view
*/
@ -152,50 +237,71 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$view = new View('@UsersManager/userSettings');
$userLogin = Piwik::getCurrentUserLogin();
$user = APIUsersManager::getInstance()->getUser($userLogin);
$user = Request::processRequest('UsersManager.getUser', array('userLogin' => $userLogin));
$view->userAlias = $user['alias'];
$view->userEmail = $user['email'];
$defaultReport = APIUsersManager::getInstance()->getUserPreference($userLogin, APIUsersManager::PREFERENCE_DEFAULT_REPORT);
$view->ignoreSalt = $this->getIgnoreCookieSalt();
$userPreferences = new UserPreferences();
$defaultReport = $userPreferences->getDefaultReport();
if ($defaultReport === false) {
$defaultReport = $this->getDefaultWebsiteId();
$defaultReport = $userPreferences->getDefaultWebsiteId();
}
$view->defaultReport = $defaultReport;
if ($defaultReport == 'MultiSites') {
$view->defaultReportSiteName = Site::getNameFor($this->getDefaultWebsiteId());
$defaultSiteId = $userPreferences->getDefaultWebsiteId();
$view->defaultReportIdSite = $defaultSiteId;
$view->defaultReportSiteName = Site::getNameFor($defaultSiteId);
} else {
$view->defaultReportIdSite = $defaultReport;
$view->defaultReportSiteName = Site::getNameFor($defaultReport);
}
$view->defaultDate = $this->getDefaultDateForUser($userLogin);
$view->availableDefaultDates = array(
'today' => Piwik::translate('General_Today'),
'yesterday' => Piwik::translate('General_Yesterday'),
'previous7' => Piwik::translate('General_PreviousDays', 7),
'previous30' => Piwik::translate('General_PreviousDays', 30),
'last7' => Piwik::translate('General_LastDays', 7),
'last30' => Piwik::translate('General_LastDays', 30),
'week' => Piwik::translate('General_CurrentWeek'),
'month' => Piwik::translate('General_CurrentMonth'),
'year' => Piwik::translate('General_CurrentYear'),
);
$view->availableDefaultDates = $this->getDefaultDates();
$view->languages = APILanguagesManager::getInstance()->getAvailableLanguageNames();
$view->currentLanguageCode = LanguagesManager::getLanguageCodeForCurrentUser();
$view->currentTimeformat = LanguagesManager::uses12HourClockForCurrentUser();
$view->ignoreCookieSet = IgnoreCookie::isIgnoreCookieFound();
$this->initViewAnonymousUserSettings($view);
$view->piwikHost = Url::getCurrentHost();
$this->setBasicVariablesView($view);
return $view->render();
}
/**
* The "Anonymous Settings" admin UI screen view
*/
public function anonymousSettings()
{
Piwik::checkUserHasSuperUserAccess();
$view = new View('@UsersManager/anonymousSettings');
$view->availableDefaultDates = $this->getDefaultDates();
$this->initViewAnonymousUserSettings($view);
$this->setBasicVariablesView($view);
return $view->render();
}
public function setIgnoreCookie()
{
Piwik::checkUserHasSomeViewAccess();
Piwik::checkUserIsNotAnonymous();
$this->checkTokenInUrl();
$salt = Common::getRequestVar('ignoreSalt', false, 'string');
if ($salt !== $this->getIgnoreCookieSalt()) {
throw new Exception("Not authorized");
}
IgnoreCookie::setIgnoreCookie();
Piwik::redirectToModule('UsersManager', 'userSettings', array('token_auth' => false));
@ -213,11 +319,13 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$userLogin = 'anonymous';
// Which websites are available to the anonymous users?
$anonymousSitesAccess = APIUsersManager::getInstance()->getSitesAccessFromUser($userLogin);
$anonymousSitesAccess = Request::processRequest('UsersManager.getSitesAccessFromUser', array('userLogin' => $userLogin));
$anonymousSites = array();
foreach ($anonymousSitesAccess as $info) {
$idSite = $info['site'];
$site = APISitesManager::getInstance()->getSiteFromId($idSite);
$site = Request::processRequest('SitesManager.getSiteFromId', array('idSite' => $idSite));
// Work around manual website deletion
if (!empty($site)) {
$anonymousSites[$idSite] = $site;
@ -226,7 +334,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$view->anonymousSites = $anonymousSites;
// Which report is displayed by default to the anonymous user?
$anonymousDefaultReport = APIUsersManager::getInstance()->getUserPreference($userLogin, APIUsersManager::PREFERENCE_DEFAULT_REPORT);
$anonymousDefaultReport = Request::processRequest('UsersManager.getUserPreference', array('userLogin' => $userLogin, 'preferenceName' => APIUsersManager::PREFERENCE_DEFAULT_REPORT));
if ($anonymousDefaultReport === false) {
if (empty($anonymousSites)) {
$anonymousDefaultReport = Piwik::getLoginPluginName();
@ -283,12 +391,14 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$defaultReport = Common::getRequestVar('defaultReport');
$defaultDate = Common::getRequestVar('defaultDate');
$language = Common::getRequestVar('language');
$timeFormat = Common::getRequestVar('timeformat');
$userLogin = Piwik::getCurrentUserLogin();
$this->processPasswordChange($userLogin);
LanguagesManager::setLanguageForSession($language);
APILanguagesManager::getInstance()->setLanguageForUser($userLogin, $language);
APILanguagesManager::getInstance()->set12HourClockForUser($userLogin, $timeFormat);
APIUsersManager::getInstance()->setUserPreference($userLogin,
APIUsersManager::PREFERENCE_DEFAULT_REPORT,
@ -304,6 +414,18 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
return $toReturn;
}
private function noAdminAccessToWebsite($idSiteSelected, $defaultReportSiteName, $message)
{
$view = new View('@UsersManager/noWebsiteAdminAccess');
$view->idSiteSelected = $idSiteSelected;
$view->defaultReportSiteName = $defaultReportSiteName;
$view->message = $message;
$this->setBasicVariablesView($view);
return $view->render();
}
private function processPasswordChange($userLogin)
{
$alias = Common::getRequestVar('alias');
@ -315,7 +437,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
|| !empty($passwordBis)
) {
if ($password != $passwordBis) {
throw new Exception(Piwik::translate('Login_PasswordsDoNotMatch'));
throw new Exception($this->translator->translate('Login_PasswordsDoNotMatch'));
}
$newPassword = $password;
}
@ -334,7 +456,19 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
// logs the user in with the new password
if ($newPassword !== false) {
\Piwik\Registry::get('auth')->initSession($userLogin, md5($newPassword), $rememberMe = false);
$sessionInitializer = new SessionInitializer();
$auth = StaticContainer::get('Piwik\Auth');
$auth->setLogin($userLogin);
$auth->setPassword($password);
$sessionInitializer->initSession($auth, $rememberMe = false);
}
}
/**
* @return string
*/
private function getIgnoreCookieSalt()
{
return md5(SettingsPiwik::getSalt());
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\UsersManager;
use Piwik\Piwik;
use Piwik\Common;
use Piwik\Option;
use Piwik\Piwik;
/**
* Class that logs the time the current user is accessing the current resource (which
@ -35,7 +35,6 @@ class LastSeenTimeLogger
public function logCurrentUserLastSeenTime()
{
$module = Common::getRequestVar('module', false);
$action = Common::getRequestVar('action', false);
$currentUserLogin = Piwik::getCurrentUserLogin();
// only log time for non-anonymous visits to the reporting UI

View file

@ -0,0 +1,34 @@
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\UsersManager;
use Piwik\Menu\MenuAdmin;
use Piwik\Menu\MenuUser;
use Piwik\Piwik;
class Menu extends \Piwik\Plugin\Menu
{
public function configureAdminMenu(MenuAdmin $menu)
{
if (Piwik::isUserHasSomeAdminAccess()) {
$menu->addManageItem('UsersManager_MenuUsers', $this->urlForAction('index'), $order = 2);
}
if (Piwik::hasUserSuperUserAccess() && API::getInstance()->getSitesAccessFromUser('anonymous')) {
$menu->addSettingsItem('UsersManager_AnonymousUser', $this->urlForAction('anonymousSettings'), $order = 20);
}
}
public function configureUserMenu(MenuUser $menu)
{
if (!Piwik::isUserIsAnonymous()) {
$menu->addItem('UsersManager_MenuPersonal', 'General_Settings', $this->urlForAction('userSettings'), 0);
}
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -22,10 +22,18 @@ use Piwik\Piwik;
* Existing Permissions are listed given a login via "getSitesAccessFromUser", or a website ID via "getUsersAccessFromSite",
* or you can list all users and websites for a given permission via "getUsersSitesFromAccess". Permissions are set and updated
* via the method "setUserAccess".
* See also the documentation about <a href='http://piwik.org/docs/manage-users/' target='_blank'>Managing Users</a> in Piwik.
* See also the documentation about <a href='http://piwik.org/docs/manage-users/' rel='noreferrer' target='_blank'>Managing Users</a> in Piwik.
*/
class Model
{
private static $rawPrefix = 'user';
private $table;
public function __construct()
{
$this->table = Common::prefixTable(self::$rawPrefix);
}
/**
* Returns the list of all the users
*
@ -39,13 +47,12 @@ class Model
if (!empty($userLogins)) {
$where = 'WHERE login IN (' . Common::getSqlStringFieldsArray($userLogins) . ')';
$bind = $userLogins;
$bind = $userLogins;
}
$users = Db::get()->fetchAll("SELECT *
FROM " . Common::prefixTable("user") . "
$where
ORDER BY login ASC", $bind);
$users = $this->getDb()->fetchAll("SELECT * FROM " . $this->table . "
$where
ORDER BY login ASC", $bind);
return $users;
}
@ -57,23 +64,21 @@ class Model
*/
public function getUsersLogin()
{
$users = Db::get()->fetchAll("SELECT login
FROM " . Common::prefixTable("user") . "
ORDER BY login ASC");
$users = $this->getDb()->fetchAll("SELECT login FROM " . $this->table . " ORDER BY login ASC");
$return = array();
foreach ($users as $login) {
$return[] = $login['login'];
}
return $return;
}
public function getUsersSitesFromAccess($access)
{
$users = Db::get()->fetchAll("SELECT login,idsite
FROM " . Common::prefixTable("access")
. " WHERE access = ?
ORDER BY login, idsite", $access);
$users = $this->getDb()->fetchAll("SELECT login,idsite FROM " . Common::prefixTable("access")
. " WHERE access = ?
ORDER BY login, idsite", $access);
$return = array();
foreach ($users as $user) {
@ -85,9 +90,8 @@ class Model
public function getUsersAccessFromSite($idSite)
{
$users = Db::get()->fetchAll("SELECT login,access
FROM " . Common::prefixTable("access")
. " WHERE idsite = ?", $idSite);
$users = $this->getDb()->fetchAll("SELECT login,access FROM " . Common::prefixTable("access")
. " WHERE idsite = ?", $idSite);
$return = array();
foreach ($users as $user) {
@ -99,9 +103,9 @@ class Model
public function getUsersLoginWithSiteAccess($idSite, $access)
{
$users = Db::get()->fetchAll("SELECT login
FROM " . Common::prefixTable("access")
. " WHERE idsite = ? AND access = ?", array($idSite, $access));
$users = $this->getDb()->fetchAll("SELECT login
FROM " . Common::prefixTable("access")
. " WHERE idsite = ? AND access = ?", array($idSite, $access));
$logins = array();
foreach ($users as $user) {
@ -129,9 +133,8 @@ class Model
*/
public function getSitesAccessFromUser($userLogin)
{
$users = Db::get()->fetchAll("SELECT idsite,access
FROM " . Common::prefixTable("access")
. " WHERE login = ?", $userLogin);
$users = $this->getDb()->fetchAll("SELECT idsite,access FROM " . Common::prefixTable("access")
. " WHERE login = ?", $userLogin);
$return = array();
foreach ($users as $user) {
@ -146,23 +149,30 @@ class Model
public function getUser($userLogin)
{
return Db::get()->fetchRow("SELECT *
FROM " . Common::prefixTable("user")
. " WHERE login = ?", $userLogin);
$db = $this->getDb();
$matchedUsers = $db->fetchAll("SELECT * FROM " . $this->table . " WHERE login = ?", $userLogin);
// for BC in 2.15 LTS, if there is a user w/ an exact match to the requested login, return that user.
// this is done since before this change, login was case sensitive. until 3.0, we want to maintain
// this behavior.
foreach ($matchedUsers as $user) {
if ($user['login'] == $userLogin) {
return $user;
}
}
return reset($matchedUsers);
}
public function getUserByEmail($userEmail)
{
return Db::get()->fetchRow("SELECT *
FROM " . Common::prefixTable("user")
. " WHERE email = ?", $userEmail);
return $this->getDb()->fetchRow("SELECT * FROM " . $this->table . " WHERE email = ?", $userEmail);
}
public function getUserByTokenAuth($tokenAuth)
{
return Db::get()->fetchRow('SELECT *
FROM ' . Common::prefixTable('user') . '
WHERE token_auth = ?', $tokenAuth);
return $this->getDb()->fetchRow('SELECT * FROM ' . $this->table . ' WHERE token_auth = ?', $tokenAuth);
}
public function addUser($userLogin, $passwordTransformed, $email, $alias, $tokenAuth, $dateRegistered)
@ -177,12 +187,12 @@ class Model
'superuser_access' => 0
);
Db::get()->insert(Common::prefixTable("user"), $user);
$this->getDb()->insert($this->table, $user);
}
public function setSuperUserAccess($userLogin, $hasSuperUserAccess)
{
Db::get()->update(Common::prefixTable("user"),
$this->getDb()->update($this->table,
array(
'superuser_access' => $hasSuperUserAccess ? 1 : 0
),
@ -190,19 +200,24 @@ class Model
);
}
/**
* Note that this returns the token_auth which is as private as the password!
*
* @return array[] containing login, email and token_auth
*/
public function getUsersHavingSuperUserAccess()
{
$users = Db::get()->fetchAll("SELECT login, email
FROM " . Common::prefixTable("user") . "
WHERE superuser_access = 1
ORDER BY date_registered ASC");
$users = $this->getDb()->fetchAll("SELECT login, email, token_auth
FROM " . Common::prefixTable("user") . "
WHERE superuser_access = 1
ORDER BY date_registered ASC");
return $users;
}
public function updateUser($userLogin, $password, $email, $alias, $tokenAuth)
{
Db::get()->update(Common::prefixTable("user"),
$this->getDb()->update($this->table,
array(
'password' => $password,
'alias' => $alias,
@ -215,24 +230,22 @@ class Model
public function userExists($userLogin)
{
$count = Db::get()->fetchOne("SELECT count(*)
FROM " . Common::prefixTable("user") . "
WHERE login = ?", $userLogin);
$count = $this->getDb()->fetchOne("SELECT count(*) FROM " . $this->table . " WHERE login = ?", $userLogin);
return $count != 0;
}
public function userEmailExists($userEmail)
{
$count = Db::get()->fetchOne("SELECT count(*)
FROM " . Common::prefixTable("user") . "
WHERE email = ?", $userEmail);
$count = $this->getDb()->fetchOne("SELECT count(*) FROM " . $this->table . " WHERE email = ?", $userEmail);
return $count != 0;
}
public function addUserAccess($userLogin, $access, $idSites)
{
foreach ($idSites as $idsite) {
Db::get()->insert(Common::prefixTable("access"),
$this->getDb()->insert(Common::prefixTable("access"),
array("idsite" => $idsite,
"login" => $userLogin,
"access" => $access)
@ -242,7 +255,7 @@ class Model
public function deleteUserOnly($userLogin)
{
Db::get()->query("DELETE FROM " . Common::prefixTable("user") . " WHERE login = ?", $userLogin);
$this->getDb()->query("DELETE FROM " . $this->table . " WHERE login = ?", $userLogin);
/**
* Triggered after a user has been deleted.
@ -258,12 +271,12 @@ class Model
public function deleteUserAccess($userLogin, $idSites = null)
{
if (is_null($idSites)) {
Db::get()->query("DELETE FROM " . Common::prefixTable("access") .
$this->getDb()->query("DELETE FROM " . Common::prefixTable("access") .
" WHERE login = ?",
array($userLogin));
} else {
foreach ($idSites as $idsite) {
Db::get()->query("DELETE FROM " . Common::prefixTable("access") .
$this->getDb()->query("DELETE FROM " . Common::prefixTable("access") .
" WHERE idsite = ? AND login = ?",
array($idsite, $userLogin)
);
@ -271,4 +284,9 @@ class Model
}
}
private function getDb()
{
return Db::get();
}
}

View file

@ -0,0 +1,49 @@
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\UsersManager;
use Piwik\Access;
class Tasks extends \Piwik\Plugin\Tasks
{
/**
* @var Model
*/
private $usersModel;
/**
* @param API
*/
private $usersManagerApi;
public function __construct(Model $usersModel, API $usersManagerApi)
{
$this->usersModel = $usersModel;
$this->usersManagerApi = $usersManagerApi;
}
public function schedule()
{
$this->daily("setUserDefaultReportPreference");
}
public function setUserDefaultReportPreference()
{
// We initialize the default report user preference for each user (if it hasn't been inited before) for performance,
// doing this lets us avoid loading all siteIds (which can be 50k or more) when this preference is requested.
// getting the user preference can be called quite often when generating links etc (to get defaultWebsiteId).
$usersModel = $this->usersModel;
$usersManagerApi = $this->usersManagerApi;
Access::getInstance()->doAsSuperUser(function () use ($usersModel, $usersManagerApi) {
$allUsers = $usersModel->getUsers(array());
foreach ($allUsers as $user) {
$usersManagerApi->initUserPreferenceWithDefault($user['login'], API::PREFERENCE_DEFAULT_REPORT);
}
});
}
}

View file

@ -0,0 +1,183 @@
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\UsersManager;
use Piwik\Access;
/**
* This class offers methods to filter a list of users, logins, or anything that is related to users/logins.
*
* * By default a super user is allowed to see all users.
* * A user having admin access is allowed to see all other users that have view or admin access to the same access.
* * A user not having any admin access is only allowed to see the own user.
*
* The methods in this class make sure to only return the data for logins / users the current user actually has
* permission to see.
*
* FYI: The anonymous user is not treated in any special way. The anonymous user is a regular user with no access or
* view access only and can only see itself.
*/
class UserAccessFilter
{
/**
* @var Model
*/
private $model;
/**
* @var Access
*/
private $access;
/**
* Holds a list of all idSites the current user has view access to. Only used for caching.
* @var array
*/
private $idSitesWithAdmin;
/**
* Holds a list of all user logins that have admin access. Only used for caching
* @var array Array ('loginName' => array(idsites...))
*/
private $usersWithAdminAccess;
/**
* Holds a list of all user logins that have view access. Only used for caching
* @var array Array ('loginName' => array(idsites...))
*/
private $usersWithViewAccess;
public function __construct(Model $model, Access $access)
{
$this->model = $model;
$this->access = $access;
}
/**
* Removes all array values where the current user has no permission to see the existence of a given login index/key.
* @param array $arrayIndexedByLogin An array that is indexed by login / usernames. Eg:
* array('username1' => 5, 'username2' => array(...), ...)
* @return array
*/
public function filterLoginIndexedArray($arrayIndexedByLogin)
{
if ($this->access->hasSuperUserAccess()) {
return $arrayIndexedByLogin; // this part is not needed but makes it faster for super user.
}
$allowedLogins = $this->filterLogins(array_keys($arrayIndexedByLogin));
return array_intersect_key($arrayIndexedByLogin, array_flip($allowedLogins));
}
/**
* Removes all users from the list of the given users where the current user has no permission to see the existence
* of that other user.
* @param array $users An array of arrays. Each inner array must have a key 'login'. Eg:
* array(array('login' => 'username1'), array('login' => 'username2'), ...)
* @return array
*/
public function filterUsers($users)
{
if ($this->access->hasSuperUserAccess()) {
return $users;
}
if (!$this->access->isUserHasSomeAdminAccess()) {
// keep only own user if it is in the list
foreach ($users as $user) {
if ($this->isOwnLogin($user['login'])) {
return array($user);
}
}
return array();
}
foreach ($users as $index => $user) {
if (!$this->isNonSuperUserAllowedToSeeThisLogin($user['login'])) {
unset($users[$index]);
}
}
return array_values($users);
}
/**
* Returns the given user only if the current user has permission to see the given user
* @param array $user An array containing a key 'login'
* @return bool
*/
public function filterUser($user)
{
if ($this->access->hasSuperUserAccess() || $this->isNonSuperUserAllowedToSeeThisLogin($user['login'])) {
return $user;
}
}
/**
* Removes all logins from the list of logins where the current user has no permission to see them.
*
* @param string[] $logins An array of logins / usernames. Eg array('username1', 'username2')
* @return array
*/
public function filterLogins($logins)
{
if ($this->access->hasSuperUserAccess()) {
return $logins;
}
if (!$this->access->isUserHasSomeAdminAccess()) {
// keep only own user if it is in the list
foreach ($logins as $login) {
if ($this->isOwnLogin($login)) {
return array($login);
}
}
return array();
}
foreach ($logins as $index => $login) {
if (!$this->isNonSuperUserAllowedToSeeThisLogin($login)) {
unset($logins[$index]);
}
}
return array_values($logins);
}
protected function isNonSuperUserAllowedToSeeThisLogin($login)
{
// we do not test for super user access here for better performance as we would otherwise test for access for
// each single login in the other calling methods.
return $this->hasAccessToSameSite($login) || $this->isOwnLogin($login);
}
private function isOwnLogin($login)
{
return $login === $this->access->getLogin();
}
private function hasAccessToSameSite($login)
{
// users is allowed to see other users having view or admin access to these sites
if (!isset($this->idSitesWithAdmin)) {
$this->idSitesWithAdmin = $this->access->getSitesIdWithAdminAccess();
$this->usersWithAdminAccess = $this->model->getUsersSitesFromAccess('admin');
$this->usersWithViewAccess = $this->model->getUsersSitesFromAccess('view');
}
return (
(isset($this->usersWithViewAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithViewAccess[$login]))
||
(isset($this->usersWithAdminAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithAdminAccess[$login]))
);
}
}

View file

@ -0,0 +1,172 @@
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\UsersManager;
use Piwik\Config;
use Piwik\Period\PeriodValidator;
use Piwik\Piwik;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Plugins\UsersManager\API as APIUsersManager;
class UserPreferences
{
/**
* @var APIUsersManager
*/
private $api;
public function __construct()
{
$this->api = APIUsersManager::getInstance();
}
/**
* Returns default site ID that Piwik should load.
*
* _Note: This value is a Piwik setting set by each user._
*
* @return bool|int
* @api
*/
public function getDefaultWebsiteId()
{
$defaultReport = $this->getDefaultReport();
if (is_numeric($defaultReport) && Piwik::isUserHasViewAccess($defaultReport)) {
return $defaultReport;
}
$sitesId = APISitesManager::getInstance()->getSitesIdWithAtLeastViewAccess();
if (!empty($sitesId)) {
return $sitesId[0];
}
return false;
}
/**
* Returns default site ID that Piwik should load.
*
* _Note: This value is a Piwik setting set by each user._
*
* @return bool|int
* @api
*/
public function getDefaultReport()
{
// User preference: default website ID to load
$defaultReport = $this->api->getUserPreference(Piwik::getCurrentUserLogin(), APIUsersManager::PREFERENCE_DEFAULT_REPORT);
if (!is_numeric($defaultReport)) {
return $defaultReport;
}
if ($defaultReport && Piwik::isUserHasViewAccess($defaultReport)) {
return $defaultReport;
}
return false;
}
/**
* Returns default date for Piwik reports.
*
* _Note: This value is a Piwik setting set by each user._
*
* @return string `'today'`, `'2010-01-01'`, etc.
* @api
*/
public function getDefaultDate()
{
list($defaultDate, $defaultPeriod) = $this->getDefaultDateAndPeriod();
return $defaultDate;
}
/**
* Returns default period type for Piwik reports.
*
* @param string $defaultDate the default date string from which the default period will be guessed
* @return string `'day'`, `'week'`, `'month'`, `'year'` or `'range'`
* @api
*/
public function getDefaultPeriod($defaultDate = null)
{
list($defaultDate, $defaultPeriod) = $this->getDefaultDateAndPeriod($defaultDate);
return $defaultPeriod;
}
private function getDefaultDateAndPeriod($defaultDate = null)
{
$defaultPeriod = $this->getDefaultPeriodWithoutValidation($defaultDate);
if (! $defaultDate) {
$defaultDate = $this->getDefaultDateWithoutValidation();
}
$periodValidator = new PeriodValidator();
if (! $periodValidator->isPeriodAllowedForUI($defaultPeriod)) {
$defaultDate = $this->getSystemDefaultDate();
$defaultPeriod = $this->getSystemDefaultPeriod();
}
return array($defaultDate, $defaultPeriod);
}
public function getDefaultDateWithoutValidation()
{
// NOTE: a change in this function might mean a change in plugins/UsersManager/javascripts/usersSettings.js as well
$userSettingsDate = $this->api->getUserPreference(Piwik::getCurrentUserLogin(), APIUsersManager::PREFERENCE_DEFAULT_REPORT_DATE);
if ($userSettingsDate == 'yesterday') {
return $userSettingsDate;
}
// if last7, last30, etc.
if (strpos($userSettingsDate, 'last') === 0
|| strpos($userSettingsDate, 'previous') === 0
) {
return $userSettingsDate;
}
return 'today';
}
public function getDefaultPeriodWithoutValidation($defaultDate = null)
{
if (empty($defaultDate)) {
$defaultDate = $this->api->getUserPreference(Piwik::getCurrentUserLogin(), APIUsersManager::PREFERENCE_DEFAULT_REPORT_DATE);
}
if (empty($defaultDate)) {
return $this->getSystemDefaultPeriod();
}
if (in_array($defaultDate, array('today', 'yesterday'))) {
return 'day';
}
if (strpos($defaultDate, 'last') === 0
|| strpos($defaultDate, 'previous') === 0
) {
return 'range';
}
return $defaultDate;
}
private function getSystemDefaultDate()
{
return Config::getInstance()->General['default_day'];
}
private function getSystemDefaultPeriod()
{
return Config::getInstance()->General['default_period'];
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -10,7 +10,6 @@ namespace Piwik\Plugins\UsersManager;
use Exception;
use Piwik\Db;
use Piwik\Menu\MenuAdmin;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\SettingsPiwik;
@ -22,21 +21,21 @@ use Piwik\SettingsPiwik;
class UsersManager extends \Piwik\Plugin
{
const PASSWORD_MIN_LENGTH = 6;
const PASSWORD_MAX_LENGTH = 26;
const PASSWORD_MAX_LENGTH = 80;
/**
* @see Piwik\Plugin::getListHooksRegistered
* @see Piwik\Plugin::registerEvents
*/
public function getListHooksRegistered()
public function registerEvents()
{
return array(
'Menu.Admin.addItems' => 'addMenu',
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'SitesManager.deleteSite.end' => 'deleteSite',
'Tracker.Cache.getSiteAttributes' => 'recordAdminUsersInCache',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'Platform.initialized' => 'onPlatformInitialized'
'Platform.initialized' => 'onPlatformInitialized',
'CronArchive.getTokenAuth' => 'getCronArchiveTokenAuth'
);
}
@ -64,9 +63,20 @@ class UsersManager extends \Piwik\Plugin
foreach ($users as $user) {
$tokens[] = $user['token_auth'];
}
$attributes['admin_token_auth'] = $tokens;
}
public function getCronArchiveTokenAuth(&$tokens)
{
$model = new Model();
$superUsers = $model->getUsersHavingSuperUserAccess();
foreach($superUsers as $superUser) {
$tokens[] = $superUser['token_auth'];
}
}
/**
* Delete user preferences associated with a particular site
*/
@ -84,31 +94,17 @@ class UsersManager extends \Piwik\Plugin
{
$jsFiles[] = "plugins/UsersManager/javascripts/usersManager.js";
$jsFiles[] = "plugins/UsersManager/javascripts/usersSettings.js";
$jsFiles[] = "plugins/UsersManager/javascripts/giveViewAccess.js";
}
/**
* Get CSS files
*/
function getStylesheetFiles(&$stylesheets)
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/UsersManager/stylesheets/usersManager.less";
}
/**
* Add admin menu items
*/
function addMenu()
{
MenuAdmin::getInstance()->add('CoreAdminHome_MenuManage', 'UsersManager_MenuUsers',
array('module' => 'UsersManager', 'action' => 'index'),
Piwik::isUserHasSomeAdminAccess(),
$order = 2);
MenuAdmin::getInstance()->add('CoreAdminHome_MenuManage', 'UsersManager_MenuUserSettings',
array('module' => 'UsersManager', 'action' => 'userSettings'),
Piwik::isUserHasSomeViewAccess(),
$order = 3);
}
/**
* Returns true if the password is complex enough (at least 6 characters and max 26 characters)
*
@ -122,15 +118,35 @@ class UsersManager extends \Piwik\Plugin
) {
return true;
}
$l = strlen($input);
return $l >= self::PASSWORD_MIN_LENGTH && $l <= self::PASSWORD_MAX_LENGTH;
}
public static function checkPassword($password)
{
/**
* Triggered before core password validator check password.
*
* This event exists for enable option to create custom password validation rules.
* It can be used to validate password (length, used chars etc) and to notify about checking password.
*
* **Example**
*
* Piwik::addAction('UsersManager.checkPassword', function ($password) {
* if (strlen($password) < 10) {
* throw new Exception('Password is too short.');
* }
* });
*
* @param string $password Checking password in plain text.
*/
Piwik::postEvent('UsersManager.checkPassword', array($password));
if (!self::isValidPasswordString($password)) {
throw new Exception(Piwik::translate('UsersManager_ExceptionInvalidPassword', array(self::PASSWORD_MIN_LENGTH,
self::PASSWORD_MAX_LENGTH)));
self::PASSWORD_MAX_LENGTH)));
}
}
@ -141,6 +157,20 @@ class UsersManager extends \Piwik\Plugin
return md5($password);
}
/**
* Checks the password hash length. Used as a sanity check.
*
* @param string $passwordHash The password hash to check.
* @param string $exceptionMessage Message of the exception thrown.
* @throws Exception if the password hash length is incorrect.
*/
public static function checkPasswordHash($passwordHash, $exceptionMessage)
{
if (strlen($passwordHash) != 32) { // MD5 hash length
throw new Exception($exceptionMessage);
}
}
public function getClientSideTranslationKeys(&$translationKeys)
{
$translationKeys[] = "General_OrCancel";
@ -150,5 +180,7 @@ class UsersManager extends \Piwik\Plugin
$translationKeys[] = "UsersManager_ConfirmGrantSuperUserAccess";
$translationKeys[] = "UsersManager_ConfirmProhibitOtherUsersSuperUserAccess";
$translationKeys[] = "UsersManager_ConfirmProhibitMySuperUserAccess";
$translationKeys[] = "UsersManager_ExceptionUserHasViewAccessAlready";
$translationKeys[] = "UsersManager_ExceptionNoValueForUsernameOrEmail";
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,176 @@
/*!
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
$(document).ready(function () {
function hideLoading()
{
$('#giveUserAccessToViewReports').prop('disabled', false);
$('#ajaxLoadingGiveViewAccess').hide();
}
function showLoading()
{
$('#giveUserAccessToViewReports').prop('disabled', true);
$('#ajaxLoadingGiveViewAccess').show();
}
function showErrorNotification(errorMessage)
{
var placeAt = '#ajaxErrorGiveViewAccess';
$(placeAt).show();
var UI = require('piwik/UI');
var notification = new UI.Notification();
notification.show(errorMessage, {
placeat: placeAt,
context: 'error',
id: 'ajaxHelper',
type: null
});
notification.scrollToNotification();
hideLoading();
}
function createNewAjaxHelper()
{
var ajaxHandler = new ajaxHelper();
ajaxHandler.setCompleteCallback(function (xhr, status) {
if (xhr &&
xhr.responseJSON &&
xhr.responseJSON.message &&
xhr.responseJSON.result &&
xhr.responseJSON.result == 'error') {
hideLoading();
}
if (status && String(status).toLowerCase() !== 'sucess') {
hideLoading();
}
});
ajaxHandler.addParams({
module: 'API',
format: 'json'
}, 'GET');
ajaxHandler.setErrorElement('#ajaxErrorGiveViewAccess');
return ajaxHandler;
}
function sendViewAccess(userLogin)
{
sendUpdateUserAccess(userLogin, 'view', function () { window.location.reload(); });
setTimeout(hideLoading, 250);
// we hide loading after a bit since we cannot influence the ajax request in case of any error
}
function setViewAccessForUserToAllWebsitesIfUserConfirms(userLogin)
{
// ask confirmation
$('#confirm').find('#login').text(userLogin);
function onValidate() {
sendViewAccess(userLogin);
}
piwikHelper.modalConfirm('#confirm', {yes: onValidate, no: hideLoading})
}
function setViewAccessForUserIfNotAlreadyHasAccess(userLogin, idSites)
{
var ajaxHandler = createNewAjaxHelper();
ajaxHandler.addParams({
method: 'UsersManager.getUsersAccessFromSite',
userLogin: userLogin,
idSite: idSites
}, 'GET');
ajaxHandler.setCallback(function (users) {
var userLogins = [];
if (users && users[0]) {
userLogins = $.map(users[0], function (val, key) {
return (''+ key).toLowerCase();
});
}
if (-1 !== userLogins.indexOf(userLogin.toLowerCase())) {
showErrorNotification(_pk_translate('UsersManager_ExceptionUserHasViewAccessAlready'));
} else {
sendViewAccess(userLogin);
}
});
ajaxHandler.send();
}
function ifUserExists(usernameOrEmail, callback)
{
var ajaxHandler = createNewAjaxHelper();
ajaxHandler.addParams({
method: 'UsersManager.userExists',
userLogin: usernameOrEmail,
}, 'GET');
ajaxHandler.setCallback(callback);
ajaxHandler.send();
}
function getUsernameFromEmail(usernameOrEmail, callback)
{
var ajaxHandler = createNewAjaxHelper();
ajaxHandler.addParams({
method: 'UsersManager.getUserLoginFromUserEmail',
userEmail: usernameOrEmail,
}, 'GET');
ajaxHandler.setCallback(callback);
ajaxHandler.send();
}
function giveViewAccessToUser(userLogin)
{
var idSites = getIdSites();
if (idSites === 'all') {
setViewAccessForUserToAllWebsitesIfUserConfirms(userLogin);
} else {
setViewAccessForUserIfNotAlreadyHasAccess(userLogin, idSites);
}
}
$('#showGiveViewAccessForm').click(function () {
$('#giveViewAccessForm').toggle()
});
$('#giveViewAccessForm #user_invite').keypress(function (e) {
var key = e.keyCode || e.which;
if (key == 13) {
$('#giveViewAccessForm #giveUserAccessToViewReports').click();
}
});
$('#giveViewAccessForm #giveUserAccessToViewReports').click(function () {
showLoading();
var usernameOrEmail = $('#user_invite').val();
if (!usernameOrEmail) {
showErrorNotification(_pk_translate('UsersManager_ExceptionNoValueForUsernameOrEmail'));
return;
}
ifUserExists(usernameOrEmail, function (isUserName) {
if (isUserName && isUserName.value) {
giveViewAccessToUser(usernameOrEmail);
} else {
getUsernameFromEmail(usernameOrEmail, function (login) {
if (login && login.value) {
giveViewAccessToUser(login.value);
} else {
hideLoading();
}
});
}
});
});
});

View file

@ -1,5 +1,5 @@
/*!
* Piwik - Web Analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -229,7 +229,11 @@ $(document).ready(function () {
$(this)
.toggle()
.parent()
.prepend($('<input type="submit" class="submit updateuser" value="' + _pk_translate('General_Save') + '" />')
.prepend($('<a class="canceluser">' + _pk_translate('General_OrCancel', ['', '']) + '</a>')
.click(function () {
piwikHelper.redirect();
})
).prepend($('<input type="submit" class="submit updateuser" value="' + _pk_translate('General_Save') + '" />')
.click(function () {
var onValidate = function () {
sendUpdateUserAJAX($('tr#' + idRow));
@ -240,7 +244,7 @@ $(document).ready(function () {
onValidate();
}
})
);
);
});
$('.editable').keypress(submitOnEnter);
@ -259,7 +263,7 @@ $(document).ready(function () {
}
);
$('.addrow').click(function () {
$('.admin .user .add-user').click(function () {
piwikHelper.hideAjaxError();
$(this).toggle();
@ -268,10 +272,10 @@ $(document).ready(function () {
newRowId = 'row' + newRowId;
$($.parseHTML(' <tr id="' + newRowId + '">\
<td><input id="useradd_login" value="login?" size="10" /></td>\
<td><input id="useradd_password" value="password" size="10" /></td>\
<td><input id="useradd_email" value="email@domain.com" size="15" /></td>\
<td><input id="useradd_alias" value="alias" size="15" /></td>\
<td><input id="useradd_login" placeholder="username" size="10" /></td>\
<td><input id="useradd_password" placeholder="password" size="10" /></td>\
<td><input id="useradd_email" placeholder="email@domain.com" size="15" /></td>\
<td><input id="useradd_alias" placeholder="alias" size="15" /></td>\
<td>-</td>\
<td>-</td>\
<td><input type="submit" class="submit adduser" value="' + _pk_translate('General_Save') + '" /></td>\
@ -284,12 +288,11 @@ $(document).ready(function () {
$('.cancel').click(function () {
piwikHelper.hideAjaxError();
$(this).parents('tr').remove();
$('.addrow').toggle();
$('.add-user').toggle();
});
});
$('#access .updateAccess')
.click(bindUpdateAccess);
$('#access .updateAccess').click(bindUpdateAccess);
$('#superUserAccess .accessGranted, #superUserAccess .updateAccess').click(bindUpdateSuperUserAccess);
@ -299,4 +302,12 @@ $(document).ready(function () {
piwik.broadcast.propagateNewPage('segment=&idSite=' + site.id, false);
}
});
// Show the token_auth
$('.token_auth').click(function () {
var token = $(this).data('token');
if ($(this).text() != token) {
$(this).text(token);
}
});
});

View file

@ -1,5 +1,5 @@
/*!
* Piwik - Web Analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -38,6 +38,7 @@ function sendUserSettingsAJAX() {
postParams.defaultReport = defaultReport;
postParams.defaultDate = defaultDate;
postParams.language = $('#userSettingsTable #language').val();
postParams.timeformat = $('#userSettingsTable #timeformat').val();
var ajaxHandler = new ajaxHelper();
ajaxHandler.addParams({

View file

@ -0,0 +1,24 @@
{
"UsersManager": {
"AddUser": "አዲስ ተጤቃሚ ጨምር",
"Alias": "ተለዋጭ ስም",
"AllWebsites": "ሁሉንም ድር ጣቢያዎች",
"ApplyToAllWebsites": "በሁሉም ድር ጣቢያዎች ላይ ተግብር",
"DeleteConfirm": "እርግጠኛ ነህ ተጠቃሚዎቹን መሰረዝ ትፈልጋለህ %s?",
"Email": "ኢ-ሜይል",
"ExceptionAccessValues": "የግቤት መድረሻ ከሚከተሉት አንዱ እሴት ሊኖረው ይገባል: [ %s ]",
"ExceptionAdminAnonymous": "የአስተዳዳሪን ፈቃድ ላልታወቀ ሰው መስጠት አይቻልም",
"ExceptionDeleteDoesNotExist": "ተጠቃሚው '%s' የለም ስለዚህ ሊሰረዝ አይችልም",
"ExceptionEditAnonymous": "ያልታወቀው ተጠቃሚን መሰረዝ ወይም አርትእ አይቻልም። በፒዊክ ያልገባን ተጤቃሚ ለመግለፅ ይጠቅማል። ለምሳሌ የርስዎን ስታቲስቲክ 'የትይታ' ፈቃድ 'ላልታወቀ' ተጠቃሚ በመስጠት ግልፅ ማድረግ ትችላለህ።",
"ExceptionEmailExists": "በዚህ ኢ-ሜይል ተጠቃሚ '%s'አለ.",
"ExceptionInvalidEmail": "ኢ-ሜይሉ ትክክለኛ ቅርፀት የለውም",
"ManageAccess": "መድረሻ መንጅ",
"MenuUsers": "ተጠቃሚዎች",
"PrivAdmin": "አስተዳዳሪ",
"PrivNone": "መድረሻ የለም",
"PrivView": "ትእይታ",
"User": "ተጠቃሚ",
"UsersManagement": "የተጠቃሚዎች ምነጃ",
"UsersManagementMainDescription": "አዳዲስ ተጤቃሚዎችን ይፍጠሩ ወይም ያሉትን ያልቁ።ፈቃዳቸውን ከላይ ማዘጋጀት ይቻላል."
}
}

View file

@ -0,0 +1,42 @@
{
"UsersManager": {
"AddUser": "أضف مستخدم جديد",
"Alias": "اللقب",
"AllWebsites": "كافة المواقع",
"ApplyToAllWebsites": "تطبيق على كافة المواقع",
"ClickHereToDeleteTheCookie": "انقر هنا لحذف الكوكيز وليتتبع Piwik زياراتك",
"DeleteConfirm": "هل ترغب حقاً في حذف المستخدم %s؟",
"Email": "البريد الإلكتروني",
"ExceptionAccessValues": "بارامتيرات الوصول يجب أن تتضمن أحد القيم التالية: [%s]",
"ExceptionAdminAnonymous": "لا يمكنك منح \"المدير\" وصولاً للمستخدم \"مجهول\"",
"ExceptionDeleteDoesNotExist": "المستخدم '%s' غير موجود ولذلك لا يمكن حذفه.",
"ExceptionEditAnonymous": "لا يمكن تحرير أو حذف المستخدم \"مجهول\"، فهو يستخدم من قبل Piwik لتعريف المستخدم الذي لم يقم بتسجيل الدخول بعد. على سبيل المثال، يمكنك جعل صفحة الإحصائيات عامة من خلال منح المستخدم \"مجهول\" صلاحيات \"المشاهدة\".",
"ExceptionEmailExists": "المستخدم بعنوان البريد '%s' موجود مسبقاً.",
"ExceptionInvalidEmail": "صيغة البريد الإلكتروني غير صحيحة",
"ExceptionInvalidPassword": "يجب أن يكون طول كلمة المرور بين %1$s و %2$s رمزاً.",
"ExceptionPasswordMD5HashExpected": "يتوقع UsersManager.getTokenAuth كلمة مرور مشفرة باستخدام MD5 (طولها 32 رمزاً). الرجاء استدعاء الدالة md5() لكلمة المرور قبل استدعاء هذه الدالة.",
"ExceptionUserDoesNotExist": "المستخدم '%s' غير موجود.",
"ExcludeVisitsViaCookie": "استثني زياراتك باستخدام Cookies",
"ForAnonymousUsersReportDateToLoadByDefault": "للمستخدمين المجهولين، حدد تاريخ التقرير",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "إذا كنت ترغب في تغيير كلمة المرور، اكتب واحدة جديدة، أو اتركها فارغة لعدم تغييرها.",
"ManageAccess": "إدارة صلاحيات الوصول",
"MenuAnonymousUserSettings": "إعدادات المستخدمين المجهولين",
"MenuUsers": "المستخدمون",
"MenuUserSettings": "إعدادات المستخدم",
"PrivAdmin": "إشراف",
"PrivNone": "بدون وصول",
"PrivView": "مشاهدة",
"ReportDateToLoadByDefault": "تاريخ التقرير ليتم تحميله",
"ReportToLoadByDefault": "التقرير الافتراضي",
"TheLoginScreen": "شاشة تسجيل الدخول",
"ThereAreCurrentlyNRegisteredUsers": "يوجد حالياً %s مستخدم مسجل.",
"TypeYourPasswordAgain": "اكتب كلمة المرور الجديدة مرة أخرى.",
"User": "المستخدم",
"UsersManagement": "إدارة المستخدمين",
"UsersManagementMainDescription": "أنشئ متسخدم جديد أو قم بتحديث مستخدم قائم. يمكنك أن تضبط صلاحياتهم بالأعلى.",
"WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess": "عندما لا يسجل المستخدمون دخولهم ويزورون Piwik،فسيمكنهم الوصول إلى",
"YourUsernameCannotBeChanged": "لا يمكن تغيير اسم المستخدم الخاص بك.",
"YourVisitsAreIgnoredOnDomain": "%1$s زياراتك يتم تجاهلها في Piwik%2$s %3$s(تم العثور على كوكيز التجاهل في متصفحك).",
"YourVisitsAreNotIgnored": "%1$s لا يتم تجاهل زياراتك في Piwik%2$s (كوكيز التجاهل غير موجودة في متصفحك)."
}
}

View file

@ -0,0 +1,43 @@
{
"UsersManager": {
"AddUser": "Дадаць новага карыстача",
"Alias": "Аліас",
"AllWebsites": "Усе сайты",
"ApplyToAllWebsites": "Ужыць да ўсіх сайтаў",
"ChangePasswordConfirm": "Зменяючы парол, вы таксама зменяеце token_auth карыстальніка. Вы сапраўды жадаеце працягнуць?",
"ClickHereToDeleteTheCookie": "Націсніце тут, каб выдаліць cookie і пачаць адсочванне вашых наведванняў Piwik",
"ClickHereToSetTheCookieOnDomain": "Націсніце тут, каб усталяваць cookie, які выключыць адсочванне вашых наведванняў на вэб-сайтах з Piwik на %s",
"DeleteConfirm": "Вы сапраўды жадаеце выдаліць карыстача %s?",
"ExceptionAccessValues": "Параметр доступу можа мець толькі адно з наступных значэнняў: [ %s ]",
"ExceptionAdminAnonymous": "Вы не можаце даваць правы 'Адмін' ананімнаму карыстачу.",
"ExceptionDeleteDoesNotExist": "Карыстача '%s' не існуе, таму ён не можа быць выдалены.",
"ExceptionEditAnonymous": "Ананімны карыстач не можа быць выдалены. Ён неабходзен Piwik для ідэнтыфікацыі карыстачоў, якія не ўвайшлі ў сістэму. Дапушчальна, вы можаце зрабіць статыстыку публічнай, падаючы права 'Прагляд' ананімнаму карыстачу.",
"ExceptionEmailExists": "Карыстач з Email '%s' ужо існуе.",
"ExceptionInvalidEmail": "Email няправільнага фармату",
"ExceptionInvalidPassword": "Даўжыня пароля павінна быць паміж %1$s і %2$s знакаў.",
"ExceptionPasswordMD5HashExpected": "UsersManager.getTokenAuth партабуе MD5-хэшаваны пароль ( даужыней ў 32 знака). Калі ласка, запытайце md5() функцыю перад выклікам гэтага метаду.",
"ExceptionUserDoesNotExist": "Карыстач '%s' не існуе.",
"ExcludeVisitsViaCookie": "Сключыць вашыя наведванні выкарыстоўваючы cookie",
"ForAnonymousUsersReportDateToLoadByDefault": "Дата справаздачы для загрузкі па змаўчанні, для ананімных карыстальнікаў",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "Калі вы жадаеце змяніць пароль, то ўвядзіце новы. У адваротным выпадку пакіньце поле пустым.",
"ManageAccess": "Кіраванне правамі дазволу",
"MenuAnonymousUserSettings": "Ананімныя карыстацкія наладкі",
"MenuUsers": "Карыстачы",
"MenuUserSettings": "Наладкі карыстальніка",
"PrivAdmin": "Адмін",
"PrivNone": "Няма доступу",
"PrivView": "Прагляд",
"ReportDateToLoadByDefault": "Дата справаздачы для загрузкі па змаўчанні",
"ReportToLoadByDefault": "Справаздача, якая загружаецца па змаўчанні",
"TheLoginScreen": "Форма аўтарызацыі",
"ThereAreCurrentlyNRegisteredUsers": "Зарэгістраваныя карыстальнікі %s.",
"TypeYourPasswordAgain": "Калі ласка, увядзіце новы пароль яшчэ раз.",
"User": "Карыстач",
"UsersManagement": "Кіраванне карыстачамі",
"UsersManagementMainDescription": "Стварэнне новых карыстачоў ці рэдагаванне існуючых. Таксама Вы можаце задаць правы дазволу для карыстача.",
"WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess": "Калі карыстальнікі не аўтарызаваны і наведваюць Piwik, яны павінны атрымліваць доступ да",
"YourUsernameCannotBeChanged": "Ваша імя карыстальніка не можа быць зменена.",
"YourVisitsAreIgnoredOnDomain": "%1$sВашы наведванні ігнаруюцца Piwik на %2$s %3$s (Piwik знайшоў ў вашым браўзэры ігнаруючыя cookie).",
"YourVisitsAreNotIgnored": "%1$sВашы наведванні не ігнаруюцца Piwik%2$s (Piwik не знайшоў ў вашым браўзэры ігнаруючыя cookie)."
}
}

View file

@ -0,0 +1,57 @@
{
"UsersManager": {
"AddUser": "Добави нов потребител",
"Alias": "Псевдоним",
"AllWebsites": "Всички сайтове",
"AnonymousUserHasViewAccess": "Забележка: потребител %1$s има %2$s достъп до този сайт.",
"AnonymousUserHasViewAccess2": "Аналитичните доклади и информацията за посетителите, са публично видими.",
"ApplyToAllWebsites": "Запомни за всички сайтове",
"ChangePasswordConfirm": "Промяната на паролата ще промени и токена за верификация на потребителя. Желаете ли да продължите?",
"ClickHereToDeleteTheCookie": "Натиснете тук, за да изтриете бисквитката и Piwik да отчита Вашите посещения",
"ClickHereToSetTheCookieOnDomain": "Натиснете тук, за да зададете бисквитка, която ще Ви гарантира, че Вашите посещения няма да се отчитат от Piwik в %s",
"DeleteConfirm": "Наистина ли искате да изтриете потребителя %s?",
"Email": "Имейл",
"EmailYourAdministrator": "%1$sПишете на администратора Ви за този проблем%2$s.",
"ExceptionAccessValues": "Този параметър може да има само един от следните параметри: [ %s ]",
"ExceptionAdminAnonymous": "Не може да зададете 'админ' права на 'анонимен' потребител.",
"ExceptionDeleteDoesNotExist": "Потребителя '%s' не съществува, по тази причина не може да бъде изтрит.",
"ExceptionDeleteOnlyUserWithSuperUserAccess": "Изтриването на потребител '%s' не е възможно.",
"ExceptionEditAnonymous": "Анонимният потребител не може да бъде редактиран или изтрит. Piwik по този начин дефинира в система потребители, които не са влезли. Например можете да направите данните на брояча ви публични, като зададете 'преглед' права на 'анонимен' потребител.",
"ExceptionEmailExists": "Потребител с имейл '%s' вече съществува.",
"ExceptionInvalidEmail": "Е-пощата, който сте въвели не е валиден.",
"ExceptionInvalidPassword": "Дължината на паролата трябва да бъде между %1$s и %2$s символа.",
"ExceptionPasswordMD5HashExpected": "UsersManager.getTokenAuth очаква MD5-хеширана парола (32 символа дълъг низ). Моля, извикайте md5() функцията на паролата преди да извикате този метод.",
"ExceptionRemoveSuperUserAccessOnlySuperUser": "Премахването на права на привилигирован потребител за потребител '%s' не е възможно.",
"ExceptionUserDoesNotExist": "Потребителя '%s' не съществува.",
"ExceptionYouMustGrantSuperUserAccessFirst": "Трябва да съществува поне един привилигирован потребител. Моля, дайде нужните права на друг потребител.",
"ExcludeVisitsViaCookie": "Изключете Вашите посещения с помощта на бисквитка",
"ForAnonymousUsersReportDateToLoadByDefault": "За анонимни потребители, дата доклад да се зареди по подразбиране",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "Ако желаете да промените паролата си, въведете нова. В противен случай оставете полето празно.",
"InjectedHostCannotChangePwd": "В момента вие посещавате страница от неизвестен хост(%1$s). Не можете да смените паролата, преди да отстраните този проблем.",
"LastSeen": "Последно видяно",
"ManageAccess": "Управление на правата",
"MenuAnonymousUserSettings": "Настройки на анонимните потребители",
"MenuUsers": "Потребители",
"MenuUserSettings": "Потребителски настройки",
"NoteNoAnonymousUserAccessSettingsWontBeUsed2": "Бележка: Не можете да променяте настройките в тази секция, защото нямате никакви сайтове с разрешен достъп за анонимни потребители.",
"NoUsersExist": "Не са налични потребители, все още.",
"PrivAdmin": "Админ",
"PrivNone": "Без права",
"PrivView": "Преглед",
"ReportDateToLoadByDefault": "Отчет от дата да се зареди по подразбиране",
"ReportToLoadByDefault": "Доклад за зареждане по подразбиране",
"SuperUserAccessManagement": "Управление на достъпа на привилигированите потребители",
"SuperUserAccessManagementGrantMore": "Тук могат да се предоставят права „привилигирован потребител“ на потребителите. Тази функция трябва да се използва внимателно.",
"SuperUserAccessManagementMainDescription": "Привилигированите потребители имат пълни права. Те могат да извършват всички административни задачи, като например добавяне на нови уебсайтове за наблюдение, добавяне на потребители, промяна на потребителския достъп, активиране и деактивиране на добавки и дори инсталация на нови добавки от магазина.",
"TheLoginScreen": "В екрана за вход",
"ThereAreCurrentlyNRegisteredUsers": "Има %s регистрирани потребители.",
"TypeYourPasswordAgain": "Вашата нова парола отново.",
"User": "Потребител",
"UsersManagement": "Управление на потребители",
"UsersManagementMainDescription": "Създайте нови потребители или управлявайте вече съществуващи. Също така и можете да задавате правата за достъп.",
"WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess": "Когато потребителите не са влезли и посетят Piwik, те се нуждаят от достъп",
"YourUsernameCannotBeChanged": "Потребителското име не може да се променя.",
"YourVisitsAreIgnoredOnDomain": "%1$sВашите посещения са игнорирани от Piwik в %2$s %3$s (Piwik игнорира бисквитката, намерена във Вашият браузър).",
"YourVisitsAreNotIgnored": "%1$sВашите посещения не се игнорират от Piwik %2$s(Бисквитката за игнориране на Вашите посещения, не е открита във Вашият браузър)."
}
}

View file

@ -0,0 +1,6 @@
{
"UsersManager": {
"PrivAdmin": "Administracija",
"PrivView": "Vidi"
}
}

View file

@ -0,0 +1,46 @@
{
"UsersManager": {
"AddUser": "Afegeix un usuari nou",
"Alias": "Àlies",
"AllWebsites": "Tots els llocs",
"ApplyToAllWebsites": "Aplica a tots els llocs",
"ChangePasswordConfirm": "Canviar la contrasenya implica canviar el toquen d'autenticació del 'usuari. Esteu segurs que voleu continuar?",
"ClickHereToDeleteTheCookie": "Feu click aquí per eliminar la galeta i permetre al Piwik rastrejar les vostres visites.",
"ClickHereToSetTheCookieOnDomain": "Feu click aquí per guardar una galeta que exclourà les vostres visitis al Piwik de %s",
"DeleteConfirm": "Esteu segur que voleu eliminar l'usuari %s?",
"Email": "Correu-e",
"EmailYourAdministrator": "%1$sEnvieu un email al vostre administrador explicant el problema%2$s.",
"ExceptionAccessValues": "El paràmetre permisos ha de tenir un dels següents valors: [ %s ]",
"ExceptionAdminAnonymous": "No podeu donar permisos d'administració a l'usuari 'anonymous' (anònim).",
"ExceptionDeleteDoesNotExist": "L'usuari '%s' no existeix i, per tant, no es pot esborrar.",
"ExceptionEditAnonymous": "L'usuari anònim no es pot editar o esborrar. El Piwik el fa servir per als usuaris que no han iniciat encara la sessió. Per exemple, podeu fer públiques les vostres estadístiques garantint el permís 'vista' a l'usuari 'anonymous' (anònim).",
"ExceptionEmailExists": "La direcció de correu-e '%s' ja està en un altre compte.",
"ExceptionInvalidEmail": "La direcció de correu-e no té un format vàlid.",
"ExceptionInvalidPassword": "La longitud de la contrasenya ha de estar entre %1$s i %2$s caràcters.",
"ExceptionUserDoesNotExist": "L'usuari '%s' no existeix.",
"ExcludeVisitsViaCookie": "Exclou les teues visites utilitzant cookies",
"ForAnonymousUsersReportDateToLoadByDefault": "Pels usuaris anònims, introduïu la data dels informes per defecte",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "Si voleu canviar la contrasenya teclegeu-n'hi una de nova, sinó deixeu-ho en blanc.",
"InjectedHostCannotChangePwd": "Actualment esteu visitan amb un host desconegut (%1$s). No podeu canviar la vostra contrasenya fins que corregiu aquest problema.",
"ManageAccess": "Gestiona els permisos",
"MenuAnonymousUserSettings": "Preferències de l'usuari anònim",
"MenuUsers": "Usuaris",
"MenuUserSettings": "Preferències d'usuari",
"NoteNoAnonymousUserAccessSettingsWontBeUsed2": "Nota: No podeu canviar la configuració en aquest secció, perquè no teniu cap lloc web que pot ser visitat per usuaris anònims.",
"PrivAdmin": "Administració",
"PrivNone": "Sense accés",
"PrivView": "Vista",
"ReportDateToLoadByDefault": "Data dels informes per defecte",
"ReportToLoadByDefault": "Informe per defecte",
"TheLoginScreen": "Pàgina d'entrada",
"ThereAreCurrentlyNRegisteredUsers": "Actualment hi ha %s usuaris registrats",
"TypeYourPasswordAgain": "Introduïu de nou la nova contrasenya.",
"User": "Usuari",
"UsersManagement": "Gestiona els usuaris",
"UsersManagementMainDescription": "Creeu nous usuaris o actualitzeu els existents. Podeu configurar els seus permisos a dalt.",
"WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess": "Quan un usuari no esta identificat i visita el Piwik, han d'accedir",
"YourUsernameCannotBeChanged": "No es pot canviar el vostre nom d'usuari",
"YourVisitsAreIgnoredOnDomain": "%1$sLes vostres visites són ignorades pel Piwik %2$s %3$s (la galeta d'ignorància del Piwik s'ha trobat al vostre navegador).",
"YourVisitsAreNotIgnored": "%1$sLes vostres visites no són ignorades pel Piwik%2$s (la galeta d'ignorància del Piwik no s'ha trobat al vostre navegador)."
}
}

View file

@ -0,0 +1,75 @@
{
"UsersManager": {
"AddUser": "Přidat nového uživatele",
"Alias": "Alias",
"AllWebsites": "Všechny weby",
"AnonymousUser": "Anonymní uživatel",
"AnonymousUserHasViewAccess": "Poznámka: %1$s uživatel má právo k přístupu k %2$s",
"AnonymousUserHasViewAccess2": "Vaše analytická hlášení a informace o návštěvnících jsou veřejně dostupná.",
"ApplyToAllWebsites": "Použít na všechny weby",
"ChangeAllConfirm": "Opravdu chcete povolit přístup ke všem webovým stránkám uživateli '%s'?",
"ChangePasswordConfirm": "Změna hesla také změní uživatelův token_auth. Opravdu chcete pokračovat?",
"ClickHereToDeleteTheCookie": "Klinětě zde pro vymazání cookie a zaznamenávání vaších návštěv",
"ClickHereToSetTheCookieOnDomain": "Klikněte zde pro nastavení cookie, která vynechá vaše návštěvy na webech monitorováných Piwikem na %s",
"ConfirmGrantSuperUserAccess": "Opravdu chcete uživateli %s povolit super-uživatelský přístup?",
"ConfirmProhibitMySuperUserAccess": "%s, opravdu chcete odstranit svůjvlastn í super-uživatelský přístup? Přijdete o všechna oprávnění a o přístup k datům stránek a budete odhlášen z Piwiku.",
"ConfirmProhibitOtherUsersSuperUserAccess": "Opravdu chcete odstranit super-uživatelský přístup pro '%s'? Tento uživatel přijde o všechna práva a o přístup ke všem stránkám. Nezapomeňte mu poté povolit přístup k těm které potřebuje, je-li to nutné.",
"DeleteConfirm": "Jste si jistí, že chcete vymazat uživatele %s?",
"Email": "Email",
"EmailYourAdministrator": "%1$sPošlete administrátorovi email o tomto problému%2$s.",
"EnterUsernameOrEmail": "Zadejte uživatelské jméno nebo emailovou adresu",
"ExceptionAccessValues": "Parametr přístupu musí mít jednu z následujících hodnot: [ %s ]",
"ExceptionAdminAnonymous": "Nemůžete dát 'admin' přístup 'anonymous' uživateli.",
"ExceptionDeleteDoesNotExist": "Uživatel '%s' neexistuje a proto nemůže být vymazán.",
"ExceptionDeleteOnlyUserWithSuperUserAccess": "Smazání uživatele %s není možné.",
"ExceptionEditAnonymous": "'Anonymous' uživatel nemůže být upraven, nebo vymazán. Je použit Piwikem k definici uživatele, který ještě není přihlášen. Například můžete zveřejnit vaše statistiky udělením oprávnění 'view' uživateli 'anonymous'.",
"ExceptionEmailExists": "Uživatel s emailem '%s' již existuje.",
"ExceptionInvalidEmail": "Email nemá platný formát.",
"ExceptionInvalidLoginFormat": "Uživatelské jméno musí být v rozmezí %1$s až %2$s znaků a obsahovat pouze písmena, čísla, či následující znaky '_' '-' '.' '@' '+'",
"ExceptionInvalidPassword": "Délka hesla musí být mezi %1$s a %2$s znaky.",
"ExceptionLoginExists": "Uživatel '%s' již existuje.",
"ExceptionPasswordMD5HashExpected": "UsersManager.getTokenAuth očekává heslo v podobě MD5 hashe (32 znaků dlouhého řetězce). Prosím nejprve zavoltejte metodu md5() na tomto hesle.",
"ExceptionRemoveSuperUserAccessOnlySuperUser": "Odebrání super-uživatelského přístupu uživateli %s není možné.",
"ExceptionSuperUserAccess": "Tento uživatel již má super-uživatelský přístup, takže má přístup k datům všech stránek. Můžete super uživatelský přístup odstranit a zkusit to znovu.",
"ExceptionUserDoesNotExist": "Uživatel '%s' neexistuje.",
"ExceptionYouMustGrantSuperUserAccessFirst": "Musí zůstat alespoň jeden uživatel se super-uživatelským přístupem. Nejdříve ho někomu přidělte.",
"ExceptionUserHasViewAccessAlready": "Tento uživatel má již přístup k této webové stránce.",
"ExceptionNoValueForUsernameOrEmail": "Zadejte prosím uživatelské jméno nebo emailovou adresu.",
"ExcludeVisitsViaCookie": "Vynechat vaše navštěvy pomocí cookie",
"ForAnonymousUsersReportDateToLoadByDefault": "Datum hlášení, které se má načíst jako výchozí pro anonymní uživatele",
"GiveViewAccess": "Povolit přístup pro čtení",
"GiveViewAccessTitle": "Povolí existujícímu uživateli zobrazování reportů pro %s",
"GiveViewAccessInstructions": "Pro přiřazení práv k zobrazení %s existujícímu uživateli, zadejte jeho uživatelské jméno nebo emailovou adresu",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "Pokud chcete změnit heslo, zapiště jej. Jinak jej nevyplňujte.",
"InjectedHostCannotChangePwd": "Aktuálně navštěvujete Piwik s neznámým hostitelem %1$s. Dokud tento problém nevyřešíte, nemůžete změnit heslo.",
"LastSeen": "Naposledy spatřen",
"MainDescription": "Rozhodnout, kteří uživatelé mají přístup k webovým stránkám. Lze také přidat přístup na všechny webové stránky najednou vybráním \"Apply to all websites\" z nabídky webových stránek.",
"ManageAccess": "Správa přístupu",
"MenuAnonymousUserSettings": "Nastavení anonymního uživatele",
"MenuUsers": "Uživatelé",
"MenuUserSettings": "Nastavení uživatele",
"MenuPersonal": "Osobní",
"PersonalSettings": "Osobní nastavení",
"NoteNoAnonymousUserAccessSettingsWontBeUsed2": "Poznámka: Nemůžete měnit nastavení v této sekci, protože žádná z vašich stránek nemůže být zobrazena anonymním uživatelem.",
"NoUsersExist": "Zatím nejsou žádní uživatelé.",
"PluginDescription": "Správa uživatelů vám umožňuje přidávat nové uživatele, upravovat existující a přidávat oprávnění k zobrazování nebo správě webových stránek.",
"PrivAdmin": "Administrátor",
"PrivNone": "Žádné oprávnění",
"PrivView": "Zobrazit",
"ReportDateToLoadByDefault": "Datum hlášení, které se má načíst jako výchozí",
"ReportToLoadByDefault": "Hlášení, které se má načíst jako výchozí",
"SuperUserAccessManagement": "Spravovat super-uživatelský přístup",
"SuperUserAccessManagementGrantMore": "Zde můžete přidělovat super-uživatelský přístup jiným uživatelům Piwiku. Používejte tuto funkci opatrně.",
"SuperUserAccessManagementMainDescription": "Super-uživatelé mají nejvyšší oprávnění. Mohou vykonávat všechny administrativní operace, jako je přidávání stránek k monitorování, přidávání uživatelů, změna uživatelských oprávnění, povolování a zakazování zásuvných modulů a dokonce jejich instalace z obchodu.",
"TheLoginScreen": "Přihlašovací obrazovka",
"ThereAreCurrentlyNRegisteredUsers": "Aktuálně je %s registrovaných uživatelů.",
"TypeYourPasswordAgain": "Zapiště vaše nové heslo znova",
"User": "Uživatel",
"UsersManagement": "Správa uživatelů",
"UsersManagementMainDescription": "Vytvořte nové uživatele, nebo aktualizujte existující. Níže můžete nastavit jejich oprávnění.",
"WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess": "Když uživatelé nejsou přihlášeni do Piwiku, mohou přistupovat k",
"YourUsernameCannotBeChanged": "Vaše uživatelské jméno nemůže být změněno",
"YourVisitsAreIgnoredOnDomain": "%1$sVaše návštěvy jsou vynechávány Piwikem na %2$s %3$s (cookie pro vynechání byla nalezena ve vašem prohlížeči).",
"YourVisitsAreNotIgnored": "%1$sVaše návštěvy nejsou vynechávány Piwikem%2$s (cookie pro vynechání nebyla nalezena ve vašem prohlížeči)."
}
}

Some files were not shown because too many files have changed in this diff Show more