Skip to content

Commit

Permalink
Update global settings to support excluding common PII params
Browse files Browse the repository at this point in the history
  • Loading branch information
caddoo committed Nov 4, 2024
1 parent b32171a commit f6b5ff4
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 36 deletions.
50 changes: 49 additions & 1 deletion plugins/SitesManager/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class API extends \Piwik\Plugin\API
public const OPTION_EXCLUDED_USER_AGENTS_GLOBAL = 'SitesManager_ExcludedUserAgentsGlobal';
public const OPTION_EXCLUDED_REFERRERS_GLOBAL = 'SitesManager_ExcludedReferrersGlobal';
public const OPTION_KEEP_URL_FRAGMENTS_GLOBAL = 'SitesManager_KeepURLFragmentsGlobal';
public const OPTION_EXCLUDE_TYPE_QUERY_PARAMS_GLOBAL = 'SitesManager_ExcludeTypeQueryParamsGlobal';

/**
* @var SettingsProvider
Expand Down Expand Up @@ -1126,7 +1127,17 @@ public function getExcludedQueryParameters(int $idSite): array
public function getExcludedQueryParametersGlobal()
{
Piwik::checkUserHasSomeViewAccess();
return Option::get(self::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL);

switch ($this->getExclusionTypeForQueryParams()) {
case SitesManager::URL_PARAM_EXCLUSION_TYPE_NAME_NO_EXCLUSIONS:
return '';
case SitesManager::URL_PARAM_EXCLUSION_TYPE_NAME_COMMON_PII_EXCLUSIONS:
return implode(',', SitesManager::COMMON_URL_PARAMS_TO_EXCLUDE);
case SitesManager::URL_PARAM_EXCLUSION_TYPE_NAME_CUSTOM_EXCLUSIONS:
return Option::get(self::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL);
default:
return Option::get(self::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL);
}
}

/**
Expand Down Expand Up @@ -1346,6 +1357,43 @@ public function setDefaultTimezone($defaultTimezone)
return true;
}

public function setExclusionTypeForQueryParams(string $exclusionTypeForQueryParams): void
{
Piwik::checkUserHasSuperUserAccess();

if (!in_array($exclusionTypeForQueryParams, SitesManager::URL_PARAM_EXCLUSION_TYPES)) {
throw new Exception($this->translator->translate('SitesManager_ExceptionInvalidExclusionType'));
}

Option::set(self::OPTION_EXCLUDE_TYPE_QUERY_PARAMS_GLOBAL, $exclusionTypeForQueryParams);

Cache::deleteTrackerCache();
}

/**
* Gets the exclusion type, if the option is not present in the store then it infers the type based on if there are
* custom exclusions already defined.
*
* @return string
*/
public function getExclusionTypeForQueryParams(): string
{
Piwik::checkUserHasSomeViewAccess();

$result = Option::get(self::OPTION_EXCLUDE_TYPE_QUERY_PARAMS_GLOBAL);

if (!empty($result)) {
return $result;
}

$excludedQueryParamsGlobal = Option::get(self::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL);

if (empty($excludedQueryParamsGlobal)) {
return SitesManager::URL_PARAM_EXCLUSION_TYPE_NAME_NO_EXCLUSIONS;
}
return SitesManager::URL_PARAM_EXCLUSION_TYPE_NAME_CUSTOM_EXCLUSIONS;
}

