Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Giehl <stefan@matomo.org>2022-04-12 11:01:53 +0300
committerGitHub <noreply@github.com>2022-04-12 11:01:53 +0300
commitb12ef7e8fa0bc4f693244f4110c64564613f380c (patch)
tree637470d65f01c85d2620f9d393cbef770099f008
parent341265be9076ce16b96b023029092ddfb0c8b155 (diff)
Prevent failure in scheduled report task if a user does no longer have access (#19068)
* Prevent failure in scheduled report task if a user does no longer have access * apply PSR12 code formatting
-rw-r--r--plugins/ScheduledReports/API.php196
1 files changed, 121 insertions, 75 deletions
diff --git a/plugins/ScheduledReports/API.php b/plugins/ScheduledReports/API.php
index 2259c0e56b..0d0e9d6be7 100644
--- a/plugins/ScheduledReports/API.php
+++ b/plugins/ScheduledReports/API.php
@@ -1,4 +1,5 @@
<?php
+
/**
* Matomo - free/libre analytics platform
*
@@ -6,6 +7,7 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
+
namespace Piwik\Plugins\ScheduledReports;
use Exception;
@@ -67,7 +69,7 @@ class API extends \Piwik\Plugin\API
private $enableSaveReportOnDisk = false;
// static cache storing reports
- public static $cache = array();
+ public static $cache = [];
/**
* @var LoggerInterface
@@ -98,9 +100,20 @@ class API extends \Piwik\Plugin\API
*
* @return int idReport generated
*/
- public function addReport($idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false,
- $evolutionPeriodFor = 'prev', $evolutionPeriodN = null, $periodParam = null)
- {
+ public function addReport(
+ $idSite,
+ $description,
+ $period,
+ $hour,
+ $reportType,
+ $reportFormat,
+ $reports,
+ $parameters,
+ $idSegment = false,
+ $evolutionPeriodFor = 'prev',
+ $evolutionPeriodN = null,
+ $periodParam = null
+ ) {
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasViewAccess($idSite);
@@ -115,13 +128,13 @@ class API extends \Piwik\Plugin\API
// validation of requested reports
$reports = self::validateRequestedReports($idSite, $reportType, $reports);
- $idReport = $this->getModel()->createReport(array(
+ $idReport = $this->getModel()->createReport([
'idsite' => $idSite,
'login' => $currentUser,
'description' => $description,
'idsegment' => $idSegment,
'period' => $period,
- 'period_param'=> $periodParam,
+ 'period_param' => $periodParam,
'hour' => $hour,
'type' => $reportType,
'format' => $reportFormat,
@@ -131,7 +144,7 @@ class API extends \Piwik\Plugin\API
'deleted' => 0,
'evolution_graph_within_period' => $evolutionPeriodFor == 'each',
'evolution_graph_period_n' => $evolutionPeriodN ?: ImageGraph::getDefaultGraphEvolutionLastPeriods(),
- ));
+ ]);
return $idReport;
}
@@ -155,9 +168,21 @@ class API extends \Piwik\Plugin\API
*
* @see addReport()
*/
- public function updateReport($idReport, $idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false,
- $evolutionPeriodFor = 'prev', $evolutionPeriodN = null, $periodParam = null)
- {
+ public function updateReport(
+ $idReport,
+ $idSite,
+ $description,
+ $period,
+ $hour,
+ $reportType,
+ $reportFormat,
+ $reports,
+ $parameters,
+ $idSegment = false,
+ $evolutionPeriodFor = 'prev',
+ $evolutionPeriodN = null,
+ $periodParam = null
+ ) {
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasViewAccess($idSite);
@@ -176,11 +201,11 @@ class API extends \Piwik\Plugin\API
// validation of requested reports
$reports = self::validateRequestedReports($idSite, $reportType, $reports);
- $this->getModel()->updateReport($idReport, array(
+ $this->getModel()->updateReport($idReport, [
'description' => $description,
'idsegment' => $idSegment,
'period' => $period,
- 'period_param'=> $periodParam,
+ 'period_param' => $periodParam,
'hour' => $hour,
'type' => $reportType,
'format' => $reportFormat,
@@ -188,9 +213,9 @@ class API extends \Piwik\Plugin\API
'reports' => $reports,
'evolution_graph_within_period' => $evolutionPeriodFor == 'each',
'evolution_graph_period_n' => $evolutionPeriodN ?: ImageGraph::getDefaultGraphEvolutionLastPeriods(),
- ));
+ ]);
- self::$cache = array();
+ self::$cache = [];
}
/**
@@ -204,11 +229,11 @@ class API extends \Piwik\Plugin\API
$report = reset($APIScheduledReports);
Piwik::checkUserHasSuperUserAccessOrIsTheUser($report['login']);
- $this->getModel()->updateReport($idReport, array(
+ $this->getModel()->updateReport($idReport, [
'deleted' => 1,
- ));
+ ]);
- self::$cache = array();
+ self::$cache = [];
}
/**
@@ -232,10 +257,11 @@ class API extends \Piwik\Plugin\API
}
$sqlWhere = '';
- $bind = array();
+ $bind = [];
// Super user gets all reports back, other users only their own
- if (!Piwik::hasUserSuperUserAccess()
+ if (
+ !Piwik::hasUserSuperUserAccess()
|| $ifSuperUserReturnOnlySuperUserReports
) {
$sqlWhere .= "AND login = ?";
@@ -269,7 +295,8 @@ class API extends \Piwik\Plugin\API
WHERE deleted = 0
$sqlWhere", $bind);
// When a specific report was requested and not found, throw an error
- if ($idReport !== false
+ if (
+ $idReport !== false
&& empty($reports)
) {
throw new Exception("Requested report couldn't be found.");
@@ -282,7 +309,10 @@ class API extends \Piwik\Plugin\API
// decode report list
$report['reports'] = json_decode($report['reports'], true);
- if (!empty($report['parameters']['additionalEmails']) && is_array($report['parameters']['additionalEmails'])) {
+ if (
+ !empty($report['parameters']['additionalEmails'])
+ && is_array($report['parameters']['additionalEmails'])
+ ) {
$report['parameters']['additionalEmails'] = array_values($report['parameters']['additionalEmails']);
}
@@ -315,8 +345,15 @@ class API extends \Piwik\Plugin\API
* @param bool|false|array $parameters array of parameters
* @return array|void
*/
- public function generateReport($idReport, $date, $language = false, $outputType = false, $period = false, $reportFormat = false, $parameters = false)
- {
+ public function generateReport(
+ $idReport,
+ $date,
+ $language = false,
+ $outputType = false,
+ $period = false,
+ $reportFormat = false,
+ $parameters = false
+ ) {
Piwik::checkUserIsNotAnonymous();
if (!$this->enableSaveReportOnDisk && $outputType == self::OUTPUT_SAVE_ON_DISK) {
@@ -373,7 +410,7 @@ class API extends \Piwik\Plugin\API
$availableReportMetadata = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite);
// we need to lookup which reports metadata are registered in this report
- $reportMetadata = array();
+ $reportMetadata = [];
foreach ($availableReportMetadata as $metadata) {
if (in_array($metadata['uniqueId'], $report['reports'])) {
$reportMetadata[] = $metadata;
@@ -386,12 +423,12 @@ class API extends \Piwik\Plugin\API
$_GET['filter_truncate'] = Config::getInstance()->General['scheduled_reports_truncate'];
$prettyDate = null;
- $processedReports = array();
+ $processedReports = [];
$segment = self::getSegment($report['idsegment']);
foreach ($reportMetadata as $action) {
$apiModule = $action['module'];
$apiAction = $action['action'];
- $apiParameters = array();
+ $apiParameters = [];
if (isset($action['parameters'])) {
$apiParameters = $action['parameters'];
}
@@ -410,7 +447,8 @@ class API extends \Piwik\Plugin\API
// when a view/admin user created a report, workaround the fact that "Super User"
// is enforced in Scheduled tasks, and ensure Multisites.getAll only return the websites that this user can access
$userLogin = $report['login'];
- if (!empty($userLogin)
+ if (
+ !empty($userLogin)
&& !Piwik::hasTheUserSuperUserAccess($userLogin)
) {
$_GET['_restrictSitesToLogin'] = $userLogin;
@@ -418,7 +456,7 @@ class API extends \Piwik\Plugin\API
}
}
- $params = array(
+ $params = [
'idSite' => $idSite,
'period' => $period,
'date' => $date,
@@ -430,7 +468,7 @@ class API extends \Piwik\Plugin\API
'language' => $language,
'serialize' => 0,
'format' => 'original'
- );
+ ];
if ($segment != null) {
$params['segment'] = urlencode($segment['definition']);
@@ -442,10 +480,10 @@ class API extends \Piwik\Plugin\API
$processedReport = Request::processRequest('API.getProcessedReport', $params);
} catch (\Exception $ex) {
// NOTE: can't use warning or error because the log message will appear in the UI as a notification
- $this->logger->info("Error getting '?{report}' when generating scheduled report: {exception}", array(
+ $this->logger->info("Error getting '?{report}' when generating scheduled report: {exception}", [
'report' => Http::buildQuery($params),
'exception' => $ex->getMessage(),
- ));
+ ]);
$this->logger->debug($ex);
@@ -492,7 +530,7 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent(
self::PROCESS_REPORTS_EVENT,
- array(&$processedReports, $reportType, $outputType, $report)
+ [&$processedReports, $reportType, $outputType, $report]
);
$reportRenderer = null;
@@ -514,7 +552,7 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent(
self::GET_RENDERER_INSTANCE_EVENT,
- array(&$reportRenderer, $reportType, $outputType, $report)
+ [&$reportRenderer, $reportType, $outputType, $report]
);
if (is_null($reportRenderer)) {
@@ -527,47 +565,44 @@ class API extends \Piwik\Plugin\API
$reportRenderer->setReport($report);
// render report
- $description = str_replace(array("\r", "\n"), ' ', Common::unsanitizeInputValue($report['description']));
+ $description = str_replace(["\r", "\n"], ' ', Common::unsanitizeInputValue($report['description']));
- list($reportSubject, $reportTitle) = self::getReportSubjectAndReportTitle(Common::unsanitizeInputValue(Site::getNameFor($idSite)), $report['reports']);
+ [$reportSubject, $reportTitle] = self::getReportSubjectAndReportTitle(Common::unsanitizeInputValue(Site::getNameFor($idSite)), $report['reports']);
// if reporting for a segment, use the segment's name in the title
- if(is_array($segment) && strlen($segment['name'])) {
- $reportTitle .= " - ".$segment['name'];
+ if (is_array($segment) && strlen($segment['name'])) {
+ $reportTitle .= " - " . $segment['name'];
}
$filename = "$reportTitle - $prettyDate - $description";
$reportRenderer->renderFrontPage($reportTitle, $prettyDate, $description, $reportMetadata, $segment);
- array_walk($processedReports, array($reportRenderer, 'renderReport'));
+ array_walk($processedReports, [$reportRenderer, 'renderReport']);
switch ($outputType) {
-
case self::OUTPUT_SAVE_ON_DISK:
// only used for SendReport
$outputFilename = strtoupper($reportFormat) . ' ' . ucfirst($reportType) . ' Report - ' . $idReport . '.' . $date . '.' . $idSite . '.' . $language;
- $outputFilename .= ' - ' . Common::getRandomString(40,'abcdefghijklmnoprstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ_');
+ $outputFilename .= ' - ' . Common::getRandomString(40, 'abcdefghijklmnoprstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ_');
$outputFilename = $reportRenderer->sendToDisk($outputFilename);
$additionalFiles = $this->getAttachments($reportRenderer, $report, $processedReports, $prettyDate);
- return array(
+ return [
$outputFilename,
$prettyDate,
$reportSubject,
$reportTitle,
$additionalFiles,
- );
+ ];
break;
case self::OUTPUT_INLINE:
-
$reportRenderer->sendToBrowserInline($filename);
break;
case self::OUTPUT_RETURN:
-
return $reportRenderer->getRenderedReport();
break;
@@ -600,7 +635,7 @@ class API extends \Piwik\Plugin\API
// generate report
$this->enableSaveReportOnDisk = true;
try {
- list($outputFilename, $prettyDate, $reportSubject, $reportTitle, $additionalFiles) =
+ [$outputFilename, $prettyDate, $reportSubject, $reportTitle, $additionalFiles] =
$this->generateReport(
$idReport,
$date,
@@ -608,7 +643,11 @@ class API extends \Piwik\Plugin\API
self::OUTPUT_SAVE_ON_DISK,
$report['period_param']
);
-
+ } catch (NoAccessException $e) {
+ // This might occur if for some reason a report exists where the user does no longer have access to the
+ // configured site. Normally those reports should be automatically deleted.
+ Log::info("Skipping report as user does no longer have access to configured site");
+ return;
} catch (\Throwable $e) {
$this->enableSaveReportOnDisk = false;
throw new RetryableException($e->getMessage());
@@ -655,7 +694,7 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent(
self::SEND_REPORT_EVENT,
- array(
+ [
&$reportType,
$report,
$contents,
@@ -666,12 +705,12 @@ class API extends \Piwik\Plugin\API
$additionalFiles,
\Piwik\Period\Factory::build($report['period_param'], $date),
$force
- )
+ ]
);
// Update flag in DB
$now = Date::now()->getDatetime();
- $this->getModel()->updateReport($report['idreport'], array('ts_last_sent' => $now));
+ $this->getModel()->updateReport($report['idreport'], ['ts_last_sent' => $now]);
if (!Development::isEnabled()) {
@chmod($outputFilename, 0600);
@@ -690,20 +729,21 @@ class API extends \Piwik\Plugin\API
// if the only report is "All websites", we don't display the site name
$reportTitle = $websiteName;
$reportSubject = $websiteName;
- if (count($reports) == 1
+ if (
+ count($reports) == 1
&& $reports[0] == 'MultiSites_getAll'
) {
$reportSubject = Piwik::translate('General_MultiSitesSummary');
$reportTitle = $reportSubject;
}
- return array($reportSubject, $reportTitle);
+ return [$reportSubject, $reportTitle];
}
private static function validateReportParameters($reportType, $parameters)
{
// get list of valid parameters
- $availableParameters = array();
+ $availableParameters = [];
/**
* Triggered when gathering the available parameters for a scheduled report type.
@@ -717,7 +757,7 @@ class API extends \Piwik\Plugin\API
* @param string $reportType A string ID describing how the report is sent, eg,
* `'sms'` or `'email'`.
*/
- Piwik::postEvent(self::GET_REPORT_PARAMETERS_EVENT, array(&$availableParameters, $reportType));
+ Piwik::postEvent(self::GET_REPORT_PARAMETERS_EVENT, [&$availableParameters, $reportType]);
// unset invalid parameters
$availableParameterKeys = array_keys($availableParameters);
@@ -744,7 +784,7 @@ class API extends \Piwik\Plugin\API
* @param string $reportType A string ID describing how the report is sent, eg,
* `'sms'` or `'email'`.
*/
- Piwik::postEvent(self::VALIDATE_PARAMETERS_EVENT, array(&$parameters, $reportType));
+ Piwik::postEvent(self::VALIDATE_PARAMETERS_EVENT, [&$parameters, $reportType]);
return json_encode($parameters);
}
@@ -764,7 +804,7 @@ class API extends \Piwik\Plugin\API
// retrieve available reports
$availableReportMetadata = self::getReportMetadata($idSite, $reportType);
- $availableReportIds = array();
+ $availableReportIds = [];
foreach ($availableReportMetadata as $reportMetadata) {
$availableReportIds[] = $reportMetadata['uniqueId'];
}
@@ -778,8 +818,16 @@ class API extends \Piwik\Plugin\API
return json_encode($requestedReports);
}
- private static function validateCommonReportAttributes($period, $hour, &$description, &$idSegment, $reportType, $reportFormat, $evolutionPeriodFor, $evolutionPeriodN)
- {
+ private static function validateCommonReportAttributes(
+ $period,
+ $hour,
+ &$description,
+ &$idSegment,
+ $reportType,
+ $reportFormat,
+ $evolutionPeriodFor,
+ $evolutionPeriodN
+ ) {
self::validateReportPeriod($period);
self::validateReportHour($hour);
self::validateAndTruncateDescription($description);
@@ -791,7 +839,7 @@ class API extends \Piwik\Plugin\API
private static function validateReportPeriod($period)
{
- $availablePeriods = array('day', 'week', 'month', 'never');
+ $availablePeriods = ['day', 'week', 'month', 'never'];
if (!in_array($period, $availablePeriods)) {
throw new Exception('Period schedule must be one of the following: ' . implode(', ', $availablePeriods) . ' (got ' . $period . ')');
}
@@ -807,13 +855,10 @@ class API extends \Piwik\Plugin\API
private static function validateIdSegment(&$idSegment)
{
if (empty($idSegment) || (is_numeric($idSegment) && $idSegment == 0)) {
-
$idSegment = null;
} elseif (!is_numeric($idSegment)) {
-
throw new Exception('Invalid segment identifier. Should be an integer.');
} elseif (self::getSegment($idSegment) == null) {
-
throw new Exception('Segment with id ' . $idSegment . ' does not exist or SegmentEditor is not activated.');
}
}
@@ -837,7 +882,7 @@ class API extends \Piwik\Plugin\API
throw new Exception(
Piwik::translate(
'General_ExceptionInvalidReportRendererFormat',
- array($reportFormat, implode(', ', $reportFormats))
+ [$reportFormat, implode(', ', $reportFormats)]
)
);
}
@@ -853,7 +898,8 @@ class API extends \Piwik\Plugin\API
throw new \Exception('The evolutionPeriodN param has no effect when evolutionPeriodFor is "each".');
}
- if (!empty($evolutionPeriodN)
+ if (
+ !empty($evolutionPeriodN)
&& (!is_numeric($evolutionPeriodN) || (int)$evolutionPeriodN < 0)
) {
throw new \Exception('Evolution period amount must be a positive number (got ' . $evolutionPeriodN . ').');
@@ -865,7 +911,7 @@ class API extends \Piwik\Plugin\API
*/
public static function getReportMetadata($idSite, $reportType)
{
- $availableReportMetadata = array();
+ $availableReportMetadata = [];
/**
* TODO: change this event so it returns a list of API methods instead of report metadata arrays.
@@ -883,7 +929,7 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent(
self::GET_REPORT_METADATA_EVENT,
- array(&$availableReportMetadata, $reportType, $idSite)
+ [&$availableReportMetadata, $reportType, $idSite]
);
return $availableReportMetadata;
@@ -911,7 +957,7 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent(
self::ALLOW_MULTIPLE_REPORTS_EVENT,
- array(&$allowMultipleReports, $reportType)
+ [&$allowMultipleReports, $reportType]
);
return $allowMultipleReports;
}
@@ -921,7 +967,7 @@ class API extends \Piwik\Plugin\API
*/
public static function getReportTypes()
{
- $reportTypes = array();
+ $reportTypes = [];
/**
* Triggered when gathering all available transport mediums.
@@ -932,7 +978,7 @@ class API extends \Piwik\Plugin\API
* @param array &$reportTypes An array mapping transport medium IDs with the paths to those
* mediums' icons. Add your new backend's ID to this array.
*/
- Piwik::postEvent(self::GET_REPORT_TYPES_EVENT, array(&$reportTypes));
+ Piwik::postEvent(self::GET_REPORT_TYPES_EVENT, [&$reportTypes]);
return $reportTypes;
}
@@ -942,7 +988,7 @@ class API extends \Piwik\Plugin\API
*/
public static function getReportFormats($reportType)
{
- $reportFormats = array();
+ $reportFormats = [];
/**
* Triggered when gathering all available scheduled report formats.
@@ -958,7 +1004,7 @@ class API extends \Piwik\Plugin\API
*/
Piwik::postEvent(
self::GET_REPORT_FORMATS_EVENT,
- array(&$reportFormats, $reportType)
+ [&$reportFormats, $reportType]
);
return $reportFormats;
@@ -969,7 +1015,7 @@ class API extends \Piwik\Plugin\API
*/
public static function getReportRecipients($report)
{
- $recipients = array();
+ $recipients = [];
/**
* Triggered when getting the list of recipients of a scheduled report.
@@ -987,7 +1033,7 @@ class API extends \Piwik\Plugin\API
* @param array $report An array describing the scheduled report that is being
* generated.
*/
- Piwik::postEvent(self::GET_REPORT_RECIPIENTS_EVENT, array(&$recipients, $report['type'], $report));
+ Piwik::postEvent(self::GET_REPORT_RECIPIENTS_EVENT, [&$recipients, $report['type'], $report]);
return $recipients;
}
@@ -998,7 +1044,6 @@ class API extends \Piwik\Plugin\API
public static function getSegment($idSegment)
{
if (self::isSegmentEditorActivated() && !empty($idSegment)) {
-
$segment = APISegmentEditor::getInstance()->get($idSegment);
if ($segment) {
@@ -1030,10 +1075,11 @@ class API extends \Piwik\Plugin\API
$idSitesUserHasAccess = SitesManagerApi::getInstance()->getSitesIdWithAtLeastViewAccess($login);
- if (empty($idSitesUserHasAccess)
+ if (
+ empty($idSitesUserHasAccess)
|| !in_array($idSite, $idSitesUserHasAccess)
) {
- throw new NoAccessException(Piwik::translate('General_ExceptionPrivilege', array("'view'")));
+ throw new NoAccessException(Piwik::translate('General_ExceptionPrivilege', ["'view'"]));
}
}