From: Marcin Haba Date: Sat, 17 Apr 2021 16:14:00 +0000 (+0200) Subject: baculum: Implement support for assigning multiple API hosts to one user X-Git-Tag: Release-11.0.3~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e37c94805ec6d77439b8dfa6242d2a9c55d6334;p=thirdparty%2Fbacula.git baculum: Implement support for assigning multiple API hosts to one user Changes: - managing many API hosts assigned to user without need to re-login for each API host - support for autochanger management on remote API hosts - new tabs to configure remote file daemon and storage daemons directly on Storage page or Client page --- diff --git a/gui/baculum/protected/Common/Class/BClientScript.php b/gui/baculum/protected/Common/Class/BClientScript.php index ce92ed0d5..7f41cf579 100644 --- a/gui/baculum/protected/Common/Class/BClientScript.php +++ b/gui/baculum/protected/Common/Class/BClientScript.php @@ -31,7 +31,7 @@ Prado::using('System.Web.UI.WebControls.TClientScript'); */ class BClientScript extends TClientScript { - const SCRIPTS_VERSION = 18; + const SCRIPTS_VERSION = 19; public function getScriptUrl() { diff --git a/gui/baculum/protected/Common/Class/ConfigIni.php b/gui/baculum/protected/Common/Class/ConfigIni.php index 5ac57275e..d73947e52 100644 --- a/gui/baculum/protected/Common/Class/ConfigIni.php +++ b/gui/baculum/protected/Common/Class/ConfigIni.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2019 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -77,8 +77,14 @@ class ConfigIni extends CommonModule implements ConfigFormat { $content .= "[$section]\n"; foreach($options as $option => $value) { if (is_array($value)) { + $str_keys = array_filter(array_keys($value), 'is_string'); + $is_assoc = (count($str_keys) > 0); // check if array is associative foreach($value as $k => $v) { $v = $this->prepareValue($v); + if (!$is_assoc) { + // array with numeric indexes, set empty key + $k = ''; + } $content .= "{$option}[$k] = $v\n"; } } else { diff --git a/gui/baculum/protected/Common/Class/OAuth2.php b/gui/baculum/protected/Common/Class/OAuth2.php index 485b39403..0b55fe45e 100644 --- a/gui/baculum/protected/Common/Class/OAuth2.php +++ b/gui/baculum/protected/Common/Class/OAuth2.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2019 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -87,7 +87,7 @@ abstract class OAuth2 extends CommonModule { * Temportary set to 15 minutes for testst purposes. * In production the value SHOULD BE changed. */ - const ACCESS_TOKEN_EXPIRES_TIME = 90000; + const ACCESS_TOKEN_EXPIRES_TIME = 120; /** * Scope pattern. diff --git a/gui/baculum/protected/Common/Portlets/BSimpleRepeater.php b/gui/baculum/protected/Common/Portlets/BSimpleRepeater.php new file mode 100644 index 000000000..bd8e40eff --- /dev/null +++ b/gui/baculum/protected/Common/Portlets/BSimpleRepeater.php @@ -0,0 +1,93 @@ + + * @category Control + * @package Baculum Web + */ +class BSimpleRepeater extends TDataBoundControl { + + /** + * Stores item template object + */ + private $_itemTemplate; + + /** + * Get template for items. + * + * @return ITemplate template + */ + public function getItemTemplate() { + return $this->_itemTemplate; + } + + /** + * Set template for items. + * + * @param ITemplate $tpl template + * @return none + */ + public function setItemTemplate($tpl) { + if ($tpl instanceof \Prado\Web\UI\ITemplate) { + $this->_itemTemplate = $tpl; + } + } + + /** + * Data binding. + * + * @param $data data from data source + * @return none + */ + protected function performDataBinding($data) { + for ($i = 0; $i < count($data); $i++) { + $this->createItem($data[$i]); + } + } + + /** + * Create single repeater item. + * + * return BSimpleRepeaterItem repeater item + */ + private function createItem($data) { + $item = new BSimpleRepeaterItem; + if ($item instanceof \Prado\IDataRenderer) { + $item->setData($data); + } + if ($this->_itemTemplate) { + $this->_itemTemplate->instantiateIn($item, $this); + } + return $item; + } + + public function render($writer) { + $this->renderChildren($writer); + } +} +?> diff --git a/gui/baculum/protected/Common/Portlets/BSimpleRepeaterItem.php b/gui/baculum/protected/Common/Portlets/BSimpleRepeaterItem.php new file mode 100644 index 000000000..9a7299792 --- /dev/null +++ b/gui/baculum/protected/Common/Portlets/BSimpleRepeaterItem.php @@ -0,0 +1,44 @@ + + * @category Control + * @package Baculum Web + */ +class BSimpleRepeaterItem extends \Prado\Web\UI\TControl implements \Prado\IDataRenderer { + + private $_data = []; + + public function getData() { + return $this->_data; + } + + public function setData($data) { + $this->_data = $data; + } +} +?> diff --git a/gui/baculum/protected/Web/Class/BaculumAPIClient.php b/gui/baculum/protected/Web/Class/BaculumAPIClient.php index 9f139367a..c4602f357 100644 --- a/gui/baculum/protected/Web/Class/BaculumAPIClient.php +++ b/gui/baculum/protected/Web/Class/BaculumAPIClient.php @@ -292,7 +292,7 @@ class BaculumAPIClient extends WebModule { $cached = null; $ret = null; if (is_null($host)) { - $host = $this->User->getAPIHosts(); + $host = $this->User->getDefaultAPIHost(); } if ($use_cache === true) { $cached = $this->getSessionCache($host, $params); @@ -333,7 +333,7 @@ class BaculumAPIClient extends WebModule { */ public function set(array $params, array $options = array(), $host = null, $show_error = true) { if (is_null($host)) { - $host = $this->User->getAPIHosts(); + $host = $this->User->getDefaultAPIHost(); } $host_cfg = $this->getHostParams($host); $uri = $this->getURIResource($host, $params); @@ -370,7 +370,7 @@ class BaculumAPIClient extends WebModule { */ public function create(array $params, array $options, $host = null, $show_error = true) { if (is_null($host)) { - $host = $this->User->getAPIHosts(); + $host = $this->User->getDefaultAPIHost(); } $host_cfg = $this->getHostParams($host); $uri = $this->getURIResource($host, $params); @@ -402,7 +402,7 @@ class BaculumAPIClient extends WebModule { */ public function remove(array $params, $host = null, $show_error = true) { if (is_null($host)) { - $host = $this->User->getAPIHosts(); + $host = $this->User->getDefaultAPIHost(); } $host_cfg = $this->getHostParams($host); $uri = $this->getURIResource($host, $params); diff --git a/gui/baculum/protected/Web/Class/BaculumWebPage.php b/gui/baculum/protected/Web/Class/BaculumWebPage.php index 703d77625..2e6a4c459 100644 --- a/gui/baculum/protected/Web/Class/BaculumWebPage.php +++ b/gui/baculum/protected/Web/Class/BaculumWebPage.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2020 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -53,6 +53,13 @@ class BaculumWebPage extends BaculumPage { // without config there is no way to call api below return; } + + if (!$this->IsCallBack && !$this->IsPostBack && !$this->isDefaultAPIHost()) { + $this->goToPage('SelectAPIHost'); + // without API host selected we can't continue + return; + } + Logging::$debug_enabled = (isset($this->web_config['baculum']['debug']) && $this->web_config['baculum']['debug'] == 1); if (!$this->IsPostBack && !$this->IsCallBack) { $this->postInitActions(); @@ -61,6 +68,20 @@ class BaculumWebPage extends BaculumPage { } } + /** + * Check if default API host is set. + * If it isn't direct to API host selection page. + * + * @return none + */ + private function isDefaultAPIHost() { + $def_api_host = $this->User->getDefaultAPIHost(); + $auth = $this->getModule('auth'); + $page = $this->Service->getRequestedPagePath(); + $pages_no_host = [$auth->getLoginPage(), 'SelectAPIHost']; + return (!is_null($def_api_host) || in_array($page, $pages_no_host)); + } + /** * Set page session values. * diff --git a/gui/baculum/protected/Web/Class/PageCategory.php b/gui/baculum/protected/Web/Class/PageCategory.php index 6f3976f2a..f15c09495 100644 --- a/gui/baculum/protected/Web/Class/PageCategory.php +++ b/gui/baculum/protected/Web/Class/PageCategory.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2020 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -50,6 +50,7 @@ class PageCategory extends WebModule { */ const MONITOR = 'Monitor'; const BACULUM_ERROR = 'BaculumError'; + const SELECT_API_HOST = 'SelectAPIHost'; /** * Public pages - always allowed @@ -87,7 +88,8 @@ class PageCategory extends WebModule { private function getSystemCategories() { return [ self::MONITOR, - self::BACULUM_ERROR + self::BACULUM_ERROR, + self::SELECT_API_HOST ]; } diff --git a/gui/baculum/protected/Web/Class/WebUser.php b/gui/baculum/protected/Web/Class/WebUser.php index 3b9e22bcd..3d2652327 100644 --- a/gui/baculum/protected/Web/Class/WebUser.php +++ b/gui/baculum/protected/Web/Class/WebUser.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2020 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -37,6 +37,7 @@ class WebUser extends TUser { const EMAIL = 'Email'; const DESCRIPTION = 'Description'; const API_HOSTS = 'ApiHosts'; + const DEFAULT_API_HOST = 'DefaultApiHost'; const IPS = 'Ips'; const ENABLED = 'Enabled'; const IN_CONFIG = 'InConfig'; @@ -162,10 +163,8 @@ class WebUser extends TUser { /** * Set API hosts. - * So far is supported only one API host per user. - * In the future this method can support more API hosts per user. * - * @param string $api_hosts API hosts + * @param array $api_hosts user API hosts * @return none */ public function setAPIHosts($api_hosts) { @@ -175,20 +174,80 @@ class WebUser extends TUser { /** * API hosts getter. * - * @return string API host + * @return array user API hosts */ public function getAPIHosts() { + $api_hosts = []; $hosts = $this->getState(self::API_HOSTS); - $hosts = explode(',', $hosts); - if (count($hosts) == 1 && !empty($hosts[0])) { - $api_hosts = $hosts[0]; + /** + * This checking is for backward compatibility because previously + * hosts were written in session as string. Now it is written as array. + */ + if (is_string($hosts)) { + if (!empty($hosts)) { + $hosts = explode(',', $hosts); + } else { + $hosts = []; + } + } elseif (is_null($hosts)) { + $hosts = []; + } + + if (count($hosts) > 0) { + $api_hosts = $hosts; } else { - // default API host - $api_hosts = HostConfig::MAIN_CATALOG_HOST; + // add default API host + $api_hosts[] = HostConfig::MAIN_CATALOG_HOST; } return $api_hosts; } + /** + * Set default API host for user. + * It determines which host will be used as default API host to login + * to Baculum Web interface. This host needs to have at least the catalog + * and the console capabilities. + * + * @param string $api_host default API host + * @return none + */ + public function setDefaultAPIHost($api_host) { + $this->setState(self::DEFAULT_API_HOST, $api_host); + $application = $this->getManager()->getApplication(); + $application->getModule('auth')->updateSessionUser($this); + } + + /** + * Get default API host for user. + * If default API host is not set, there happens a try to determine + * this host if user has only one API host assigned. + * + * @return string|null default API host or null if no default host set + */ + public function getDefaultAPIHost() { + $def_host = $this->getState(self::DEFAULT_API_HOST); + if (!$def_host) { + $api_hosts = $this->getAPIHosts(); + if (count($api_hosts) == 1) { + // only one host assigned, so use it as default host + $def_host = $api_hosts[0]; + $this->setDefaultAPIHost($def_host); + } + } + return $def_host; + } + + /** + * Check if given API host belongs to user API hosts. + * + * @param string $api_host API host to check + * @return boolean true if API host belongs to user API hosts, otherwise false + */ + public function isUserAPIHost($api_host) { + $api_hosts = $this->getAPIHosts(); + return in_array($api_host, $api_hosts); + } + /** * IP address restriction setter. * diff --git a/gui/baculum/protected/Web/Class/WebUserConfig.php b/gui/baculum/protected/Web/Class/WebUserConfig.php index 256a8b04d..d7eb33ade 100644 --- a/gui/baculum/protected/Web/Class/WebUserConfig.php +++ b/gui/baculum/protected/Web/Class/WebUserConfig.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2020 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -70,7 +70,6 @@ class WebUserConfig extends ConfigFileModule { 'description', 'email', 'roles', - 'api_hosts', 'enabled', 'ips' ]; @@ -97,6 +96,14 @@ class WebUserConfig extends ConfigFileModule { continue; } $user_config['username'] = $username; + // for API hosts backward compatibility + if (key_exists('api_hosts', $user_config)) { + if (!is_array($user_config['api_hosts'])) { + $user_config['api_hosts'] = !empty($user_config['api_hosts']) ? [$user_config['api_hosts']] : []; + } + } else { + $user_config['api_hosts'] = []; + } $config[$username] = $user_config; } return $config; diff --git a/gui/baculum/protected/Web/Data/data_desc.json b/gui/baculum/protected/Web/Data/data_desc.json index 027fb844b..25af95d41 100644 --- a/gui/baculum/protected/Web/Data/data_desc.json +++ b/gui/baculum/protected/Web/Data/data_desc.json @@ -1803,7 +1803,7 @@ }, "Messages": { "Name": { - "Required": false, + "Required": true, "ValueType": "name", "DefaultValue": 0, "FieldType": "TextBox", @@ -3490,7 +3490,7 @@ }, "Messages": { "Name": { - "Required": false, + "Required": true, "ValueType": "name", "DefaultValue": 0, "FieldType": "TextBox", @@ -4227,7 +4227,7 @@ }, "Messages": { "Name": { - "Required": false, + "Required": true, "ValueType": "name", "DefaultValue": 0, "FieldType": "TextBox", diff --git a/gui/baculum/protected/Web/JavaScript/misc.js b/gui/baculum/protected/Web/JavaScript/misc.js index 907b866d8..f056478ae 100644 --- a/gui/baculum/protected/Web/JavaScript/misc.js +++ b/gui/baculum/protected/Web/JavaScript/misc.js @@ -989,9 +989,9 @@ function openElementOnCursor(e, element, offsetX, offsetY) { offsetY = 0; } var x = (e.clientX + offsetX).toString(); - var y = (e.clientY + offsetY + window.pageYOffset).toString(); + var y = (e.clientY + offsetY).toString(); $('#' + element).css({ - position: 'absolute', + position: 'fixed', left: x + 'px', top: y + 'px', zIndex: 1000 diff --git a/gui/baculum/protected/Web/Lang/en/messages.mo b/gui/baculum/protected/Web/Lang/en/messages.mo index 44a01c253..44fddc761 100644 Binary files a/gui/baculum/protected/Web/Lang/en/messages.mo and b/gui/baculum/protected/Web/Lang/en/messages.mo differ diff --git a/gui/baculum/protected/Web/Lang/en/messages.po b/gui/baculum/protected/Web/Lang/en/messages.po index 71883eadb..58ab65d90 100644 --- a/gui/baculum/protected/Web/Lang/en/messages.po +++ b/gui/baculum/protected/Web/Lang/en/messages.po @@ -2801,8 +2801,8 @@ msgstr "Default role for imported users:" msgid "Advanced options" msgstr "Advanced options" -msgid "Default API host for imported users:" -msgstr "Default API host for imported users:" +msgid "Default API hosts for imported users:" +msgstr "Default API hosts for imported users:" msgid "Log in" msgstr "Log in" @@ -3301,3 +3301,36 @@ msgstr "Tip: To use bulk autochanger actions, please select table rows." msgid "Mount volume" msgstr "Mount volume" + +msgid "API hosts:" +msgstr "API hosts:" + +msgid "Please select API host" +msgstr "Please select API host" + +msgid "FD address" +msgstr "FD address" + +msgid "FD port" +msgstr "FD port" + +msgid "FD API host" +msgstr "FD API host" + +msgid "Configure file daemon" +msgstr "Configure file daemon" + +msgid "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." +msgstr "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." + +msgid "SD API host" +msgstr "SD API host" + +msgid "SD address" +msgstr "SD address" + +msgid "SD port" +msgstr "SD port" + +msgid "Configure storage daemon" +msgstr "Configure storage daemon" diff --git a/gui/baculum/protected/Web/Lang/ja/messages.mo b/gui/baculum/protected/Web/Lang/ja/messages.mo index a039df50c..54f869868 100644 Binary files a/gui/baculum/protected/Web/Lang/ja/messages.mo and b/gui/baculum/protected/Web/Lang/ja/messages.mo differ diff --git a/gui/baculum/protected/Web/Lang/ja/messages.po b/gui/baculum/protected/Web/Lang/ja/messages.po index 3893d5868..e1705ce14 100644 --- a/gui/baculum/protected/Web/Lang/ja/messages.po +++ b/gui/baculum/protected/Web/Lang/ja/messages.po @@ -2887,8 +2887,8 @@ msgstr "Default role for imported users:" msgid "Advanced options" msgstr "Advanced options" -msgid "Default API host for imported users:" -msgstr "Default API host for imported users:" +msgid "Default API hosts for imported users:" +msgstr "Default API hosts for imported users:" msgid "Log in" msgstr "Log in" @@ -3387,3 +3387,36 @@ msgstr "Tip: To use bulk autochanger actions, please select table rows." msgid "Mount volume" msgstr "Mount volume" + +msgid "API hosts:" +msgstr "API hosts:" + +msgid "Please select API host" +msgstr "Please select API host" + +msgid "FD address" +msgstr "FD address" + +msgid "FD port" +msgstr "FD port" + +msgid "FD API host" +msgstr "FD API host" + +msgid "Configure file daemon" +msgstr "Configure file daemon" + +msgid "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." +msgstr "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." + +msgid "SD API host" +msgstr "SD API host" + +msgid "SD address" +msgstr "SD address" + +msgid "SD port" +msgstr "SD port" + +msgid "Configure storage daemon" +msgstr "Configure storage daemon" diff --git a/gui/baculum/protected/Web/Lang/pl/messages.mo b/gui/baculum/protected/Web/Lang/pl/messages.mo index f3574c5cb..9047ea14f 100644 Binary files a/gui/baculum/protected/Web/Lang/pl/messages.mo and b/gui/baculum/protected/Web/Lang/pl/messages.mo differ diff --git a/gui/baculum/protected/Web/Lang/pl/messages.po b/gui/baculum/protected/Web/Lang/pl/messages.po index e7a797070..1f64bcb37 100644 --- a/gui/baculum/protected/Web/Lang/pl/messages.po +++ b/gui/baculum/protected/Web/Lang/pl/messages.po @@ -2811,8 +2811,8 @@ msgstr "Domyślna rola dla zaimportowanych użytkowników:" msgid "Advanced options" msgstr "Opcje zaawansowane" -msgid "Default API host for imported users:" -msgstr "Domyślny host API dla zaimportowanych użytkowników:" +msgid "Default API hosts for imported users:" +msgstr "Domyślne hosty API dla zaimportowanych użytkowników:" msgid "Log in" msgstr "Zaloguj" @@ -3312,3 +3312,35 @@ msgstr "Wskazówka: W celu użycia akcji zbiorczych zmieniarki taśm, proszę za msgid "Mount volume" msgstr "Montuj wolumen" +msgid "API hosts:" +msgstr "Hosty API:" + +msgid "Please select API host" +msgstr "Proszę wybrać host API" + +msgid "FD address" +msgstr "Adres FD" + +msgid "FD port" +msgstr "Port FD" + +msgid "FD API host" +msgstr "Host API FD" + +msgid "Configure file daemon" +msgstr "Konfiguruj file daemon" + +msgid "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." +msgstr "Wystąpił problem z załadowaniem konfiguracji zasobu. Proszę sprawdzić czy wybrany host API działa i czy dostarcza dostęp do konfiguracji tego zasobu." + +msgid "SD API host" +msgstr "Host API SD" + +msgid "SD address" +msgstr "Adres SD" + +msgid "SD port" +msgstr "Port SD" + +msgid "Configure storage daemon" +msgstr "Konfiguruj storage daemon" diff --git a/gui/baculum/protected/Web/Lang/pt/messages.mo b/gui/baculum/protected/Web/Lang/pt/messages.mo index 026172184..7952f0abf 100644 Binary files a/gui/baculum/protected/Web/Lang/pt/messages.mo and b/gui/baculum/protected/Web/Lang/pt/messages.mo differ diff --git a/gui/baculum/protected/Web/Lang/pt/messages.po b/gui/baculum/protected/Web/Lang/pt/messages.po index 8a7d024b1..68c2bfc36 100644 --- a/gui/baculum/protected/Web/Lang/pt/messages.po +++ b/gui/baculum/protected/Web/Lang/pt/messages.po @@ -2811,8 +2811,8 @@ msgstr "Função padrão para usuários importados:" msgid "Advanced options" msgstr "Opções avançadas" -msgid "Default API host for imported users:" -msgstr "Host API padrão para usuários importados:" +msgid "Default API hosts for imported users:" +msgstr "Default API hosts for imported users:" msgid "Log in" msgstr "Efetuar Login" @@ -3312,3 +3312,35 @@ msgstr "Dica: Para usar ações do autochanger em massa, selecione linhas de tab msgid "Mount volume" msgstr "Montar volume" +msgid "API hosts:" +msgstr "API hosts:" + +msgid "Please select API host" +msgstr "Please select API host" + +msgid "FD address" +msgstr "FD address" + +msgid "FD port" +msgstr "FD port" + +msgid "FD API host" +msgstr "FD API host" + +msgid "Configure file daemon" +msgstr "Configure file daemon" + +msgid "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." +msgstr "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." + +msgid "SD API host" +msgstr "SD API host" + +msgid "SD address" +msgstr "SD address" + +msgid "SD port" +msgstr "SD port" + +msgid "Configure storage daemon" +msgstr "Configure storage daemon" diff --git a/gui/baculum/protected/Web/Lang/ru/messages.mo b/gui/baculum/protected/Web/Lang/ru/messages.mo index 0401ccbf5..c96707feb 100644 Binary files a/gui/baculum/protected/Web/Lang/ru/messages.mo and b/gui/baculum/protected/Web/Lang/ru/messages.mo differ diff --git a/gui/baculum/protected/Web/Lang/ru/messages.po b/gui/baculum/protected/Web/Lang/ru/messages.po index 4cfd21a81..d6f6191bc 100644 --- a/gui/baculum/protected/Web/Lang/ru/messages.po +++ b/gui/baculum/protected/Web/Lang/ru/messages.po @@ -2811,8 +2811,8 @@ msgstr "Роль по умолчанию для импортированных msgid "Advanced options" msgstr "Расширенные настройки" -msgid "Default API host for imported users:" -msgstr "Хост API по умолчанию для импортированных пользователей:" +msgid "Default API hosts for imported users:" +msgstr "Default API hosts for imported users:" msgid "Log in" msgstr "Вход" @@ -3312,3 +3312,35 @@ msgstr "Подсказка: Чтобы использовать массовые msgid "Mount volume" msgstr "Монтировать том" +msgid "API hosts:" +msgstr "API hosts:" + +msgid "Please select API host" +msgstr "Please select API host" + +msgid "FD address" +msgstr "FD address" + +msgid "FD port" +msgstr "FD port" + +msgid "FD API host" +msgstr "FD API host" + +msgid "Configure file daemon" +msgstr "Configure file daemon" + +msgid "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." +msgstr "There was a problem with loading the resource configuration. Please check if selected API host is working and if it provides access to the resource configuration." + +msgid "SD API host" +msgstr "SD API host" + +msgid "SD address" +msgstr "SD address" + +msgid "SD port" +msgstr "SD port" + +msgid "Configure storage daemon" +msgstr "Configure storage daemon" diff --git a/gui/baculum/protected/Web/Layouts/Main.php b/gui/baculum/protected/Web/Layouts/Main.php index 217b677a8..5e0e254cb 100644 --- a/gui/baculum/protected/Web/Layouts/Main.php +++ b/gui/baculum/protected/Web/Layouts/Main.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2019 Kern Sibbald + * Copyright (C) 2013-2021 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -34,9 +34,32 @@ class Main extends TTemplateControl { public $web_config; + public function onInit($param) { + parent::onInit($param); + if ($this->getPage()->IsPostBack || $this->getPage()->IsCallBack) { + return; + } + $api_hosts = $this->User->getAPIHosts(); + $this->UserAPIHosts->DataSource = array_combine($api_hosts, $api_hosts); + $this->UserAPIHosts->SelectedValue = $this->User->getDefaultAPIHost(); + $this->UserAPIHosts->dataBind(); + if (count($api_hosts) === 1) { + $this->UserAPIHostsContainter->Visible = false; + } + } + + public function onPreRender($param) { parent::onPreRender($param); $this->web_config = $this->Application->getModule('web_config')->getConfig(); } + + public function setAPIHost($sender, $param) { + $api_host = $this->UserAPIHosts->SelectedValue; + if (!empty($api_host)) { + $this->User->setDefaultAPIHost($api_host); + $this->getResponse()->reload(); + } + } } ?> diff --git a/gui/baculum/protected/Web/Layouts/Main.tpl b/gui/baculum/protected/Web/Layouts/Main.tpl index e93aa840f..2bc50e70d 100644 --- a/gui/baculum/protected/Web/Layouts/Main.tpl +++ b/gui/baculum/protected/Web/Layouts/Main.tpl @@ -39,6 +39,17 @@ + + <%[ API host: ]%> + + + diff --git a/gui/baculum/protected/Web/Pages/ClientView.php b/gui/baculum/protected/Web/Pages/ClientView.php index a7b4ac161..bd627383e 100644 --- a/gui/baculum/protected/Web/Pages/ClientView.php +++ b/gui/baculum/protected/Web/Pages/ClientView.php @@ -20,6 +20,7 @@ * Bacula(R) is a registered trademark of Kern Sibbald. */ +Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList'); Prado::using('System.Web.UI.ActiveControls.TActiveLabel'); Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton'); Prado::using('System.Web.UI.ActiveControls.TCallback'); @@ -38,6 +39,7 @@ class ClientView extends BaculumWebPage { const CLIENTID = 'ClientId'; const CLIENT_NAME = 'ClientName'; + const CLIENT_ADDRESS = 'ClientAddress'; public function onInit($param) { parent::onInit($param); @@ -60,31 +62,127 @@ class ClientView extends BaculumWebPage { } $this->setClientId($clientid); $clientshow = $this->getModule('api')->get( - array('clients', $clientid, 'show'), + ['clients', $clientid, 'show', '?output=json'], null, true ); if ($clientshow->error === 0) { - $this->ShowLog->Text = implode(PHP_EOL, $clientshow->output); + if (property_exists($clientshow->output, 'enabled')) { + $this->OEnabled->Text = $clientshow->output->enabled == 1 ? Prado::localize('Yes') : Prado::localize('No'); + } + if (property_exists($clientshow->output, 'address')) { + $this->setClientAddress($clientshow->output->address); + $this->OFDAddress->Text = $clientshow->output->address; + } + if (property_exists($clientshow->output, 'fdport')) { + $this->OFDPort->Text = $clientshow->output->fdport; + } + if (property_exists($clientshow->output, 'maxjobs') && property_exists($clientshow->output, 'numjobs')) { + $this->ORunningJobs->Text = $clientshow->output->numjobs . '/' . $clientshow->output->maxjobs; + } + if (property_exists($clientshow->output, 'autoprune')) { + $this->OAutoPrune->Text = $clientshow->output->autoprune = 1 ? Prado::localize('Yes') : Prado::localize('No'); + } + if (property_exists($clientshow->output, 'jobretention')) { + $this->OJobRetention->Text = $clientshow->output->jobretention; + } + if (property_exists($clientshow->output, 'fileretention')) { + $this->OFileRetention->Text = $clientshow->output->fileretention; + } } - $client = $this->getModule('api')->get( - array('clients', $clientid) - ); - if ($client->error === 0) { - $this->setClientName($client->output->name); + if (property_exists($clientshow->output, 'name')) { + // set name from client show + $this->setClientName($clientshow->output->name); + } else { + // set name from catalog data request + $client = $this->getModule('api')->get( + array('clients', $clientid) + ); + if ($client->error === 0) { + $this->setClientName($client->output->name); + } } + $this->setAPIHosts(); } - public function onPreRender($param) { - parent::onPreRender($param); - if ($this->IsCallBack || $this->IsPostBack) { - return; - } + public function setDIRClientConfig($sender, $param) { + $this->FDFileDaemonConfig->unloadDirectives(); if (!empty($_SESSION['dir'])) { - $this->ClientConfig->setComponentName($_SESSION['dir']); - $this->ClientConfig->setResourceName($this->getClientName()); - $this->ClientConfig->setLoadValues(true); - $this->ClientConfig->raiseEvent('OnDirectiveListLoad', $this, null); + $this->DIRClientConfig->setComponentName($_SESSION['dir']); + $this->DIRClientConfig->setResourceName($this->getClientName()); + $this->DIRClientConfig->setLoadValues(true); + $this->DIRClientConfig->raiseEvent('OnDirectiveListLoad', $this, null); + } + } + + private function setAPIHosts() { + $def_host = null; + $api_hosts = $this->getModule('host_config')->getConfig(); + $user_api_hosts = $this->User->getAPIHosts(); + $client_address = $this->getClientAddress(); + foreach ($api_hosts as $name => $attrs) { + if (in_array($name, $user_api_hosts) && $attrs['address'] === $client_address) { + $def_host = $name; + break; + } + } + $this->UserAPIHosts->DataSource = array_combine($user_api_hosts, $user_api_hosts); + if ($def_host) { + $this->UserAPIHosts->SelectedValue = $def_host; + } else { + $this->UserAPIHosts->SelectedValue = $this->User->getDefaultAPIHost(); + } + $this->UserAPIHosts->dataBind(); + if (count($user_api_hosts) === 1) { + $this->UserAPIHostsContainter->Visible = false; + } + } + + private function getFDName() { + $fdname = null; + if (!$this->User->isUserAPIHost($this->UserAPIHosts->SelectedValue)) { + // Validation error. Somebody manually modified select values + return $fdname; + } + $result = $this->getModule('api')->get(['config'], $this->UserAPIHosts->SelectedValue); + if ($result->error === 0) { + for ($i = 0; $i < count($result->output); $i++) { + if ($result->output[$i]->component_type === 'fd' && $result->output[$i]->state) { + $fdname = $result->output[$i]->component_name; + } + + } + } + return $fdname; + } + + public function loadFDFileDaemonConfig($sender, $param) { + $this->DIRClientConfig->unloadDirectives(); + $component_name = $this->getFDName(); + if (!is_null($component_name)) { + $this->FDFileDaemonConfigErr->Display = 'None'; + $this->FDFileDaemonConfig->setHost($this->UserAPIHosts->SelectedValue); + $this->FDFileDaemonConfig->setComponentName($component_name); + $this->FDFileDaemonConfig->setResourceName($component_name); + $this->FDFileDaemonConfig->setLoadValues(true); + $this->FDFileDaemonConfig->raiseEvent('OnDirectiveListLoad', $this, null); + } else { + $this->FDFileDaemonConfigErr->Display = 'Dynamic'; + } + } + + public function loadFDResourcesConfig($sender, $param) { + $resource_type = $param->getCallbackParameter(); + $this->DIRClientConfig->unloadDirectives(); + $this->FDFileDaemonConfig->unloadDirectives(); + $component_name = $this->getFDName(); + if (!is_null($component_name) && !empty($resource_type)) { + $this->FileDaemonResourcesConfig->setHost($this->UserAPIHosts->SelectedValue); + $this->FileDaemonResourcesConfig->setResourceType($resource_type); + $this->FileDaemonResourcesConfig->setComponentName($component_name); + $this->FileDaemonResourcesConfig->loadResourceListTable(); + } else { + $this->FileDaemonResourcesConfig->showError(true); } } @@ -127,6 +225,24 @@ class ClientView extends BaculumWebPage { return $this->getViewState(self::CLIENT_NAME); } + /** + * Set client address. + * + * @return none; + */ + public function setClientAddress($address) { + $this->setViewState(self::CLIENT_ADDRESS, $address); + } + + /** + * Get client address. + * + * @return string address + */ + public function getClientAddress() { + return $this->getViewState(self::CLIENT_ADDRESS); + } + public function status($sender, $param) { $raw_status = $this->getModule('api')->get( ['clients', $this->getClientId(), 'status'] diff --git a/gui/baculum/protected/Web/Pages/NewResource.php b/gui/baculum/protected/Web/Pages/NewResource.php index 7d8a2bf63..af33052d2 100644 --- a/gui/baculum/protected/Web/Pages/NewResource.php +++ b/gui/baculum/protected/Web/Pages/NewResource.php @@ -61,7 +61,7 @@ class NewResource extends BaculumWebPage { $this->setComponentName($component_name); $this->setResourceType($resource_type); // Non-admin can configure only host assigned to him - $this->NewResource->setHost($this->User->getAPIHosts()); + $this->NewResource->setHost($this->User->getDefaultAPIHost()); $this->NewResource->setComponentType($component_type); $this->NewResource->setComponentName($component_name); $this->NewResource->setResourceType($resource_type); @@ -77,8 +77,9 @@ class NewResource extends BaculumWebPage { public function setHosts() { $config = $this->getModule('host_config')->getConfig(); $hosts = array('' => Prado::localize('Please select host')); + $user_api_hosts = $this->User->getAPIHosts(); foreach ($config as $host => $vals) { - if ($host !== $this->User->getAPIHosts()) { + if (!in_array($host, $user_api_hosts)) { continue; } $item = "Host: $host, Address: {$vals['address']}, Port: {$vals['port']}"; diff --git a/gui/baculum/protected/Web/Pages/ScheduleList.page b/gui/baculum/protected/Web/Pages/ScheduleList.page index 6d24406f0..e44d7dc7e 100644 --- a/gui/baculum/protected/Web/Pages/ScheduleList.page +++ b/gui/baculum/protected/Web/Pages/ScheduleList.page @@ -11,23 +11,22 @@
- - - - - - - - - - - - - - - - -
<%[ Name ]%><%[ Actions ]%>
<%[ Name ]%><%[ Actions ]%>
+ + + + + + + + + + + + + + + +
<%[ Name ]%><%[ Actions ]%>
<%[ Name ]%><%[ Actions ]%>
-
- - - -
-
- <%[ Slot number: ]%> - - -
+
+ + + +
+
+ <%[ Slot number: ]%> + + +
+
+
+

<%[ General ]%>

+ + + + + + + + + + + + + +
<%[ SD address ]%>
<%[ SD port ]%>
<%[ Running jobs ]%>
+
+
+

<%[ Device ]%>

+ + + + + + + + + + + + + +
<%[ Device name ]%>
<%[ Media type ]%>
<%[ Autochanger ]%>
+
+