diff --git a/CHANGELOG.md b/CHANGELOG.md index 90e532c..f47bdb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Changelog +* 5.3.1 - 2026-06-08 - Added restrict access check for MultiSites.getAll report for non superusers * 5.3.0 - 2026-05-11 - Added alert description and helptexts * 5.2.6 - 2026-04-27 - Updated API documentation * 5.2.5 - 2026-03-30 - Added escaping for report_matched value diff --git a/Processor.php b/Processor.php index 6fcdf7a..6ca1349 100755 --- a/Processor.php +++ b/Processor.php @@ -248,6 +248,8 @@ public function getValueForAlertInPast($alert, $idSite, $subPeriodN) $params = array_merge($params, $report['parameters']); } + $params = $this->restrictMultiSitesReportToAlertOwner($params, $report, $alert); + $subtableId = DataTable\Manager::getInstance()->getMostRecentTableId(); $table = ApiRequest::processRequest($report['module'] . '.' . $report['action'], $params, $default = []); @@ -264,6 +266,22 @@ public function getValueForAlertInPast($alert, $idSite, $subPeriodN) return $value; } + protected function restrictMultiSitesReportToAlertOwner(array $params, array $report, array $alert): array + { + if ( + $report['module'] !== 'MultiSites' + || $report['action'] !== 'getAll' + || empty($alert['login']) + || Piwik::hasTheUserSuperUserAccess($alert['login']) + ) { + return $params; + } + + $params['_restrictSitesToLogin'] = $alert['login']; + + return $params; + } + /** * Checks whether the archive status is complete. We throw an exception if the status is something other than * complete. If no status is found, we do nothing. diff --git a/phpstan/phpstan.modified.neon b/phpstan/phpstan.modified.neon index 1cd88df..ddb9ff9 100644 --- a/phpstan/phpstan.modified.neon +++ b/phpstan/phpstan.modified.neon @@ -2,4 +2,5 @@ includes: - ../phpstan.neon parameters: level: 5 - tmpDir: /tmp/phpstan/CustomAlerts/modified \ No newline at end of file + tmpDir: /tmp/phpstan/CustomAlerts/modified + treatPhpDocTypesAsCertain: false diff --git a/plugin.json b/plugin.json index d0a992b..d9bec1d 100644 --- a/plugin.json +++ b/plugin.json @@ -1,7 +1,7 @@ { "name": "CustomAlerts", "description": "Create custom Alerts to be notified of important changes on your website or app! ", - "version": "5.3.0", + "version": "5.3.1", "require": { "matomo": ">=5.0.0-b1,<6.0.0-b1" }, diff --git a/tests/Integration/ProcessorTest.php b/tests/Integration/ProcessorTest.php index 11b34da..38e63fc 100644 --- a/tests/Integration/ProcessorTest.php +++ b/tests/Integration/ProcessorTest.php @@ -68,6 +68,11 @@ public function shouldBeTriggered($alert, $metricOne, $metricTwo) { return parent::shouldBeTriggered($alert, $metricOne, $metricTwo); } + + public function restrictMultiSitesReportToAlertOwner(array $params, array $report, array $alert): array + { + return parent::restrictMultiSitesReportToAlertOwner($params, $report, $alert); + } } /** @@ -619,6 +624,39 @@ public function test_processAlert_shouldOnlyBeTriggeredIfAlertMatches() $processorMock->processAlert($alert, 1); } + public function test_restrictMultiSitesReportToAlertOwner_shouldRestrictMultiSitesGetAllForAlertOwner() + { + $params = $this->processor->restrictMultiSitesReportToAlertOwner( + [], + ['module' => 'MultiSites', 'action' => 'getAll'], + ['login' => 'aUser'] + ); + + $this->assertSame('aUser', $params['_restrictSitesToLogin']); + } + + public function test_restrictMultiSitesReportToAlertOwner_shouldNotRestrictSuperUserAlertOwner() + { + $params = $this->processor->restrictMultiSitesReportToAlertOwner( + [], + ['module' => 'MultiSites', 'action' => 'getAll'], + ['login' => 'superUserLogin'] + ); + + $this->assertArrayNotHasKey('_restrictSitesToLogin', $params); + } + + public function test_restrictMultiSitesReportToAlertOwner_shouldNotRestrictOtherReports() + { + $params = $this->processor->restrictMultiSitesReportToAlertOwner( + [], + ['module' => 'VisitsSummary', 'action' => 'get'], + ['login' => 'aUser'] + ); + + $this->assertArrayNotHasKey('_restrictSitesToLogin', $params); + } + public function test_shouldBeTriggered_ShouldFail_IfInvalidConditionGiven() { $this->expectException(\Exception::class);