]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
baculum: Add Microsoft 365 email list endpoints
authorMarcin Haba <marcin.haba@bacula.pl>
Thu, 18 Aug 2022 07:28:35 +0000 (09:28 +0200)
committerMarcin Haba <marcin.haba@bacula.pl>
Thu, 17 Nov 2022 09:05:10 +0000 (10:05 +0100)
gui/baculum/protected/API/Modules/Bconsole.php
gui/baculum/protected/API/Modules/ConsoleOutputJSONPage.php [new file with mode: 0644]
gui/baculum/protected/API/Pages/API/PluginM365EmailList.php [new file with mode: 0644]
gui/baculum/protected/API/Pages/API/endpoints.xml
gui/baculum/protected/API/openapi_baculum.json
gui/baculum/protected/Common/Modules/Miscellaneous.php

index 872a0454462442b320d3a518c5827d3e07f4eba4..e6589226541372f00719d551497863ebcff5a0cd 100644 (file)
@@ -97,7 +97,8 @@ class Bconsole extends APIModule {
                '.status',
                '.ls',
                'setbandwidth',
-               '.query'
+               '.query',
+               '.jlist'
        );
 
        private $config;
diff --git a/gui/baculum/protected/API/Modules/ConsoleOutputJSONPage.php b/gui/baculum/protected/API/Modules/ConsoleOutputJSONPage.php
new file mode 100644 (file)
index 0000000..313557e
--- /dev/null
@@ -0,0 +1,51 @@
+<?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;
+
+/**
+ * Get console output for JSON type commands (like .jlist).
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+abstract class ConsoleOutputJSONPage extends ConsoleOutputPage {
+
+       /**
+        * Parse '.jlist' type command output.
+        *
+        * @param array $output dot query command output
+        * @return object parsed output or empty object if there occurs a problem with parsing output
+        */
+       protected function parseOutput(array $output) {
+               $out = new \StdClass;
+               for ($i = 0; $i < count($output); $i++) {
+                       if (preg_match('/^[{\[]/', $output[$i]) === 1) {
+                               $out = json_decode($output[$i]);
+                               break;
+                       }
+               }
+               return $out;
+       }
+}
+?>
diff --git a/gui/baculum/protected/API/Pages/API/PluginM365EmailList.php b/gui/baculum/protected/API/Pages/API/PluginM365EmailList.php
new file mode 100644 (file)
index 0000000..b229cb1
--- /dev/null
@@ -0,0 +1,212 @@
+<?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\API\Modules\ConsoleOutputJSONPage;
+use Baculum\Common\Modules\Logging;
+use Baculum\Common\Modules\Errors\{ClientError,PluginError,PluginM365Error};
+
+/**
+ * List emails backed up using Microsoft 365 plugin.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+class PluginM365EmailList extends ConsoleOutputJSONPage {
+
+       public function get() {
+               $misc = $this->getModule('misc');
+               $client = null;
+               $clientid = $this->Request->contains('id') ? (int)$this->Request['id'] : 0;
+               $result = $this->getModule('bconsole')->bconsoleCommand(
+                       $this->director,
+                       ['.client'],
+                       null,
+                       true
+               );
+               if ($result->exitcode === 0) {
+                       $client_val = $this->getModule('client')->getClientById($clientid);
+                       if (is_object($client_val) && in_array($client_val->name, $result->output)) {
+                               $client = $client_val->name;
+                       } else {
+                               $this->output = ClientError::MSG_ERROR_CLIENT_DOES_NOT_EXISTS;
+                               $this->error = ClientError::ERROR_CLIENT_DOES_NOT_EXISTS;
+                               return;
+                       }
+               } else {
+                       $this->output = PluginError::MSG_ERROR_WRONG_EXITCODE;
+                       $this->error = PluginError::ERROR_WRONG_EXITCODE;
+                       return;
+               }
+
+               $tenantid = $this->Request->contains('tenantid') ? $this->Request['tenantid'] : null;
+               $fd_plugin_cfg = $this->getModule('fd_plugin_cfg')->getConfig('m365', $client, $tenantid);
+               if (!empty($tenantid) && (!$misc->isValidUUID($tenantid) || count($fd_plugin_cfg) == 0)) {
+                       $this->output = PluginM365Error::MSG_ERROR_TENANT_DOES_NOT_EXISTS;
+                       $this->error = PluginM365Error::ERROR_TENANT_DOES_NOT_EXISTS;
+                       return;
+               }
+               $tenant = $fd_plugin_cfg['tenant_name'];
+
+               $params = [
+                       'client' => $client,
+                       'tenant' => $tenant
+               ];
+               if ($this->Request->contains('mailbox') && $misc->isValidEmail($this->Request['mailbox'])) {
+                       $params['mailbox'] = $this->Request['mailbox'];
+               }
+               if ($this->Request->contains('mailbox_pattern') && $misc->isValidEmail($this->Request['mailbox_pattern'])) {
+                       $params['mailbox_pattern'] = $this->Request['mailbox_pattern'];
+               }
+               if ($this->Request->contains('limit') && $misc->isValidInteger($this->Request['limit'])) {
+                       $params['limit'] = (int)$this->Request['limit'];
+               }
+               if ($this->Request->contains('mintime') && $misc->isValidBDate($this->Request['mintime'])) {
+                       $params['mintime'] = $this->Request['mintime'];
+               }
+               if ($this->Request->contains('maxtime') && $misc->isValidBDate($this->Request['maxtime'])) {
+                       $params['maxtime'] = $this->Request['maxtime'];
+               }
+               if ($this->Request->contains('folder') && $misc->isValidFilename($this->Request['folder'])) {
+                       $params['folder'] = $this->Request['folder'];
+               }
+               if ($this->Request->contains('tags') && $misc->isValidName($this->Request['tags'])) {
+                       $params['tags'] = $this->Request['tags'];
+               }
+               if ($this->Request->contains('from') && $misc->isValidEmail($this->Request['from'])) {
+                       $params['from'] = $this->Request['from'];
+               }
+               if ($this->Request->contains('to') && $misc->isValidEmail($this->Request['to'])) {
+                       $params['to'] = $this->Request['to'];
+               }
+               if ($this->Request->contains('cc') && $misc->isValidEmail($this->Request['cc'])) {
+                       $params['cc'] = $this->Request['cc'];
+               }
+               if ($this->Request->contains('minsize') && $misc->isValidInteger($this->Request['minsize'])) {
+                       $params['minsize'] = $this->Request['minsize'];
+               }
+               if ($this->Request->contains('maxsize') && $misc->isValidInteger($this->Request['maxsize'])) {
+                       $params['maxsize'] = $this->Request['maxsize'];
+               }
+               if ($this->Request->contains('conversationid') && $misc->isValidNameExt($this->Request['conversationid'])) {
+                       $params['conversationid'] =  $this->Request['conversationid'];
+               }
+               $out = $this->getJSONOutput($params);
+
+               $output = [];
+               $error = PluginM365Error::ERROR_NO_ERRORS;
+               if ($out->exitcode === 0) {
+                       $output = $out->output;
+               } else {
+                       $error = PluginM365Error::ERROR_WRONG_EXITCODE;
+                       $output = PluginM365Error::MSG_ERROR_WRONG_EXITCODE . implode(PHP_EOL, $out->output);
+               }
+               $this->output = $output;
+               $this->error = $error;
+       }
+
+       /**
+        * Get M365 email list in JSON string format.
+        *
+        * @param array $params command parameters
+        * @return StdClass object with output and exitcode
+        */
+       protected function getRawOutput($params = []) {
+               $cmd = [
+                       '.jlist',
+                       'metadata',
+                       'type="email"',
+                       'tenant="' . $params['tenant'] . '"'
+               ];
+
+               if (key_exists('mailbox', $params)) {
+                       $cmd[] ='owner="' .  $params['mailbox'] . '"';
+               }
+               if (key_exists('mailbox_pattern', $params)) {
+                       $cmd[] ='owner="' .  $params['mailbox_pattern'] . '%"';
+               }
+               if (key_exists('limit', $params)) {
+                       $cmd[] ='limit="' .  $params['limit'] . '"';
+               }
+               if (key_exists('mintime', $params)) {
+                       $cmd[] ='mintime="' .  $params['mintime'] . ' 0:00:00"';
+               }
+               if (key_exists('maxtime', $params)) {
+                       $cmd[] ='maxtime="' .  $params['maxtime'] . ' 23:59:59"';
+               }
+               if (key_exists('folder', $params)) {
+                       $cmd[] ='foldername="' .  $params['folder'] . '"';
+               }
+               if (key_exists('tags', $params)) {
+                       $cmd[] ='tags="' .  $params['tags'] . '"';
+               }
+               if (key_exists('from', $params)) {
+                       $cmd[] ='from="' .  $params['from'] . '"';
+               }
+               if (key_exists('to', $params)) {
+                       $cmd[] ='to="' .  $params['to'] . '"';
+               }
+               if (key_exists('cc', $params)) {
+                       $cmd[] ='cc="' .  $params['cc'] . '"';
+               }
+               if (key_exists('minsize', $params)) {
+                       $cmd[] ='minsize="' .  $params['minsize'] . '"';
+               }
+               if (key_exists('maxsize', $params)) {
+                       $cmd[] ='maxsize="' .  $params['maxsize'] . '"';
+               }
+               if (key_exists('conversationid', $params)) {
+                       $cmd[] ='conversationid="' .  $params['conversationid'] . '"';
+               }
+               $ret = $this->getModule('bconsole')->bconsoleCommand(
+                       $this->director,
+                       $cmd
+               );
+
+               if ($ret->exitcode !== 0) {
+                       $this->getModule('logging')->log(
+                               Logging::CATEGORY_EXECUTE,
+                               'Wrong output from m365 RAW email list: ' . implode(PHP_EOL, $ret->output)
+                       );
+               }
+               return $ret;
+       }
+
+       /**
+        * Get M365 email list in validated and formatted JSON format.
+        *
+        * @param array $params command parameters
+        * @return StdClass object with output and exitcode
+        */
+       protected function getJSONOutput($params = []) {
+               $ret = $this->getRawOutput($params);
+               if ($ret->exitcode === 0) {
+                       $ret->output = $this->parseOutput($ret->output);
+                       if ($ret->output->error === 0) {
+                               $ret->output = $ret->output->data;
+                       } else {
+                               $ret->output = $ret->output->errmsg;
+                       }
+               }
+               return $ret;
+       }
+}
index f8316f8e6e0e7b6c6aae93c503d6fd0f2be46bbc..bf6416936bf1924b6e85cc858cfc45abbb2462d7 100644 (file)
        <!-- Plugins -->
        <!-- M365 Plugin -->
        <url ServiceParameter="PluginM365ListLoggedUsers" pattern="api/v2/plugins/m365/{id}/users/" parameters.id="\d+" />
