summaryrefslogtreecommitdiffstats
path: root/modules-available/eventlog/pages
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/eventlog/pages')
-rw-r--r--modules-available/eventlog/pages/log.inc.php56
-rw-r--r--modules-available/eventlog/pages/mailconfigs.inc.php99
-rw-r--r--modules-available/eventlog/pages/rules.inc.php187
-rw-r--r--modules-available/eventlog/pages/transports.inc.php179
4 files changed, 521 insertions, 0 deletions
diff --git a/modules-available/eventlog/pages/log.inc.php b/modules-available/eventlog/pages/log.inc.php
new file mode 100644
index 00000000..66826b08
--- /dev/null
+++ b/modules-available/eventlog/pages/log.inc.php
@@ -0,0 +1,56 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ User::assertPermission('view');
+ User::setLastSeenEvent(Property::getLastWarningId());
+ }
+
+ public static function doRender()
+ {
+ $lines = array();
+ $paginate = new Paginate("SELECT logid, dateline, logtypeid, description, extra FROM eventlog ORDER BY logid DESC", 50);
+ $res = $paginate->exec();
+ foreach ($res as $row) {
+ $row['date'] = Util::prettyTime($row['dateline']);
+ $row['icon'] = self::typeToIcon($row['logtypeid']);
+ $row['color'] = self::typeToColor($row['logtypeid']);
+ $lines[] = $row;
+ }
+
+ $paginate->render('_page', array(
+ 'list' => $lines
+ ));
+ }
+
+ private static function typeToIcon(string $type): string
+ {
+ switch ($type) {
+ case 'info':
+ return 'ok';
+ case 'warning':
+ return 'exclamation-sign';
+ case 'failure':
+ return 'remove';
+ default:
+ return 'question-sign';
+ }
+ }
+
+ private static function typeToColor(string $type): string
+ {
+ switch ($type) {
+ case 'warning':
+ return 'orange';
+ case 'failure':
+ return 'red';
+ case 'info':
+ default:
+ return '';
+ }
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/eventlog/pages/mailconfigs.inc.php b/modules-available/eventlog/pages/mailconfigs.inc.php
new file mode 100644
index 00000000..0ba71104
--- /dev/null
+++ b/modules-available/eventlog/pages/mailconfigs.inc.php
@@ -0,0 +1,99 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ if (Request::isPost()) {
+ User::assertPermission('filter.mailconfigs.edit');
+ $action = Request::post('action');
+ if ($action === 'save-mailconfig') {
+ self::saveMailconfig();
+ } elseif ($action === 'delete-mailconfig') {
+ self::deleteMailconfig();
+ } else {
+ Message::addError('main.invalid-action', $action);
+ }
+ Util::redirect('?do=eventlog&show=mailconfigs');
+ }
+ }
+
+ private static function saveMailconfig()
+ {
+ User::assertPermission('filter.mailconfigs.edit');
+ $id = Request::post('id', Request::REQUIRED, 'int');
+ $data = [
+ 'host' => Request::post('host', Request::REQUIRED, 'string'),
+ 'port' => Request::post('port', Request::REQUIRED, 'int'),
+ 'ssl' => Request::post('ssl', Request::REQUIRED, 'string'),
+ 'senderaddress' => Request::post('senderaddress', Request::REQUIRED, 'string'),
+ 'replyto' => Request::post('replyto', '', 'string'),
+ 'username' => Request::post('username', '', 'string'),
+ 'password' => Request::post('password', '', 'string'),
+ ];
+ if ($id === 0) {
+ // NEW
+ Database::exec("INSERT INTO mail_config (host, port, `ssl`, senderaddress, replyto, username, password)
+ VALUES (:host, :port, :ssl, :senderaddress, :replyto, :username, :password)", $data);
+ } else {
+ // UPDATE
+ $data['configid'] = $id;
+ Database::exec("UPDATE mail_config SET host = :host, port = :port, `ssl` = :ssl,
+ senderaddress = :senderaddress, replyto = :replyto, username = :username, password = :password
+ WHERE configid = :configid", $data);
+ }
+ Message::addSuccess("event-mailconfig-saved", $id);
+ Util::redirect('?do=eventlog&show=mailconfigs');
+ }
+
+ private static function deleteMailconfig()
+ {
+ User::assertPermission('filter.mailconfigs.edit');
+ $id = Request::post('id', Request::REQUIRED, 'int');
+ Database::exec("DELETE FROM mail_config WHERE configid = :id", ['id' => $id]);
+ }
+
+ /*
+ *
+ */
+
+ public static function doRender()
+ {
+ User::assertPermission('filter.mailconfigs.view');
+ $id = Request::get('id', null, 'int');
+ if ($id !== null) {
+ self::showMailconfigEditor($id);
+ } else {
+ // LIST
+ $data = [];
+ $data['configs'] = Database::queryAll('SELECT configid, host, port, `ssl`, senderaddress, replyto
+ FROM mail_config
+ ORDER BY host');
+ Render::addTemplate('page-filters-mailconfigs', $data);
+ }
+ }
+
+ /**
+ * @param int $id Config to edit. If id is 0, a new config will be created.
+ */
+ private static function showMailconfigEditor(int $id)
+ {
+ User::assertPermission('filter.mailconfigs.edit');
+ if ($id !== 0) {
+ // EDIT
+ $data = Database::queryFirst('SELECT configid, host, port, `ssl`, senderaddress, replyto,
+ username, password
+ FROM mail_config
+ WHERE configid = :id', ['id' => $id]);
+ if ($data === false) {
+ Message::addError('invalid-mailconfig-id', $id);
+ Util::redirect('?do=eventlog&show=mailconfigs');
+ }
+ } else {
+ $data = ['configid' => 0];
+ }
+ Render::addTemplate('page-filters-edit-mailconfig', $data);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/eventlog/pages/rules.inc.php b/modules-available/eventlog/pages/rules.inc.php
new file mode 100644
index 00000000..7b43cfdb
--- /dev/null
+++ b/modules-available/eventlog/pages/rules.inc.php
@@ -0,0 +1,187 @@
+<?php
+
+class SubPage
+{
+
+ const OP_LIST = ['*', '=', '!=', '<', '<=', '>', '>=', 'regex'];
+
+ public static function doPreprocess()
+ {
+ if (Request::isPost()) {
+ User::assertPermission('filter.rules.edit');
+ $action = Request::post('action');
+ if ($action === 'save-filter') {
+ self::saveRule();
+ } elseif ($action === 'delete-filter') {
+ self::deleteRule();
+ } else {
+ Message::addError('main.invalid-action', $action);
+ }
+ Util::redirect('?do=eventlog&show=rules');
+ }
+ }
+
+ private static function saveRule()
+ {
+ User::assertPermission('filter.rules.edit');
+ $id = Request::post('id', Request::REQUIRED, 'int');
+ $type = Request::post('type', Request::REQUIRED, 'string');
+ $title = Request::post('title', Request::REQUIRED, 'string');
+ $message = Request::post('message', Request::REQUIRED, 'string');
+ $transports = Request::post('transports', [], 'array');
+ $filters = Request::post('filter', Request::REQUIRED, 'array');
+ $filters = array_filter($filters, function ($item) {
+ return is_array($item) && !empty($item['path']) && !empty($item['op']);
+ });
+ foreach ($filters as $index => &$item) {
+ $item['index'] = $index;
+ }
+ unset($item);
+ if (empty($filters)) {
+ Message::addError('no-valid-filters');
+ Util::redirect('?do=eventlog&show=rules');
+ }
+ if ($id === 0) {
+ $id = null;
+ }
+ $data = [
+ 'id' => $id,
+ 'type' => $type,
+ 'title' => $title,
+ 'description' => Request::post('description', '', 'string'),
+ 'data' => json_encode(['list' => array_values($filters)]),
+ 'subject' => Request::post('subject', '', 'string'),
+ 'message' => $message,
+ ];
+ if ($id === null) {
+ // NEW
+ Database::exec("INSERT INTO notification_rule (ruleid, title, description, type, datafilter, subject, message)
+ VALUES (:id, :title, :description, :type, :data, :subject, :message)", $data);
+ $id = Database::lastInsertId();
+ } else {
+ Database::exec("UPDATE notification_rule SET type = :type, title = :title, description = :description, datafilter = :data,
+ subject = :subject, message = :message
+ WHERE ruleid = :id", $data);
+ }
+ if (empty($transports)) {
+ Database::exec("DELETE FROM notification_rule_x_transport WHERE ruleid = :id", ['id' => $id]);
+ } else {
+ Database::exec("DELETE FROM notification_rule_x_transport
+ WHERE ruleid = :id AND transportid NOT IN (:transports)",
+ ['id' => $id, 'transports' => $transports]);
+ Database::exec("INSERT IGNORE INTO notification_rule_x_transport (ruleid, transportid)
+ VALUES :list", ['list' => array_map(function ($i) use ($id) { return [$id, $i]; }, $transports)]);
+ }
+ Message::addSuccess("event-rule-saved", $id);
+ Util::redirect('?do=eventlog&show=rules');
+ }
+
+ private static function deleteRule()
+ {
+ User::assertPermission('filter.rules.edit');
+ $id = Request::post('id', Request::REQUIRED, 'int');
+ Database::exec("DELETE FROM notification_rule WHERE ruleid = :id", ['id' => $id]);
+ }
+
+ /*
+ *
+ */
+
+ public static function doRender()
+ {
+ User::assertPermission('filter.rules.view');
+ $id = Request::get('id', null, 'int');
+ if ($id !== null) {
+ self::showRuleEditor($id);
+ } else {
+ // LIST
+ $data = [];
+ $data['filters'] = Database::queryAll('SELECT ruleid, type, title, datafilter,
+ Count(transportid) AS useCount
+ FROM notification_rule
+ LEFT JOIN notification_rule_x_transport sfxb USING (ruleid)
+ GROUP BY ruleid, title
+ ORDER BY title, ruleid');
+ Permission::addGlobalTags($data['perms'], null, ['filter.rules.edit']);
+ Render::addTemplate('page-filters-rules', $data);
+ }
+ }
+
+ /**
+ * @param int $id Rule to edit. If id is 0, a new rule will be created.
+ */
+ private static function showRuleEditor(int $id)
+ {
+ // EDIT
+ User::assertPermission('filter.rules.edit');
+ $filterIdx = 0;
+ $knownIdxList = [];
+ if ($id !== 0) {
+ $data = Database::queryFirst('SELECT ruleid, title, description, type, datafilter, subject, message
+ FROM notification_rule WHERE ruleid = :id', ['id' => $id]);
+ if ($data === false) {
+ Message::addError('invalid-rule-id', $id);
+ Util::redirect('?do=eventlog&show=rules');
+ }
+ if (Request::get('copy', false, 'bool')) {
+ $data['ruleid'] = 0;
+ $data['title'] = '';
+ }
+ $list = json_decode($data['datafilter'], true);
+ if (!is_array($list['list'])) {
+ $list['list'] = [];
+ }
+ foreach ($list['list'] as $item) {
+ if (isset($item['index'])) {
+ $knownIdxList[] = $item['index'];
+ }
+ }
+ foreach ($list['list'] as &$item) {
+ if (!isset($item['index'])) {
+ while (in_array($filterIdx, $knownIdxList)) {
+ $filterIdx++;
+ }
+ $item['index'] = $filterIdx++;
+ }
+ $item['operators'] = [];
+ foreach (self::OP_LIST as $op) {
+ $item['operators'][] = [
+ 'name' => $op,
+ 'selected' => ($op === $item['op']) ? 'selected' : '',
+ ];
+ }
+ }
+ $data['filter'] = $list['list'];
+ } else {
+ // New entry
+ $data = ['filter' => [], 'ruleid' => 0];
+ }
+ // Add suggestions for type
+ $data['types'] = Database::queryColumnArray("SELECT DISTINCT type
+ FROM notification_sample
+ ORDER BY type");
+ //
+ Module::isAvailable('bootstrap_multiselect');
+ $data['transports'] = Database::queryAll("SELECT nb.transportid, nb.title,
+ IF(sfxb.ruleid IS NULL, '', 'selected') AS selected
+ FROM notification_backend nb
+ LEFT JOIN notification_rule_x_transport sfxb ON (sfxb.transportid = nb.transportid AND sfxb.ruleid = :id)",
+ ['id' => $id]);
+ if (Module::isAvailable('statistics')) {
+ // Filter keys to suggest for events with machineuuid in data
+ $data['machine_keys'] = array_keys(FilterRuleProcessor::HW_QUERIES);
+ }
+ // Add a few empty rows at the bottom
+ for ($i = 0; $i < 8; ++$i) {
+ while (in_array($filterIdx, $knownIdxList)) {
+ $filterIdx++;
+ }
+ $data['filter'][] = [
+ 'index' => $filterIdx++,
+ 'operators' => array_map(function ($item) { return ['name' => $item]; }, self::OP_LIST),
+ ];
+ }
+ Render::addTemplate('page-filters-edit-rule', $data);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/eventlog/pages/transports.inc.php b/modules-available/eventlog/pages/transports.inc.php
new file mode 100644
index 00000000..439c650c
--- /dev/null
+++ b/modules-available/eventlog/pages/transports.inc.php
@@ -0,0 +1,179 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ if (Request::isPost()) {
+ User::assertPermission('filter.transports.edit');
+ $action = Request::post('action');
+ if ($action === 'save-transport') {
+ self::saveTransport();
+ } elseif ($action === 'delete-transport') {
+ self::deleteTransport();
+ } else {
+ Message::addError('main.invalid-action', $action);
+ }
+ Util::redirect('?do=eventlog&show=transports');
+ }
+ }
+
+ private static function saveTransport()
+ {
+ User::assertPermission('filter.transports.edit');
+ $id = Request::post('id', Request::REQUIRED, 'int');
+ $rules = Request::post('rules', [], 'array');
+ static $types = [
+ 'type' => [Request::REQUIRED, 'string', ['mail', 'irc', 'http', 'group']],
+ 'mail-config-id' => [0, 'int'],
+ 'mail-users' => [[], 'int[]'],
+ 'mail-extra-mails' => ['', 'string'],
+ 'irc-server' => ['', 'string'],
+ 'irc-server-password' => ['', 'string'],
+ 'irc-target' => ['', 'string'],
+ 'irc-nickname' => ['', 'string'],
+ 'http-uri' => ['', 'string'],
+ 'http-method' => ['', 'string', ['GET', 'POST']],
+ 'http-post-field' => ['', 'string'],
+ 'http-post-format' => ['', 'string', ['FORM', 'JSON', 'JSON_AUTO']],
+ 'group-list' => [[], 'int[]'],
+ ];
+ $data = [];
+ foreach ($types as $key => $def) {
+ if (substr($def[1], -1) === ']') {
+ $type = substr($def[1], 0, -2);
+ $array = true;
+ } else {
+ $type = $def[1];
+ $array = false;
+ }
+ if ($array) {
+ $value = Request::post($key, [], 'array');
+ foreach ($value as &$v) {
+ settype($v, $type);
+ if (isset($def[2]) && !in_array($v, $def[2])) {
+ Message::addWarning('main.value-invalid', $key, $v);
+ }
+ }
+ } else {
+ $value = Request::post($key, $def[0], $type);
+ if (isset($def[2]) && !in_array($value, $def[2])) {
+ Message::addWarning('main.value-invalid', $key, $value);
+ }
+ }
+ $data[$key] = $value;
+ }
+ //die(print_r($data));
+ $params = [
+ 'title' => Request::post('title', 'Backend', 'string'),
+ 'description' => Request::post('description', '', 'string'),
+ 'data' => json_encode($data),
+ ];
+ if ($id === 0) {
+ $res = Database::exec("INSERT INTO notification_backend (title, description, data)
+ VALUES (:title, :description, :data)", $params);
+ $id = Database::lastInsertId();
+ } else {
+ $params['transportid'] = $id;
+ $res = Database::exec("UPDATE notification_backend
+ SET title = :title, description = :description, data = :data
+ WHERE transportid = :transportid", $params);
+ }
+ if (empty($rules)) {
+ Database::exec("DELETE FROM notification_rule_x_transport WHERE transportid = :id", ['id' => $id]);
+ } else {
+ Database::exec("DELETE FROM notification_rule_x_transport
+ WHERE transportid = :id AND ruleid NOT IN (:rules)",
+ ['id' => $id, 'rules' => $rules]);
+ Database::exec("INSERT IGNORE INTO notification_rule_x_transport (ruleid, transportid)
+ VALUES :list", ['list' => array_map(function ($i) use ($id) { return [$i, $id]; }, $rules)]);
+ }
+ if ($res > 0) {
+ Message::addSuccess('transport-saved', $id);
+ }
+ Util::redirect('?do=eventlog&show=transports&section=transports');
+ }
+
+ private static function deleteTransport()
+ {
+ User::assertPermission('filter.transports.edit');
+ $id = Request::post('id', Request::REQUIRED, 'int');
+ Database::exec("DELETE FROM notification_backend WHERE transportid = :id", ['id' => $id]);
+ }
+
+ /*
+ *
+ */
+
+ public static function doRender()
+ {
+ User::assertPermission('filter.transports.view');
+ $id = Request::get('id', null, 'int');
+ if ($id !== null) {
+ self::showTransportEditor($id);
+ } else {
+ // LIST
+ $data = [];
+ $data['transports'] = [];
+ foreach (Database::queryAll('SELECT transportid, title, data,
+ Count(ruleid) AS useCount
+ FROM notification_backend nb
+ LEFT JOIN notification_rule_x_transport sfxb USING (transportid)
+ GROUP BY transportid, title
+ ORDER BY title, transportid') as $transport) {
+ $json = json_decode($transport['data'], true);
+ $transport['type'] = $json['type'];
+ $transport['details'] = NotificationTransport::getInstance($json);
+ $data['transports'][] = $transport;
+ }
+ Render::addTemplate('page-filters-transports', $data);
+ }
+ }
+
+ /**
+ * @param int $id Transport to edit, 0 to create a new one
+ */
+ private static function showTransportEditor(int $id)
+ {
+ User::assertPermission('filter.transports.edit');
+ if ($id !== 0) {
+ $entry = Database::queryFirst('SELECT transportid, title, description, data
+ FROM notification_backend
+ WHERE transportid = :id', ['id' => $id]);
+ if ($entry === false) {
+ Message::addError('invalid-transport-id', $id);
+ Util::redirect('?do=eventlog&show=transports&section=transports');
+ }
+ $entry['data'] = json_decode($entry['data'], true);
+ $entry[($entry['data']['type'] ?? '') . '_selected'] = 'selected';
+ $entry[($entry['data']['http-method'] ?? '') . '_selected'] = 'selected';
+ $entry[($entry['data']['http-post-format'] ?? '') . '_selected'] = 'selected';
+ } else {
+ $entry = ['transportid' => $id, 'data' => [], 'backends' => []];
+ }
+ $entry['users'] = [];
+ foreach (Database::queryAll("SELECT userid, login, fullname, email FROM user ORDER BY login") as $row) {
+ $row['disabled'] = strpos($row['email'], '@') ? '' : 'disabled';
+ $row['selected'] = in_array($row['userid'], $entry['data']['mail-users'] ?? []) ? 'selected' : '';
+ $entry['users'][] = $row;
+ }
+ $entry['mailconfigs'] = [];
+ foreach (Database::queryAll("SELECT configid, host, port, senderaddress FROM mail_config") as $row) {
+ $row['selected'] = $row['configid'] == ($entry['data']['mail-config-id'] ?? []) ? 'selected' : '';
+ $entry['mailconfigs'][] = $row;
+ }
+ foreach (Database::queryAll("SELECT transportid, title FROM notification_backend") as $row) {
+ $row['selected'] = in_array($row['transportid'], ($entry['data']['group-list'] ?? [])) ? 'selected' : '';
+ $entry['backends'][] = $row;
+ }
+ Module::isAvailable('bootstrap_multiselect');
+ $entry['rules'] = Database::queryAll("SELECT sf.ruleid, sf.title,
+ IF(sfxb.transportid IS NULL, '', 'selected') AS selected
+ FROM notification_rule sf
+ LEFT JOIN notification_rule_x_transport sfxb ON (sf.ruleid = sfxb.ruleid AND sfxb.transportid = :id)",
+ ['id' => $id]);
+ Render::addTemplate('page-filters-edit-transport', $entry);
+ }
+
+} \ No newline at end of file