Support Content-Security-Policy (#2857)

resolves #2845
This commit is contained in:
Johannes Meyer 2024-01-25 10:44:48 +01:00 committed by GitHub
commit 35c6086db3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 148 additions and 212 deletions

View File

@ -304,17 +304,21 @@ class BasketController extends ActionController
$this->translate('modified'),
'director/basket/snapshotobject',
$linkParams,
['style' => 'color: orange; font-weight: bold']
['class' => 'basket-modified']
);
} else {
$link = Html::tag('span', ['style' => 'color: green'], $this->translate('unchanged'));
$link = Html::tag(
'span',
['class' => 'basket-unchanged'],
$this->translate('unchanged')
);
}
} else {
$link = Link::create(
$this->translate('new'),
'director/basket/snapshotobject',
$linkParams,
['style' => 'color: green; font-weight: bold']
['class' => 'basket-new']
);
}
$table->addNameValueRow($key, $link);
@ -333,7 +337,6 @@ class BasketController extends ActionController
$this->content()->add(Html::tag('h2', $type));
$this->content()->add($table);
}
$this->content()->add(Html::tag('div', ['style' => 'height: 5em']));
}
/**

View File

@ -376,25 +376,27 @@ class ConfigController extends ActionController
}
$baseUrl = $this->url()->without(['left', 'right']);
$this->content()->add(Html::tag('form', ['action' => (string) $baseUrl, 'method' => 'GET'], [
new HtmlString($this->view->formSelect(
'left',
$leftSum,
['class' => 'autosubmit', 'style' => 'width: 37%'],
[null => $this->translate('- please choose -')] + $configs
)),
Link::create(
Icon::create('flapping'),
$baseUrl,
['left' => $rightSum, 'right' => $leftSum]
),
new HtmlString($this->view->formSelect(
'right',
$rightSum,
['class' => 'autosubmit', 'style' => 'width: 37%'],
[null => $this->translate('- please choose -')] + $configs
)),
]));
$this->content()->add(
Html::tag('form', ['action' => (string) $baseUrl, 'method' => 'GET', 'class' => 'director-form'], [
new HtmlString($this->view->formSelect(
'left',
$leftSum,
['class' => ['autosubmit', 'config-diff']],
[null => $this->translate('- please choose -')] + $configs
)),
Link::create(
Icon::create('flapping'),
$baseUrl,
['left' => $rightSum, 'right' => $leftSum]
),
new HtmlString($this->view->formSelect(
'right',
$rightSum,
['class' => ['autosubmit', 'config-diff']],
[null => $this->translate('- please choose -')] + $configs
)),
])
);
if ($rightSum === null || $leftSum === null || ! strlen($rightSum) || ! strlen($leftSum)) {
return;

View File

@ -216,7 +216,7 @@ class DataController extends ActionController
$subTitle = $this->translate('Add a new instance');
}
$this->content()->add(Html::tag('h2', ['style' => 'margin-top: 2em'], $subTitle));
$this->content()->add(Html::tag('h2', ['class' => 'dictionary-header'], $subTitle));
$form->handleRequest($this->getRequest());
$this->content()->add($form);
if ($form->succeeded()) {
@ -326,7 +326,7 @@ class DataController extends ActionController
Table::row([
$this->translate('Key / Instance'),
$this->translate('Properties')
], ['style' => 'text-align: left'], 'th')
], ['class' => 'text-align-left'], 'th')
);
foreach ($currentValue as $key => $item) {
$table->add(Table::row([

View File

@ -180,9 +180,7 @@ class ImportsourceController extends ActionController
'target' => '_blank',
'class' => 'icon-download',
]
))->add(Link::create('[..]', '#', null, [
'onclick' => 'javascript:$("table.raw-data-table").toggleClass("collapsed");'
]));
));
try {
(new ImportsourceHookTable())->setImportSource($source)->renderTo($this);
} catch (Exception $e) {

View File

@ -380,10 +380,7 @@ class SyncruleController extends ActionController
protected function firstNames($objects, $max = 50)
{
$names = [];
$list = new UnorderedList();
$list->addAttributes([
'style' => 'list-style-type: none; marign: 0; padding: 0',
]);
$list = new UnorderedList([], ['class' => 'unordred-list']);
$total = count($objects);
$i = 0;
PrefetchCache::forget();

View File

@ -11,9 +11,6 @@ use Icinga\Module\Director\Web\Form\DirectorForm;
class AddToBasketForm extends DirectorForm
{
/** @var Basket */
private $basket;
private $type = '(has not been set)';
private $names = [];
@ -30,7 +27,6 @@ class AddToBasketForm extends DirectorForm
'b' => 'basket_name',
])->order('basket_name'));
$names = [];
$basket = null;
if ($this->hasBeenSent()) {
$basketName = $this->getSentValue('basket');
@ -38,25 +34,17 @@ class AddToBasketForm extends DirectorForm
$basket = Basket::load($basketName, $this->getDb());
}
}
$count = 0;
$type = $this->type;
$names = [];
foreach ($this->names as $name) {
if (! empty($names)) {
$names[] = ', ';
}
if ($basket && $basket->hasObject($type, $name)) {
$names[] = Html::tag('span', [
'style' => 'text-decoration: line-through'
], $name);
} else {
$count++;
if (! $basket || ! $basket->hasObject($this->type, $name)) {
$names[] = $name;
}
}
$this->addHtmlHint((new HtmlDocument())->add([
'The following objects will be added: ',
$names
]));
$this->addHtmlHint(
(new HtmlDocument())
->add(sprintf('The following objects will be added: %s', implode(", ", $names)))
);
$this->addElement('select', 'basket', [
'label' => $this->translate('Basket'),
'multiOptions' => $this->optionalEnum($enum),
@ -64,10 +52,10 @@ class AddToBasketForm extends DirectorForm
'class' => 'autosubmit',
]);
if ($count > 0) {
if (! empty($names)) {
$this->setSubmitLabel(sprintf(
$this->translate('Add %s objects'),
$count
count($names)
));
} else {
$this->setSubmitLabel($this->translate('Add'));
@ -112,18 +100,18 @@ class AddToBasketForm extends DirectorForm
'Configuration objects have been added to the chosen basket "%s"'
), $basketName));
return parent::onSuccess();
} else {
$this->addHtmlHint(Hint::error(Html::sprintf($this->translate(
'Please check your Basket configuration, %s does not support'
. ' single "%s" configuration objects'
), Link::create(
$basketName,
'director/basket',
['name' => $basketName],
['data-base-target' => '_next']
), $type)));
return false;
}
$this->addHtmlHint(Hint::error(Html::sprintf($this->translate(
'Please check your Basket configuration, %s does not support'
. ' single "%s" configuration objects'
), Link::create(
$basketName,
'director/basket',
['name' => $basketName],
['data-base-target' => '_next']
), $type)));
return false;
}
}

