From 33a5f765b9ae5c86d63abc9c9d3c0dd3e0eb5ef9 Mon Sep 17 00:00:00 2001 From: raviks789 <33730024+raviks789@users.noreply.github.com> Date: Tue, 18 Jul 2023 10:30:27 +0200 Subject: [PATCH] Use `style` element to create css class for dynamic inline style The `style` element with `nonce` attribute is used to create css classes for inline styles that are not static. This prevents Content-Security-Policy violations. --- .../Web/Widget/Chart/HistoryColorGrid.php | 53 ++++++++--- .../views/scripts/timeline/index.phtml | 87 +++++++++++++---- .../views/scripts/index/index.phtml | 95 ++++++++++++++++--- public/css/icinga/setup.less | 8 -- 4 files changed, 192 insertions(+), 51 deletions(-) diff --git a/library/Icinga/Web/Widget/Chart/HistoryColorGrid.php b/library/Icinga/Web/Widget/Chart/HistoryColorGrid.php index ed1e37790..b7b50d046 100644 --- a/library/Icinga/Web/Widget/Chart/HistoryColorGrid.php +++ b/library/Icinga/Web/Widget/Chart/HistoryColorGrid.php @@ -6,7 +6,9 @@ namespace Icinga\Web\Widget\Chart; use DateInterval; use DateTime; use Icinga\Util\Color; +use Icinga\Util\Csp; use Icinga\Web\Widget\AbstractWidget; +use ipl\Web\Style; /** * Display a colored grid that visualizes a set of values for each day @@ -32,6 +34,9 @@ class HistoryColorGrid extends AbstractWidget private $color; public $opacity = 1.0; + /** @var array> History grid css rulesets */ + protected $rulesets = []; + public function __construct($color = '#51e551', $start = null, $end = null) { $this->setColor($color); @@ -123,18 +128,30 @@ class HistoryColorGrid extends AbstractWidget { if (array_key_exists($day, $this->data) && $this->data[$day]['value'] > 0) { $entry = $this->data[$day]; - return ''; + $this->rulesets['.grid-day-with-entry-' . $entry['value']] = [ + 'background-color' => $this->calculateColor($entry['value']), + 'opacity' => $this->opacity + ]; + + return ''; } else { - return ''; + if (! isset($this->rulesets['.grid-day-no-entry'])) { + $this->rulesets['.grid-day-no-entry'] = [ + 'background-color' => $this->calculateColor(0), + 'opacity' => $this->opacity + ]; + } + + return ''; } } @@ -366,8 +383,18 @@ class HistoryColorGrid extends AbstractWidget } $grid = $this->createGrid(); if ($this->orientation === self::ORIENTATION_HORIZONTAL) { - return $this->renderHorizontal($grid); + $html = $this->renderHorizontal($grid); + } else { + $html = $this->renderVertical($grid); } - return $this->renderVertical($grid); + + $historyGridStyle = new Style(); + $historyGridStyle->setNonce(Csp::getStyleNonce()); + + foreach ($this->rulesets as $selector => $properties) { + $historyGridStyle->add($selector, $properties); + } + + return $html . $historyGridStyle; } } diff --git a/modules/monitoring/application/views/scripts/timeline/index.phtml b/modules/monitoring/application/views/scripts/timeline/index.phtml index af3b406cc..cab18ebc9 100644 --- a/modules/monitoring/application/views/scripts/timeline/index.phtml +++ b/modules/monitoring/application/views/scripts/timeline/index.phtml @@ -1,9 +1,15 @@ getGroupInfo(); $firstRow = ! $beingExtended; +$timelineStyle = (new Style()) + ->setNonce(Csp::getStyleNonce()) + ->setModule('monitoring'); if (! $beingExtended && !$this->compact): ?>
@@ -79,24 +85,72 @@ if (! $beingExtended && !$this->compact): ?> $labelAndColor): ?> calculateCircleWidth($timeInfo[1][$groupName], 2); $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$groupName], 2); ?> -
-
+ add( + "#circle-box-$styleId", + ['width' => $extrapolatedCircleWidth] + ); + + $timelineStyle->add( + "#outer-circle-$styleId", + [ + 'width' => $extrapolatedCircleWidth, + 'height' => $extrapolatedCircleWidth, + 'margin-top' => sprintf( + '-%Fem', + (float)substr($extrapolatedCircleWidth, 0, -2) / 2 + ) + ] + ); + + ?> +
+
-
-
+ add( + "#circle-box-$styleId", + ['width' => $circleWidth] + ); + + $timelineStyle->add( + "#outer-circle-$styleId", + [ + 'width' => $circleWidth, + 'height' => $circleWidth, + 'margin-top' => sprintf( + '-%Fem', + (float)substr($circleWidth, 0, -2) / 2 + ) + ] + ); + + ?> +
+
+add( + "#inner-circle-$styleId", + [ + 'width' => $circleWidth, + 'height' => $circleWidth, + 'margin-top' => sprintf( + '-%Fem', + (float)substr($circleWidth, 0, -2) / 2 + ), + 'margin-left' => sprintf( + '-%Fem', + (float)substr($circleWidth, 0, -2) / 2 + ), + ] +); +?> qlink( '', $timeInfo[1][$groupName]->getDetailUrl(), @@ -112,12 +166,8 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g strtolower($labelAndColor['label']), $titleTime ), - 'class' => 'inner-circle ' . $timeInfo[1][$groupName]->getClass(), - 'style' => sprintf( - 'width: %2$s; height: %2$s; margin-top: -%1$Fem; margin-left: -%1$Fem;', - (float) substr($circleWidth, 0, -2) / 2, - (string) $circleWidth - ) + 'id' => "inner-circle-$styleId", + 'class' => "inner-circle " . $timeInfo[1][$groupName]->getClass() ) ); ?>
@@ -143,3 +193,4 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
+ diff --git a/modules/setup/application/views/scripts/index/index.phtml b/modules/setup/application/views/scripts/index/index.phtml index cbb50653c..32952e7d3 100644 --- a/modules/setup/application/views/scripts/index/index.phtml +++ b/modules/setup/application/views/scripts/index/index.phtml @@ -1,12 +1,17 @@ getPages(); $finished = isset($success); $configPages = array_slice($pages, 3, count($pages) - 4, true); $currentPos = array_search($wizard->getCurrentPage(), $pages, true); list($configPagesLeft, $configPagesRight) = array_chunk($configPages, (int)(count($configPages) / 2), true); +$setupStyle = (new Style()) + ->setSelector('.setup-header > .progress-bar') + ->setNonce(Csp::getStyleNonce()); $visitedPages = array_keys($wizard->getPageData()); $maxProgress = max(array_merge([0], array_keys(array_filter( @@ -14,6 +19,13 @@ $maxProgress = max(array_merge([0], array_keys(array_filter( function ($page) use ($visitedPages) { return in_array($page->getName(), $visitedPages); } )))); +$setupStyle->add( + '.width-percent-10', + ['width' => '10%'] +)->add( + '.width-percent-60', + ['width' => '60%'] +); ?>
@@ -76,14 +88,43 @@ $maxProgress = max(array_merge([0], array_keys(array_filter( $pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '') ); ?> -
+ add( + '.step .left-line-' . $pos, + [ + 'float' => 'left', + 'width' => sprintf( + '%.2F%%', + 100 - (count($configPagesLeft) - 1) * $lineWidth + ), + 'margin-right' => 0 + ] + ); + ?> +
-
+ add( + '.step .left-line-' . $pos, + [ + 'float' => 'left', + 'width' => $lineWidth . '%', + 'margin-right' => '-0.1em' + ] + ); + ?> +
-
+ add( + '.step .left-line-' . $pos, + [ + 'float' => 'left', + 'width' => $lineWidth . '%' + ] + ); + ?> +
@@ -106,14 +147,43 @@ $maxProgress = max(array_merge([0], array_keys(array_filter( $pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '') ); ?> -
+ add( + '.step .right-line-' . $pos, + [ + 'float' => 'left', + 'width' => $lineWidth . '%', + 'margin-right' => '-0.1em' + ] + ); + ?> +
-
+ add( + '.step .right-line-' . $pos, + [ + 'float' => 'left', + 'width' => sprintf( + '%.2F%%', + 100 - (count($configPagesRight) - 1) * $lineWidth + ), + 'margin-right' => 0 + ] + ); + ?> +
-
+ add( + '.step .right-line-' . $pos, + [ + 'float' => 'left', + 'width' => $lineWidth . '%' + ] + ); + ?> +
@@ -151,3 +221,4 @@ $maxProgress = max(array_merge([0], array_keys(array_filter( } ?>
+ diff --git a/public/css/icinga/setup.less b/public/css/icinga/setup.less index 25cc6ef7e..c848bc7dd 100644 --- a/public/css/icinga/setup.less +++ b/public/css/icinga/setup.less @@ -114,14 +114,6 @@ } } -.width-percent-10 { - width: 10%; -} - -.width-percent-60 { - width: 60%; -} - .setup-content { padding: 1.5em 10em 0 10em;