+       <url ServiceParameter="PluginM365EmailList" pattern="api/v2/plugins/m365/{id}/{tenantid}/emails/" parameters.id="\d+" parameters.tenantid="[a-zA-Z0-9:.\-_ ]+" />
 
        <!-- OLD API v1 -->
        <!-- general endpoint -->
index 51a64702fa091ac7bf7ff82354bce043fc5602ab..4f39bbda2d1183236bcca58c5987252fb2999255 100644 (file)
                        },
                        "Event": {
                                "$ref": "#/definitions/Event"
+                       },
+                       "PluginM365Emails": {
+                               "type": "array",
+                               "items": {
+                                       "$ref": "#/definitions/PluginM365Email"
+                               }
+                       },
+                       "PluginM365Email": {
+                               "$ref": "#/definitions/PluginM365Email"
                        }
                },
                "parameters": {
                        },
                        "TenantId": {
                                "name": "tenantid",
-                               "in": "query",
+                               "in": "path",
                                "description": "Tenant identifier",
-                               "required": false,
+                               "required": true,
                                "schema": {
                                        "type": "string"
                                }
                                                "$ref": "#/components/parameters/ClientId"
                                        },
                                        {
-                                               "$ref": "#/components/parameters/TenantId"
+                                               "name": "tenantid",
+                                               "in": "path",
+                                               "description": "Tenant identifier",
+                                               "required": false,
+                                               "schema": {
+                                                       "type": "string"
+                                               }
                                        },
                                        {
                                                "$ref": "#/components/parameters/Output"
                                        }
                                ]
                        }
