Skip to content

Commit

Permalink
Apply csp to inline css style
Browse files Browse the repository at this point in the history
  • Loading branch information
sukhwinder33445 committed Jul 18, 2023
1 parent 95b50e9 commit 729ade3
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 57 deletions.
56 changes: 56 additions & 0 deletions library/Icingadb/Common/InlineStyleWithCsp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Icingadb\Common;

use Icinga\Application\Icinga;
use Icinga\Util\Csp;
use ipl\Html\BaseHtmlElement;
use ipl\Web\Style;

trait InlineStyleWithCsp
{
/** @var ?Style Used classes are prefixed with `style` */
private $style;

protected function getStyle(): Style
{
if ($this->style === null) {
$parentSelector = $this->getCssClasses($this);

Csp::createNonces(); // todo: must work without
$this->style = (new Style())
->setSelector($parentSelector)
->setModule(Icinga::app()->getRequest()->getModuleName())
->setNonce(Csp::getStyleNonce());
}

return $this->style;
}


/**
* Get css classes of the given element (with `.` prefix)
*
* @param BaseHtmlElement $element
*
* @return string
*/
protected function getCssClasses(BaseHtmlElement $element): string
{
$classes = array_map(
function($value) {return preg_replace('/^|\s/', '.', $value);},
(array) $element->getAttributes()->get('class')->getValue()
);

return implode('', $classes);
}

protected function addStyle(BaseHtmlElement $element, array $properties): void
{
$randomClass = uniqid('style-', false);
$this->getStyle()->add($this->getCssClasses($element) . '.' . $randomClass, $properties);
$element->addAttributes(['class' => $randomClass]);
}
}
46 changes: 25 additions & 21 deletions library/Icingadb/Widget/Detail/CheckStatistics.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Icinga\Module\Icingadb\Widget\Detail;

use Icinga\Date\DateFormatter;
use Icinga\Module\Icingadb\Common\InlineStyleWithCsp;
use Icinga\Module\Icingadb\Widget\CheckAttempt;
use Icinga\Module\Icingadb\Widget\EmptyState;
use Icinga\Util\Format;
Expand All @@ -23,6 +24,8 @@

class CheckStatistics extends Card
{
use InlineStyleWithCsp;

const TOP_LEFT_BUBBLE_FLAG = <<<'SVG'
<svg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'>
<path class='bg' d='M0 0L13 13L3.15334e-06 13L0 0Z'/>
Expand Down Expand Up @@ -124,7 +127,7 @@ protected function assembleBody(BaseHtmlElement $body)
}
}

$progressBar->getAttributes()->add('style', sprintf('width: %s%%', $leftNow));
$this->addStyle($progressBar, ['width' => $leftNow . '%']);

$leftExecutionEnd = $nextCheckTime !== null ? $durationScale * (
1 - ($nextCheckTime - $executionEndTime) / ($nextCheckTime - $lastUpdateTime)
Expand All @@ -138,10 +141,8 @@ protected function assembleBody(BaseHtmlElement $body)
'class' => ['highlighted', 'marker', 'right'],
'title' => $nextCheckTime !== null ? DateFormatter::formatDateTime($nextCheckTime) : null
]));
$markerExecutionEnd = new HtmlElement('div', Attributes::create([
'class' => ['highlighted', 'marker'],
'style' => sprintf('left: %F%%', $hPadding + $leftExecutionEnd),
]));
$markerExecutionEnd = new HtmlElement('div', Attributes::create(['class' => ['highlighted', 'marker']]));
$this->addStyle($markerExecutionEnd, ['left' => ($hPadding + $leftExecutionEnd) . '%']);

$progress = new HtmlElement('div', Attributes::create([
'class' => ['progress', time() < $executionEndTime ? 'running' : null]
Expand Down Expand Up @@ -178,10 +179,7 @@ protected function assembleBody(BaseHtmlElement $body)
);
$executionEnd = new HtmlElement(
'li',
Attributes::create([
'class' => 'positioned',
'style' => sprintf('left: %F%%', $hPadding + $leftExecutionEnd)
]),
Attributes::create(['class' => 'positioned']),
new HtmlElement(
'div',
Attributes::create(['class' => ['bubble', 'upwards', 'top-left-aligned']]),
Expand All @@ -197,29 +195,27 @@ protected function assembleBody(BaseHtmlElement $body)
)
);

$this->addStyle($executionEnd, ['left' => ($hPadding + $leftExecutionEnd) . '%']);

$intervalLine = new HtmlElement(
'li',
Attributes::create([
'class' => 'interval-line',
'style' => sprintf(
'left: %F%%; width: %F%%;',
$hPadding + $leftExecutionEnd,
$durationScale - $leftExecutionEnd
)
]),
Attributes::create(['class' => 'interval-line']),
new VerticalKeyValue(
t('Interval'),
$checkInterval
? Format::seconds($checkInterval)
: (new EmptyState(t('n. a.')))->setTag('span')
)
);

$this->addStyle($intervalLine, [
'left' => ($hPadding + $leftExecutionEnd) . '%',
'width' => ($durationScale - $leftExecutionEnd) . '%'
]);

$executionLine = new HtmlElement(
'li',
Attributes::create([
'class' => ['interval-line', 'execution-line'],
'style' => sprintf('left: %F%%; width: %F%%;', $hPadding, $leftExecutionEnd)
]),
Attributes::create(['class' => ['interval-line', 'execution-line']]),
new VerticalKeyValue(
sprintf('%s / %s', t('Execution Time'), t('Latency')),
FormattedString::create(
Expand All @@ -233,6 +229,12 @@ protected function assembleBody(BaseHtmlElement $body)
)
)
);

$this->addStyle($executionLine, [
'left' => $hPadding . '%',
'width' => $leftExecutionEnd . '%'
]);

if ($executionEndTime !== null) {
$executionLine->addHtml(new HtmlElement('div', Attributes::create(['class' => 'start'])));
$executionLine->addHtml(new HtmlElement('div', Attributes::create(['class' => 'end'])));
Expand Down Expand Up @@ -368,5 +370,7 @@ protected function assemble()
)
));
}