/**
* Update an existing website.
* If only one URL is specified then only the main url will be updated.
Expand Down
14 changes: 13 additions & 1 deletion plugins/SitesManager/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ public function globalSettings()
{
Piwik::checkUserHasSuperUserAccess();

return $this->renderTemplate('globalSettings');
return $this->renderTemplate(
'globalSettings',
[
'commonSensitiveQueryParams' => SitesManager::COMMON_URL_PARAMS_TO_EXCLUDE
]
);
}

public function getGlobalSettings()
Expand All @@ -73,6 +78,11 @@ public function getGlobalSettings()
$globalSettings['excludedQueryParametersGlobal'] = API::getInstance()->getExcludedQueryParametersGlobal();
$globalSettings['excludedUserAgentsGlobal'] = API::getInstance()->getExcludedUserAgentsGlobal();
$globalSettings['excludedReferrersGlobal'] = API::getInstance()->getExcludedReferrersGlobal();
$globalSettings['exclusionTypeForQueryParams'] = API::getInstance()->getExclusionTypeForQueryParams();

if ($globalSettings['exclusionTypeForQueryParams'] !== 'custom_exclusions') {
$globalSettings['excludedQueryParametersGlobal'] = '';
}

return $response->getResponse($globalSettings);
}
Expand All @@ -95,6 +105,7 @@ public function setGlobalSettings()
$searchKeywordParameters = Common::getRequestVar('searchKeywordParameters', $default = "");
$searchCategoryParameters = Common::getRequestVar('searchCategoryParameters', $default = "");
$keepURLFragments = Common::getRequestVar('keepURLFragments', $default = 0);
$exclusionTypeForQueryParams = Common::getRequestVar('exclusionTypeForQueryParams', $default = "");

$api = API::getInstance();
$api->setDefaultTimezone($timezone);
Expand All @@ -105,6 +116,7 @@ public function setGlobalSettings()
$api->setGlobalExcludedReferrers($excludedReferrers);
$api->setGlobalSearchParameters($searchKeywordParameters, $searchCategoryParameters);
$api->setKeepURLFragmentsGlobal($keepURLFragments);
$api->setExclusionTypeForQueryParams($exclusionTypeForQueryParams);

$toReturn = $response->getResponse();
} catch (Exception $e) {
Expand Down
36 changes: 36 additions & 0 deletions plugins/SitesManager/SitesManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,36 @@ class SitesManager extends \Piwik\Plugin
public const KEEP_URL_FRAGMENT_YES = 1;
public const KEEP_URL_FRAGMENT_NO = 2;

public const COMMON_URL_PARAMS_TO_EXCLUDE = ['creditcardnumber', 'off', 'kreditkarte', 'debitcard', 'kreditkort',
'kredietkaart', ' kartakredytowa', 'cvv', 'cc', 'ccc', 'cccsc', 'cccvc', 'ccexpiry', 'ccexpyear', 'ccexpmonth',
'cccvv', 'cctype', 'cvc', 'exp', 'ccname', 'cardnumber', 'ccnumber', 'username', 'creditcard', 'name',
'fullname', 'familyname', 'firstname', 'vorname', 'nachname', 'lastname', 'nickname', 'surname', 'login',
'formlogin', 'konto', 'user', 'website', 'domain', 'gender', 'company', 'firma', 'geschlecht', 'email',
'emailaddress', 'emailadresse', 'mail', 'epos', 'ebost', 'epost', 'eposta', 'authpw', 'token_auth',
'tokenauth', 'token', 'pin', 'ibanaccountnum', 'ibanaccountnumber', 'account', 'accountnum', 'auth', 'age',
'alter', 'tel', 'city', 'cell', 'cellphone', 'bic', 'iban', 'swift', 'kontonummer', 'konto', 'kontonr',
'phone', 'mobile', 'mobiili', 'mobilne', 'handynummer', 'téléphone', 'telefono', 'ssn', 'socialsecuritynumber',
'socialsec', 'socsec', 'address', 'addressline1', 'addressline2','billingaddress', 'billingaddress1',
'billingaddress2','shippingaddress', 'shippingaddress1', 'shippingaddress2', 'vat', 'vatnumber', 'gst',
'gstnumber', 'tax', 'taxnumber', 'steuernummer', 'adresse', 'indirizzo', 'adres', 'dirección', 'osoite',
'address1', 'address2', 'address3', 'street', 'strasse', 'rue', 'via', 'ulica', 'calle', 'sokak', 'zip',
'zipcode', 'plz', 'postleitzahl', 'postalcode', 'postcode', 'dateofbirth', 'dob', 'telephone', 'telefon',
'telefonnr', 'telefonnummer', 'password', 'passwort', 'kennwort', 'wachtwoord', 'contraseña', 'passord',
'hasło', 'heslo', 'wagwoord', 'parole', 'contrasenya', 'heslo', 'clientid', 'identifier', 'id',
'consumersecret', 'webhooksecret', 'consumerkey', 'keyconsumersecret', 'keyconsumerkey', 'clientsecret',
'secret', 'secretq', 'secretquestion', 'privatekey', 'publickey', 'pw', 'pwd', 'pwrd', 'pword', 'paword',
'pasword', 'paswort', 'pass'];

public const URL_PARAM_EXCLUSION_TYPE_NAME_NO_EXCLUSIONS = 'no_exclusions';
public const URL_PARAM_EXCLUSION_TYPE_NAME_COMMON_PII_EXCLUSIONS = 'common_pii_exclusions';
public const URL_PARAM_EXCLUSION_TYPE_NAME_CUSTOM_EXCLUSIONS = 'custom_exclusions';

public const URL_PARAM_EXCLUSION_TYPES = [
self::URL_PARAM_EXCLUSION_TYPE_NAME_NO_EXCLUSIONS,
self::URL_PARAM_EXCLUSION_TYPE_NAME_COMMON_PII_EXCLUSIONS,
self::URL_PARAM_EXCLUSION_TYPE_NAME_CUSTOM_EXCLUSIONS
];

/**
* @see \Piwik\Plugin::registerEvents
*/
Expand Down Expand Up @@ -478,6 +508,12 @@ public function getClientSideTranslationKeys(&$translationKeys)
$translationKeys[] = 'SitesManager_SiteWithoutDataOtherInstallMethods';
$translationKeys[] = 'Mobile_NavigationBack';
$translationKeys[] = 'SitesManager_SiteWithoutDataInstallWithX';
$translationKeys[] = 'SitesManager_ExclusionTypeOptionNoExclusions';
$translationKeys[] = 'SitesManager_ExclusionTypeOptionCommonPIIExclusions';
$translationKeys[] = 'SitesManager_ExclusionTypeOptionCustomExclusions';
$translationKeys[] = 'SitesManager_ExclusionTypeDescriptionNoExclusions';
$translationKeys[] = 'SitesManager_ExclusionTypeDescriptionCommonPIIExclusions';
$translationKeys[] = 'SitesManager_ExclusionTypeDescriptionCustomExclusions';
}