View File

@ -264,15 +264,6 @@ class IcingaHostForm extends DirectorObjectForm
return $this;
}
protected function strikeGroupLinks(BaseHtmlElement $links)
{
/** @var BaseHtmlElement $link */
foreach ($links->getContent() as $link) {
$link->getAttributes()->add('style', 'text-decoration: strike');
}
$links->add('aha');
}
protected function getInheritedGroups()
{
if ($this->hasObject()) {
@ -297,9 +288,7 @@ class IcingaHostForm extends DirectorObjectForm
);
}
return Html::tag('span', [
'style' => 'line-height: 2.5em; padding-left: 0.5em'
], $links);
return Html::tag('span', ['class' => 'host-group-links'], $links);
}
protected function getAppliedGroups()

View File

@ -17,10 +17,7 @@ class RemoveLinkForm extends DirectorForm
{
// Required to detect the right instance
$this->formName = 'RemoveSet' . sha1(json_encode($params));
parent::__construct([
'style' => 'float: right',
'data-base-target' => '_self'
]);
parent::__construct(['data-base-target' => '_self']);
$this->label = $label;
$this->title = $title;
foreach ($params as $name => $value) {
@ -38,7 +35,7 @@ class RemoveLinkForm extends DirectorForm
public function setup()
{
$this->setAttrib('class', 'inline');
$this->addAttribs(['class' => ['inline', 'remove-link-form']]);
$this->addHtml(Icon::create('cancel'));
$this->addSubmitButton($this->label, [
'class' => 'link-button',

View File

@ -223,7 +223,7 @@ abstract class ActionController extends Controller implements ControlsAndContent
// Hint -> $this->view->compact is the only way since v2.8.0
if ($this->view->compact || $this->getOriginalUrl()->getParam('view') === 'compact') {
if ($this->view->controls) {
$this->controls()->getAttributes()->add('style', 'display: none;');
$this->controls()->getAttributes()->add('class', 'compact');
}
}
} else {

View File

@ -219,8 +219,7 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
protected function createFakeRemoveLinkForReadonlyView()
{
return Html::tag('span', [
'class' => 'icon-paste',
'style' => 'float: right; font-weight: normal',
'class' => ['icon-paste', 'seviceset-obj-link'],
], $this->host->getObjectName());
}
@ -228,8 +227,7 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
{
$hostname = $host->getObjectName();
return Link::create($hostname, 'director/host/services', ['name' => $hostname], [
'class' => 'icon-paste',
'style' => 'float: right; font-weight: normal',
'class' => ['icon-paste', 'seviceset-obj-link'],
'data-base-target' => '_next',
'title' => sprintf(
$this->translate('This set has been inherited from %s'),

View File

@ -1,113 +0,0 @@
<?php
namespace Icinga\Module\Director\Web\Table;
use Icinga\Module\Director\PlainObjectRenderer;
use Icinga\Module\Director\Web\Form\QuickForm;
use Zend_Form_Element as ZfElement;
use Zend_Form_DisplayGroup as ZfDisplayGroup;
class ReadOnlyFormAvpTable
{
protected $form;
public function __construct(QuickForm $form)
{
$this->form = $form;
}
protected function renderDisplayGroups(QuickForm $form)
{
$html = '';
foreach ($form->getDisplayGroups() as $group) {
$elements = $this->filterGroupElements($group);
if (empty($elements)) {
continue;
}
$html .= '<tr><th colspan="2" style="text-align: right">' . $group->getLegend() . '</th></tr>';
$html .= $this->renderElements($elements);
}
return $html;
}
/**
* @param ZfDisplayGroup $group
* @return ZfElement[]
*/
protected function filterGroupElements(ZfDisplayGroup $group)
{
$blacklist = array('disabled', 'assign_filter');
$elements = array();
/** @var ZfElement $element */
foreach ($group->getElements() as $element) {
if ($element->getValue() === null) {
continue;
}
if ($element->getType() === 'Zend_Form_Element_Hidden') {
continue;
}
if (in_array($element->getName(), $blacklist)) {
continue;
}
$elements[] = $element;
}
return $elements;
}
protected function renderElements($elements)
{
$html = '';
foreach ($elements as $element) {
$html .= $this->renderElement($element);
}
return $html;
}
/**
* @param ZfElement $element
*
* @return string
*/
protected function renderElement(ZfElement $element)
{
$value = $element->getValue();
return '<tr><th>'
. $this->escape($element->getLabel())
. '</th><td>'
. $this->renderValue($value)
. '</td></tr>';
}
protected function renderValue($value)
{
if (is_string($value)) {
return $this->escape($value);
} elseif (is_array($value)) {
return $this->escape(implode(', ', $value));
}
return $this->escape(PlainObjectRenderer::render($value));
}
protected function escape($string)
{
return htmlspecialchars($string);
}
public function render()
{
$this->form->initializeForObject();
return '<table class="name-value-table">' . "\n"
. $this->renderDisplayGroups($this->form)
. '</table>';
}
}

View File

@ -60,7 +60,7 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
$name,
Html::tag(
'span',
['style' => 'font-style: italic'],
['class' => 'font-italic'],
$this->translate(' - not in use -')
)
];

View File

@ -83,8 +83,7 @@ class ActivityLogInfo extends HtmlDocument
/** @var Url $url */
$url = $url->without('checksum')->without('show');
$div = Html::tag('div', [
'class' => 'pagination-control',
'style' => 'float: right; width: 5em'
'class' => ['pagination-control', 'activity-log-control'],
]);
$ul = Html::tag('ul', ['class' => 'nav tab-nav']);

View File

@ -73,7 +73,8 @@ class DeploymentInfo extends HtmlDocument
protected function createInfoTable()
{
$dep = $this->deployment;
$table = new NameValueTable();
$table = (new NameValueTable())
->addAttributes(['class' => 'deployment-details']);
$table->addNameValuePairs([
$this->translate('Deployment time') => $dep->start_time,
$this->translate('Sent to') => $dep->peer_identity,
@ -136,16 +137,21 @@ class DeploymentInfo extends HtmlDocument
} else {
return [$this->translate('Unknown, failed to collect related information'), new Icon('help')];
}
} elseif ($dep->startup_succeeded === 'y') {
return $this->colored('green', [$this->translate('Succeeded'), new Icon('ok')]);
} else {
return $this->colored('red', [$this->translate('Failed'), new Icon('cancel')]);
}
}
$div = Html::tag('div')->setSeparator(' ');
protected function colored($color, array $content)
{
return Html::tag('div', ['style' => "color: $color;"], $content)->setSeparator(' ');
if ($dep->startup_succeeded === 'y') {
$div
->addAttributes(['class' => 'succeeded'])
->add([$this->translate('Succeeded'), new Icon('ok')]);
} else {
$div
->addAttributes(['class' => 'failed'])
->add([$this->translate('Failed'), new Icon('cancel')]);
}
return $div;
}
}
public function render()

View File

@ -49,6 +49,15 @@ div.action-bar > a {
margin-right: 1em;
}
.controls.compact {
display: none;
}
.controls > .pagination-control.activity-log-control {
float: right;
width: 5em;
}
.controls > .pagination-control li > a {
padding: 0.5em 0 0.5em 0;
}
@ -337,6 +346,10 @@ table.avp th {
left: -100%;
}
form.remove-link-form {
float: right;
}
form.director-form input[type=file] {
padding-right: 1em;
}
@ -462,6 +475,11 @@ form.director-form dl {
padding: 0;
}
form.director-form .host-group-links {
line-height: 2.5em;
padding-left: 0.5em;
}
.strike-links a, table.common-table .strike-links a {
text-decoration: line-through;
&:hover {
@ -502,6 +520,12 @@ form.director-form.editor {
}
}
ul.unordred-list {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.extensible-set {
margin: 0;
padding: 0;
@ -917,6 +941,10 @@ form.director-form dd.active li.active input.related-action[type='submit'] {
}
form.director-form {
select.config-diff {
width: auto;
}
p.description {
color: @gray;
font-style: italic;
@ -1223,6 +1251,17 @@ div.content.compact table.icinga-objects thead {
display: none;
}
table.deployment-details {
.succeeded {
color: @state-ok;
}
.failed {
color: @color-critical;
}
}
table.deployment-log {
tr td:nth-child(2), tr th:nth-child(2) {
@ -1833,3 +1872,36 @@ table.table-basket-changes {
min-width: 10em;
}
}
.font-italic {
font-style: italic;
}
.table-basket-changes {
.basket-new {
color: green;
font-weight: bold
}
.basket-modified {
color: orange;
font-weight: bold
}
.basket-unchanged {
color: green;
}
}
.seviceset-obj-link {
float: right;
font-weight: normal
}
.dictionary-header {
margin-top: 2em;
}
.text-align-left {
text-align: left
}