echo $this->getStyle();
}
}
73 changes: 37 additions & 36 deletions library/Icingadb/Widget/Detail/DowntimeCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Icinga\Module\Icingadb\Widget\Detail;

use Icinga\Module\Icingadb\Common\InlineStyleWithCsp;
use Icinga\Module\Icingadb\Model\Downtime;
use ipl\Html\Attributes;
use ipl\Html\HtmlElement;
Expand All @@ -15,6 +16,8 @@

class DowntimeCard extends BaseHtmlElement
{
use InlineStyleWithCsp;

protected $downtime;

protected $duration;
Expand Down Expand Up @@ -85,15 +88,15 @@ protected function assemble()

$markerFlexStart = new HtmlElement('div', Attributes::create([
'class' => ['highlighted', 'marker'],
'style' => sprintf('left: %F%%', $flexStartLeft)
]));
$this->addStyle($markerFlexStart, ['left' => $flexStartLeft . '%']);

$markerFlexEnd = new HtmlElement('div', Attributes::create([
'class' => ['highlighted', 'marker'],
'style' => sprintf('left: %F%%', $flexEndLeft)
'class' => ['highlighted', 'marker']
]));
$this->addStyle($markerFlexEnd, ['left' => $flexEndLeft . '%']);

$markerStart->getAttributes()->remove('class', 'highlighted');
$markerStart->getAttributes()->remove('class', 'highlighted'); // TODO:(note) these looks redudant to me
$markerEnd->getAttributes()->remove('class', 'highlighted');

$scheduledEndBubble = new HtmlElement(
Expand All @@ -110,19 +113,26 @@ protected function assemble()
'class' => ['progress', 'downtime-elapsed'],
'data-animate-progress' => true,
'data-start-time' => ((float) $this->downtime->start_time->format('U.u')),
'data-end-time' => ((float) $this->downtime->end_time->format('U.u')),
'style' => sprintf('left: %F%%; width: %F%%;', $flexStartLeft, $flexEndLeft - $flexStartLeft)
'data-end-time' => ((float) $this->downtime->end_time->format('U.u'))
]), new HtmlElement(
'div',
Attributes::create(['class' => 'bar']),
new HtmlElement('div', Attributes::create(['class' => 'now']))
));

$this->addStyle($timelineProgress, [
'left' => $flexStartLeft . '%',
'width' => ($flexEndLeft - $flexStartLeft) . '%'
]);

if (time() > $this->end) {
$markerEnd->getAttributes()
->set('style', sprintf('left: %F%%', $hPadding + $this->calcRelativeLeft($this->end)));
$scheduledEndBubble->getAttributes()
->set('style', sprintf('left: %F%%', $hPadding + $this->calcRelativeLeft($this->end)));
$this->addStyle($markerEnd, [
'left' => ($hPadding + $this->calcRelativeLeft($this->end)) . '%'
]);

$this->addStyle($scheduledEndBubble, [
'left' => ($hPadding + $this->calcRelativeLeft($this->end)) . '%'
]);
} else {
$scheduledEndBubble->getAttributes()
->add('class', 'right');
Expand All @@ -141,32 +151,21 @@ protected function assemble()
$scheduledEndBubble
]);

$above->add([
Html::tag(
'li',
[
'class' => 'positioned',
'style' => sprintf('left: %F%%', $flexStartLeft)
],
Html::tag(
'div',
['class' => ['bubble', ($evade ? 'left-aligned' : null)]],
new VerticalKeyValue(t('Start'), new TimeAgo($this->downtime->start_time->getTimestamp()))
)
),
Html::tag(
'li',
[
'class' => 'positioned',
'style' => sprintf('left: %F%%', $flexEndLeft)
],
Html::tag(
'div',
['class' => ['bubble', ($evade ? 'right-aligned' : null)]],
new VerticalKeyValue(t('End'), new TimeUntil($this->downtime->end_time->getTimestamp()))
)
)
]);
$aboveStart = Html::tag('li', ['class' => 'positioned'], Html::tag(
'div',
['class' => ['bubble', ($evade ? 'left-aligned' : null)]],
new VerticalKeyValue(t('Start'), new TimeAgo($this->downtime->start_time->getTimestamp()))
));
$this->addStyle($aboveStart, ['left' => $flexStartLeft . '%']);

$aboveEnd = Html::tag('li', ['class' => 'positioned'], Html::tag(
'div',
['class' => ['bubble', ($evade ? 'right-aligned' : null)]],
new VerticalKeyValue(t('End'), new TimeUntil($this->downtime->end_time->getTimestamp()))
));
$this->addStyle($aboveEnd, ['left' => $flexEndLeft . '%']);

$above->add([$aboveStart, $aboveEnd]);
} elseif ($this->downtime->is_flexible) {
$this->addAttributes(['class' => 'flexible']);

Expand Down Expand Up @@ -249,6 +248,8 @@ protected function assemble()
$timeline,
$below
]);

echo $this->getStyle();
}

protected function calcRelativeLeft($value)
Expand Down

0 comments on commit 729ade3

Please sign in to comment.