public static function renderTrackingCodeEmail(int $idSite)
Expand Down
9 changes: 8 additions & 1 deletion plugins/SitesManager/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@
"SiteWithoutDataSPADescription": "It is easy to start tracking your Single Page Application (SPA) or Progressive Web App (PWA) using Matomo Analytics. The easiest way to do this is using the Matomo Tag Manager (%1$slearn more%2$s) using the steps below, alternatively you can use the JavaScript Tracking code (%3$sfollowing this guide%4$s).",
"SiteWithoutDataSPAFollowStepCompleted": "%1$sCongratulations!%2$s You have successfully installed the Matomo Analytics tracking code via the Matomo Tag Manager. To verify that hits are being tracked, visit your SPA / PWA and check that this data is visible in your Matomo instance.",
"OtherWaysTabDescription": "Even if the solutions provided in the other tabs were not right for you, you can easily setup Matomo with one of the methods below. You may need the following information:",
"ImageTrackingDescription": "When a visitor has disabled JavaScript, or when JavaScript cannot be used, you can use an image tracking link to track visitors. For the whole list of options you can use with an image tracking link, see the %1$sTracking API Documentation%2$s."
"ImageTrackingDescription": "When a visitor has disabled JavaScript, or when JavaScript cannot be used, you can use an image tracking link to track visitors. For the whole list of options you can use with an image tracking link, see the %1$sTracking API Documentation%2$s.",
"ExclusionTypeOptionNoExclusions": "No exclusions",
"ExclusionTypeOptionCommonPIIExclusions": "Sensible PII exclusions",
"ExclusionTypeOptionCustomExclusions": "Custom exclusions",
"ExclusionTypeDescriptionNoExclusions": "Select this option to include all URL parameters in tracking and reports. No parameters will be excluded, providing a complete view of the URL data for each visit.",
"ExclusionTypeDescriptionCommonPIIExclusions": "Choose this option to exclude a common set of potentially sensitive URL parameters from tracking and reports. These include these parameters: \"%1$s\"",
"ExclusionTypeDescriptionCustomExclusions": "Enter your own list of URL parameters to exclude from tracking and reports. Customize further by pressing the button below the textarea to add a predefined set of common exclusions. You can adjust this list as needed to fit your privacy and tracking requirements.",
"ExceptionInvalidExclusionType": "The exclusion type you provided is invalid"
}
}
5 changes: 5 additions & 0 deletions plugins/SitesManager/stylesheets/SitesManager.less
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@
margin-bottom: 7px;
}
}

.limited-height-scrolling-textarea textarea {
max-height: 400px;
overflow-y: auto;
}
}

td.editable-site-field:hover {
Expand Down
4 changes: 1 addition & 3 deletions plugins/SitesManager/templates/globalSettings.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,5 @@
{% set title %}{{ 'SitesManager_GlobalWebsitesSettings'|translate }}{% endset %}

{% block content %}

<div vue-entry="SitesManager.ManageGlobalSettings"></div>

<div vue-entry="SitesManager.ManageGlobalSettings" common-sensitive-query-params="{{ commonSensitiveQueryParams|json_encode }}"></div>
{% endblock %}
68 changes: 68 additions & 0 deletions plugins/SitesManager/tests/Integration/ApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Piwik\Plugin;
use Piwik\Plugins\IntranetMeasurable\Type as IntranetType;
use Piwik\Plugins\MobileAppMeasurable;
use Piwik\Plugins\SitesManager\SitesManager;
use Piwik\Plugins\WebsiteMeasurable\Type as WebsiteType;
use Piwik\Plugins\SitesManager\API;
use Piwik\Plugins\SitesManager\Model;
Expand Down Expand Up @@ -1614,7 +1615,74 @@ public function testSetGlobalExcludedReferrersWithValidValue()
$this->assertEquals('http://example.com/path', $excludedReferrers);
}

