summaryrefslogtreecommitdiffstats
path: root/application/forms/Jobs/ScheduleForm.php
blob: ae47e58b68037e4937437b9245112189e24e0189 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
<?php

/* Icinga Web 2 X.509 Module | (c) 2023 Icinga GmbH | GPLv2 */

namespace Icinga\Module\X509\Forms\Jobs;

use DateTime;
use Exception;
use Icinga\Application\Icinga;
use Icinga\Application\Web;
use Icinga\Authentication\Auth;
use Icinga\Module\X509\Common\Database;
use Icinga\Module\X509\Model\X509Schedule;
use Icinga\User;
use Icinga\Util\Json;
use Icinga\Web\Notification;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Contract\FormSubmitElement;
use ipl\Html\HtmlDocument;
use ipl\Html\HtmlElement;
use ipl\Validator\CallbackValidator;
use ipl\Web\Compat\CompatForm;
use ipl\Web\FormElement\ScheduleElement;
use Psr\Http\Message\RequestInterface;

use function ipl\Stdlib\get_php_type;

class ScheduleForm extends CompatForm
{
    /** @var int */
    protected $jobId;

    /** @var ?X509Schedule */
    protected $schedule;

    /** @var ScheduleElement */
    protected $scheduleElement;

    public function __construct(X509Schedule $schedule = null)
    {
        $this->schedule = $schedule;
        $this->scheduleElement = new ScheduleElement('schedule_element');

        /** @var Web $app */
        $app = Icinga::app();
        $this->scheduleElement->setIdProtector([$app->getRequest(), 'protectId']);
    }

    protected function isUpdating(): bool
    {
        return $this->schedule !== null;
    }

    public function setJobId(int $jobId): self
    {
        $this->jobId = $jobId;

        return $this;
    }

    /**
     * Get multipart updates
     *
     * @return array<int, BaseHtmlElement>
     */
    public function getPartUpdates(): array
    {
        /** @var RequestInterface $request */
        $request = $this->getRequest();

        return $this->scheduleElement->prepareMultipartUpdate($request);
    }

    public function hasBeenSubmitted(): bool
    {
        if (! $this->hasBeenSent()) {
            return false;
        }

        $button = $this->getPressedSubmitElement();

        return $button && ($button->getName() === 'submit' || $button->getName() === 'btn_remove');
    }

    protected function assemble(): void
    {
        $this->addElement('text', 'name', [
            'required'    => true,
            'label'       => $this->translate('Name'),
            'description' => $this->translate('Schedule name'),
        ]);

        $this->addElement('checkbox', 'full_scan', [
            'required'    => false,
            'class'       => 'autosubmit',
            'label'       => $this->translate('Full Scan'),
            'description' => $this->translate(
                'Scan all known and unknown targets of this job. (Defaults to only scan unknown targets)'
            )
        ]);

        if ($this->getPopulatedValue('full_scan', 'n') === 'n') {
            $this->addElement('checkbox', 'rescan', [
                'required'    => false,
                'class'       => 'autosubmit',
                'label'       => $this->translate('Rescan'),
                'description' => $this->translate('Rescan only targets that have been scanned before')
            ]);

            $this->addElement('text', 'since_last_scan', [
                'required'    => false,
                'label'       => $this->translate('Since Last Scan'),
                'placeholder' => '-24 hours',
                'description' => $this->translate(
                    'Scan targets whose last scan is older than the specified date/time, which can also be an'
                    . ' English textual datetime description like "2 days". If you want to scan only unknown targets'
                    . ' you can set this to "null".'
                ),
                'validators'  => [
                    new CallbackValidator(function ($value, CallbackValidator $validator) {
                        if ($value !== null && $value !== 'null') {
                            try {
                                new DateTime($value);
                            } catch (Exception $_) {
                                $validator->addMessage($this->translate('Invalid textual date time'));

                                return false;
                            }
                        }

                        return true;
                    })
                ]
            ]);
        }

        $this->addHtml(HtmlElement::create('div', ['class' => 'schedule-element-separator']));
        $this->addElement($this->scheduleElement);

        $this->addElement('submit', 'submit', [
            'label' => $this->isUpdating() ? $this->translate('Update') : $this->translate('Schedule')
        ]);

        if ($this->isUpdating()) {
            $removeButton = $this->createElement('submit', 'btn_remove', [
                'class' => 'btn-remove',
                'label' => $this->translate('Remove Schedule'),
            ]);
            $this->registerElement($removeButton);

            /** @var HtmlDocument $wrapper */
            $wrapper = $this->getElement('submit')->getWrapper();
            $wrapper->prepend($removeButton);
        }
    }

    protected function onSuccess(): void
    {
        /** @var X509Schedule $schedule */
        $schedule = $this->schedule;
        $conn = Database::get();
        /** @var FormSubmitElement $submitElement */
        $submitElement = $this->getPressedSubmitElement();
        if ($submitElement->getName() === 'btn_remove') {
            $conn->delete('x509_schedule', ['id = ?' => $schedule->id]);

            Notification::success($this->translate('Deleted schedule successfully'));
        } else {
            $config = $this->getValues();
            unset($config['name']);
            unset($config['schedule_element']);

            $frequency = $this->scheduleElement->getValue();
            $config['type'] = get_php_type($frequency);
            $config['frequency'] = Json::encode($frequency);

            /** @var User $user */
            $user = Auth::getInstance()->getUser();
            if (! $this->isUpdating()) {
                $conn->insert('x509_schedule', [
                    'job_id' => $this->schedule ? $this->schedule->job_id : $this->jobId,
                    'name'   => $this->getValue('name'),
                    'author' => $user->getUsername(),
                    'config' => Json::encode($config),
                    'ctime'  => (new DateTime())->getTimestamp() * 1000.0,
                    'mtime'  => (new DateTime())->getTimestamp() * 1000.0
                ]);
                $message = $this->translate('Created schedule successfully');
            } else {
                $conn->update('x509_schedule', [
                    'name'   => $this->getValue('name'),
                    'config' => Json::encode($config),
                    'mtime'  => (new DateTime())->getTimestamp() * 1000.0
                ], ['id = ?' => $schedule->id]);
                $message = $this->translate('Updated schedule successfully');
            }

            Notification::success($message);
        }
    }
}