]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
baculum: Add event list and single event record endpoints
authorMarcin Haba <marcin.haba@bacula.pl>
Tue, 16 Aug 2022 14:13:47 +0000 (16:13 +0200)
committerMarcin Haba <marcin.haba@bacula.pl>
Thu, 17 Nov 2022 09:05:10 +0000 (10:05 +0100)
gui/baculum/protected/API/Modules/Database.php
gui/baculum/protected/API/Modules/EventManager.php [new file with mode: 0644]
gui/baculum/protected/API/Modules/EventRecord.php [new file with mode: 0644]
gui/baculum/protected/API/Pages/API/Event.php [new file with mode: 0644]
gui/baculum/protected/API/Pages/API/Events.php [new file with mode: 0644]
gui/baculum/protected/API/Pages/API/ObjectClass.php
gui/baculum/protected/API/Pages/API/config.xml
gui/baculum/protected/API/Pages/API/endpoints.xml
gui/baculum/protected/API/openapi_baculum.json
gui/baculum/protected/Common/Modules/Errors/EventError.php [new file with mode: 0644]
gui/baculum/protected/Common/Modules/Miscellaneous.php

index c13a7030f3618b53ffcc2732a91f972c2962f54b..4c0883c82f679c081c294ea87bfee852347cdfc6 100644 (file)
@@ -174,6 +174,7 @@ class Database extends APIModule {
                                } else {
                                        $cond[] = "$key = :$kval";
                                        $vals[":$kval"] = $value['vals'];
+                                       $value['operator'] = '';
                                }
                                $condition[] = implode(' ' . $value['operator'] . ' ', $cond);
                                foreach ($vals as $pkey => $pval) {
diff --git a/gui/baculum/protected/API/Modules/EventManager.php b/gui/baculum/protected/API/Modules/EventManager.php
new file mode 100644 (file)
index 0000000..491451a
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum   - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+namespace Baculum\API\Modules;
+
+/**
+ * Event manager module.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category Module
+ * @package Baculum API
+ */
+class EventManager extends APIModule {
+
+       /**
+        * Get event list.
+        *
+        * @param array $criteria list of optional query criterias
+        * @param array $time_scope time range for events time
+        * @param int|null $limit_val limit results value
+        */
+       public function getEvents($criteria = [], $time_scope = [], $limit_val = null) {
+               $sort_col = 'EventsId';
+               $db_params = $this->getModule('api_config')->getConfig('db');
+               if ($db_params['type'] === Database::PGSQL_TYPE) {
+                   $sort_col = strtolower($sort_col);
+               }
+               $order = ' ORDER BY ' . $sort_col . ' DESC';
+               $limit = '';
+               if(is_int($limit_val) && $limit_val > 0) {
+                       $limit = ' LIMIT ' . $limit_val;
+               }
+
+               $where = Database::getWhere($criteria, true);
+
+               $wh = [];
+               if (key_exists('eventstimestart', $time_scope)) {
+                       $wh[] = " Events.EventsTime >= '{$time_scope['eventstimestart']} 00:00:00' ";
+               }
+               if (key_exists('eventstimeend', $time_scope)) {
+                       $wh[] = " Events.EventsTime <= '{$time_scope['eventstimeend']} 23:59:59' ";
+               }
+               $where['where'] .= implode(' AND ', $wh);
+               if (!empty($where['where'])) {
+                       $where['where'] = ' WHERE ' . $where['where'];
+               }
+
+               $sql = 'SELECT Events.* FROM Events ' . $where['where'] . $order . $limit;
+
+               return EventRecord::finder()->findAllBySql($sql, $where['params']);
+       }
+
+       /**
+        * Get single event record by eventid.
+        *
+        * @param integer $eventid event identifier
+        * @return EventRecord single event record or null on failure
+        */
+       public function getEventById($eventid) {
+               $params = [
+                       'Events.EventsId' => [
+                               'vals' => $eventid,
+                       ]
+               ];
+               $obj = $this->getEvents($params, [], 1);
+               if (is_array($obj) && count($obj) > 0) {
+                       $obj = array_shift($obj);
+               }
+               return $obj;
+       }
+}
diff --git a/gui/baculum/protected/API/Modules/EventRecord.php b/gui/baculum/protected/API/Modules/EventRecord.php
new file mode 100644 (file)
index 0000000..e533816
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum   - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+namespace Baculum\API\Modules;
+
+/**
+ * Event record module.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category Database
+ * @package Baculum API
+ */
+class EventRecord extends APIDbModule {
+
+       const TABLE = 'Events';
+
+       public $eventsid;
+       public $eventscode;
+       public $eventstype;
+       public $eventstime;
+       public $eventsinserttime;
+       public $eventsdaemon;
+       public $eventssource;
+       public $eventsref;
+       public $eventstext;
+
+       public static function finder($className = __CLASS__) {
+               return parent::finder($className);
+       }
+}
+?>
diff --git a/gui/baculum/protected/API/Pages/API/Event.php b/gui/baculum/protected/API/Pages/API/Event.php
new file mode 100644 (file)
index 0000000..0849079
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum   - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+use Baculum\Common\Modules\Errors\EventError;
+
+/**
+ * Event endpoint.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+class Event extends BaculumAPIServer {
+
+       public function get() {
+               $eventid = $this->Request->contains('id') ? (int)$this->Request['id'] : 0;
+
+               $event = $this->getModule('event')->getEventById($eventid);
+               if (is_object($event)) {
+                       $this->output = $event;
+                       $this->error = EventError::ERROR_NO_ERRORS;
+               } else {
+                       $this->output = EventError::MSG_ERROR_EVENT_DOES_NOT_EXIST;
+                       $this->error = EventError::ERROR_EVENT_DOES_NOT_EXIST;
+               }
+       }
+}
diff --git a/gui/baculum/protected/API/Pages/API/Events.php b/gui/baculum/protected/API/Pages/API/Events.php
new file mode 100644 (file)
index 0000000..fa59f1f
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum   - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+use Baculum\Common\Modules\Errors\EventError;
+
+/**
+ * Events endpoint.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+class Events extends BaculumAPIServer {
+
+       public function get() {
+               $misc = $this->getModule('misc');
+               $limit = $this->Request->contains('limit') ? intval($this->Request['limit']) : 0;
+               $eventscode = $this->Request->contains('eventscode') && $misc->isValidName($this->Request['eventscode']) ? $this->Request['eventscode'] : null;
+               $eventstype = $this->Request->contains('eventstype') && $misc->isValidName($this->Request['eventstype']) ? $this->Request['eventstype'] : null;
+               $eventstimestart = $this->Request->contains('eventstimestart') && $misc->isValidBDate($this->Request['eventstimestart']) ? $this->Request['eventstimestart'] : null;
+               $eventstimeend = $this->Request->contains('eventstimeend') && $misc->isValidBDate($this->Request['eventstimeend']) ? $this->Request['eventstimeend'] : null;
+               $eventsdaemon = $this->Request->contains('eventsdaemon') && $misc->isValidName($this->Request['eventsdaemon']) ? $this->Request['eventsdaemon'] : null;
+               $eventssource = $this->Request->contains('eventssource') && $misc->isValidNameExt($this->Request['eventssource']) ? $this->Request['eventssource'] : null;
+               $eventsref = $this->Request->contains('eventsref') && $misc->isValidName($this->Request['eventsref']) ? $this->Request['eventsref'] : null;
+               $eventstext = $this->Request->contains('eventstext') && $misc->isValidName($this->Request['eventstext']) ? $this->Request['eventstext'] : null;
+
+               $params = $time_scope =  [];
+               if (!empty($eventscode)) {
+                       $params['Events.EventsCode']['vals'] = $eventscode;
+               }
+               if (!empty($eventstype)) {
+                       $params['Events.EventsType']['vals'] = $eventstype;
+               }
+               if (!empty($eventsdaemon)) {
+                       $params['Events.EventsDaemon']['vals'] = $eventsdaemon;
+               }
+               if (!empty($eventssource)) {
+                       $params['Events.EventsSource']['vals'] = $eventssource;
+               }
+               if (!empty($eventsref)) {
+                       $params['Events.EventsRef']['vals'] = $eventsref;
+               }
+               if (!empty($eventstext)) {
+                       $params['Events.EventsText']['vals'] = $eventstext;
+               }
+               if (!empty($eventstimestart)) {
+                       $time_scope['eventstimestart'] = $eventstimestart;
+               }
+               if (!empty($eventstimeend)) {
+                       $time_scope['eventstimeend'] = $eventstimeend;
+               }
+
+               $events = $this->getModule('event')->getEvents($params, $time_scope, $limit);
+               $this->output = $events;
+               $this->error = EventError::ERROR_NO_ERRORS;
+       }
+}
index d198e654452b3ffd418d282685ed66b40429fc5e..8276a5c5ce55db02b18b3ae376f341576fb9b73c 100644 (file)
@@ -23,7 +23,7 @@
 use Baculum\Common\Modules\Errors\ObjectError;
 
 /**
- * Objects endpoint.
+ * Object endpoint.
  *
  * @author Marcin Haba <marcin.haba@bacula.pl>
  * @category API
index 96abe56cdcb2fe931e51260201e7ad396585bd71..56e6ccd5ea33395d62a4c81d021a87f6b0c4d6b6 100644 (file)
@@ -29,6 +29,7 @@
                <module id="version" class="Baculum\API\Modules\VersionManager" />
                <module id="volume" class="Baculum\API\Modules\VolumeManager" />
                <module id="object" class="Baculum\API\Modules\ObjectManager" />
+               <module id="event" class="Baculum\API\Modules\EventManager" />
                <!-- tools modules -->
                <module id="bconsole" class="Baculum\API\Modules\Bconsole" />
                <module id="json_tools" class="Baculum\API\Modules\JSONTools" />
index fd929b7824e5d084ce4a3013fc3da9547338ab42..f8316f8e6e0e7b6c6aae93c503d6fd0f2be46bbc 100644 (file)
        <url ServiceParameter="BVFSCleanUp" pattern="api/v2/bvfs/cleanup/" />
        <!-- joblog endpoints -->
        <url ServiceParameter="JobLog" pattern="api/v2/joblog/{id}/" parameters.id="\d+" />
-       <!-- event endpoints -->
+       <!-- object endpoints -->
        <url ServiceParameter="Objects" pattern="api/v2/objects/" />
        <url ServiceParameter="ObjectClass" pattern="api/v2/objects/{id}/" parameters.id="\d+" />
        <url ServiceParameter="ObjectVersions" pattern="api/v2/objects/versions/{uuid}" parameters.uuid="[a-zA-Z0-9:.\-_ ]+" />
        <url ServiceParameter="ObjectStatsCategorySum" pattern="api/v2/objects/stats/category-sum/" />
        <url ServiceParameter="ObjectStatsCategoryStatus" pattern="api/v2/objects/stats/category-status/" />
        <url ServiceParameter="ObjectStatsSizeSum" pattern="api/v2/objects/stats/size-sum/" />
+       <!-- event endpoints -->
+       <url ServiceParameter="Events" pattern="api/v2/events/" />
+       <url ServiceParameter="Event" pattern="api/v2/events/{id}" parameters.id="\d+" />
        <!-- @TODO: Separate this endpoint outside 'joblog' -->
        <url ServiceParameter="Messages" pattern="api/v2/joblog/messages" />
        <!-- fileset endpoints -->
index 32a0b03d10e8ba8bf5cef3d749f758e6e22f9bef..51a64702fa091ac7bf7ff82354bce043fc5602ab 100644 (file)
                        },
                        "Object": {
                                "$ref": "#/definitions/Object"
+                       },
+                       "Events": {
+                               "type": "array",
+                               "items": {
+                                       "$ref": "#/definitions/Event"
+                               }
+                       },
+                       "Event": {
+                               "$ref": "#/definitions/Event"
                        }
                },
                "parameters": {
                                ]
                        }
                },
+               "/api/v2/events": {
+                       "get": {
+                               "tags": ["events"],
+                               "summary": "Event list",
+                               "description": "Get event list.",
+                               "responses": {
+                                       "200": {
+                                               "description": "List of events",
+                                               "content": {
+                                                       "application/json": {
+                                                               "schema": {
+                                                                       "type": "object",
+                                                                       "properties": {
+                                                                               "output": {
+                                                                                       "$ref": "#/components/schemas/Events"
+                                                                               },
+                                                                               "error": {
+                                                                                       "type": "integer",
+                                                                                       "description": "Error code",
+                                                                                       "enum": [0, 1, 2, 3, 6, 7, 1000]
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               },
+                               "parameters": [
+                                       {
+                                               "$ref": "#/components/parameters/Limit"
+                                       },
+                                       {
+                                               "name": "eventscode",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event code",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventstype",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event type",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventstimestart",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event time start in form: YYYY-MM-DD",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventstimeend",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event time end in form: YYYY-MM-DD",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventsdaemon",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event daemon",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventssource",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event source",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventsref",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event reference",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "eventstext",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Event text",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       }
+                               ]
+                       }
+               },
+               "/api/v2/events/{eventid}": {
+                       "get": {
+                               "tags": ["events"],
+                               "summary": "Event by eventid",
+                               "description": "Get single event.",
+                               "responses": {
+                                       "200": {
+                                               "description": "Single event by eventid",
+                                               "content": {
+                                                       "application/json": {
+                                                               "schema": {
+                                                                       "type": "object",
+                                                                       "properties": {
+                                                                               "output": {
+                                                                                       "$ref": "#/components/schemas/Event"
+                                                                               },
+                                                                               "error": {
+                                                                                       "type": "integer",
+                                                                                       "description": "Error code",
+                                                                                       "enum": [0, 1, 2, 3, 6, 7, 1000]
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               },
+                               "parameters": [
+                                       {
+                                               "name": "eventid",
+                                               "in": "path",
+                                               "required": true,
+                                               "description": "Event identifier",
+                                               "schema": {
+                                                       "type": "integer"
+                                               }
+                                       }
+                               ]
+                       }
+               },
                "/api/v2/plugins/m365/{clientid}/users": {
                        "get": {
                                "tags": ["plugins"],
                                        "type": "integer"
                                }
                        }
+               },
+               "Event": {
+                       "type": "object",
+                       "properties": {
+                               "eventsid": {
+                                       "description": "Event identifier",
+                                       "type": "integer"
+                               },
+                               "eventscode": {
+                                       "description": "Event code",
+                                       "type": "string"
+                               },
+                               "eventstype": {
+                                       "description": "Event type",
+                                       "type": "string"
+                               },
+                               "eventstime": {
+                                       "description": "Event time (YYYY-MM-DD HH:MM::SS)",
+                                       "type": "string"
+                               },
+                               "eventsinserttime": {
+                                       "description": "Event insert time (YYYY-MM-DD HH:MM::SS.ms)",
+                                       "type": "string"
+                               },
+                               "eventsdaemon": {
+                                       "description": "Event daemon",
+                                       "type": "string"
+                               },
+                               "eventssource": {
+                                       "description": "Event source",
+                                       "type": "string"
+                               },
+                               "eventsref": {
+                                       "description": "Event reference",
+                                       "type": "string"
+                               },
+                               "eventstext": {
+                                       "description": "Event text",
+                                       "type": "string"
+                               }
+                       }
                }
        }
 }
diff --git a/gui/baculum/protected/Common/Modules/Errors/EventError.php b/gui/baculum/protected/Common/Modules/Errors/EventError.php
new file mode 100644 (file)
index 0000000..102d5c8
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum   - Bacula web interface
+ *
+ * Copyright (C) 2013-2022 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+namespace Baculum\Common\Modules\Errors;
+
+/**
+ * Event error class.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category Errors
+ * @package Baculum Common
+ */
+class EventError extends GenericError {
+       const ERROR_EVENT_DOES_NOT_EXIST = 510;
+
+       const MSG_ERROR_EVENT_DOES_NOT_EXIST = 'Event does not exist.';
+}
index 9bebc11c1bb41959623c5aabccd4158e68bb0bbe..86f33bedfc8c23b0ccd81c632f0a7194a5143165 100644 (file)
@@ -222,6 +222,10 @@ class Miscellaneous extends TModule {
                return (preg_match('/^[\w:\.\-\s]{1,127}$/', $name) === 1);
        }
 
+       public function isValidNameExt($name_ext) {
+               return (preg_match('/^[\w:\.\-\s\*]{1,127}$/', $name_ext) === 1);
+       }
+
        public function isValidState($state) {
                return (preg_match('/^[\w\-]+$/', $state) === 1);
        }
@@ -266,6 +270,10 @@ class Miscellaneous extends TModule {
                return (preg_match('/^b2\d+$/', $path) === 1);
        }
 
+       public function isValidBDate($date) {
+               return (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) === 1);
+       }
+
        public function isValidBDateAndTime($time) {
                return (preg_match('/^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}$/', $time) === 1);
        }