From 051a391444afde144818c12f73638d1948b7febc Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 1 Mar 2023 10:22:13 +0100 Subject: [PATCH 1/7] CommandForm#getCommand(): take (and process) multiple objects, not just one --- application/forms/Command/CommandForm.php | 35 +++++------- .../Instance/ToggleInstanceFeaturesForm.php | 4 +- .../Command/Object/AcknowledgeProblemForm.php | 41 +++++++------- .../forms/Command/Object/AddCommentForm.php | 33 ++++++----- .../forms/Command/Object/CheckNowForm.php | 37 ++++++------- .../Command/Object/DeleteCommentForm.php | 23 ++++---- .../Command/Object/DeleteDowntimeForm.php | 29 +++++----- .../Command/Object/ProcessCheckResultForm.php | 32 +++++------ .../Object/RemoveAcknowledgementForm.php | 23 ++++---- .../Command/Object/ScheduleCheckForm.php | 37 ++++++------- .../Object/ScheduleHostDowntimeForm.php | 55 +++++++++---------- .../Object/ScheduleServiceDowntimeForm.php | 43 +++++++-------- .../Object/SendCustomNotificationForm.php | 27 +++++---- .../Object/ToggleObjectFeaturesForm.php | 43 ++++++++------- 14 files changed, 224 insertions(+), 238 deletions(-) diff --git a/application/forms/Command/CommandForm.php b/application/forms/Command/CommandForm.php index 7fb79663a..5aa991c2c 100644 --- a/application/forms/Command/CommandForm.php +++ b/application/forms/Command/CommandForm.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Forms\Command; +use ArrayIterator; use Exception; use Icinga\Application\Logger; use Icinga\Module\Icingadb\Command\IcingaCommand; @@ -13,6 +14,7 @@ use ipl\Html\Form; use ipl\Orm\Model; use ipl\Web\Common\CsrfCounterMeasure; +use Traversable; abstract class CommandForm extends Form { @@ -71,13 +73,13 @@ abstract protected function assembleElements(); abstract protected function assembleSubmitButton(); /** - * Get the command to issue for the given object + * Get the commands to issue for the given objects * - * @param Model $object + * @param Traversable $objects * - * @return IcingaCommand|IcingaCommand[]|null NULL in case no command should be issued for the object + * @return Traversable */ - abstract protected function getCommand(Model $object); + abstract protected function getCommands(Traversable $objects): Traversable; protected function assemble() { @@ -89,23 +91,14 @@ protected function assemble() protected function onSuccess() { $errors = []; - foreach ($this->getObjects() as $object) { - $commands = $this->getCommand($object); - if ($commands === null) { - continue; - } - - if ($commands instanceof IcingaCommand) { - $commands = [$commands]; - } - - foreach ($commands as $command) { - try { - $this->sendCommand($command); - } catch (Exception $e) { - Logger::error($e->getMessage()); - $errors[] = $e->getMessage(); - } + $objects = $this->getObjects(); + + foreach ($this->getCommands(is_array($objects) ? new ArrayIterator($objects) : $objects) as $command) { + try { + $this->sendCommand($command); + } catch (Exception $e) { + Logger::error($e->getMessage()); + $errors[] = $e->getMessage(); } } diff --git a/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php b/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php index eb270dab9..4c382447f 100644 --- a/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php +++ b/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php @@ -8,8 +8,8 @@ use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; -use ipl\Orm\Model; use ipl\Web\FormDecorator\IcingaFormDecorator; +use Traversable; class ToggleInstanceFeaturesForm extends CommandForm { @@ -136,7 +136,7 @@ protected function assembleSubmitButton() { } - protected function getCommand(Model $object): \Generator + protected function getCommands(Traversable $objects): Traversable { foreach ($this->features as $feature => $spec) { $featureState = $this->getElement($feature)->isChecked(); diff --git a/application/forms/Command/Object/AcknowledgeProblemForm.php b/application/forms/Command/Object/AcknowledgeProblemForm.php index 6b6914a10..ed5a13cd4 100644 --- a/application/forms/Command/Object/AcknowledgeProblemForm.php +++ b/application/forms/Command/Object/AcknowledgeProblemForm.php @@ -15,10 +15,10 @@ use ipl\Html\Attributes; use ipl\Html\HtmlElement; use ipl\Html\Text; -use ipl\Orm\Model; use ipl\Validator\CallbackValidator; use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\Widget\Icon; +use Traversable; class AcknowledgeProblemForm extends CommandForm { @@ -187,28 +187,27 @@ protected function assembleSubmitButton() (new IcingaFormDecorator())->decorate($this->getElement('btn_submit')); } - /** - * @return ?AcknowledgeProblemCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/acknowledge-problem', $object)) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/acknowledge-problem', $object)) { + continue; + } - $command = new AcknowledgeProblemCommand(); - $command->setObject($object); - $command->setComment($this->getValue('comment')); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); - $command->setNotify($this->getElement('notify')->isChecked()); - $command->setSticky($this->getElement('sticky')->isChecked()); - $command->setPersistent($this->getElement('persistent')->isChecked()); - - if (($expireTime = $this->getValue('expire_time')) !== null) { - /** @var DateTime $expireTime */ - $command->setExpireTime($expireTime->getTimestamp()); - } + $command = new AcknowledgeProblemCommand(); + $command->setObject($object); + $command->setComment($this->getValue('comment')); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command->setNotify($this->getElement('notify')->isChecked()); + $command->setSticky($this->getElement('sticky')->isChecked()); + $command->setPersistent($this->getElement('persistent')->isChecked()); + + if (($expireTime = $this->getValue('expire_time')) !== null) { + /** @var DateTime $expireTime */ + $command->setExpireTime($expireTime->getTimestamp()); + } - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/AddCommentForm.php b/application/forms/Command/Object/AddCommentForm.php index 8820669df..98ea392b9 100644 --- a/application/forms/Command/Object/AddCommentForm.php +++ b/application/forms/Command/Object/AddCommentForm.php @@ -15,10 +15,10 @@ use ipl\Html\Attributes; use ipl\Html\HtmlElement; use ipl\Html\Text; -use ipl\Orm\Model; use ipl\Validator\CallbackValidator; use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\Widget\Icon; +use Traversable; class AddCommentForm extends CommandForm { @@ -142,25 +142,24 @@ protected function assembleSubmitButton() (new IcingaFormDecorator())->decorate($this->getElement('btn_submit')); } - /** - * @return ?AddCommentCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/comment/add', $object)) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/comment/add', $object)) { + continue; + } - $command = new AddCommentCommand(); - $command->setObject($object); - $command->setComment($this->getValue('comment')); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command = new AddCommentCommand(); + $command->setObject($object); + $command->setComment($this->getValue('comment')); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); - if (($expireTime = $this->getValue('expire_time'))) { - /** @var DateTime $expireTime */ - $command->setExpireTime($expireTime->getTimestamp()); - } + if (($expireTime = $this->getValue('expire_time'))) { + /** @var DateTime $expireTime */ + $command->setExpireTime($expireTime->getTimestamp()); + } - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/CheckNowForm.php b/application/forms/Command/Object/CheckNowForm.php index 136b40eae..68ea53873 100644 --- a/application/forms/Command/Object/CheckNowForm.php +++ b/application/forms/Command/Object/CheckNowForm.php @@ -8,8 +8,8 @@ use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; -use ipl\Orm\Model; use ipl\Web\Widget\Icon; +use Traversable; class CheckNowForm extends CommandForm { @@ -46,26 +46,25 @@ protected function assembleSubmitButton() ); } - /** - * @return ?ScheduleCheckCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if ( - ! $this->isGrantedOn('icingadb/command/schedule-check', $object) - && ( - ! $object->active_checks_enabled - || ! $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) - ) - ) { - return null; - } + foreach ($objects as $object) { + if ( + ! $this->isGrantedOn('icingadb/command/schedule-check', $object) + && ( + ! $object->active_checks_enabled + || ! $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) + ) + ) { + continue; + } - $command = new ScheduleCheckCommand(); - $command->setObject($object); - $command->setCheckTime(time()); - $command->setForced(); + $command = new ScheduleCheckCommand(); + $command->setObject($object); + $command->setCheckTime(time()); + $command->setForced(); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/DeleteCommentForm.php b/application/forms/Command/Object/DeleteCommentForm.php index 1889c7bbf..2b86db37d 100644 --- a/application/forms/Command/Object/DeleteCommentForm.php +++ b/application/forms/Command/Object/DeleteCommentForm.php @@ -8,9 +8,9 @@ use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; -use ipl\Orm\Model; use ipl\Web\Common\RedirectOption; use ipl\Web\Widget\Icon; +use Traversable; class DeleteCommentForm extends CommandForm { @@ -55,19 +55,18 @@ protected function assembleSubmitButton() ); } - /** - * @return ?DeleteCommentCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/comment/delete', $object->{$object->object_type})) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/comment/delete', $object->{$object->object_type})) { + continue; + } - $command = new DeleteCommentCommand(); - $command->setCommentName($object->name); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command = new DeleteCommentCommand(); + $command->setCommentName($object->name); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/DeleteDowntimeForm.php b/application/forms/Command/Object/DeleteDowntimeForm.php index c34c9a899..58d6260fb 100644 --- a/application/forms/Command/Object/DeleteDowntimeForm.php +++ b/application/forms/Command/Object/DeleteDowntimeForm.php @@ -8,9 +8,9 @@ use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; -use ipl\Orm\Model; use ipl\Web\Common\RedirectOption; use ipl\Web\Widget\Icon; +use Traversable; class DeleteDowntimeForm extends CommandForm { @@ -67,22 +67,21 @@ protected function assembleSubmitButton() ); } - /** - * @return ?DeleteDowntimeCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if ( - ! $this->isGrantedOn('icingadb/command/downtime/delete', $object->{$object->object_type}) - || $object->scheduled_by !== null - ) { - return null; - } + foreach ($objects as $object) { + if ( + ! $this->isGrantedOn('icingadb/command/downtime/delete', $object->{$object->object_type}) + || $object->scheduled_by !== null + ) { + continue; + } - $command = new DeleteDowntimeCommand(); - $command->setDowntimeName($object->name); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command = new DeleteDowntimeCommand(); + $command->setDowntimeName($object->name); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/ProcessCheckResultForm.php b/application/forms/Command/Object/ProcessCheckResultForm.php index a6fb8b30f..e5a88f4a5 100644 --- a/application/forms/Command/Object/ProcessCheckResultForm.php +++ b/application/forms/Command/Object/ProcessCheckResultForm.php @@ -15,6 +15,7 @@ use ipl\Orm\Model; use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\Widget\Icon; +use Traversable; class ProcessCheckResultForm extends CommandForm { @@ -136,24 +137,23 @@ protected function assembleSubmitButton() (new IcingaFormDecorator())->decorate($this->getElement('btn_submit')); } - /** - * @return ?ProcessCheckResultCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if ( - ! $object->passive_checks_enabled - || ! $this->isGrantedOn('icingadb/command/process-check-result', $object) - ) { - return null; - } + foreach ($objects as $object) { + if ( + ! $object->passive_checks_enabled + || ! $this->isGrantedOn('icingadb/command/process-check-result', $object) + ) { + continue; + } - $command = new ProcessCheckResultCommand(); - $command->setObject($object); - $command->setStatus($this->getValue('status')); - $command->setOutput($this->getValue('output')); - $command->setPerformanceData($this->getValue('perfdata')); + $command = new ProcessCheckResultCommand(); + $command->setObject($object); + $command->setStatus($this->getValue('status')); + $command->setOutput($this->getValue('output')); + $command->setPerformanceData($this->getValue('perfdata')); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/RemoveAcknowledgementForm.php b/application/forms/Command/Object/RemoveAcknowledgementForm.php index a69706a79..8001e6cf1 100644 --- a/application/forms/Command/Object/RemoveAcknowledgementForm.php +++ b/application/forms/Command/Object/RemoveAcknowledgementForm.php @@ -9,8 +9,8 @@ use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; -use ipl\Orm\Model; use ipl\Web\Widget\Icon; +use Traversable; class RemoveAcknowledgementForm extends CommandForm { @@ -63,19 +63,18 @@ protected function assembleSubmitButton() ); } - /** - * @return ?RemoveAcknowledgementCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/remove-acknowledgement', $object)) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/remove-acknowledgement', $object)) { + continue; + } - $command = new RemoveAcknowledgementCommand(); - $command->setObject($object); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command = new RemoveAcknowledgementCommand(); + $command->setObject($object); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/ScheduleCheckForm.php b/application/forms/Command/Object/ScheduleCheckForm.php index 853516f23..752ecf9ff 100644 --- a/application/forms/Command/Object/ScheduleCheckForm.php +++ b/application/forms/Command/Object/ScheduleCheckForm.php @@ -14,9 +14,9 @@ use ipl\Html\Attributes; use ipl\Html\HtmlElement; use ipl\Html\Text; -use ipl\Orm\Model; use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\Widget\Icon; +use Traversable; class ScheduleCheckForm extends CommandForm { @@ -109,26 +109,25 @@ protected function assembleSubmitButton() (new IcingaFormDecorator())->decorate($this->getElement('btn_submit')); } - /** - * @return ?ScheduleCheckCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if ( - ! $this->isGrantedOn('icingadb/command/schedule-check', $object) - && ( - ! $object->active_checks_enabled - || ! $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) - ) - ) { - return null; - } + foreach ($objects as $object) { + if ( + ! $this->isGrantedOn('icingadb/command/schedule-check', $object) + && ( + ! $object->active_checks_enabled + || ! $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) + ) + ) { + continue; + } - $command = new ScheduleCheckCommand(); - $command->setObject($object); - $command->setForced($this->getElement('force_check')->isChecked()); - $command->setCheckTime($this->getValue('check_time')->getTimestamp()); + $command = new ScheduleCheckCommand(); + $command->setObject($object); + $command->setForced($this->getElement('force_check')->isChecked()); + $command->setCheckTime($this->getValue('check_time')->getTimestamp()); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/ScheduleHostDowntimeForm.php b/application/forms/Command/Object/ScheduleHostDowntimeForm.php index dc6fc210e..1ad2c8256 100644 --- a/application/forms/Command/Object/ScheduleHostDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleHostDowntimeForm.php @@ -10,8 +10,8 @@ use Icinga\Module\Icingadb\Command\Object\PropagateHostDowntimeCommand; use Icinga\Module\Icingadb\Command\Object\ScheduleHostDowntimeCommand; use Icinga\Web\Notification; -use ipl\Orm\Model; use ipl\Web\FormDecorator\IcingaFormDecorator; +use Traversable; class ScheduleHostDowntimeForm extends ScheduleServiceDowntimeForm { @@ -87,36 +87,35 @@ protected function assembleElements() $decorator->decorate($this->getElement('child_options')); } - /** - * @return ?PropagateHostDowntimeCommand|ScheduleHostDowntimeCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/downtime/schedule', $object)) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/downtime/schedule', $object)) { + continue; + } - if (($childOptions = (int) $this->getValue('child_options'))) { - $command = new PropagateHostDowntimeCommand(); - $command->setTriggered($childOptions === 1); - } else { - $command = new ScheduleHostDowntimeCommand(); - } + if (($childOptions = (int) $this->getValue('child_options'))) { + $command = new PropagateHostDowntimeCommand(); + $command->setTriggered($childOptions === 1); + } else { + $command = new ScheduleHostDowntimeCommand(); + } - $command->setObject($object); - $command->setComment($this->getValue('comment')); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); - $command->setStart($this->getValue('start')->getTimestamp()); - $command->setEnd($this->getValue('end')->getTimestamp()); - $command->setForAllServices($this->getElement('all_services')->isChecked()); - - if ($this->getElement('flexible')->isChecked()) { - $command->setFixed(false); - $command->setDuration( - $this->getValue('hours') * 3600 + $this->getValue('minutes') * 60 - ); - } + $command->setObject($object); + $command->setComment($this->getValue('comment')); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command->setStart($this->getValue('start')->getTimestamp()); + $command->setEnd($this->getValue('end')->getTimestamp()); + $command->setForAllServices($this->getElement('all_services')->isChecked()); + + if ($this->getElement('flexible')->isChecked()) { + $command->setFixed(false); + $command->setDuration( + $this->getValue('hours') * 3600 + $this->getValue('minutes') * 60 + ); + } - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php index c7c978279..a0c6401fe 100644 --- a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php @@ -14,10 +14,10 @@ use ipl\Html\Attributes; use ipl\Html\HtmlElement; use ipl\Html\Text; -use ipl\Orm\Model; use ipl\Validator\CallbackValidator; use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\Widget\Icon; +use Traversable; class ScheduleServiceDowntimeForm extends CommandForm { @@ -245,29 +245,28 @@ protected function assembleSubmitButton() (new IcingaFormDecorator())->decorate($this->getElement('btn_submit')); } - /** - * @return ?ScheduleServiceDowntimeCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/downtime/schedule', $object)) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/downtime/schedule', $object)) { + continue; + } - $command = new ScheduleServiceDowntimeCommand(); - $command->setObject($object); - $command->setComment($this->getValue('comment')); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); - $command->setStart($this->getValue('start')->getTimestamp()); - $command->setEnd($this->getValue('end')->getTimestamp()); - - if ($this->getElement('flexible')->isChecked()) { - $command->setFixed(false); - $command->setDuration( - $this->getValue('hours') * 3600 + $this->getValue('minutes') * 60 - ); - } + $command = new ScheduleServiceDowntimeCommand(); + $command->setObject($object); + $command->setComment($this->getValue('comment')); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command->setStart($this->getValue('start')->getTimestamp()); + $command->setEnd($this->getValue('end')->getTimestamp()); + + if ($this->getElement('flexible')->isChecked()) { + $command->setFixed(false); + $command->setDuration( + $this->getValue('hours') * 3600 + $this->getValue('minutes') * 60 + ); + } - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/SendCustomNotificationForm.php b/application/forms/Command/Object/SendCustomNotificationForm.php index 9813def14..d5585f755 100644 --- a/application/forms/Command/Object/SendCustomNotificationForm.php +++ b/application/forms/Command/Object/SendCustomNotificationForm.php @@ -13,9 +13,9 @@ use ipl\Html\Attributes; use ipl\Html\HtmlElement; use ipl\Html\Text; -use ipl\Orm\Model; use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\Widget\Icon; +use Traversable; class SendCustomNotificationForm extends CommandForm { @@ -109,21 +109,20 @@ protected function assembleSubmitButton() (new IcingaFormDecorator())->decorate($this->getElement('btn_submit')); } - /** - * @return ?SendCustomNotificationCommand - */ - protected function getCommand(Model $object) + protected function getCommands(Traversable $objects): Traversable { - if (! $this->isGrantedOn('icingadb/command/send-custom-notification', $object)) { - return null; - } + foreach ($objects as $object) { + if (! $this->isGrantedOn('icingadb/command/send-custom-notification', $object)) { + continue; + } - $command = new SendCustomNotificationCommand(); - $command->setObject($object); - $command->setComment($this->getValue('comment')); - $command->setForced($this->getElement('forced')->isChecked()); - $command->setAuthor($this->getAuth()->getUser()->getUsername()); + $command = new SendCustomNotificationCommand(); + $command->setObject($object); + $command->setComment($this->getValue('comment')); + $command->setForced($this->getElement('forced')->isChecked()); + $command->setAuthor($this->getAuth()->getUser()->getUsername()); - return $command; + yield $command; + } } } diff --git a/application/forms/Command/Object/ToggleObjectFeaturesForm.php b/application/forms/Command/Object/ToggleObjectFeaturesForm.php index 8b2d2d251..f4474095a 100644 --- a/application/forms/Command/Object/ToggleObjectFeaturesForm.php +++ b/application/forms/Command/Object/ToggleObjectFeaturesForm.php @@ -11,6 +11,7 @@ use ipl\Html\FormElement\CheckboxElement; use ipl\Orm\Model; use ipl\Web\FormDecorator\IcingaFormDecorator; +use Traversable; class ToggleObjectFeaturesForm extends CommandForm { @@ -158,31 +159,33 @@ protected function assembleSubmitButton() { } - protected function getCommand(Model $object): \Generator + protected function getCommands(Traversable $objects): Traversable { - foreach ($this->features as $feature => $spec) { - if ($this->getElement($feature) instanceof CheckboxElement) { - $featureState = $this->getElement($feature)->isChecked(); - } else { - $featureState = $this->getElement($feature)->getValue(); - } + foreach ($objects as $object) { + foreach ($this->features as $feature => $spec) { + if ($this->getElement($feature) instanceof CheckboxElement) { + $featureState = $this->getElement($feature)->isChecked(); + } else { + $featureState = $this->getElement($feature)->getValue(); + } - if ( - ! $this->isGrantedOn($spec['permission'], $object) - || $featureState === self::LEAVE_UNCHANGED - || (int) $featureState === (int) $this->featureStatus[$feature] - ) { - continue; - } + if ( + ! $this->isGrantedOn($spec['permission'], $object) + || $featureState === self::LEAVE_UNCHANGED + || (int) $featureState === (int) $this->featureStatus[$feature] + ) { + continue; + } - $command = new ToggleObjectFeatureCommand(); - $command->setObject($object); - $command->setFeature($feature); - $command->setEnabled((int) $featureState); + $command = new ToggleObjectFeatureCommand(); + $command->setObject($object); + $command->setFeature($feature); + $command->setEnabled((int) $featureState); - $this->submittedFeatures[] = $command; + $this->submittedFeatures[] = $command; - yield $command; + yield $command; + } } } } From b4222228cc0d33adf8ed913f2b50f516e66f5b48 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 1 Mar 2023 11:28:18 +0100 Subject: [PATCH 2/7] ObjectCommand and derivates: handle multiple objects --- application/controllers/HostController.php | 2 +- application/controllers/ServiceController.php | 2 +- .../Command/Object/AcknowledgeProblemForm.php | 2 +- .../forms/Command/Object/AddCommentForm.php | 2 +- .../forms/Command/Object/CheckNowForm.php | 2 +- .../Command/Object/ProcessCheckResultForm.php | 2 +- .../Object/RemoveAcknowledgementForm.php | 2 +- .../Command/Object/ScheduleCheckForm.php | 2 +- .../Object/ScheduleHostDowntimeForm.php | 2 +- .../Object/ScheduleServiceDowntimeForm.php | 2 +- .../Object/SendCustomNotificationForm.php | 2 +- .../Object/ToggleObjectFeaturesForm.php | 2 +- .../Command/Object/GetObjectCommand.php | 38 +--------- .../Icingadb/Command/Object/ObjectCommand.php | 51 ------------- .../Command/Object/ObjectsCommand.php | 52 +++++++++++++ .../Object/ProcessCheckResultCommand.php | 2 +- .../Object/RemoveAcknowledgementCommand.php | 2 +- .../Command/Object/ScheduleCheckCommand.php | 2 +- .../Object/ToggleObjectFeatureCommand.php | 2 +- .../Command/Object/WithCommentCommand.php | 2 +- .../Renderer/IcingaApiCommandRenderer.php | 75 ++++++++++++------- 21 files changed, 117 insertions(+), 133 deletions(-) delete mode 100644 library/Icingadb/Command/Object/ObjectCommand.php create mode 100644 library/Icingadb/Command/Object/ObjectsCommand.php diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index e7b1a2af0..5296edcd0 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -86,7 +86,7 @@ public function indexAction() public function sourceAction() { $this->assertPermission('icingadb/object/show-source'); - $apiResult = (new CommandTransport())->send((new GetObjectCommand())->setObject($this->host)); + $apiResult = (new CommandTransport())->send((new GetObjectCommand())->setObjects([$this->host])); if ($this->host->state->is_overdue) { $this->controls->addAttributes(['class' => 'overdue']); diff --git a/application/controllers/ServiceController.php b/application/controllers/ServiceController.php index 9a10dccf4..19db61104 100644 --- a/application/controllers/ServiceController.php +++ b/application/controllers/ServiceController.php @@ -91,7 +91,7 @@ public function indexAction() public function sourceAction() { $this->assertPermission('icingadb/object/show-source'); - $apiResult = (new CommandTransport())->send((new GetObjectCommand())->setObject($this->service)); + $apiResult = (new CommandTransport())->send((new GetObjectCommand())->setObjects([$this->service])); if ($this->service->state->is_overdue) { $this->controls->addAttributes(['class' => 'overdue']); diff --git a/application/forms/Command/Object/AcknowledgeProblemForm.php b/application/forms/Command/Object/AcknowledgeProblemForm.php index ed5a13cd4..ecbfea600 100644 --- a/application/forms/Command/Object/AcknowledgeProblemForm.php +++ b/application/forms/Command/Object/AcknowledgeProblemForm.php @@ -195,7 +195,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new AcknowledgeProblemCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); $command->setNotify($this->getElement('notify')->isChecked()); diff --git a/application/forms/Command/Object/AddCommentForm.php b/application/forms/Command/Object/AddCommentForm.php index 98ea392b9..a6864e144 100644 --- a/application/forms/Command/Object/AddCommentForm.php +++ b/application/forms/Command/Object/AddCommentForm.php @@ -150,7 +150,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new AddCommentCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); diff --git a/application/forms/Command/Object/CheckNowForm.php b/application/forms/Command/Object/CheckNowForm.php index 68ea53873..e713e15c5 100644 --- a/application/forms/Command/Object/CheckNowForm.php +++ b/application/forms/Command/Object/CheckNowForm.php @@ -60,7 +60,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new ScheduleCheckCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setCheckTime(time()); $command->setForced(); diff --git a/application/forms/Command/Object/ProcessCheckResultForm.php b/application/forms/Command/Object/ProcessCheckResultForm.php index e5a88f4a5..7b9e5fb02 100644 --- a/application/forms/Command/Object/ProcessCheckResultForm.php +++ b/application/forms/Command/Object/ProcessCheckResultForm.php @@ -148,7 +148,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new ProcessCheckResultCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setStatus($this->getValue('status')); $command->setOutput($this->getValue('output')); $command->setPerformanceData($this->getValue('perfdata')); diff --git a/application/forms/Command/Object/RemoveAcknowledgementForm.php b/application/forms/Command/Object/RemoveAcknowledgementForm.php index 8001e6cf1..66fe723d6 100644 --- a/application/forms/Command/Object/RemoveAcknowledgementForm.php +++ b/application/forms/Command/Object/RemoveAcknowledgementForm.php @@ -71,7 +71,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new RemoveAcknowledgementCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setAuthor($this->getAuth()->getUser()->getUsername()); yield $command; diff --git a/application/forms/Command/Object/ScheduleCheckForm.php b/application/forms/Command/Object/ScheduleCheckForm.php index 752ecf9ff..4fd992325 100644 --- a/application/forms/Command/Object/ScheduleCheckForm.php +++ b/application/forms/Command/Object/ScheduleCheckForm.php @@ -123,7 +123,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new ScheduleCheckCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setForced($this->getElement('force_check')->isChecked()); $command->setCheckTime($this->getValue('check_time')->getTimestamp()); diff --git a/application/forms/Command/Object/ScheduleHostDowntimeForm.php b/application/forms/Command/Object/ScheduleHostDowntimeForm.php index 1ad2c8256..cbade08e2 100644 --- a/application/forms/Command/Object/ScheduleHostDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleHostDowntimeForm.php @@ -101,7 +101,7 @@ protected function getCommands(Traversable $objects): Traversable $command = new ScheduleHostDowntimeCommand(); } - $command->setObject($object); + $command->setObjects([$object]); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); $command->setStart($this->getValue('start')->getTimestamp()); diff --git a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php index a0c6401fe..52ca028db 100644 --- a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php @@ -253,7 +253,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new ScheduleServiceDowntimeCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); $command->setStart($this->getValue('start')->getTimestamp()); diff --git a/application/forms/Command/Object/SendCustomNotificationForm.php b/application/forms/Command/Object/SendCustomNotificationForm.php index d5585f755..bf29997b7 100644 --- a/application/forms/Command/Object/SendCustomNotificationForm.php +++ b/application/forms/Command/Object/SendCustomNotificationForm.php @@ -117,7 +117,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new SendCustomNotificationCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setComment($this->getValue('comment')); $command->setForced($this->getElement('forced')->isChecked()); $command->setAuthor($this->getAuth()->getUser()->getUsername()); diff --git a/application/forms/Command/Object/ToggleObjectFeaturesForm.php b/application/forms/Command/Object/ToggleObjectFeaturesForm.php index f4474095a..b2d41ceb0 100644 --- a/application/forms/Command/Object/ToggleObjectFeaturesForm.php +++ b/application/forms/Command/Object/ToggleObjectFeaturesForm.php @@ -178,7 +178,7 @@ protected function getCommands(Traversable $objects): Traversable } $command = new ToggleObjectFeatureCommand(); - $command->setObject($object); + $command->setObjects([$object]); $command->setFeature($feature); $command->setEnabled((int) $featureState); diff --git a/library/Icingadb/Command/Object/GetObjectCommand.php b/library/Icingadb/Command/Object/GetObjectCommand.php index 372a555b3..8448f8ded 100644 --- a/library/Icingadb/Command/Object/GetObjectCommand.php +++ b/library/Icingadb/Command/Object/GetObjectCommand.php @@ -4,47 +4,11 @@ namespace Icinga\Module\Icingadb\Command\Object; -use Icinga\Module\Icingadb\Model\Host; -use Icinga\Module\Icingadb\Model\Service; -use LogicException; - -class GetObjectCommand extends ObjectCommand +class GetObjectCommand extends ObjectsCommand { /** @var array */ protected $attributes; - /** - * Get the object name used in the Icinga 2 API - * - * @return string - */ - public function getObjectName(): string - { - switch (true) { - case $this->object instanceof Service: - return $this->object->host->name . '!' . $this->object->name; - default: - return $this->object->name; - } - } - - /** - * Get the sub-route of the endpoint for this object - * - * @return string - */ - public function getObjectPluralType(): string - { - switch (true) { - case $this->object instanceof Host: - return 'hosts'; - case $this->object instanceof Service: - return 'services'; - default: - throw new LogicException(sprintf('Invalid object type %s provided', get_class($this->object))); - } - } - /** * Get the attributes to query * diff --git a/library/Icingadb/Command/Object/ObjectCommand.php b/library/Icingadb/Command/Object/ObjectCommand.php deleted file mode 100644 index 7dae79976..000000000 --- a/library/Icingadb/Command/Object/ObjectCommand.php +++ /dev/null @@ -1,51 +0,0 @@ -object = $object; - - return $this; - } - - /** - * Get the involved object - * - * @return Model - */ - public function getObject(): Model - { - if ($this->object === null) { - throw new \LogicException( - 'You are accessing an unset property. Please make sure to set it beforehand.' - ); - } - - return $this->object; - } -} diff --git a/library/Icingadb/Command/Object/ObjectsCommand.php b/library/Icingadb/Command/Object/ObjectsCommand.php new file mode 100644 index 000000000..f59347ca3 --- /dev/null +++ b/library/Icingadb/Command/Object/ObjectsCommand.php @@ -0,0 +1,52 @@ + + */ + protected $objects; + + /** + * Set the involved objects + * + * @param Traversable $objects + * + * @return $this + */ + public function setObjects(Traversable $objects): self + { + $this->objects = $objects; + + return $this; + } + + /** + * Get the involved objects + * + * @return Traversable + */ + public function getObjects(): Traversable + { + if ($this->objects === null) { + throw new \LogicException( + 'You are accessing an unset property. Please make sure to set it beforehand.' + ); + } + + return $this->objects; + } +} diff --git a/library/Icingadb/Command/Object/ProcessCheckResultCommand.php b/library/Icingadb/Command/Object/ProcessCheckResultCommand.php index 3d7e956e5..24ae2f3ae 100644 --- a/library/Icingadb/Command/Object/ProcessCheckResultCommand.php +++ b/library/Icingadb/Command/Object/ProcessCheckResultCommand.php @@ -7,7 +7,7 @@ /** * Submit a passive check result for a host or service */ -class ProcessCheckResultCommand extends ObjectCommand +class ProcessCheckResultCommand extends ObjectsCommand { /** * Host up diff --git a/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php b/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php index 49a22a307..4c4a9b3f6 100644 --- a/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php +++ b/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php @@ -7,7 +7,7 @@ /** * Remove a problem acknowledgement from a host or service */ -class RemoveAcknowledgementCommand extends ObjectCommand +class RemoveAcknowledgementCommand extends ObjectsCommand { use CommandAuthor; } diff --git a/library/Icingadb/Command/Object/ScheduleCheckCommand.php b/library/Icingadb/Command/Object/ScheduleCheckCommand.php index c3f209732..88a7fd3e0 100644 --- a/library/Icingadb/Command/Object/ScheduleCheckCommand.php +++ b/library/Icingadb/Command/Object/ScheduleCheckCommand.php @@ -7,7 +7,7 @@ /** * Schedule a check */ -class ScheduleCheckCommand extends ObjectCommand +class ScheduleCheckCommand extends ObjectsCommand { /** * Time when the next check of a host or service is to be scheduled diff --git a/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php b/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php index 699a11339..ec6628921 100644 --- a/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php +++ b/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php @@ -7,7 +7,7 @@ /** * Enable or disable a feature of an Icinga object, i.e. host or service */ -class ToggleObjectFeatureCommand extends ObjectCommand +class ToggleObjectFeatureCommand extends ObjectsCommand { /** * Feature for enabling or disabling active checks of a host or service diff --git a/library/Icingadb/Command/Object/WithCommentCommand.php b/library/Icingadb/Command/Object/WithCommentCommand.php index 299c998fa..fc92eb115 100644 --- a/library/Icingadb/Command/Object/WithCommentCommand.php +++ b/library/Icingadb/Command/Object/WithCommentCommand.php @@ -7,7 +7,7 @@ /** * Base class for commands adding comments */ -abstract class WithCommentCommand extends ObjectCommand +abstract class WithCommentCommand extends ObjectsCommand { use CommandAuthor; diff --git a/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php b/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php index aa1cdbee8..44671996f 100644 --- a/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php +++ b/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php @@ -24,6 +24,8 @@ use Icinga\Module\Icingadb\Command\IcingaCommand; use InvalidArgumentException; use ipl\Orm\Model; +use LogicException; +use Traversable; /** * Icinga command renderer for the Icinga command file @@ -64,19 +66,44 @@ public function setApp(string $app): self /** * Apply filter to query data * - * @param array $data + * @param array $data + * @param Traversable $objects + * + * @return ?Model Any of the objects (useful for further type-dependent handling) + */ + protected function applyFilter(array &$data, Traversable $objects): ?Model + { + $object = null; + + foreach ($objects as $object) { + if ($object instanceof Service) { + $data['services'][] = sprintf('%s!%s', $object->host->name, $object->name); + } else { + $data['hosts'][] = $object->name; + } + } + + return $object; + } + + /** + * Get the sub-route of the endpoint for an object + * * @param Model $object * - * @return void + * @return string */ - protected function applyFilter(array &$data, Model $object) + protected function getObjectPluralType(Model $object): string { if ($object instanceof Host) { - $data['host'] = $object->name; - } else { - /** @var Service $object */ - $data['service'] = sprintf('%s!%s', $object->host->name, $object->name); + return 'hosts'; } + + if ($object instanceof Service) { + return 'services'; + } + + throw new LogicException(sprintf('Invalid object type %s provided', get_class($object))); } /** @@ -100,17 +127,13 @@ public function render(IcingaCommand $command): IcingaApiCommand public function renderGetObject(GetObjectCommand $command): IcingaApiCommand { - $endpoint = sprintf( - 'objects/%s/%s', - $command->getObjectPluralType(), - rawurlencode($command->getObjectName()) - ); - $data = [ 'all_joins' => 1, 'attrs' => $command->getAttributes() ?: [] ]; + $endpoint = 'objects/' . $this->getObjectPluralType($this->applyFilter($data, $command->getObjects())); + return IcingaApiCommand::create($endpoint, $data)->setMethod('GET'); } @@ -126,7 +149,7 @@ public function renderAddComment(AddCommentCommand $command): IcingaApiCommand $data['expiry'] = $command->getExpireTime(); } - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } @@ -139,7 +162,7 @@ public function renderSendCustomNotification(SendCustomNotificationCommand $comm 'force' => $command->getForced() ]; - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } @@ -152,7 +175,7 @@ public function renderProcessCheckResult(ProcessCheckResultCommand $command): Ic 'performance_data' => $command->getPerformanceData() ]; - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } @@ -164,7 +187,7 @@ public function renderScheduleCheck(ScheduleCheckCommand $command): IcingaApiCom 'force' => $command->getForced() ]; - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } @@ -189,7 +212,7 @@ public function renderScheduleDowntime(ScheduleServiceDowntimeCommand $command): $data['all_services'] = true; } - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } @@ -208,7 +231,7 @@ public function renderAcknowledgeProblem(AcknowledgeProblemCommand $command): Ic $data['expiry'] = $command->getExpireTime(); } - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } @@ -235,13 +258,7 @@ public function renderToggleObjectFeature(ToggleObjectFeatureCommand $command): } $endpoint = 'objects/'; - $object = $command->getObject(); - if ($object instanceof Host) { - $endpoint .= 'hosts'; - } else { - /** @var Service $object */ - $endpoint .= 'services'; - } + $objects = $command->getObjects(); $data = [ 'attrs' => [ @@ -249,7 +266,9 @@ public function renderToggleObjectFeature(ToggleObjectFeatureCommand $command): ] ]; - $this->applyFilter($data, $object); + + $endpoint .= $this->getObjectPluralType($this->applyFilter($data, $objects)); + return IcingaApiCommand::create($endpoint, $data); } @@ -280,7 +299,7 @@ public function renderRemoveAcknowledgement(RemoveAcknowledgementCommand $comman $endpoint = 'actions/remove-acknowledgement'; $data = ['author' => $command->getAuthor()]; - $this->applyFilter($data, $command->getObject()); + $this->applyFilter($data, $command->getObjects()); return IcingaApiCommand::create($endpoint, $data); } From 1a04927c8bbe1954f7785e56c03d2c03a80e979e Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 1 Mar 2023 11:37:54 +0100 Subject: [PATCH 3/7] Introduce CommandForm#filterGrantedOn() --- application/forms/Command/CommandForm.php | 20 +++++++++++++++++++ .../Instance/ToggleInstanceFeaturesForm.php | 3 --- .../Command/Object/AcknowledgeProblemForm.php | 3 --- .../forms/Command/Object/AddCommentForm.php | 3 --- .../forms/Command/Object/CheckNowForm.php | 3 --- .../Command/Object/DeleteCommentForm.php | 2 -- .../Command/Object/DeleteDowntimeForm.php | 2 -- .../Command/Object/ProcessCheckResultForm.php | 3 --- .../Object/RemoveAcknowledgementForm.php | 3 --- .../Command/Object/ScheduleCheckForm.php | 3 --- .../Object/ScheduleServiceDowntimeForm.php | 3 --- .../Object/SendCustomNotificationForm.php | 3 --- .../Object/ToggleObjectFeaturesForm.php | 3 --- 13 files changed, 20 insertions(+), 34 deletions(-) diff --git a/application/forms/Command/CommandForm.php b/application/forms/Command/CommandForm.php index 5aa991c2c..b16b5e862 100644 --- a/application/forms/Command/CommandForm.php +++ b/application/forms/Command/CommandForm.php @@ -6,9 +6,11 @@ use ArrayIterator; use Exception; +use Generator; use Icinga\Application\Logger; use Icinga\Module\Icingadb\Command\IcingaCommand; use Icinga\Module\Icingadb\Command\Transport\CommandTransport; +use Icinga\Module\Icingadb\Common\Auth; use Icinga\Web\Notification; use Icinga\Web\Session; use ipl\Html\Form; @@ -18,6 +20,7 @@ abstract class CommandForm extends Form { + use Auth; use CsrfCounterMeasure; protected $defaultAttributes = ['class' => 'icinga-form icinga-controls']; @@ -126,4 +129,21 @@ protected function sendCommand(IcingaCommand $command) { (new CommandTransport())->send($command); } + + /** + * Yield the $objects the currently logged in user has the permission $permission for + * + * @param string $permission + * @param Traversable $objects + * + * @return Generator + */ + protected function filterGrantedOn(string $permission, Traversable $objects): Generator + { + foreach ($objects as $object) { + if ($this->isGrantedOn($permission, $object)) { + yield $object; + } + } + } } diff --git a/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php b/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php index 4c382447f..cf14db8a4 100644 --- a/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php +++ b/application/forms/Command/Instance/ToggleInstanceFeaturesForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Instance; use Icinga\Module\Icingadb\Command\Instance\ToggleInstanceFeatureCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; use ipl\Web\FormDecorator\IcingaFormDecorator; @@ -13,8 +12,6 @@ class ToggleInstanceFeaturesForm extends CommandForm { - use Auth; - protected $features; protected $featureStatus; diff --git a/application/forms/Command/Object/AcknowledgeProblemForm.php b/application/forms/Command/Object/AcknowledgeProblemForm.php index ecbfea600..23098fbb2 100644 --- a/application/forms/Command/Object/AcknowledgeProblemForm.php +++ b/application/forms/Command/Object/AcknowledgeProblemForm.php @@ -8,7 +8,6 @@ use DateTime; use Icinga\Application\Config; use Icinga\Module\Icingadb\Command\Object\AcknowledgeProblemCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; @@ -22,8 +21,6 @@ class AcknowledgeProblemForm extends CommandForm { - use Auth; - public function __construct() { $this->on(self::ON_SUCCESS, function () { diff --git a/application/forms/Command/Object/AddCommentForm.php b/application/forms/Command/Object/AddCommentForm.php index a6864e144..2cba04153 100644 --- a/application/forms/Command/Object/AddCommentForm.php +++ b/application/forms/Command/Object/AddCommentForm.php @@ -8,7 +8,6 @@ use DateTime; use Icinga\Application\Config; use Icinga\Module\Icingadb\Command\Object\AddCommentCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; @@ -22,8 +21,6 @@ class AddCommentForm extends CommandForm { - use Auth; - public function __construct() { $this->on(self::ON_SUCCESS, function () { diff --git a/application/forms/Command/Object/CheckNowForm.php b/application/forms/Command/Object/CheckNowForm.php index e713e15c5..288b164b5 100644 --- a/application/forms/Command/Object/CheckNowForm.php +++ b/application/forms/Command/Object/CheckNowForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; use Icinga\Module\Icingadb\Command\Object\ScheduleCheckCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; use ipl\Web\Widget\Icon; @@ -13,8 +12,6 @@ class CheckNowForm extends CommandForm { - use Auth; - protected $defaultAttributes = ['class' => 'inline']; public function __construct() diff --git a/application/forms/Command/Object/DeleteCommentForm.php b/application/forms/Command/Object/DeleteCommentForm.php index 2b86db37d..55e2a28a4 100644 --- a/application/forms/Command/Object/DeleteCommentForm.php +++ b/application/forms/Command/Object/DeleteCommentForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; use Icinga\Module\Icingadb\Command\Object\DeleteCommentCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; use ipl\Web\Common\RedirectOption; @@ -14,7 +13,6 @@ class DeleteCommentForm extends CommandForm { - use Auth; use RedirectOption; protected $defaultAttributes = ['class' => 'inline']; diff --git a/application/forms/Command/Object/DeleteDowntimeForm.php b/application/forms/Command/Object/DeleteDowntimeForm.php index 58d6260fb..18d3ca5af 100644 --- a/application/forms/Command/Object/DeleteDowntimeForm.php +++ b/application/forms/Command/Object/DeleteDowntimeForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; use Icinga\Module\Icingadb\Command\Object\DeleteDowntimeCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; use ipl\Web\Common\RedirectOption; @@ -14,7 +13,6 @@ class DeleteDowntimeForm extends CommandForm { - use Auth; use RedirectOption; protected $defaultAttributes = ['class' => 'inline']; diff --git a/application/forms/Command/Object/ProcessCheckResultForm.php b/application/forms/Command/Object/ProcessCheckResultForm.php index 7b9e5fb02..e3fd1ab68 100644 --- a/application/forms/Command/Object/ProcessCheckResultForm.php +++ b/application/forms/Command/Object/ProcessCheckResultForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; use Icinga\Module\Icingadb\Command\Object\ProcessCheckResultCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; @@ -19,8 +18,6 @@ class ProcessCheckResultForm extends CommandForm { - use Auth; - public function __construct() { $this->on(self::ON_SUCCESS, function () { diff --git a/application/forms/Command/Object/RemoveAcknowledgementForm.php b/application/forms/Command/Object/RemoveAcknowledgementForm.php index 66fe723d6..692f753e4 100644 --- a/application/forms/Command/Object/RemoveAcknowledgementForm.php +++ b/application/forms/Command/Object/RemoveAcknowledgementForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; use Icinga\Module\Icingadb\Command\Object\RemoveAcknowledgementCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; @@ -14,8 +13,6 @@ class RemoveAcknowledgementForm extends CommandForm { - use Auth; - public function __construct() { $this->on(self::ON_SUCCESS, function () { diff --git a/application/forms/Command/Object/ScheduleCheckForm.php b/application/forms/Command/Object/ScheduleCheckForm.php index 4fd992325..b4b6e404f 100644 --- a/application/forms/Command/Object/ScheduleCheckForm.php +++ b/application/forms/Command/Object/ScheduleCheckForm.php @@ -7,7 +7,6 @@ use DateInterval; use DateTime; use Icinga\Module\Icingadb\Command\Object\ScheduleCheckCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; @@ -20,8 +19,6 @@ class ScheduleCheckForm extends CommandForm { - use Auth; - public function __construct() { $this->on(self::ON_SUCCESS, function () { diff --git a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php index 52ca028db..07eb793df 100644 --- a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php @@ -8,7 +8,6 @@ use DateTime; use Icinga\Application\Config; use Icinga\Module\Icingadb\Command\Object\ScheduleServiceDowntimeCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; use ipl\Html\Attributes; @@ -21,8 +20,6 @@ class ScheduleServiceDowntimeForm extends CommandForm { - use Auth; - /** @var DateTime downtime start */ protected $start; diff --git a/application/forms/Command/Object/SendCustomNotificationForm.php b/application/forms/Command/Object/SendCustomNotificationForm.php index bf29997b7..483d49ce7 100644 --- a/application/forms/Command/Object/SendCustomNotificationForm.php +++ b/application/forms/Command/Object/SendCustomNotificationForm.php @@ -6,7 +6,6 @@ use Icinga\Application\Config; use Icinga\Module\Icingadb\Command\Object\SendCustomNotificationCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; use Icinga\Web\Notification; @@ -19,8 +18,6 @@ class SendCustomNotificationForm extends CommandForm { - use Auth; - public function __construct() { $this->on(self::ON_SUCCESS, function () { diff --git a/application/forms/Command/Object/ToggleObjectFeaturesForm.php b/application/forms/Command/Object/ToggleObjectFeaturesForm.php index b2d41ceb0..15bc6c110 100644 --- a/application/forms/Command/Object/ToggleObjectFeaturesForm.php +++ b/application/forms/Command/Object/ToggleObjectFeaturesForm.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; use Icinga\Module\Icingadb\Command\Object\ToggleObjectFeatureCommand; -use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; use ipl\Html\FormElement\CheckboxElement; @@ -15,8 +14,6 @@ class ToggleObjectFeaturesForm extends CommandForm { - use Auth; - const LEAVE_UNCHANGED = 'noop'; protected $features; From b92eeb69e7200ccde84fbf786a5bf1ffd80b75ee Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 1 Mar 2023 13:11:15 +0100 Subject: [PATCH 4/7] Actually let ObjectsCommand derivates process multiple objects at once --- .../Command/Object/AcknowledgeProblemForm.php | 8 ++--- .../forms/Command/Object/AddCommentForm.php | 8 ++--- .../forms/Command/Object/CheckNowForm.php | 25 +++++++++------- .../Command/Object/ProcessCheckResultForm.php | 16 +++++----- .../Object/RemoveAcknowledgementForm.php | 8 ++--- .../Command/Object/ScheduleCheckForm.php | 25 +++++++++------- .../Object/ScheduleHostDowntimeForm.php | 8 ++--- .../Object/ScheduleServiceDowntimeForm.php | 8 ++--- .../Object/SendCustomNotificationForm.php | 8 ++--- .../Object/ToggleObjectFeaturesForm.php | 30 +++++++++---------- 10 files changed, 71 insertions(+), 73 deletions(-) diff --git a/application/forms/Command/Object/AcknowledgeProblemForm.php b/application/forms/Command/Object/AcknowledgeProblemForm.php index 23098fbb2..608b26b8d 100644 --- a/application/forms/Command/Object/AcknowledgeProblemForm.php +++ b/application/forms/Command/Object/AcknowledgeProblemForm.php @@ -186,13 +186,11 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/acknowledge-problem', $object)) { - continue; - } + $granted = $this->filterGrantedOn('icingadb/command/acknowledge-problem', $objects); + if ($granted->valid()) { $command = new AcknowledgeProblemCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); $command->setNotify($this->getElement('notify')->isChecked()); diff --git a/application/forms/Command/Object/AddCommentForm.php b/application/forms/Command/Object/AddCommentForm.php index 2cba04153..56dfbe539 100644 --- a/application/forms/Command/Object/AddCommentForm.php +++ b/application/forms/Command/Object/AddCommentForm.php @@ -141,13 +141,11 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/comment/add', $object)) { - continue; - } + $granted = $this->filterGrantedOn('icingadb/command/comment/add', $objects); + if ($granted->valid()) { $command = new AddCommentCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); diff --git a/application/forms/Command/Object/CheckNowForm.php b/application/forms/Command/Object/CheckNowForm.php index 288b164b5..b7a506ce7 100644 --- a/application/forms/Command/Object/CheckNowForm.php +++ b/application/forms/Command/Object/CheckNowForm.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; +use Generator; use Icinga\Module\Icingadb\Command\Object\ScheduleCheckCommand; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; @@ -45,19 +46,23 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if ( - ! $this->isGrantedOn('icingadb/command/schedule-check', $object) - && ( - ! $object->active_checks_enabled - || ! $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) - ) - ) { - continue; + $granted = (function () use ($objects): Generator { + foreach ($objects as $object) { + if ( + $this->isGrantedOn('icingadb/command/schedule-check', $object) + || ( + $object->active_checks_enabled + && $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) + ) + ) { + yield $object; + } } + })(); + if ($granted->valid()) { $command = new ScheduleCheckCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setCheckTime(time()); $command->setForced(); diff --git a/application/forms/Command/Object/ProcessCheckResultForm.php b/application/forms/Command/Object/ProcessCheckResultForm.php index e3fd1ab68..aee7c3425 100644 --- a/application/forms/Command/Object/ProcessCheckResultForm.php +++ b/application/forms/Command/Object/ProcessCheckResultForm.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; +use Generator; use Icinga\Module\Icingadb\Command\Object\ProcessCheckResultCommand; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; @@ -136,16 +137,17 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if ( - ! $object->passive_checks_enabled - || ! $this->isGrantedOn('icingadb/command/process-check-result', $object) - ) { - continue; + $granted = (function () use ($objects): Generator { + foreach ($this->filterGrantedOn('icingadb/command/process-check-result', $objects) as $object) { + if ($object->passive_checks_enabled) { + yield $object; + } } + })(); + if ($granted->valid()) { $command = new ProcessCheckResultCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setStatus($this->getValue('status')); $command->setOutput($this->getValue('output')); $command->setPerformanceData($this->getValue('perfdata')); diff --git a/application/forms/Command/Object/RemoveAcknowledgementForm.php b/application/forms/Command/Object/RemoveAcknowledgementForm.php index 692f753e4..29e9bd61a 100644 --- a/application/forms/Command/Object/RemoveAcknowledgementForm.php +++ b/application/forms/Command/Object/RemoveAcknowledgementForm.php @@ -62,13 +62,11 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/remove-acknowledgement', $object)) { - continue; - } + $granted = $this->filterGrantedOn('icingadb/command/remove-acknowledgement', $objects); + if ($granted->valid()) { $command = new RemoveAcknowledgementCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setAuthor($this->getAuth()->getUser()->getUsername()); yield $command; diff --git a/application/forms/Command/Object/ScheduleCheckForm.php b/application/forms/Command/Object/ScheduleCheckForm.php index b4b6e404f..433b38a5a 100644 --- a/application/forms/Command/Object/ScheduleCheckForm.php +++ b/application/forms/Command/Object/ScheduleCheckForm.php @@ -6,6 +6,7 @@ use DateInterval; use DateTime; +use Generator; use Icinga\Module\Icingadb\Command\Object\ScheduleCheckCommand; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Module\Icingadb\Model\Host; @@ -108,19 +109,23 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if ( - ! $this->isGrantedOn('icingadb/command/schedule-check', $object) - && ( - ! $object->active_checks_enabled - || ! $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) - ) - ) { - continue; + $granted = (function () use ($objects): Generator { + foreach ($objects as $object) { + if ( + $this->isGrantedOn('icingadb/command/schedule-check', $object) + || ( + $object->active_checks_enabled + && $this->isGrantedOn('icingadb/command/schedule-check/active-only', $object) + ) + ) { + yield $object; + } } + })(); + if ($granted->valid()) { $command = new ScheduleCheckCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setForced($this->getElement('force_check')->isChecked()); $command->setCheckTime($this->getValue('check_time')->getTimestamp()); diff --git a/application/forms/Command/Object/ScheduleHostDowntimeForm.php b/application/forms/Command/Object/ScheduleHostDowntimeForm.php index cbade08e2..bc211143f 100644 --- a/application/forms/Command/Object/ScheduleHostDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleHostDowntimeForm.php @@ -89,11 +89,9 @@ protected function assembleElements() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/downtime/schedule', $object)) { - continue; - } + $granted = $this->filterGrantedOn('icingadb/command/downtime/schedule', $objects); + if ($granted->valid()) { if (($childOptions = (int) $this->getValue('child_options'))) { $command = new PropagateHostDowntimeCommand(); $command->setTriggered($childOptions === 1); @@ -101,7 +99,7 @@ protected function getCommands(Traversable $objects): Traversable $command = new ScheduleHostDowntimeCommand(); } - $command->setObjects([$object]); + $command->setObjects($granted); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); $command->setStart($this->getValue('start')->getTimestamp()); diff --git a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php index 07eb793df..184a4e8bf 100644 --- a/application/forms/Command/Object/ScheduleServiceDowntimeForm.php +++ b/application/forms/Command/Object/ScheduleServiceDowntimeForm.php @@ -244,13 +244,11 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/downtime/schedule', $object)) { - continue; - } + $granted = $this->filterGrantedOn('icingadb/command/downtime/schedule', $objects); + if ($granted->valid()) { $command = new ScheduleServiceDowntimeCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setComment($this->getValue('comment')); $command->setAuthor($this->getAuth()->getUser()->getUsername()); $command->setStart($this->getValue('start')->getTimestamp()); diff --git a/application/forms/Command/Object/SendCustomNotificationForm.php b/application/forms/Command/Object/SendCustomNotificationForm.php index 483d49ce7..d1d981790 100644 --- a/application/forms/Command/Object/SendCustomNotificationForm.php +++ b/application/forms/Command/Object/SendCustomNotificationForm.php @@ -108,13 +108,11 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/send-custom-notification', $object)) { - continue; - } + $granted = $this->filterGrantedOn('icingadb/command/send-custom-notification', $objects); + if ($granted->valid()) { $command = new SendCustomNotificationCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setComment($this->getValue('comment')); $command->setForced($this->getElement('forced')->isChecked()); $command->setAuthor($this->getAuth()->getUser()->getUsername()); diff --git a/application/forms/Command/Object/ToggleObjectFeaturesForm.php b/application/forms/Command/Object/ToggleObjectFeaturesForm.php index 15bc6c110..50767da70 100644 --- a/application/forms/Command/Object/ToggleObjectFeaturesForm.php +++ b/application/forms/Command/Object/ToggleObjectFeaturesForm.php @@ -158,26 +158,24 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - foreach ($this->features as $feature => $spec) { - if ($this->getElement($feature) instanceof CheckboxElement) { - $featureState = $this->getElement($feature)->isChecked(); - } else { - $featureState = $this->getElement($feature)->getValue(); - } + foreach ($this->features as $feature => $spec) { + if ($this->getElement($feature) instanceof CheckboxElement) { + $state = $this->getElement($feature)->isChecked(); + } else { + $state = $this->getElement($feature)->getValue(); + } - if ( - ! $this->isGrantedOn($spec['permission'], $object) - || $featureState === self::LEAVE_UNCHANGED - || (int) $featureState === (int) $this->featureStatus[$feature] - ) { - continue; - } + if ($state === self::LEAVE_UNCHANGED || (int) $state === (int) $this->featureStatus[$feature]) { + continue; + } + + $granted = $this->filterGrantedOn($spec['permission'], $objects); + if ($granted->valid()) { $command = new ToggleObjectFeatureCommand(); - $command->setObjects([$object]); + $command->setObjects($granted); $command->setFeature($feature); - $command->setEnabled((int) $featureState); + $command->setEnabled((int) $state); $this->submittedFeatures[] = $command; From cd5f52c1bcd3c301aa1693fb4c8b4d12f7ddee5c Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 1 Mar 2023 14:33:05 +0100 Subject: [PATCH 5/7] DeleteCommentCommand: process multiple objects at once --- .../Command/Object/DeleteCommentForm.php | 13 ++++-- .../Command/Object/DeleteCommentCommand.php | 41 +------------------ .../Renderer/IcingaApiCommandRenderer.php | 8 +++- 3 files changed, 17 insertions(+), 45 deletions(-) diff --git a/application/forms/Command/Object/DeleteCommentForm.php b/application/forms/Command/Object/DeleteCommentForm.php index 55e2a28a4..25275baf2 100644 --- a/application/forms/Command/Object/DeleteCommentForm.php +++ b/application/forms/Command/Object/DeleteCommentForm.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; +use Generator; use Icinga\Module\Icingadb\Command\Object\DeleteCommentCommand; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; @@ -55,13 +56,17 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if (! $this->isGrantedOn('icingadb/command/comment/delete', $object->{$object->object_type})) { - continue; + $granted = (function () use ($objects): Generator { + foreach ($objects as $object) { + if ($this->isGrantedOn('icingadb/command/comment/delete', $object->{$object->object_type})) { + yield $object; + } } + })(); + if ($granted->valid()) { $command = new DeleteCommentCommand(); - $command->setCommentName($object->name); + $command->setObjects($granted); $command->setAuthor($this->getAuth()->getUser()->getUsername()); yield $command; diff --git a/library/Icingadb/Command/Object/DeleteCommentCommand.php b/library/Icingadb/Command/Object/DeleteCommentCommand.php index 8bfc2a372..c06a73c9d 100644 --- a/library/Icingadb/Command/Object/DeleteCommentCommand.php +++ b/library/Icingadb/Command/Object/DeleteCommentCommand.php @@ -4,49 +4,10 @@ namespace Icinga\Module\Icingadb\Command\Object; -use Icinga\Module\Icingadb\Command\IcingaCommand; - /** * Delete a host or service comment */ -class DeleteCommentCommand extends IcingaCommand +class DeleteCommentCommand extends ObjectsCommand { use CommandAuthor; - - /** - * Name of the comment - * - * @var string - */ - protected $commentName; - - /** - * Get the name of the comment - * - * @return string - */ - public function getCommentName(): string - { - if ($this->commentName === null) { - throw new \LogicException( - 'You are accessing an unset property. Please make sure to set it beforehand.' - ); - } - - return $this->commentName; - } - - /** - * Set the name of the comment - * - * @param string $commentName - * - * @return $this - */ - public function setCommentName(string $commentName): self - { - $this->commentName = $commentName; - - return $this; - } } diff --git a/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php b/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php index 44671996f..5b9f206d5 100644 --- a/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php +++ b/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php @@ -274,10 +274,16 @@ public function renderToggleObjectFeature(ToggleObjectFeatureCommand $command): public function renderDeleteComment(DeleteCommentCommand $command): IcingaApiCommand { + $comments = []; + + foreach ($command->getObjects() as $object) { + $comments[] = $object->name; + } + $endpoint = 'actions/remove-comment'; $data = [ 'author' => $command->getAuthor(), - 'comment' => $command->getCommentName() + 'comments' => $comments ]; return IcingaApiCommand::create($endpoint, $data); From bbf2739b6e5bd2f3d1ab1b83517ae57c2a022b61 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 1 Mar 2023 14:41:34 +0100 Subject: [PATCH 6/7] DeleteDowntimeCommand: process multiple objects at once --- .../Command/Object/DeleteDowntimeForm.php | 19 +++++--- .../Command/Object/DeleteDowntimeCommand.php | 47 +------------------ .../Renderer/IcingaApiCommandRenderer.php | 8 +++- 3 files changed, 20 insertions(+), 54 deletions(-) diff --git a/application/forms/Command/Object/DeleteDowntimeForm.php b/application/forms/Command/Object/DeleteDowntimeForm.php index 18d3ca5af..5f695b962 100644 --- a/application/forms/Command/Object/DeleteDowntimeForm.php +++ b/application/forms/Command/Object/DeleteDowntimeForm.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Icingadb\Forms\Command\Object; +use Generator; use Icinga\Module\Icingadb\Command\Object\DeleteDowntimeCommand; use Icinga\Module\Icingadb\Forms\Command\CommandForm; use Icinga\Web\Notification; @@ -67,16 +68,20 @@ protected function assembleSubmitButton() protected function getCommands(Traversable $objects): Traversable { - foreach ($objects as $object) { - if ( - ! $this->isGrantedOn('icingadb/command/downtime/delete', $object->{$object->object_type}) - || $object->scheduled_by !== null - ) { - continue; + $granted = (function () use ($objects): Generator { + foreach ($objects as $object) { + if ( + $this->isGrantedOn('icingadb/command/downtime/delete', $object->{$object->object_type}) + && $object->scheduled_by === null + ) { + yield $object; + } } + })(); + if ($granted->valid()) { $command = new DeleteDowntimeCommand(); - $command->setDowntimeName($object->name); + $command->setObjects($granted); $command->setAuthor($this->getAuth()->getUser()->getUsername()); yield $command; diff --git a/library/Icingadb/Command/Object/DeleteDowntimeCommand.php b/library/Icingadb/Command/Object/DeleteDowntimeCommand.php index a0867fa90..7b4c2827e 100644 --- a/library/Icingadb/Command/Object/DeleteDowntimeCommand.php +++ b/library/Icingadb/Command/Object/DeleteDowntimeCommand.php @@ -4,55 +4,10 @@ namespace Icinga\Module\Icingadb\Command\Object; -use Icinga\Module\Icingadb\Command\IcingaCommand; - /** * Delete a host or service downtime */ -class DeleteDowntimeCommand extends IcingaCommand +class DeleteDowntimeCommand extends ObjectsCommand { use CommandAuthor; - - /** - * Name of the downtime (Icinga 2.4+) - * - * Required for removing the downtime via Icinga 2's API. - * - * @var string - */ - protected $downtimeName; - - /** - * Get the name of the downtime (Icinga 2.4+) - * - * Required for removing the downtime via Icinga 2's API. - * - * @return string - */ - public function getDowntimeName(): string - { - if ($this->downtimeName === null) { - throw new \LogicException( - 'You are accessing an unset property. Please make sure to set it beforehand.' - ); - } - - return $this->downtimeName; - } - - /** - * Set the name of the downtime (Icinga 2.4+) - * - * Required for removing the downtime via Icinga 2's API. - * - * @param string $downtimeName - * - * @return $this - */ - public function setDowntimeName(string $downtimeName): self - { - $this->downtimeName = $downtimeName; - - return $this; - } } diff --git a/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php b/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php index 5b9f206d5..37075c994 100644 --- a/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php +++ b/library/Icingadb/Command/Renderer/IcingaApiCommandRenderer.php @@ -291,10 +291,16 @@ public function renderDeleteComment(DeleteCommentCommand $command): IcingaApiCom public function renderDeleteDowntime(DeleteDowntimeCommand $command): IcingaApiCommand { + $downtimes = []; + + foreach ($command->getObjects() as $object) { + $downtimes[] = $object->name; + } + $endpoint = 'actions/remove-downtime'; $data = [ 'author' => $command->getAuthor(), - 'downtime' => $command->getDowntimeName() + 'downtimes' => $downtimes ]; return IcingaApiCommand::create($endpoint, $data); From 137de73fd6de9d350f4a8faf7676a1e2cef55429 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 11 Jul 2023 13:49:44 +0200 Subject: [PATCH 7/7] Provide ObjectsCommand#setObject() for compatibility --- library/Icingadb/Command/Object/ObjectsCommand.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/Icingadb/Command/Object/ObjectsCommand.php b/library/Icingadb/Command/Object/ObjectsCommand.php index f59347ca3..1d7e1da97 100644 --- a/library/Icingadb/Command/Object/ObjectsCommand.php +++ b/library/Icingadb/Command/Object/ObjectsCommand.php @@ -34,6 +34,20 @@ public function setObjects(Traversable $objects): self return $this; } + /** + * Set the involved object + * + * @param Model $object + * + * @return $this + * + * @deprecated Use setObjects() instead + */ + public function setObject(Model $object): self + { + return $this->setObjects([$object]); + } + /** * Get the involved objects *