+               },
+               "/api/v2/plugins/m365/{clientid}/{tenantid}/emails": {
+                       "get": {
+                               "tags": ["plugins"],
+                               "summary": "Microsoft 365 plugin email list",
+                               "description": "Get Microsoft 365 email list.",
+                               "responses": {
+                                       "200": {
+                                               "description": "List of Microsoft 365 emails",
+                                               "content": {
+                                                       "application/json": {
+                                                               "schema": {
+                                                                       "type": "object",
+                                                                       "properties": {
+                                                                               "output": {
+                                                                                       "$ref": "#/components/schemas/PluginM365Emails"
+                                                                               },
+                                                                               "error": {
+                                                                                       "type": "integer",
+                                                                                       "description": "Error code",
+                                                                                       "enum": [0, 1, 4, 5, 6, 7, 11, 1000]
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               },
+                               "parameters": [
+                                       {
+                                               "$ref": "#/components/parameters/ClientId"
+                                       },
+                                       {
+                                               "$ref": "#/components/parameters/TenantId"
+                                       },
+                                       {
+                                               "$ref": "#/components/parameters/Limit"
+                                       },
+                                       {
+                                               "name": "mailbox",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Mailbox address",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "mailbox_pattern",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Mailbox pattern address (it can be partial email address)",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "mintime",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Date start (YYYY-MM-DD)",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "maxtime",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Date end (YYYY-MM-DD)",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "folder",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email folder name",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "tags",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email tags",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "from",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email sender (from)",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "to",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email recipient (to)",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "cc",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email copy address (cc)",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       },
+                                       {
+                                               "name": "minsize",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email minimum size in bytes",
+                                               "schema": {
+                                                       "type": "integer"
+                                               }
+                                       },
+                                       {
+                                               "name": "maxsize",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email maximum size in bytes",
+                                               "schema": {
+                                                       "type": "integer"
+                                               }
+                                       },
+                                       {
+                                               "name": "conversationid",
+                                               "in": "query",
+                                               "required": false,
+                                               "description": "Email conversation identifier",
+                                               "schema": {
+                                                       "type": "string"
+                                               }
+                                       }
+                               ]
+                       }
                }
        },
        "definitions": {
                                        "type": "string"
                                }
                        }
+               },
+               "PluginM365Email": {
+                       "type": "object",
+                       "properties": {
+                               "jobid": {
+                                       "description": "Job identifier",
+                                       "type": "integer"
+                               },
+                               "fileindex": {
+                                       "description": "File index",
+                                       "type": "integer"
+                               },
+                               "emailtenant": {
+                                       "description": "Tenant name",
+                                       "type": "string"
+                               },
+                               "emailowner": {
+                                       "description": "Email owner",
+                                       "type": "string"
+                               },
+                               "emailbodypreview": {
+                                       "description": "Email body preview",
+                                       "type": "string"
+                               },
+                               "emailcc": {
+                                       "description": "Email copy address (cc)",
+                                       "type": "string"
+                               },
+                               "emailconversationid": {
+                                       "description": "Email conversation identifier",
+                                       "type": "string"
+                               },
+                               "emailfoldername": {
+                                       "description": "Email folder name",
+                                       "type": "string"
+                               },
+                               "emailfrom": {
+                                       "description": "Email sender (from)",
+                                       "type": "string"
+                               },
+                               "emailid": {
+                                       "description": "Email identifier",
+                                       "type": "string"
+                               },
+                               "emailimportance": {
+                                       "description": "Email importance",
+                                       "type": "string"
+                               },
+                               "emailinternetmessageid": {
+                                       "description": "Email Internet message identifier",
+                                       "type": "string"
+                               },
+                               "emailisread": {
+                                       "description": "Email is read flag",
+                                       "type": "integer"
+                               },
+                               "emailisdraft": {
+                                       "description": "Email is draft flag",
+                                       "type": "integer"
+                               },
+                               "emailtime": {
+                                       "description": "Email time (YYYY-MM-DD HH:II:SS)",
+                                       "type": "string"
+                               },
+                               "emailsubject": {
+                                       "description": "Email subject",
+                                       "type": "string"
+                               },
+                               "emailtags": {
+                                       "description": "Email tags",
+                                       "type": "string"
+                               },
+                               "emailto": {
+                                       "description": "Email recipient (to)",
+                                       "type": "string"
+                               },
+                               "emailsize": {
+                                       "description": "Email size in bytes",
+                                       "type": "string"
+                               },
+                               "emailhasattachment": {
+                                       "description": "Email attachment flag",
+                                       "type": "integer"
+                               },
+                               "plugin": {
+                                       "description": "Plugin name",
+                                       "type": "string"
+                               }
+                       }
                }
        }
 }
index 86f33bedfc8c23b0ccd81c632f0a7194a5143165..6a415f7651f71969bbc910cedbc41b44598938c5 100644 (file)
@@ -223,7 +223,7 @@ class Miscellaneous extends TModule {
        }
 
        public function isValidNameExt($name_ext) {
-               return (preg_match('/^[\w:\.\-\s\*]{1,127}$/', $name_ext) === 1);
+               return (preg_match('/^[\w:\.\-\s\*=]{1,127}$/', $name_ext) === 1);
        }
 
        public function isValidState($state) {
@@ -298,6 +298,10 @@ class Miscellaneous extends TModule {
                return (preg_match('/^[\w]{8}(-[\w]{4}){3}-[\w]{12}$/', $uuid) === 1);
        }
 
+       public function isValidEmail($email) {
+               return filter_var($email, FILTER_VALIDATE_EMAIL);
+       }
+
        public function escapeCharsToConsole($path) {
                return preg_replace('/([$])/', '\\\${1}', $path);
        }