public function testGetExcludedQueryParametersGlobalShowsErrorIfNoViewRights(): void
{

}

Check failure on line 1621 in plugins/SitesManager/tests/Integration/ApiTest.php

View workflow job for this annotation

GitHub Actions / PHPCS

Function closing brace must go on the next line following the body; found 1 blank lines before brace

/**
* @dataProvider getExclusionTypesAndExpectedResults
*/
public function testGetExcludedQueryParametersGlobalShowsCorrectParamsDependingOnExclusionType($exclusionType, $expected): void
{
Option::set(API::OPTION_EXCLUDE_TYPE_QUERY_PARAMS_GLOBAL, $exclusionType);
Option::set(API::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL, 'one,two');

$this->assertEquals(
$expected,
API::getInstance()->getExcludedQueryParametersGlobal()
);
}

public function getExclusionTypesAndExpectedResults(): \Generator
{
yield 'no exclusions' => ['no_exclusions', ''];
yield 'common PII exclusions' => ['common_pii_exclusions', implode(',', SitesManager::COMMON_URL_PARAMS_TO_EXCLUDE)];
yield 'custom exclusions' => ['custom_exclusions', 'one,two'];
yield 'empty exclusion type' => ['', 'one,two'];
yield 'false exclusion type' => [false, 'one,two'];
}

/**
* @dataProvider getExclusionTypesWithUrlParamsAndExpectedResults
*/
public function testGetExclusionTypeForQueryParamsReturnsCorrectType($exclusionTypeSetting, string $excludedQueryParamsGlobal, string $expectedType): void
{
if ($exclusionTypeSetting === null) {
Option::delete(API::OPTION_EXCLUDE_TYPE_QUERY_PARAMS_GLOBAL);
} else {
Option::set(API::OPTION_EXCLUDE_TYPE_QUERY_PARAMS_GLOBAL, $exclusionTypeSetting);
}

Option::set(API::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL, $excludedQueryParamsGlobal);

$this->assertEquals(
$expectedType,
API::getInstance()->getExclusionTypeForQueryParams()
);
}

public function testSetExclusionTypeForQueryParamsThrowsExceptionIfInvalidValueProvided(): void
{
$this->expectExceptionMessage('The exclusion type you provided is invalid');
API::getInstance()->setExclusionTypeForQueryParams('bad_value');
}

public function testSetExclusionTypeForQueryParamsSetsTypeCorrectly(): void
{
API::getInstance()->setExclusionTypeForQueryParams('no_exclusions');
$this->assertEquals(
'no_exclusions',
API::getInstance()->getExclusionTypeForQueryParams()
);
}

public function getExclusionTypesWithUrlParamsAndExpectedResults(): \Generator
{
yield 'option exists already in options store' => ['no_exclusions', '', 'no_exclusions'];
yield 'option doesnt exist and excluded query parameters has data' => [null, 'myapp_name,myapp_email', 'custom_exclusions'];
yield 'option doesnt exist and excluded query parameters has no data' => [null, '', 'no_exclusions'];
}

public function provideContainerConfig()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface GlobalSettings {
excludedReferrersGlobal?: string;
searchKeywordParametersGlobal?: string;
searchCategoryParametersGlobal?: string;
exclusionTypeForQueryParams: string;
}

export default GlobalSettings;
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface SaveGlobalSettingsParams {
excludedReferrers: string;
searchKeywordParameters: string;
searchCategoryParameters: string;
excludeCommonPIIUrlParams: boolean;
}

class GlobalSettingsStore {
Expand All @@ -43,6 +44,7 @@ class GlobalSettingsStore {
excludedReferrersGlobal: '',
searchKeywordParametersGlobal: '',
searchCategoryParametersGlobal: '',
exclusionTypeForQueryParams: '',
},
});

Expand Down Expand Up @@ -87,6 +89,7 @@ class GlobalSettingsStore {
excludedReferrersGlobal: response.excludedReferrersGlobal || '',
searchKeywordParametersGlobal: response.searchKeywordParametersGlobal || '',
searchCategoryParametersGlobal: response.searchCategoryParametersGlobal || '',
exclusionTypeForQueryParams: response.exclusionTypeForQueryParams || '',
};
}).finally(() => {
this.privateState.isLoading = false;
Expand Down
Loading

0 comments on commit f6b5ff4

Please sign in to comment.