* @access public
* @param string $component_type Bacula component type
* @param array $config config
+ * @param string $file config file path
* @return array validation result, validation output and write to config result
*/
- public function setConfig($component_type, array $config) {
+ public function setConfig($component_type, array $config, $file = null) {
$result = array('is_valid' => false, 'save_result' => false, 'output' => null);
$config_content = $this->prepareConfig($config, self::CONFIG_FILE_FORMAT);
$validation = $this->validateConfig($component_type, $config_content);
$result['is_valid'] = $validation['is_valid'];
$result['result'] = $validation['result'];
if ($result['is_valid'] === true) {
- $tool_config = $this->getModule('api_config')->getJSONToolConfig($component_type);
- /**
- * @TODO: Add option to save config in a specific directory. Users may want
- * to see config and put it manually to production.
- */
- $result['save_result'] = $this->writeConfig($config, $tool_config['cfg'], self::CONFIG_FILE_FORMAT);
+ if (is_null($file)) {
+ $tool_config = $this->getModule('api_config')->getJSONToolConfig($component_type);
+ $file = $tool_config['cfg'];
+ }
+ $result['save_result'] = $this->writeConfig($config, $file, self::CONFIG_FILE_FORMAT);
}
return $result;
}
private function delete() {
$id = null;
if ($this->Request->contains('id')) {
- $id = intval($this->Request['id']);
+ $id = $this->Request['id'];
}
$this->remove($id);
}
const PTYPE_CONFIRM_YES_CMD = 3;
const PTYPE_CONFIRM_YES_BG_CMD = 4;
- const BCONSOLE_COMMAND_PATTERN = "%s%s -c %s %s 2>&1 <<END_OF_DATA\ngui on\n%s\nquit\nEND_OF_DATA";
+ const BCONSOLE_COMMAND_PATTERN = "%s%s -c \"%s\" %s 2>&1 <<END_OF_DATA\ngui on\n%s\nquit\nEND_OF_DATA";
- const BCONSOLE_BG_COMMAND_PATTERN = "echo 'gui on\n%s\nquit\n' | nohup %s%s -c %s %s >%s 2>&1 &";
+ const BCONSOLE_BG_COMMAND_PATTERN = "echo 'gui on\n%s\nquit\n' | nohup %s%s -c \"%s\" %s >%s 2>&1 &";
- const BCONSOLE_CONFIRM_YES_COMMAND_PATTERN = "%s%s -c %s %s 2>&1 <<END_OF_DATA\ngui on\n%s\nyes\nquit\nEND_OF_DATA";
+ const BCONSOLE_CONFIRM_YES_COMMAND_PATTERN = "%s%s -c \"%s\" %s 2>&1 <<END_OF_DATA\ngui on\n%s\nyes\nquit\nEND_OF_DATA";
- const BCONSOLE_CONFIRM_YES_BG_COMMAND_PATTERN = "echo 'gui on\n%s\nyes\nquit\n' | nohup %s%s -c %s %s >%s 2>&1 &";
+ const BCONSOLE_CONFIRM_YES_BG_COMMAND_PATTERN = "echo 'gui on\n%s\nyes\nquit\n' | nohup %s%s -c \"%s\" %s >%s 2>&1 &";
- const BCONSOLE_API_COMMAND_PATTERN = "%s%s -c %s %s 2>&1 <<END_OF_DATA\ngui on\n.api 2 nosignal api_opts=o\n%s\nquit\nEND_OF_DATA";
+ const BCONSOLE_API_COMMAND_PATTERN = "%s%s -c \"%s\" %s 2>&1 <<END_OF_DATA\ngui on\n.api 2 nosignal api_opts=o\n%s\nquit\nEND_OF_DATA";
- const BCONSOLE_DIRECTORS_PATTERN = "%s%s -c %s -l 2>&1";
+ const BCONSOLE_DIRECTORS_PATTERN = "%s%s -c \"%s\" -l 2>&1";
const OUTPUT_FILE_PREFIX = 'output_';
'schedules',
'config',
'status',
- 'actions'
+ 'actions',
+ 'oauth2'
];
var set_scopes = function(field_id) {
document.getElementById(field_id).value = OAuth2Scopes.join(' ');
--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2020 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.
+ */
+
+/**
+ * OAuth2 client endpoint.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+class OAuth2Client extends BaculumAPIServer {
+
+ public function get() {
+ $oauth2_client_id = $this->Request->contains('id') ? $this->Request['id'] : 0;
+ $client_id = $this->getModule('oauth2')->validateClientId($oauth2_client_id) ? $oauth2_client_id : null;
+ if (is_string($client_id)) {
+ $oauth2_cfg = $this->getModule('oauth2_config')->getConfig($client_id);
+ if (count($oauth2_cfg) > 0) {
+ $this->output = $oauth2_cfg;
+ $this->error = OAuth2Error::ERROR_NO_ERRORS;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ }
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ }
+ }
+
+ public function create($params) {
+ $oauth2 = $this->getModule('oauth2');
+ $oauth2_config = $this->getModule('oauth2_config');
+ $misc = $this->getModule('misc');
+ $oauth2_cfg = $oauth2_config->getConfig();
+
+ if (property_exists($params, 'client_id') && key_exists($params->client_id, $oauth2_cfg)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_ALREADY_EXISTS;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_ALREADY_EXISTS;
+ return;
+ }
+
+ if (property_exists($params, 'client_id') && $oauth2->validateClientId($params->client_id)) {
+ $oauth2_cfg[$params->client_id]['client_id'] = $params->client_id;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_CLIENT_ID;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_CLIENT_ID;
+ return;
+ }
+
+ if (property_exists($params, 'client_secret') && $oauth2->validateClientSecret($params->client_secret)) {
+ $oauth2_cfg[$params->client_id]['client_secret'] = $params->client_secret;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_CLIENT_SECRET;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_CLIENT_SECRET;
+ return;
+ }
+
+ if (property_exists($params, 'redirect_uri') && $oauth2->validateRedirectUri($params->redirect_uri)) {
+ $oauth2_cfg[$params->client_id]['redirect_uri'] = $params->redirect_uri;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_REDIRECT_URI;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_REDIRECT_URI;
+ return;
+ }
+
+ if (property_exists($params, 'scope') && $oauth2->validateScopes($params->scope)) {
+ $oauth2_cfg[$params->client_id]['scope'] = $params->scope;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_SCOPE;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_SCOPE;
+ return;
+ }
+
+ if (property_exists($params, 'bconsole_cfg_path')) {
+ if ($misc->isValidPath($params->bconsole_cfg_path)) {
+ $oauth2_cfg[$params->client_id]['bconsole_cfg_path'] = $params->bconsole_cfg_path;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_BCONSOLE_CFG_PATH;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_BCONSOLE_CFG_PATH;
+ return;
+ }
+ } else {
+ $oauth2_cfg[$params->client_id]['bconsole_cfg_path'] = '';
+ }
+
+ if (property_exists($params, 'name') && !empty($params->name)) {
+ if ($misc->isValidName($params->name)) {
+ $oauth2_cfg[$params->client_id]['name'] = $params->name;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_NAME;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_NAME;
+ return;
+ }
+ } else {
+ $oauth2_cfg[$params->client_id]['name'] = '';
+ }
+
+ if (property_exists($params, 'console') && property_exists($params, 'director')) {
+ if (!$misc->isValidName($params->console)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_CONSOLE;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_CONSOLE;
+ return;
+ }
+ if (!$misc->isValidName($params->director)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_DIRECTOR;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_DIRECTOR;
+ return;
+ }
+ $bs = $this->getModule('bacula_setting');
+
+ $dir_cfg = $bs->getConfig('bcons', 'Director', $params->director);
+ if ($dir_cfg['exitcode'] != 0) {
+ $this->output = $dir_cfg->output;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ return;
+ }
+
+ $console_cfg = $bs->getConfig('dir', 'Console', $params->console);
+ if ($console_cfg['exitcode'] != 0) {
+ $this->output = $console_cfg->output;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ return;
+ }
+
+ $cfg = [
+ [
+ 'Director' => [
+ 'Name' => '"' . $dir_cfg['output']['Name'] . '"',
+ 'DirPort' => $dir_cfg['output']['DirPort'],
+ 'Address' => $dir_cfg['output']['Address'],
+ 'Password' => 'XXXX'
+ ],
+ 'Console' => [
+ 'Name' => '"' . $console_cfg['output']['Name'] . '"',
+ 'Password' => '"' . $console_cfg['output']['Password'] . '"'
+ ]
+ ]
+ ];
+ $json_tools = $this->getModule('api_config')->getConfig('jsontools');
+ $dir = $json_tools['bconfig_dir'];
+ $file = sprintf('%s/bconsole-%s.cfg', $dir, $console_cfg['output']['Name']);
+ $this->getModule('bacula_config')->setConfig('bcons', $cfg, $file);
+ $oauth2_cfg[$params->client_id]['bconsole_cfg_path'] = $file;
+ }
+
+ // save config
+ $result = $oauth2_config->setConfig($oauth2_cfg);
+
+ if ($result) {
+ $this->output = $oauth2_cfg;
+ $this->error = OAuth2Error::ERROR_NO_ERRORS;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_INTERNAL_ERROR;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ }
+ }
+
+ public function set($id, $params) {
+ $oauth2_client_id = property_exists($params, 'client_id') ? $params->client_id : 0;
+ $client_id = $this->getModule('oauth2')->validateClientId($oauth2_client_id) ? $oauth2_client_id : null;
+ if (!is_string($client_id)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ return;
+ }
+
+ $oauth2 = $this->getModule('oauth2');
+ $oauth2_config = $this->getModule('oauth2_config');
+ $misc = $this->getModule('misc');
+ $oauth2_cfg = $oauth2_config->getConfig();
+
+ if (!key_exists($client_id, $oauth2_cfg)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ return;
+ }
+
+ if (property_exists($params, 'client_secret')) {
+ if ($oauth2->validateClientSecret($params->client_secret)) {
+ $oauth2_cfg[$client_id]['client_secret'] = $params->client_secret;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_CLIENT_SECRET;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_CLIENT_SECRET;
+ return;
+ }
+ }
+ if (property_exists($params, 'redirect_uri')) {
+ if ($oauth2->validateRedirectUri($params->redirect_uri)) {
+ $oauth2_cfg[$client_id]['redirect_uri'] = $params->redirect_uri;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_REDIRECT_URI;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_REDIRECT_URI;
+ return;
+ }
+ }
+ if (property_exists($params, 'scope')) {
+ if ($oauth2->validateScopes($params->scope)) {
+ $oauth2_cfg[$client_id]['scope'] = $params->scope;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_SCOPE;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_SCOPE;
+ return;
+ }
+ }
+ if (property_exists($params, 'bconsole_cfg_path')) {
+ if ($misc->isValidPath($params->bconsole_cfg_path)) {
+ $oauth2_cfg[$client_id]['bconsole_cfg_path'] = $params->bconsole_cfg_path;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_BCONSOLE_CFG_PATH;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_BCONSOLE_CFG_PATH;
+ return;
+ }
+ }
+ if (property_exists($params, 'name') && !empty($params->name)) {
+ if ($misc->isValidName($params->name)) {
+ $oauth2_cfg[$client_id]['name'] = $params->name;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_NAME;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_NAME;
+ return;
+ }
+ } else {
+ $oauth2_cfg[$client_id]['name'] = '';
+ }
+ if (property_exists($params, 'console') && property_exists($params, 'director')) {
+ if (!$misc->isValidName($params->console)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_CONSOLE;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_CONSOLE;
+ return;
+ }
+ if (!$misc->isValidName($params->director)) {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_INVALID_DIRECTOR;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_INVALID_DIRECTOR;
+ return;
+ }
+ $bs = $this->getModule('bacula_setting');
+
+ $dir_cfg = $bs->getConfig('bcons', 'Director', $params->director);
+ if ($dir_cfg['exitcode'] != 0) {
+ $this->output = $dir_cfg->output;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ return;
+ }
+
+ $console_cfg = $bs->getConfig('dir', 'Console', $params->console);
+ if ($console_cfg['exitcode'] != 0) {
+ $this->output = $console_cfg->output;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ return;
+ }
+
+ $cfg = [
+ [
+ 'Director' => [
+ 'Name' => '"' . $dir_cfg['output']['Name'] . '"',
+ 'DirPort' => $dir_cfg['output']['DirPort'],
+ 'Address' => $dir_cfg['output']['Address'],
+ 'Password' => 'XXXX'
+ ],
+ 'Console' => [
+ 'Name' => '"' . $console_cfg['output']['Name'] . '"',
+ 'Password' => '"' . $console_cfg['output']['Password'] . '"'
+ ]
+ ]
+ ];
+ $json_tools = $this->getModule('api_config')->getConfig('jsontools');
+ $dir = $json_tools['bconfig_dir'];
+ $file = sprintf('%s/bconsole-%s.cfg', $dir, $console_cfg['output']['Name']);
+ $this->getModule('bacula_config')->setConfig('bcons', $cfg, $file);
+ $oauth2_cfg[$params->client_id]['bconsole_cfg_path'] = $file;
+ }
+
+ $result = $oauth2_config->setConfig($oauth2_cfg);
+ if ($result) {
+ $this->output = $oauth2_cfg;
+ $this->error = OAuth2Error::ERROR_NO_ERRORS;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_INTERNAL_ERROR;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ }
+ }
+
+ public function remove($id) {
+ $oauth2 = $this->getModule('oauth2_config');
+ $oauth2_cfg = $oauth2->getConfig();
+ if (key_exists($id, $oauth2_cfg)) {
+ unset($oauth2_cfg[$id]);
+ $result = $oauth2->setConfig($oauth2_cfg);
+ if ($result) {
+ $this->output = [];
+ $this->error = OAuth2Error::ERROR_NO_ERRORS;
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_INTERNAL_ERROR;
+ $this->error = OAuth2Error::ERROR_INTERNAL_ERROR;
+ }
+ } else {
+ $this->output = OAuth2Error::MSG_ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ $this->error = OAuth2Error::ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST;
+ }
+ }
+}
+?>
--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2020 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.
+ */
+
+/**
+ * OAuth2 clients endpoint.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ * @category API
+ * @package Baculum API
+ */
+class OAuth2Clients extends BaculumAPIServer {
+
+ public function get() {
+ $oauth2_cfg = $this->getModule('oauth2_config')->getConfig();
+ $this->output = array_values($oauth2_cfg);
+ $this->error = ClientError::ERROR_NO_ERRORS;
+ }
+}
+?>
<url ServiceParameter="ComponentStatus" pattern="api/v1/status/{component}/" parameters.component="(director|storage|client)" />
<!-- actions endpoints -->
<url ServiceParameter="Actions" pattern="api/v1/actions/{component}/{action}/" parameters.component="(director|storage|client)" parameters.action="(start|stop|restart)" />
+ <!-- OAuth2 client endpoints -->
+ <url ServiceParameter="OAuth2Clients" pattern="api/v1/oauth2/clients/" />
+ <url ServiceParameter="OAuth2Client" pattern="api/v1/oauth2/clients/{id}/" parameters.id="[a-zA-Z0-9\-_]{32}" />
</urls>
},
"Schedule": {
"$ref": "#/definitions/Schedule"
+ },
+ "OAuth2Clients": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/OAuth2Client"
+ }
+ },
+ "OAuth2Client": {
+ "$ref": "#/definitions/OAuth2Client"
}
},
"parameters": {
}]
}
},
- "/api/v1/status/director/": {
+ "/api/v1/status/director": {
"get": {
"tags": ["status"],
"summary": "Get director status",
]
}
},
- "/api/v1/status/storage/": {
+ "/api/v1/status/storage": {
"get": {
"tags": ["status"],
"summary": "Get storage status",
]
}
},
- "/api/v1/status/client/": {
+ "/api/v1/status/client": {
"get": {
"tags": ["status"],
"summary": "Get client status",
}
]
}
+ },
+ "/api/v1/oauth2/clients": {
+ "get": {
+ "tags": ["oauth2"],
+ "summary": "OAuth2 client account list",
+ "description": "Get OAuth2 client account list.",
+ "responses": {
+ "200": {
+ "description": "List of OAuth2 clients properties",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "$ref": "#/components/schemas/OAuth2Clients"
+ },
+ "error": {
+ "type": "integer",
+ "description": "Error code",
+ "enum": [0, 6, 7, 1000]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v1/oauth2/clients/{client_id}": {
+ "get": {
+ "tags": ["oauth2"],
+ "summary": "Specific OAuth2 client account config",
+ "description": "Get specific OAuth2 client account config",
+ "responses": {
+ "200": {
+ "description": "Specific OAuth2 client account config",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "$ref": "#/components/schemas/OAuth2Client"
+ },
+ "error": {
+ "type": "integer",
+ "description": "Error code",
+ "enum": [0, 6, 7, 120, 1000]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "client_id",
+ "in": "path",
+ "required": true,
+ "description": "Client identifier (OAuth2 Client ID)",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "put": {
+ "tags": ["oauth2"],
+ "summary": "Set OAuth2 client settings",
+ "description": "Set specific OAuth2 client settings",
+ "consumes": [ "application/x-www-form-urlencoded" ],
+ "responses": {
+ "200": {
+ "description": "Set OAuth2 client settings",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "type": "object",
+ "description": "Updated OAuth2 client settings"
+ },
+ "error": {
+ "type": "integer",
+ "description": "Error code",
+ "enum": [0, 6, 7, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 1000]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "client_id",
+ "in": "body",
+ "required": true,
+ "description": "Client identifier (OAuth2 Client ID)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "client_secret",
+ "in": "body",
+ "required": true,
+ "description": "OAuth2 client secret",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "redirect_uri",
+ "in": "body",
+ "required": true,
+ "description": "OAuth2 redirect URI (OAuth2 callback)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "scope",
+ "in": "body",
+ "required": true,
+ "description": "Comma separated OAuth2 scopes",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "bconsole_cfg_path",
+ "in": "body",
+ "required": true,
+ "description": "Bconsole config file path",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "name",
+ "in": "body",
+ "required": false,
+ "description": "OAuth2 client account name",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "post": {
+ "tags": ["oauth2"],
+ "summary": "Create OAuth2 client settings",
+ "description": "Create specific OAuth2 client settings",
+ "consumes": [ "application/x-www-form-urlencoded" ],
+ "responses": {
+ "200": {
+ "description": "Create OAuth2 client settings",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "type": "object",
+ "description": "New OAuth2 client settings"
+ },
+ "error": {
+ "type": "integer",
+ "description": "Error code",
+ "enum": [0, 6, 7, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 1000]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "client_id",
+ "in": "body",
+ "required": true,
+ "description": "Client identifier (OAuth2 Client ID)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "client_secret",
+ "in": "body",
+ "required": true,
+ "description": "OAuth2 client secret",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "redirect_uri",
+ "in": "body",
+ "required": true,
+ "description": "OAuth2 redirect URI (OAuth2 callback)",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "scope",
+ "in": "body",
+ "required": true,
+ "description": "Comma separated OAuth2 scopes",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "bconsole_cfg_path",
+ "in": "body",
+ "required": true,
+ "description": "Bconsole config file path",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "name",
+ "in": "body",
+ "required": false,
+ "description": "OAuth2 client account name",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "delete": {
+ "tags": ["oauth2"],
+ "summary": "Delete OAuth2 client account",
+ "description": "Delete OAuth2 client account.",
+ "responses": {
+ "200": {
+ "description": "Delete OAuth2 client account",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "output": {
+ "type": "array",
+ "items": {
+ }
+ },
+ "error": {
+ "type": "integer",
+ "description": "Error code",
+ "enum": [0, 6, 7, 120, 1000]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "client_id",
+ "in": "path",
+ "required": true,
+ "description": "Client identifier (OAuth2 Client ID)",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ]
+ }
}
},
"definitions": {
"pattern": "[a-zA-Z0-9:.-_ ]+"
}
}
+ },
+ "OAuth2Client": {
+ "type": "object",
+ "properties": {
+ "client_id": {
+ "description": "OAuth2 client identifier (Client ID)",
+ "type": "string",
+ "pattern": "[a-zA-Z0-9-_]{32}"
+ },
+ "client_secret": {
+ "description": "OAuth2 client secret",
+ "type": "string",
+ "pattern": "\\S{6,50}"
+ },
+ "redirect_uri": {
+ "description": "Redirect URI (OAuth2 callback)",
+ "type": "string"
+ },
+ "scope": {
+ "description": "Comma separated OAuth2 scopes",
+ "type": "string"
+ },
+ "bconsole_cfg_path": {
+ "description": "Dedicated Bconsole configuration file",
+ "type": "string"
+ },
+ "name": {
+ "description": "OAuth2 client name (optional)",
+ "type": "string"
+ }
+ }
}
}
}
const ERROR_JSON_TOOLS_UNABLE_TO_PARSE_OUTPUT = 83;
const ERROR_JSON_TOOL_NOT_CONFIGURED = 84;
-
const MSG_ERROR_JSON_TOOLS_DISABLED = 'JSON tools support is disabled.';
const MSG_ERROR_JSON_TOOLS_CONNECTION_PROBLEM = 'Problem with connection to a JSON tool.';
const MSG_ERROR_JSON_TOOLS_WRONG_EXITCODE = 'JSON tool returned wrong exitcode.';
const ERROR_ACTIONS_WRONG_EXITCODE = 112;
const ERROR_ACTIONS_NOT_CONFIGURED = 113;
-
const MSG_ERROR_ACTIONS_ACTION_DOES_NOT_EXIST = 'Action does not exist.';
const MSG_ERROR_ACTIONS_DISABLED = 'Actions support is disabled.';
const MSG_ERROR_ACTIONS_WRONG_EXITCODE = 'Action command returned wrong exitcode.';
const MSG_ERROR_ACTIONS_NOT_CONFIGURED = 'Action is not configured.';
}
+
+class OAuth2Error extends GenericError {
+
+ const ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST = 120;
+ const ERROR_OAUTH2_CLIENT_ALREADY_EXISTS = 121;
+ const ERROR_OAUTH2_CLIENT_INVALID_CLIENT_ID = 122;
+ const ERROR_OAUTH2_CLIENT_INVALID_CLIENT_SECRET = 123;
+ const ERROR_OAUTH2_CLIENT_INVALID_REDIRECT_URI = 124;
+ const ERROR_OAUTH2_CLIENT_INVALID_SCOPE = 125;
+ const ERROR_OAUTH2_CLIENT_INVALID_BCONSOLE_CFG_PATH = 126;
+ const ERROR_OAUTH2_CLIENT_INVALID_NAME = 127;
+ const ERROR_OAUTH2_CLIENT_INVALID_CONSOLE = 128;
+ const ERROR_OAUTH2_CLIENT_INVALID_DIRECTOR = 129;
+
+ const MSG_ERROR_OAUTH2_CLIENT_DOES_NOT_EXIST = 'OAuth2 client does not exist.';
+ const MSG_ERROR_OAUTH2_CLIENT_ALREADY_EXISTS = 'OAuth2 client already exists.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_CLIENT_ID = 'Invalid OAuth2 client ID.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_CLIENT_SECRET = 'Invalid OAuth2 client secret.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_REDIRECT_URI = 'Invalid OAuth2 redirect URI.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_SCOPE = 'Invalid OAuth2 scope.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_BCONSOLE_CFG_PATH = 'Invalid Bconsole config path.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_NAME = 'Invalid OAuth2 client name.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_CONSOLE = 'Invalid Console name.';
+ const MSG_ERROR_OAUTH2_CLIENT_INVALID_DIRECTOR = 'Invalid Director name.';
+}
?>
*/
const CLIENT_SECRET_PATTERN = '^\S{6,50}$';
+ /**
+ * Very basic redirect URI validation pattern.
+ *
+ * @see https://tools.ietf.org/html/rfc3986#appendix-B
+ */
+ const REDIRECT_URI_PATTERN = '^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$';
+
/**
* Authorization ID (known also as 'authorization_code') regular expression pattern
* allow to set hexadecimal value of the authorization ID with length equal 40 chars.
/**
* Scope pattern.
*/
- const SCOPE_PATTERN = '^[a-zA-Z:]+$';
+ const SCOPE_PATTERN = '^[a-zA-Z0-9:]+$';
/**
* State pattern.
return (preg_match('/' . self::CLIENT_SECRET_PATTERN . '/', $secret) === 1);
}
+ /**
+ * Validate redirect URI syntax.
+ *
+ * @access public
+ * @param string $redirect_uri redirect URI value
+ * @return boolean true if redirect URI is valid, otherwise false
+ */
+ final public function validateRedirectUri($redirect_uri) {
+ return (preg_match('/' . self::REDIRECT_URI_PATTERN . '/', $redirect_uri) === 1);
+ }
+
/**
* Generate (pseudo-)random authorization identifier.
*
$this->authToHost($host, $host_cfg);
$auth = OAuth2Record::findByPk($host);
}
- if (is_array($auth) && array_key_exists('tokens', $auth)) {
+ if (is_array($auth) && key_exists('tokens', $auth) && is_array($auth['tokens'])) {
$headers[] = "Authorization: {$auth['tokens']['token_type']} {$auth['tokens']['access_token']}";
}
}
return ret;
}
+function render_string_short(data, type, row) {
+ ret = data;
+ if (type == 'display') {
+ var span = document.createElement('SPAN');
+ span.title = data;
+ if (data.length > 40) {
+ span.textContent = data.substring(0, 40) + '...';
+ } else {
+ span.textContent = data;
+ }
+ ret = span.outerHTML;
+ } else {
+ ret = data;
+ }
+ return ret;
+}
+
function set_formatters() {
Formatters.set_formatters();
}
W3TabsCommon.open.call(this, btn_id, item_id);
}
};
+var OAuth2Scopes = [
+ 'console',
+ 'jobs',
+ 'directors',
+ 'clients',
+ 'storages',
+ 'volumes',
+ 'pools',
+ 'bvfs',
+ 'joblog',
+ 'filesets',
+ 'schedules',
+ 'config',
+ 'status',
+ 'actions',
+ 'oauth2'
+];
+var set_scopes = function(field_id) {
+ document.getElementById(field_id).value = OAuth2Scopes.join(' ');
+}
function estimate_job(jobs, job, level) {
var bytes = 0;
msgid "This type of authentication is realized by an external directory service. To authenticate it uses the Baculum Web login form. The web server basic authentication can be disabled in this method."
msgstr "This type of authentication is realized by an external directory service. To authenticate it uses the Baculum Web login form. The web server basic authentication can be disabled in this method."
+
+msgid "Console ACLs"
+msgstr "Console ACLs"
+
+msgid "Add new console"
+msgstr "Add new console"
+
+msgid "Edit console"
+msgstr "Edit console"
+
+msgid "Add console"
+msgstr "Add console"
+
+msgid "OAuth2 clients"
+msgstr "OAuth2 clients"
+
+msgid "Short name"
+msgstr "Short name"
+
+msgid "Add new OAuth2 client"
+msgstr "Add new OAuth2 client"
+
+msgid "Short name:"
+msgstr "Short name:"
+
+msgid "Add OAuth2 client account"
+msgstr "Add OAuth2 client account"
+
+msgid "set all scopes"
+msgstr "set all scopes"
+
+msgid "Edit OAuth2 client account"
+msgstr "Edit OAuth2 client account"
+
+msgid "Add new API host"
+msgstr "Add new API host"
+
+msgid "Get existing API host settings:"
+msgstr "Get existing API host settings:"
+
+msgid "Get existing OAuth2 client settings:"
+msgstr "Get existing OAuth2 client settings:"
+
+msgid "API hosts"
+msgstr "API hosts"
+
+msgid "Edit API host"
+msgstr "Edit API host"
+
+msgid "Create dedicated Bconsole config file:"
+msgstr "Create dedicated Bconsole config file:"
+
+msgid "Console ACL to use in new Bconsole config file:"
+msgstr "Console ACL to use in new Bconsole config file:"
+
+msgid "Director for Bconsole config:"
+msgstr "Director for Bconsole config:"
+
+msgid "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+msgstr "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+
+msgid "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+msgstr "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+
+msgid "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+msgstr "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+
+msgid "Set all CommandAcls used by Baculum Web"
+msgstr "Set all CommandAcls used by Baculum Web"
msgid "This type of authentication is realized by an external directory service. To authenticate it uses the Baculum Web login form. The web server basic authentication can be disabled in this method."
msgstr "This type of authentication is realized by an external directory service. To authenticate it uses the Baculum Web login form. The web server basic authentication can be disabled in this method."
+
+msgid "Console ACLs"
+msgstr "Console ACLs"
+
+msgid "Add new console"
+msgstr "Add new console"
+
+msgid "Edit console"
+msgstr "Edit console"
+
+msgid "Add console"
+msgstr "Add console"
+
+msgid "OAuth2 clients"
+msgstr "OAuth2 clients"
+
+msgid "Short name"
+msgstr "Short name"
+
+msgid "Add new OAuth2 client"
+msgstr "Add new OAuth2 client"
+
+msgid "Short name:"
+msgstr "Short name:"
+
+msgid "Add OAuth2 client account"
+msgstr "Add OAuth2 client account"
+
+msgid "set all scopes"
+msgstr "set all scopes"
+
+msgid "Edit OAuth2 client account"
+msgstr "Edit OAuth2 client account"
+
+msgid "Add new API host"
+msgstr "Add new API host"
+
+msgid "Get existing API host settings:"
+msgstr "Get existing API host settings:"
+
+msgid "Get existing OAuth2 client settings:"
+msgstr "Get existing OAuth2 client settings:"
+
+msgid "API hosts"
+msgstr "API hosts"
+
+msgid "Edit API host"
+msgstr "Edit API host"
+
+msgid "Create dedicated Bconsole config file:"
+msgstr "Create dedicated Bconsole config file:"
+
+msgid "Console ACL to use in new Bconsole config file:"
+msgstr "Console ACL to use in new Bconsole config file:"
+
+msgid "Director for Bconsole config:"
+msgstr "Director for Bconsole config:"
+
+msgid "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+msgstr "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+
+msgid "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+msgstr "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+
+msgid "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+msgstr "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+
+msgid "Set all CommandAcls used by Baculum Web"
+msgstr "Set all CommandAcls used by Baculum Web"
msgid "This type of authentication is realized by an external directory service. To authenticate it uses the Baculum Web login form. The web server basic authentication can be disabled in this method."
msgstr "Ten typ uwierzytelniania jest realizowany przez zewnętrzną usługę katalogową. Do uwierzytelniania używa formularza logowania Baculum Web. Uwierzytelnianie basic serwera WWW może być wyłączone w tej metodzie."
+msgid "Console ACLs"
+msgstr "Konsole ACLs"
+
+msgid "Add new console"
+msgstr "Dodaj nowÄ… konsolÄ™"
+
+msgid "Edit console"
+msgstr "Edytuj konsolÄ™"
+
+msgid "Add console"
+msgstr "Dodaj konsolÄ™"
+
+msgid "OAuth2 clients"
+msgstr "Klienci OAuth2"
+
+msgid "Short name"
+msgstr "Nazwa"
+
+msgid "Add new OAuth2 client"
+msgstr "Dodaj nowego klienta OAuth2"
+
+msgid "Short name:"
+msgstr "Nazwa:"
+
+msgid "Add OAuth2 client account"
+msgstr "Dodaj konto klienta OAuth2"
+
+msgid "set all scopes"
+msgstr "ustaw wszystkie zakresy"
+
+msgid "Edit OAuth2 client account"
+msgstr "Edytuj konto klienta OAuth2"
+
+msgid "Add new API host"
+msgstr "Dodaj nowy host API"
+
+msgid "Get existing API host settings:"
+msgstr "Pobierz konfiguracjÄ™ istniejÄ…cego hosta API:"
+
+msgid "Get existing OAuth2 client settings:"
+msgstr "Pobierz konfiguracjÄ™ istniejÄ…cego klienta OAuth2:"
+
+msgid "API hosts"
+msgstr "Hosty API"
+
+msgid "Edit API host"
+msgstr "Edytuj host API"
+
+msgid "Create dedicated Bconsole config file:"
+msgstr "Stwórz dedykowany plik konfiguracyjny Bconsole:"
+
+msgid "Console ACL to use in new Bconsole config file:"
+msgstr "Konsole ACL do użycia w nowym pliku konfiguracyjnym:"
+
+msgid "Director for Bconsole config:"
+msgstr "ZarzÄ…dca dla pliku konfiguracyjnego Bconsole:"
+
+msgid "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+msgstr "Konsole ACL umożliwiają zdefiniowanie dostępnych zasobów dla użytkowników. Konsole są używane w konfiguracji Bacula po stronie hosta API. Jest możliwe przypisanie konsoli do klientów OAuth2, którzy mogą być użyci w hostach API. Relacja przypisania jest: Console ACL -> Klient OAuth2 -> Host API -> Konto użytkownika."
+
+
+msgid "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+msgstr "Klienci OAuth2 są konfigurowani na hostach API. Aby stworzyć klienta OAuth2 z tej strony, potrzebujesz przypisać zakres 'oauth2' na koncie OAuth2 powiązanym z twoim obecnym kontem administratora."
+
+msgid "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+msgstr "Hosty API definiują parametry połączenia do hostów z instancjami Baculum API. Możesz stworzyć połączenia do hostów API dedykowane dla określonych użytkowników poprzez przypisanie hostów API do nich na zakładce Użytkownicy. Jest możliwe utworzenie wielu połączeń do hostów API dla tej samej instancji Baculum API."
+
+msgid "Set all CommandAcls used by Baculum Web"
+msgstr "Ustaw wszystkie wartości CommandAcl używane przez Baculum Web"
msgid "This type of authentication is realized by an external directory service. To authenticate it uses the Baculum Web login form. The web server basic authentication can be disabled in this method."
msgstr "Esse tipo de autenticação é realizado por um serviço de diretório externo. Para autenticar, use o formulário de login do Baculum. A autenticação básica do servidor da web pode ser desativada nesse método."
+msgid "Console ACLs"
+msgstr "Console ACLs"
+
+msgid "Add new console"
+msgstr "Add new console"
+
+msgid "Edit console"
+msgstr "Edit console"
+
+msgid "Add console"
+msgstr "Add console"
+
+msgid "OAuth2 clients"
+msgstr "OAuth2 clients"
+
+msgid "Short name"
+msgstr "Short name"
+
+msgid "Add new OAuth2 client"
+msgstr "Add new OAuth2 client"
+
+msgid "Short name:"
+msgstr "Short name:"
+
+msgid "Add OAuth2 client account"
+msgstr "Add OAuth2 client account"
+
+msgid "set all scopes"
+msgstr "set all scopes"
+
+msgid "Edit OAuth2 client account"
+msgstr "Edit OAuth2 client account"
+
+msgid "Add new API host"
+msgstr "Add new API host"
+
+msgid "Get existing API host settings:"
+msgstr "Get existing API host settings:"
+
+msgid "Get existing OAuth2 client settings:"
+msgstr "Get existing OAuth2 client settings:"
+
+msgid "API hosts"
+msgstr "API hosts"
+
+msgid "Edit API host"
+msgstr "Edit API host"
+
+msgid "Create dedicated Bconsole config file:"
+msgstr "Create dedicated Bconsole config file:"
+
+msgid "Console ACL to use in new Bconsole config file:"
+msgstr "Console ACL to use in new Bconsole config file:"
+
+msgid "Director for Bconsole config:"
+msgstr "Director for Bconsole config:"
+
+msgid "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+msgstr "The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account."
+
+msgid "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+msgstr "The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API."
+
+msgid "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+msgstr "The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance."
+
+msgid "Set all CommandAcls used by Baculum Web"
+msgstr "Set all CommandAcls used by Baculum Web"
<button id="btn_user_security" type="button" class="w3-bar-item w3-button tab_btn w3-grey" onclick="W3Tabs.open(this.id, 'user_security');"><%[ Settings ]%></button>
<button id="btn_user_list" type="button" class="w3-bar-item w3-button tab_btn" onclick="W3Tabs.open(this.id, 'user_list'); oUserList.table.responsive.recalc();"><%[ Users ]%></button>
<button id="btn_role_list" type="button" class="w3-bar-item w3-button tab_btn" onclick="W3Tabs.open(this.id, 'role_list'); oRoleList.table.responsive.recalc();"><%[ Roles ]%></button>
+ <button id="btn_console_list" type="button" class="w3-bar-item w3-button tab_btn<%=empty($_SESSION['dir']) ? ' hide': ''%>" onclick="W3Tabs.open(this.id, 'console_list'); oConsoleList.table.responsive.recalc();"><%[ Console ACLs ]%></button>
+ <button id="btn_oauth2_client_list" type="button" class="w3-bar-item w3-button tab_btn" onclick="W3Tabs.open(this.id, 'oauth2_client_list'); oOAuth2ClientList.table.responsive.recalc();"><%[ OAuth2 clients ]%></button>
+ <button id="btn_api_host_list" type="button" class="w3-bar-item w3-button tab_btn" onclick="W3Tabs.open(this.id, 'api_host_list'); oAPIHostList.table.responsive.recalc();"><%[ API hosts ]%></button>
</div>
<div class="w3-container tab_item" id="user_security">
>
<i class="fa fa-save"></i> <%[ Save ]%>
</com:TActiveLinkButton>
- <i id="status_command_loading" class="fa fa-sync w3-spin" style="visibility: hidden;"></i>
</footer>
</div>
<com:TActiveHiddenField ID="UserWindowType" />
>
<i class="fa fa-save"></i> <%[ Save ]%>
</com:TActiveLinkButton>
- <i id="status_command_loading" class="fa fa-sync w3-spin" style="visibility: hidden;"></i>
</footer>
</div>
<com:TActiveHiddenField ID="RoleWindowType" />
</script>
<com:TCallback ID="RemoveRolesAction" OnCallback="TemplateControl.removeRoles" />
<com:Application.Web.Portlets.BulkActionsModal ID="BulkActions" />
+ <div class="w3-container tab_item" id="console_list" style="display: none">
+ <p class="w3-hide-small"><%[ The console ACLs enable to define available resources for users. The consoles are used in the Bacula configuration on the API host side. There is possible to assign the consoles to the OAuth2 clients that can be used in API hosts. The assign relation is: Console ACL -> OAuth2 client -> API host -> User account. ]%></p>
+ <div class="w3-panel">
+ <button type="button" id="add_console_btn" class="w3-button w3-green" onclick="oConsoles.load_console_window()"><i class="fa fa-plus"></i> <%[ Add new console ]%></a>
+ </div>
+ <table id="console_list_table" class="w3-table w3-striped w3-hoverable w3-white w3-margin-bottom selectable" style="width: 100%">
+ <thead>
+ <tr>
+ <th></th>
+ <th><%[ Name ]%></th>
+ <th class="w3-center">Description</th>
+ <th class="w3-center">JobACL</th>
+ <th class="w3-center">ClientACL</th>
+ <th class="w3-center">StorageACL</th>
+ <th class="w3-center">ScheduleACL</th>
+ <th class="w3-center">RunACL</th>
+ <th class="w3-center">PoolACL</th>
+ <th class="w3-center">CommandACL</th>
+ <th class="w3-center">FileSetACL</th>
+ <th class="w3-center">CatalogACL</th>
+ <th class="w3-center">WhereACL</th>
+ <th class="w3-center">PluginOptionsACL</th>
+ <th class="w3-center">BackupClientACL</th>
+ <th class="w3-center">RestoreClientACL</th>
+ <th class="w3-center">DirectoryACL</th>
+ <th class="w3-center"><%[ Action ]%></th>
+ </tr>
+ </thead>
+ <tbody id="console_list_body"></tbody>
+ <tfoot>
+ <tr>
+ <th></th>
+ <th><%[ Name ]%></th>
+ <th class="w3-center">Description</th>
+ <th class="w3-center">JobACL</th>
+ <th class="w3-center">ClientACL</th>
+ <th class="w3-center">StorageACL</th>
+ <th class="w3-center">ScheduleACL</th>
+ <th class="w3-center">RunACL</th>
+ <th class="w3-center">PoolACL</th>
+ <th class="w3-center">CommandACL</th>
+ <th class="w3-center">FileSetACL</th>
+ <th class="w3-center">CatalogACL</th>
+ <th class="w3-center">WhereACL</th>
+ <th class="w3-center">PluginOptionsACL</th>
+ <th class="w3-center">BackupClientACL</th>
+ <th class="w3-center">RestoreClientACL</th>
+ <th class="w3-center">DirectoryACL</th>
+ <th class="w3-center"><%[ Action ]%></th>
+ </tr>
+ </tfoot>
+ </table>
+ <p class="info w3-hide-medium w3-hide-small"><%[ Tip: Use left-click to select table row. Use CTRL + left-click to multiple row selection. Use SHIFT + left-click to add a range of rows to selection. ]%></p>
+<com:TCallback ID="ConsoleList" OnCallback="TemplateControl.setConsoleList" />
+<com:TCallback ID="LoadConsole" OnCallback="TemplateControl.loadConsoleWindow" />
+<com:TCallback ID="RemoveConsolesAction" OnCallback="TemplateControl.removeConsoles" />
+<script>
+var oConsoleList = {
+ ids: {
+ console_list: 'console_list_table'
+ },
+ actions: [
+ {
+ action: 'remove',
+ label: '<%[ Remove ]%>',
+ value: 'Name',
+ callback: <%=$this->RemoveConsolesAction->ActiveControl->Javascript%>
+ }
+ ],
+ data: [],
+ table: null,
+ table_toolbar: null,
+ init: function() {
+ if (!this.table) {
+ this.set_table();
+ this.set_bulk_actions();
+ this.set_events();
+ } else {
+ var page = this.table.page();
+ this.table.clear().rows.add(this.data).draw();
+ this.table.page(page).draw(false);
+ this.table_toolbar.style.display = 'none';
+ }
+ },
+ set_events: function() {
+ document.getElementById(this.ids.console_list).addEventListener('click', function(e) {
+ $(function() {
+ this.table_toolbar.style.display = this.table.rows({selected: true}).data().length > 0 ? '' : 'none';
+ }.bind(this));
+ }.bind(this));
+ },
+ set_table: function() {
+ this.table = $('#' + this.ids.console_list).DataTable({
+ data: this.data,
+ deferRender: true,
+ dom: 'lB<"table_toolbar">frtip',
+ stateSave: true,
+ buttons: [
+ 'copy', 'csv', 'colvis'
+ ],
+ columns: [
+ {
+ className: 'details-control',
+ orderable: false,
+ data: null,
+ defaultContent: '<button type="button" class="w3-button w3-blue"><i class="fa fa-angle-down"></i></button>'
+ },
+ {data: 'Name'},
+ {
+ data: 'Description',
+ visible: false
+ },
+ {
+ data: 'JobAcl',
+ render: render_string_short
+ },
+ {
+ data: 'ClientAcl',
+ render: render_string_short
+ },
+ {
+ data: 'StorageAcl',
+ render: render_string_short
+ },
+ {
+ data: 'ScheduleAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'RunAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'PoolAcl',
+ render: render_string_short
+ },
+ {
+ data: 'CommandAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'FilesetAcl',
+ render: render_string_short
+ },
+ {
+ data: 'CatalogAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'WhereAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'PluginOptionsAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'BackupClientAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'RestoreClientAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'DirectoryAcl',
+ render: render_string_short,
+ visible: false
+ },
+ {
+ data: 'Name',
+ render: function (data, type, row) {
+ var btn_edit = document.createElement('BUTTON');
+ btn_edit.className = 'w3-button w3-green';
+ btn_edit.type = 'button';
+ var i_edit = document.createElement('I');
+ i_edit.className = 'fa fa-list-ul';
+ var label_edit = document.createTextNode(' <%[ Edit ]%>');
+ btn_edit.appendChild(i_edit);
+ btn_edit.innerHTML += ' ';
+ btn_edit.style.marginRight = '8px';
+ btn_edit.appendChild(label_edit);
+ btn_edit.setAttribute('onclick', 'oConsoles.load_console_window(\'' + data + '\')');
+ return btn_edit.outerHTML;
+ }
+ }
+ ],
+ responsive: {
+ details: {
+ type: 'column'
+ }
+ },
+ columnDefs: [{
+ className: 'control',
+ orderable: false,
+ targets: 0
+ },
+ {
+ className: 'action_col',
+ orderable: false,
+ targets: [ 17 ]
+ },
+ {
+ className: "dt-center",
+ targets: [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ]
+ }],
+ select: {
+ style: 'os',
+ selector: 'td:not(:last-child):not(:first-child)',
+ blurable: false
+ },
+ order: [1, 'asc']
+ });
+ },
+ set_bulk_actions: function() {
+ this.table_toolbar = get_table_toolbar(this.table, this.actions, {
+ actions: '<%[ Actions ]%>',
+ ok: '<%[ OK ]%>'
+ });
+ }
+};
+
+var oConsoles = {
+ load_console_window: function(name) {
+ var title_add = document.getElementById('console_window_title_add');
+ var title_edit = document.getElementById('console_window_title_edit');
+ var console_win_type = document.getElementById('<%=$this->ConsoleWindowType->ClientID%>');
+ var all_command_acls = document.getElementById('<%=$this->ConsoleBaculumConfig->ClientID%>');
+ // callback is sent both for new and edit console because there is realized
+ // checking if password is allowed to set or not
+ var cb = <%=$this->LoadConsole->ActiveControl->Javascript%>;
+ cb.setCallbackParameter(name);
+ cb.dispatch();
+ if (name) {
+ // edit existing console
+ title_add.style.display = 'none';
+ title_edit.style.display = 'inline-block';
+ all_command_acls.style.display = 'none';
+ console_win_type.value = 'edit';
+ } else {
+ // add new console
+ title_add.style.display = 'inline-block';
+ title_edit.style.display = 'none';
+ all_command_acls.style.display = '';
+ console_win_type.value = 'add';
+ }
+ document.getElementById('console_window').style.display = 'block';
+ },
+ load_console_list: function() {
+ var cb = <%=$this->ConsoleList->ActiveControl->Javascript%>;
+ cb.dispatch();
+ },
+ load_console_list_cb: function(list) {
+ oConsoleList.data = list;
+ oConsoleList.init();
+ },
+ save_console_cb: function() {
+ this.load_console_list();
+ document.getElementById('console_window').style.display = 'none';
+ }
+}
+
+$(function() {
+ oConsoles.load_console_list();
+});
+ </script>
+ </div>
+ <div id="console_window" class="w3-modal">
+ <div class="w3-modal-content w3-animate-top w3-card-4">
+ <header class="w3-container w3-teal">
+ <span onclick="document.getElementById('console_window').style.display = 'none';" class="w3-button w3-display-topright">×</span>
+ <h2 id="console_window_title_add" style="display: none"><%[ Add console ]%></h2>
+ <h2 id="console_window_title_edit" style="display: none"><%[ Edit console ]%></h2>
+ </header>
+ <div class="w3-container w3-margin-left w3-margin-right w3-margin-top w3-text-teal">
+ <com:TActiveLinkButton
+ ID="ConsoleBaculumConfig"
+ CssClass="w3-right"
+ OnCommand="setAllCommandAcls"
+ CommandParameter="save"
+ >
+ <i class="fas fa-globe"></i> <%[ Set all CommandAcls used by Baculum Web ]%>
+ </com:TActiveLinkButton>
+ <com:Application.Web.Portlets.BaculaConfigDirectives
+ ID="ConsoleConfig"
+ ComponentType="dir"
+ ResourceType="Console"
+ ShowRemoveButton="false"
+ ShowCancelButton="false"
+ ShowBottomButtons="false"
+ SaveDirectiveActionOk="oConsoles.save_console_cb();"
+ OnSave="loadOAuth2ClientConsole"
+ />
+ </div>
+ </div>
+ <com:TActiveHiddenField ID="ConsoleWindowType" />
+ </div>
+ <div class="w3-container tab_item" id="oauth2_client_list" style="display: none">
+ <p class="w3-hide-small"><%[ The OAuth2 clients are configured on the API hosts. To create the OAuth2 clients from this page, you need to have an 'oauth2' scope in OAuth2 account related to your current admin user account. The OAuth2 client accounts are also possible to create directly in the panel of the Baculum API. ]%></p>
+ <div id="oauth2_client_btn" class="w3-panel">
+ <button type="button" id="add_oauth2_client_btn" class="w3-button w3-green" onclick="oOAuth2Clients.load_oauth2_client_window()"><i class="fa fa-plus"></i> <%[ Add new OAuth2 client ]%></a>
+ </div>
+ <table id="oauth2_client_list_table" class="w3-table w3-striped w3-hoverable w3-white w3-margin-bottom selectable" style="width: 100%">
+ <thead>
+ <tr>
+ <th></th>
+ <th><%[ Short name ]%></th>
+ <th class="w3-center">OAuth2 Client ID</th>
+ <th class="w3-center">Redirect URI</th>
+ <th class="w3-center">Scopes</th>
+ <th class="w3-center">Dedicated BConsole config</th>
+ <th class="w3-center"><%[ Action ]%></th>
+ </tr>
+ </thead>
+ <tbody id="oauth2_client_list_body"></tbody>
+ <tfoot>
+ <tr>
+ <th></th>
+ <th><%[ Short name ]%></th>
+ <th class="w3-center">OAuth2 Client ID</th>
+ <th class="w3-center">Redirect URI</th>
+ <th class="w3-center">Scopes</th>
+ <th class="w3-center">Dedicated BConsole config</th>
+ <th class="w3-center"><%[ Action ]%></th>
+ </tr>
+ </tfoot>
+ </table>
+ <p id="oauth2_client_table_footer" class="info w3-hide-medium w3-hide-small"><%[ Tip: Use left-click to select table row. Use CTRL + left-click to multiple row selection. Use SHIFT + left-click to add a range of rows to selection. ]%></p>
+<com:TCallback ID="OAuth2ClientList" OnCallback="TemplateControl.setOAuth2ClientList" />
+<com:TCallback ID="LoadOAuth2Client" OnCallback="TemplateControl.loadOAuth2ClientWindow" />
+<com:TCallback ID="RemoveOAuth2ClientsAction" OnCallback="TemplateControl.removeOAuth2Clients" />
+<script>
+var oOAuth2ClientList = {
+ ids: {
+ oauth2_client_list: 'oauth2_client_list_table'
+ },
+ actions: [
+ {
+ action: 'remove',
+ label: '<%[ Remove ]%>',
+ value: 'client_id',
+ callback: <%=$this->RemoveOAuth2ClientsAction->ActiveControl->Javascript%>
+ }
+ ],
+ data: [],
+ table: null,
+ table_toolbar: null,
+ init: function() {
+ if (!this.table) {
+ this.set_table();
+ this.set_bulk_actions();
+ this.set_events();
+ } else {
+ var page = this.table.page();
+ this.table.clear().rows.add(this.data).draw();
+ this.table.page(page).draw(false);
+ this.table_toolbar.style.display = 'none';
+ }
+ },
+ set_events: function() {
+ document.getElementById(this.ids.oauth2_client_list).addEventListener('click', function(e) {
+ $(function() {
+ this.table_toolbar.style.display = this.table.rows({selected: true}).data().length > 0 ? '' : 'none';
+ }.bind(this));
+ }.bind(this));
+ },
+ set_table: function() {
+ this.table = $('#' + this.ids.oauth2_client_list).DataTable({
+ data: this.data,
+ deferRender: true,
+ dom: 'lB<"table_toolbar">frtip',
+ stateSave: true,
+ buttons: [
+ 'copy', 'csv', 'colvis'
+ ],
+ columns: [
+ {
+ className: 'details-control',
+ orderable: false,
+ data: null,
+ defaultContent: '<button type="button" class="w3-button w3-blue"><i class="fa fa-angle-down"></i></button>'
+ },
+ {data: 'name'},
+ {data: 'client_id'},
+ {
+ data: 'redirect_uri',
+ render: render_string_short
+ },
+ {
+ data: 'scope',
+ render: render_string_short
+ },
+ {
+ data: 'bconsole_cfg_path',
+ render: function(data, type, row) {
+ var ret;
+ if (type == 'display') {
+ ret = '';
+ if (data) {
+ var check = document.createElement('I');
+ check.className = 'fas fa-check';
+ ret = check.outerHTML;
+ }
+ } else {
+ ret = data;
+ }
+ return ret;
+ }
+ },
+ {
+ data: 'client_id',
+ render: function (data, type, row) {
+ var btn_edit = document.createElement('BUTTON');
+ btn_edit.className = 'w3-button w3-green';
+ btn_edit.type = 'button';
+ var i_edit = document.createElement('I');
+ i_edit.className = 'fa fa-list-ul';
+ var label_edit = document.createTextNode(' <%[ Edit ]%>');
+ btn_edit.appendChild(i_edit);
+ btn_edit.innerHTML += ' ';
+ btn_edit.style.marginRight = '8px';
+ btn_edit.appendChild(label_edit);
+ btn_edit.setAttribute('onclick', 'oOAuth2Clients.load_oauth2_client_window(\'' + data + '\')');
+ return btn_edit.outerHTML;
+ }
+ }
+ ],
+ responsive: {
+ details: {
+ type: 'column'
+ }
+ },
+ columnDefs: [{
+ className: 'control',
+ orderable: false,
+ targets: 0
+ },
+ {
+ className: 'action_col',
+ orderable: false,
+ targets: [ 6 ]
+ },
+ {
+ className: "dt-center",
+ targets: [ 2, 3, 4, 5 ]
+ }],
+ select: {
+ style: 'os',
+ selector: 'td:not(:last-child):not(:first-child)',
+ blurable: false
+ },
+ order: [1, 'asc']
+ });
+ },
+ set_bulk_actions: function() {
+ this.table_toolbar = get_table_toolbar(this.table, this.actions, {
+ actions: '<%[ Actions ]%>',
+ ok: '<%[ OK ]%>'
+ });
+ }
+};
+
+var oOAuth2Clients = {
+ load_oauth2_client_window: function(name) {
+ var title_add = document.getElementById('oauth2_client_window_title_add');
+ var title_edit = document.getElementById('oauth2_client_window_title_edit');
+ var client_id = document.getElementById('<%=$this->OAuth2ClientClientId->ClientID%>');
+ var generate_client_id = document.getElementById('oauth2_client_generate_client_id_link');
+ var oauth2_client_win_type = document.getElementById('<%=$this->OAuth2ClientWindowType->ClientID%>');
+ // callback is sent both for new and edit oauth2_client because there is realized
+ // checking if password is allowed to set or not
+ var cb = <%=$this->LoadOAuth2Client->ActiveControl->Javascript%>;
+ cb.setCallbackParameter(name);
+ cb.dispatch();
+ if (name) {
+ // edit existing oauth2_client
+ title_add.style.display = 'none';
+ title_edit.style.display = 'inline-block';
+ oauth2_client_win_type.value = 'edit';
+ generate_client_id.style.display = 'none';
+ client_id.setAttribute('readonly', '');
+ } else {
+ // add new oauth2_client
+ title_add.style.display = 'inline-block';
+ title_edit.style.display = 'none';
+ oauth2_client_win_type.value = 'add';
+ generate_client_id.style.display = '';
+ client_id.removeAttribute('readonly');
+ this.clear_oauth2_client_window();
+ document.getElementById('<%=$this->OAuth2ClientRedirectURI->ClientID%>').value = document.location.origin + '/web/redirect';
+ }
+ document.getElementById('<%=$this->OAuth2ClientBconsoleCreate->ClientID%>').checked = false;
+ document.getElementById('oauth2_client_console').style.display = 'none';
+ document.getElementById('oauth2_client_bconsole_cfg').style.display = '';
+ document.getElementById('oauth2_client_window').style.display = 'block';
+ document.getElementById('oauth2_client_error').style.display = 'none';
+ },
+ load_oauth2_client_list: function() {
+ var cb = <%=$this->OAuth2ClientList->ActiveControl->Javascript%>;
+ cb.dispatch();
+ },
+ load_oauth2_client_list_cb: function(list, error) {
+ if (error == 0) {
+ oOAuth2ClientList.data = list;
+ oOAuth2ClientList.init();
+ } else if (error == 7) {
+ oOAuth2Clients.hide_oauth2_client_func();
+ }
+ },
+ clear_oauth2_client_window: function() {
+ [
+ '<%=$this->OAuth2ClientClientId->ClientID%>',
+ '<%=$this->OAuth2ClientClientSecret->ClientID%>',
+ '<%=$this->OAuth2ClientRedirectURI->ClientID%>',
+ '<%=$this->OAuth2ClientScope->ClientID%>',
+ '<%=$this->OAuth2ClientBconsoleCfgPath->ClientID%>',
+ '<%=$this->OAuth2ClientBconsoleCfgPath->ClientID%>',
+ '<%=$this->OAuth2ClientName->ClientID%>'
+ ].forEach(function(id) {
+ document.getElementById(id).value = '';
+ });
+ },
+ save_oauth2_client_cb: function(result) {
+ if (result.error == 0) {
+ document.getElementById('oauth2_client_error').style.display = 'none';
+ document.getElementById('oauth2_client_window').style.display = 'none';
+ } else {
+ document.getElementById('oauth2_client_error').textContent = result.output;
+ document.getElementById('oauth2_client_error').style.display = '';
+ }
+ },
+ hide_oauth2_client_func: function() {
+ [
+ 'oauth2_client_btn',
+ 'oauth2_client_list_table',
+ 'oauth2_client_table_footer'
+ ].forEach(function(id) {
+ document.getElementById(id).style.display = 'none';
+ });
+ }
+}
+
+$(function() {
+ oOAuth2Clients.load_oauth2_client_list();
+});
+ </script>
+ </div>
+ <div id="oauth2_client_window" class="w3-modal">
+ <div class="w3-modal-content w3-animate-top w3-card-4">
+ <header class="w3-container w3-teal">
+ <span onclick="document.getElementById('oauth2_client_window').style.display = 'none';" class="w3-button w3-display-topright">×</span>
+ <h2 id="oauth2_client_window_title_add" style="display: none"><%[ Add OAuth2 client account ]%></h2>
+ <h2 id="oauth2_client_window_title_edit" style="display: none"><%[ Edit OAuth2 client account ]%></h2>
+ </header>
+ <div class="w3-container w3-margin-left w3-margin-right w3-margin-top w3-text-teal">
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientClientId" Text="<%[ OAuth2 Client ID: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveTextBox
+ ID="OAuth2ClientClientId"
+ AutoPostBack="false"
+ CausesValidation="false"
+ MaxLength="32"
+ CssClass="w3-input w3-border"
+ />
+ <com:TRequiredFieldValidator
+ ValidationGroup="OAuth2ClientGroup"
+ ControlToValidate="OAuth2ClientClientId"
+ ErrorMessage="<%[ Please enter Client ID. ]%>"
+ ControlCssClass="field_invalid"
+ Display="Dynamic"
+ >
+ </com:TRequiredFieldValidator>
+ <com:TRegularExpressionValidator
+ ValidationGroup="OAuth2ClientGroup"
+ ControlToValidate="OAuth2ClientClientId"
+ ControlCssClass="field_invalid"
+ RegularExpression="<%=OAuth2::CLIENT_ID_PATTERN%>"
+ ErrorMessage="<%[ Invalid Client ID value. Client ID may contain a-z A-Z 0-9 - _ characters. ]%>"
+ Display="Dynamic"
+ />
+ <a id="oauth2_client_generate_client_id_link" href="javascript:void(0)" onclick="document.getElementById('<%=$this->OAuth2ClientClientId->ClientID%>').value = get_random_string('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', 32);" style="display: none"><%[ generate ]%></a>
+ </div> <i class="fa fa-asterisk w3-text-red opt_req"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientClientSecret" Text="<%[ OAuth2 Client Secret: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveTextBox
+ ID="OAuth2ClientClientSecret"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ MaxLength="50"
+ />
+ <com:TRequiredFieldValidator
+ ValidationGroup="OAuth2ClientGroup"
+ ControlToValidate="OAuth2ClientClientSecret"
+ ErrorMessage="<%[ Please enter Client Secret. ]%>"
+ ControlCssClass="field_invalid"
+ Display="Dynamic"
+ />
+ <com:TRegularExpressionValidator
+ ValidationGroup="OAuth2ClientGroup"
+ ControlToValidate="OAuth2ClientClientSecret"
+ ControlCssClass="field_invalid"
+ RegularExpression="<%=OAuth2::CLIENT_SECRET_PATTERN%>"
+ ErrorMessage="<%[ Invalid Client Secret value. Client Secret may contain any character that is not a whitespace character. ]%>"
+ Display="Dynamic"
+ />
+ <a href="javascript:void(0)" onclick="document.getElementById('<%=$this->OAuth2ClientClientSecret->ClientID%>').value = get_random_string('ABCDEFabcdef0123456789', 40); return false;"><%[ generate ]%></a>
+ </div> <i class="fa fa-asterisk w3-text-red opt_req"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientRedirectURI" Text="<%[ OAuth2 Redirect URI (example: https://baculumgui:9095/web/redirect): ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveTextBox
+ ID="OAuth2ClientRedirectURI"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ />
+ <com:TRequiredFieldValidator
+ ValidationGroup="OAuth2ClientGroup"
+ ControlToValidate="OAuth2ClientRedirectURI"
+ ControlCssClass="field_invalid"
+ ErrorMessage="<%[ Please enter Redirect URI. ]%>"
+ Display="Dynamic"
+ />
+ </div> <i class="fa fa-asterisk w3-text-red opt_req"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientScope" Text="<%[ OAuth2 scopes (space separated): ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveTextBox
+ ID="OAuth2ClientScope"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ TextMode="MultiLine"
+ />
+ <a href="javascript:void(0)" onclick="set_scopes('<%=$this->OAuth2ClientScope->ClientID%>');" style="vertical-align: top"><%[ set all scopes ]%></a>
+ <com:TRequiredFieldValidator
+ ValidationGroup="OAuth2ClientGroup"
+ ControlToValidate="OAuth2ClientScope"
+ ControlCssClass="field_invalid"
+ ErrorMessage="<%[ Please enter OAuth2 scopes. ]%>"
+ Display="Dynamic"
+ />
+ </div> <i class="fa fa-asterisk w3-text-red opt_req"></i>
+ </div>
+ <div class="w3-row w3-section" id="oauth2_client_bconsole_create">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientBconsoleCreate" Text="<%[ Create dedicated Bconsole config file: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveCheckBox
+ ID="OAuth2ClientBconsoleCreate"
+ CssClass="w3-check"
+ CausesValidation="false"
+ Attributes.onclick="$('#oauth2_client_console').slideToggle('fast');$('#oauth2_client_bconsole_cfg').slideToggle('fast');"
+ AutoPostBack="false"
+ />
+ </div>
+ </div>
+ <div id="oauth2_client_console" style="display: none">
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientConsole" Text="<%[ Console ACL to use in new Bconsole config file: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveDropDownList
+ ID="OAuth2ClientConsole"
+ CssClass="w3-select w3-border"
+ CausesValidation="false"
+ AutoPostBack="false"
+ />
+ </div>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientDirector" Text="<%[ Director for Bconsole config: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveDropDownList
+ ID="OAuth2ClientDirector"
+ CssClass="w3-select w3-border"
+ CausesValidation="false"
+ AutoPostBack="false"
+ />
+ </div>
+ </div>
+ </div>
+ <div class="w3-row w3-section" id="oauth2_client_bconsole_cfg">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientBconsoleCfgPath" Text="<%[ Dedicated Bconsole config file path: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveTextBox
+ ID="OAuth2ClientBconsoleCfgPath"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ />
+ </div>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="OAuth2ClientName" Text="<%[ Short name: ]%>" /></div>
+ <div class="w3-half">
+ <com:TActiveTextBox
+ ID="OAuth2ClientName"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ />
+ </div>
+ </div>
+ </div>
+ <footer class="w3-container w3-center">
+ <button type="button" class="w3-button w3-red" onclick="document.getElementById('oauth2_client_window').style.display = 'none';"><i class="fas fa-times"></i> <%[ Cancel ]%></button>
+ <com:TActiveLinkButton
+ ID="OAuth2ClientSave"
+ ValidationGroup="OAuth2ClientGroup"
+ CausesValidation="true"
+ OnCallback="saveOAuth2Client"
+ CssClass="w3-button w3-section w3-teal w3-padding"
+ >
+ <i class="fa fa-save"></i> <%[ Save ]%>
+ </com:TActiveLinkButton>
+ <div id="oauth2_client_error" class="w3-red" style="display: none"></div>
+ </footer>
+ </div>
+ <com:TActiveHiddenField ID="OAuth2ClientWindowType" />
+ </div>
+ <div class="w3-container tab_item" id="api_host_list" style="display: none">
+ <p class="w3-hide-small"><%[ The API hosts define connection parameters to hosts with the Baculum API instances. You can create the API host connections dedicated for specific users by assigning API hosts to them on the Users tab. There is possible to create many API host connections to the same Baculum API instance. ]%></p>
+ <div class="w3-panel">
+ <button type="button" id="add_api_host_btn" class="w3-button w3-green" onclick="oAPIHosts.load_api_host_window()"><i class="fa fa-plus"></i> <%[ Add new API host ]%></a>
+ </div>
+ <table id="api_host_list_table" class="w3-table w3-striped w3-hoverable w3-white w3-margin-bottom selectable" style="width: 100%">
+ <thead>
+ <tr>
+ <th></th>
+ <th><%[ Short name ]%></th>
+ <th class="w3-center">Protocol</th>
+ <th class="w3-center">IP address/hostname</th>
+ <th class="w3-center">Port</th>
+ <th class="w3-center">Access method</th>
+ <th class="w3-center"><%[ Action ]%></th>
+ </tr>
+ </thead>
+ <tbody id="api_host_list_body"></tbody>
+ <tfoot>
+ <tr>
+ <th></th>
+ <th><%[ Short name ]%></th>
+ <th class="w3-center">Protocol</th>
+ <th class="w3-center">IP address/hostname</th>
+ <th class="w3-center">Port</th>
+ <th class="w3-center">Access method</th>
+ <th class="w3-center"><%[ Action ]%></th>
+ </tr>
+ </tfoot>
+ </table>
+ <p class="info w3-hide-medium w3-hide-small"><%[ Tip: Use left-click to select table row. Use CTRL + left-click to multiple row selection. Use SHIFT + left-click to add a range of rows to selection. ]%></p>
+<com:TCallback ID="APIHostList" OnCallback="TemplateControl.setAPIHostList" />
+<com:TCallback ID="LoadAPIHost" OnCallback="TemplateControl.loadAPIHostWindow" />
+<com:TCallback ID="RemoveAPIHostsAction" OnCallback="TemplateControl.removeAPIHosts" />
+<script>
+var oAPIHostList = {
+ ids: {
+ api_host_list: 'api_host_list_table'
+ },
+ actions: [
+ {
+ action: 'remove',
+ label: '<%[ Remove ]%>',
+ value: 'name',
+ callback: <%=$this->RemoveAPIHostsAction->ActiveControl->Javascript%>
+ }
+ ],
+ data: [],
+ table: null,
+ table_toolbar: null,
+ init: function() {
+ if (!this.table) {
+ this.set_table();
+ this.set_bulk_actions();
+ this.set_events();
+ } else {
+ var page = this.table.page();
+ this.table.clear().rows.add(this.data).draw();
+ this.table.page(page).draw(false);
+ oAPIHostList.set_filters(this.table);
+ this.table_toolbar.style.display = 'none';
+ }
+ },
+ set_events: function() {
+ document.getElementById(this.ids.api_host_list).addEventListener('click', function(e) {
+ $(function() {
+ this.table_toolbar.style.display = this.table.rows({selected: true}).data().length > 0 ? '' : 'none';
+ }.bind(this));
+ }.bind(this));
+ },
+ set_table: function() {
+ this.table = $('#' + this.ids.api_host_list).DataTable({
+ data: this.data,
+ deferRender: true,
+ dom: 'lB<"table_toolbar">frtip',
+ stateSave: true,
+ buttons: [
+ 'copy', 'csv', 'colvis'
+ ],
+ columns: [
+ {
+ className: 'details-control',
+ orderable: false,
+ data: null,
+ defaultContent: '<button type="button" class="w3-button w3-blue"><i class="fa fa-angle-down"></i></button>'
+ },
+ {data: 'name'},
+ {data: 'protocol'},
+ {data: 'address'},
+ {data: 'port'},
+ {
+ data: 'auth_type',
+ render: function (data, type, row) {
+ var at = data;
+ if (at == 'basic') {
+ at = 'Basic';
+ } else if (at == 'oauth2') {
+ at = 'OAuth2';
+ }
+ return at;
+ }
+ },
+ {
+ data: 'name',
+ render: function (data, type, row) {
+ var btn_edit = document.createElement('BUTTON');
+ btn_edit.className = 'w3-button w3-green';
+ btn_edit.type = 'button';
+ var i_edit = document.createElement('I');
+ i_edit.className = 'fa fa-list-ul';
+ var label_edit = document.createTextNode(' <%[ Edit ]%>');
+ btn_edit.appendChild(i_edit);
+ btn_edit.innerHTML += ' ';
+ btn_edit.style.marginRight = '8px';
+ btn_edit.appendChild(label_edit);
+ btn_edit.setAttribute('onclick', 'oAPIHosts.load_api_host_window(\'' + data + '\')');
+ return btn_edit.outerHTML;
+ }
+ }
+ ],
+ responsive: {
+ details: {
+ type: 'column'
+ }
+ },
+ columnDefs: [{
+ className: 'control',
+ orderable: false,
+ targets: 0
+ },
+ {
+ className: 'action_col',
+ orderable: false,
+ targets: [ 6 ]
+ },
+ {
+ className: "dt-center",
+ targets: [ 2, 3, 4, 5 ]
+ }],
+ select: {
+ style: 'os',
+ selector: 'td:not(:last-child):not(:first-child)',
+ blurable: false
+ },
+ order: [1, 'asc'],
+ initComplete: function () {
+ oAPIHostList.set_filters(this.api());
+ }
+ });
+ },
+ set_filters: function(api) {
+ api.columns([2, 3, 4, 5]).every(function () {
+ var column = this;
+ var select = $('<select><option value=""></option></select>')
+ .appendTo($(column.footer()).empty())
+ .on('change', function () {
+ var val = dtEscapeRegex(
+ $(this).val()
+ );
+ column
+ .search(val ? '^' + val + '$' : '', true, false)
+ .draw();
+ });
+ column.cells('', column[0]).render('display').unique().sort().each(function(d, j) {
+ if (column.search() == '^' + dtEscapeRegex(d) + '$') {
+ select.append('<option value="' + d + '" selected>' + d + '</option>');
+ } else if(d) {
+ select.append('<option value="' + d + '">' + d + '</option>');
+ }
+ });
+ });
+ },
+ set_bulk_actions: function() {
+ this.table_toolbar = get_table_toolbar(this.table, this.actions, {
+ actions: '<%[ Actions ]%>',
+ ok: '<%[ OK ]%>'
+ });
+ }
+};
+
+var oAPIHosts = {
+ load_api_host_window: function(name) {
+ var title_add = document.getElementById('api_host_window_title_add');
+ var title_edit = document.getElementById('api_host_window_title_edit');
+ var api_host_win_type = document.getElementById('<%=$this->APIHostWindowType->ClientID%>');
+ var host_name = document.getElementById('<%=$this->APIHostName->ClientID%>');
+ // callback is sent both for new and edit api_host because there is realized
+ // checking if password is allowed to set or not
+ var cb = <%=$this->LoadAPIHost->ActiveControl->Javascript%>;
+ cb.setCallbackParameter(name);
+ cb.dispatch();
+ if (name) {
+ // edit existing api_host
+ title_add.style.display = 'none';
+ title_edit.style.display = 'inline-block';
+ api_host_win_type.value = 'edit';
+ host_name.setAttribute('readonly', '');
+ } else {
+ // add new api_host
+ title_add.style.display = 'inline-block';
+ title_edit.style.display = 'none';
+ api_host_win_type.value = 'add';
+ host_name.removeAttribute('readonly');
+ this.clear_api_host_window();
+ }
+ document.getElementById('api_host_window').style.display = 'block';
+ },
+ load_api_host_list: function() {
+ var cb = <%=$this->APIHostList->ActiveControl->Javascript%>;
+ cb.dispatch();
+ },
+ load_api_host_list_cb: function(list) {
+ oAPIHostList.data = list;
+ oAPIHostList.init();
+ },
+ clear_api_host_window: function() {
+ [
+ '<%=$this->APIHostAddress->ClientID%>',
+ '<%=$this->APIHostPort->ClientID%>',
+ '<%=$this->APIHostOAuth2ClientId->ClientID%>',
+ '<%=$this->APIHostOAuth2ClientSecret->ClientID%>',
+ '<%=$this->APIHostOAuth2RedirectURI->ClientID%>',
+ '<%=$this->APIHostOAuth2Scope->ClientID%>',
+ '<%=$this->APIHostName->ClientID%>',
+ '<%=$this->APIHostBasicLogin->ClientID%>',
+ '<%=$this->APIHostBasicPassword->ClientID%>'
+
+ ].forEach(function(id) {
+ document.getElementById(id).value = '';
+ });
+
+ document.getElementById('<%=$this->APIHostProtocol->ClientID%>').value = 'https';
+
+ [
+ '<%=$this->APIHostTestResultOk->ClientID%>',
+ '<%=$this->APIHostTestResultErr->ClientID%>',
+ '<%=$this->APIHostCatalogSupportYes->ClientID%>',
+ '<%=$this->APIHostCatalogSupportNo->ClientID%>',
+ '<%=$this->APIHostConsoleSupportYes->ClientID%>',
+ '<%=$this->APIHostConsoleSupportNo->ClientID%>',
+ '<%=$this->APIHostConfigSupportYes->ClientID%>',
+ '<%=$this->APIHostConfigSupportNo->ClientID%>',
+ '<%=$this->APIHostTestLoader->ClientID%>'
+ ].forEach(function(id) {
+ document.getElementById(id).style.display= 'none';
+ });
+ },
+ save_api_host_cb: function() {
+ document.getElementById('api_host_window').style.display = 'none';
+ }
+}
+
+$(function() {
+ oAPIHosts.load_api_host_list();
+});
+ </script>
+ </div>
+ <div id="api_host_window" class="w3-modal">
+ <div class="w3-modal-content w3-animate-top w3-card-4">
+ <header class="w3-container w3-teal">
+ <span onclick="document.getElementById('api_host_window').style.display = 'none';" class="w3-button w3-display-topright">×</span>
+ <h2 id="api_host_window_title_add" style="display: none"><%[ Add API host ]%></h2>
+ <h2 id="api_host_window_title_edit" style="display: none"><%[ Edit API host ]%></h2>
+ </header>
+ <div class="w3-container w3-margin-left w3-margin-right w3-margin-top w3-text-teal">
+ <div id="api_host_settings">
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostSettings" Text="<%[ Get existing API host settings: ]%>" /></div>
+ <div class="w3-col w3-third">
+ <com:TActiveDropDownList
+ ID="APIHostSettings"
+ CssClass="w3-select w3-border"
+ CausesValidation="false"
+ OnCallback="loadAPIHostSettings"
+ >
+ <prop:ClientSide.OnLoading>
+ document.getElementById('api_host_settings_loading').style.visibility = 'visible';
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ document.getElementById('api_host_settings_loading').style.visibility = 'hidden';
+ </prop:ClientSide.OnComplete>
+ </com:TActiveDropDownList>
+ </div> <i id="api_host_settings_loading" class="fas fa-sync w3-spin w3-text-black" style="visibility: hidden; margin: 10px 5px"></i>
+ </div>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostProtocol" Text="<%[ Protocol: ]%>" /></div>
+ <div class="w3-col w3-third">
+ <com:TActiveDropDownList ID="APIHostProtocol" CssClass="w3-select w3-border" Width="150px" CausesValidation="false">
+ <com:TListItem Value="http" Text="HTTP" />
+ <com:TListItem Value="https" Text="HTTPS" Selected="true"/>
+ </com:TActiveDropDownList> <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostAddress" Text="<%[ IP Address/Hostname: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox ID="APIHostAddress" CssClass="w3-input w3-border" CausesValidation="false" />
+ <com:TRequiredFieldValidator ValidationGroup="APIHostGroup" CssClass="validator-block" Display="Dynamic" ControlCssClass="invalidate" ControlToValidate="APIHostAddress" Text="<%[ Please enter API address. ]%>" />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostPort" Text="<%[ Port: ]%>" /></div>
+ <div class="w3-col w3-third">
+ <com:TActiveTextBox ID="APIHostPort" CssClass="w3-input w3-border" CausesValidation="false" Text="9096" Width="70px" Style="display: inline-block" />
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ <com:TRequiredFieldValidator ValidationGroup="APIHostGroup" CssClass="validator-block" Display="Dynamic" ControlCssClass="invalidate" ControlToValidate="APIHostPort" Text="<%[ Please enter API port. ]%>" />
+ </div>
+ </div>
+ <div class="auth_setting">
+ <div class="w3-row w3-section">
+ <com:TActiveRadioButton
+ ID="APIHostAuthOAuth2"
+ GroupName="SelectAuth"
+ CssClass="w3-radio"
+ Attributes.onclick="$('#configure_basic_auth').hide();$('#configure_oauth2_auth').show();"
+ />
+ <com:TLabel
+ ForControl="APIHostAuthOAuth2"
+ CssClass="normal w3-radio"
+ Style="vertical-align: super"
+ Text="<%[ Use OAuth2 for authorization and authentication ]%>"
+ />
+ </div>
+ <div class="w3-row w3-section">
+ <com:TActiveRadioButton
+ ID="APIHostAuthBasic"
+ GroupName="SelectAuth"
+ Checked="true"
+ CssClass="w3-radio"
+ Attributes.onclick="$('#configure_oauth2_auth').hide();$('#configure_basic_auth').show();"
+ />
+ <com:TLabel
+ ForControl="APIHostAuthBasic"
+ CssClass="normal w3-radio"
+ Style="vertical-align: super"
+ Text="<%[ Use HTTP Basic authentication ]%>"
+ />
+ </div>
+ </div>
+ <div id="configure_basic_auth" style="display: <%=($this->APIHostAuthBasic->Checked === true) ? '' : 'none';%>">
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostBasicLogin" Text="<%[ API Login: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostBasicLogin"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ />
+ <com:TRequiredFieldValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostBasicLogin"
+ ValidationGroup="APIHostBasic"
+ Text="<%[ Please enter API login. ]%>"
+ />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostBasicPassword" Text="<%[ API Password: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostBasicPassword"
+ TextMode="Password"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ PersistPassword="true"
+ />
+ <com:TRequiredFieldValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostBasicPassword"
+ ValidationGroup="APIHostBasic"
+ Text="<%[ Please enter API password. ]%>"
+ />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ </div>
+ <div id="configure_oauth2_auth" style="display: <%=($this->APIHostAuthOAuth2->Checked === true) ? '' : 'none';%>">
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostOAuth2ClientSettings" Text="<%[ Get existing OAuth2 client settings: ]%>" /></div>
+ <div class="w3-col w3-third">
+ <com:TActiveDropDownList
+ ID="APIHostOAuth2ClientSettings"
+ CssClass="w3-select w3-border"
+ CausesValidation="false"
+ OnCallback="loadOAuth2ClientSettings"
+ >
+ <prop:ClientSide.OnLoading>
+ document.getElementById('api_host_oauth2_client_settings_loading').style.visibility = 'visible';
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ document.getElementById('api_host_oauth2_client_settings_loading').style.visibility = 'hidden';
+ </prop:ClientSide.OnComplete>
+ </com:TActiveDropDownList>
+ </div> <i id="api_host_oauth2_client_settings_loading" class="fas fa-sync w3-spin w3-text-black" style="visibility: hidden; margin: 10px 5px"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostOAuth2ClientId" Text="<%[ OAuth2 Client ID: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostOAuth2ClientId"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ MaxLength="32"
+ />
+ <com:TRequiredFieldValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostOAuth2ClientId"
+ ValidationGroup="APIHostOAuth2"
+ Text="<%[ Please enter Client ID. ]%>"
+ />
+ <com:TRegularExpressionValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostOAuth2ClientId"
+ RegularExpression="<%=OAuth2::CLIENT_ID_PATTERN%>"
+ ValidationGroup="APIHostOAuth2"
+ Text="<%[ Invalid Client ID value. Client ID may contain a-z A-Z 0-9 - _ characters. ]%>"
+ />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostOAuth2ClientSecret" Text="<%[ OAuth2 Client Secret: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostOAuth2ClientSecret"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ MaxLength="50"
+ />
+ <com:TRequiredFieldValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostOAuth2ClientSecret"
+ ValidationGroup="APIHostOAuth2"
+ Text="<%[ Please enter Client Secret. ]%>"
+ />
+ <com:TRegularExpressionValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostOAuth2ClientSecret"
+ RegularExpression="<%=OAuth2::CLIENT_SECRET_PATTERN%>"
+ ValidationGroup="APIHostOAuth2"
+ Text="<%[ Invalid Client Secret value. Client Secret may contain any character that is not a whitespace character. ]%>"
+ />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostOAuth2RedirectURI" Text="<%[ OAuth2 Redirect URI (example: https://baculumgui:9095/web/redirect): ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostOAuth2RedirectURI"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ />
+ <com:TRequiredFieldValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostOAuth2RedirectURI"
+ ValidationGroup="APIHostOAuth2"
+ Text="<%[ Please enter Redirect URI. ]%>"
+ />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostOAuth2Scope" Text="<%[ OAuth2 scopes (space separated): ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostOAuth2Scope"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ TextMode="MultiLine"
+ />
+ <com:TRequiredFieldValidator
+ CssClass="validator-block"
+ Display="Dynamic"
+ ControlCssClass="invalidate"
+ ControlToValidate="APIHostOAuth2Scope"
+ ValidationGroup="APIHostOAuth2"
+ Text="<%[ Please enter OAuth2 scopes. ]%>"
+ />
+ </div>
+ <i class="fa fa-asterisk w3-text-red" style="line-height: 40px"></i>
+ </div>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostConnectionTest" Text="<%[ API connection test: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <table border="0" cellpadding="1px" id="new_host_status">
+ <tr>
+ <td align="center" valign="middle">
+ <com:TActiveLinkButton ID="APIHostConnectionTest" CausesValidation="true" OnCallback="connectionAPITest" CssClass="w3-button w3-green">
+ <prop:ClientSide.OnLoading>
+ $('#<%=$this->APIHostTestResultOk->ClientID%>').hide();
+ $('#<%=$this->APIHostTestResultErr->ClientID%>').hide();
+ $('#<%=$this->APIHostCatalogSupportYes->ClientID%>').hide();
+ $('#<%=$this->APIHostCatalogSupportNo->ClientID%>').hide();
+ $('#<%=$this->APIHostConsoleSupportYes->ClientID%>').hide();
+ $('#<%=$this->APIHostConsoleSupportNo->ClientID%>').hide();
+ $('#<%=$this->APIHostConfigSupportYes->ClientID%>').hide();
+ $('#<%=$this->APIHostConfigSupportNo->ClientID%>').hide();
+ $('#<%=$this->APIHostTestLoader->ClientID%>').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#<%=$this->APIHostTestLoader->ClientID%>').hide();
+ </prop:ClientSide.OnComplete>
+ <i class="fa fa-play"></i> <%[ test ]%>
+ </com:TActiveLinkButton>
+ </td>
+ <td valign="middle">
+ <com:TActiveLabel ID="APIHostTestLoader" Display="None"><i class="fa fa-sync w3-spin w3-text-black"></i></com:TActiveLabel>
+ <com:TActiveLabel ID="APIHostTestResultOk" Display="None" CssClass="w3-text-green" EnableViewState="false"><i class="fa fa-check"></i> <%[ OK ]%></com:TActiveLabel>
+ <com:TActiveLabel ID="APIHostTestResultErr" Display="None" CssClass="w3-text-red" EnableViewState="false"><i class="fa fa-times"></i> <%[ Connection error ]%></com:TActiveLabel>
+ </td>
+ </tr>
+ <tr>
+ <td><%[ Catalog support ]%></td>
+ <td>
+ <com:TActiveLabel ID="APIHostCatalogSupportYes" Display="None" CssClass="w3-text-green" EnableViewState="false"><i class="fa fa-check"></i> <strong><%[ Supported ]%></strong></com:TActiveLabel>
+ <com:TActiveLabel ID="APIHostCatalogSupportNo" Display="None" CssClass="w3-text-dark-grey" EnableViewState="false"><i class="fa fa-times"></i> <strong><%[ Not supported ]%></strong></com:TActiveLabel>
+ </td>
+ </tr>
+ <tr>
+ <td><%[ Console support ]%></td>
+ <td>
+ <com:TActiveLabel ID="APIHostConsoleSupportYes" Display="None" CssClass="w3-text-green" EnableViewState="false"><i class="fa fa-check"></i> <strong><%[ Supported ]%></strong></com:TActiveLabel>
+ <com:TActiveLabel ID="APIHostConsoleSupportNo" Display="None" CssClass="w3-text-dark-grey" EnableViewState="false"><i class="fa fa-times"></i> <strong><%[ Not supported ]%></strong></com:TActiveLabel>
+ </td>
+ </tr>
+ <tr>
+ <td><%[ Config support ]%></td>
+ <td>
+ <com:TActiveLabel ID="APIHostConfigSupportYes" Display="None" CssClass="w3-text-green" EnableViewState="false"><i class="fa fa-check"></i> <strong><%[ Supported ]%></strong></com:TActiveLabel>
+ <com:TActiveLabel ID="APIHostConfigSupportNo" Display="None" CssClass="w3-text-dark-grey" EnableViewState="false"><i class="fa fa-times"></i> <strong><%[ Not supported ]%></strong></com:TActiveLabel>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <div class="w3-row w3-section">
+ <div class="w3-col w3-third"><com:TLabel ForControl="APIHostName" Text="<%[ Short name: ]%>" /></div>
+ <div class="w3-col w3-half">
+ <com:TActiveTextBox
+ ID="APIHostName"
+ CssClass="w3-input w3-border"
+ CausesValidation="false"
+ />
+ </div>
+ </div>
+ </div>
+ <footer class="w3-container w3-center">
+ <button type="button" class="w3-button w3-red" onclick="document.getElementById('api_host_window').style.display = 'none';"><i class="fas fa-times"></i> <%[ Cancel ]%></button>
+ <com:TActiveLinkButton
+ ID="APIHostSave"
+ ValidationGroup="APIHostGroup"
+ CausesValidation="true"
+ OnCallback="saveAPIHost"
+ CssClass="w3-button w3-section w3-teal w3-padding"
+ Attributes.onclick="return fields_validation()"
+ >
+ <i class="fa fa-save"></i> <%[ Save ]%>
+ </com:TActiveLinkButton>
+ </footer>
+ </div>
+<script type="text/javascript">
+ var fields_validation = function() {
+ var basic = document.getElementById('<%=$this->APIHostAuthBasic->ClientID%>');
+ var oauth2 = document.getElementById('<%=$this->APIHostAuthOAuth2->ClientID%>');
+ var validation_group;
+ if (basic.checked === true) {
+ validation_group = 'APIHostBasic';
+ } else if (oauth2.checked === true) {
+ validation_group = 'APIHostOAuth2';
+ }
+ return Prado.Validation.validate(Prado.Validation.getForm(), validation_group);
+ }
+</script>
+ <com:TActiveHiddenField ID="APIHostWindowType" />
+ </div>
</com:TContent>
Prado::using('System.Web.UI.ActiveControls.TActiveLabel');
Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton');
Prado::using('System.Web.UI.ActiveControls.TActiveListBox');
+Prado::using('System.Web.UI.ActiveControls.TActiveRadioButton');
Prado::using('System.Web.UI.ActiveControls.TActiveTextBox');
Prado::using('System.Web.UI.ActiveControls.TCallback');
Prado::using('System.Web.UI.WebControls.TCheckBox');
Prado::using('System.Web.UI.WebControls.TValidationSummary');
Prado::using('Application.Common.Class.Crypto');
Prado::using('Application.Common.Class.Ldap');
+Prado::using('Application.Common.Class.OAuth2');
Prado::using('Application.Web.Class.BaculumWebPage');
+Prado::using('Application.Web.Portlets.BaculaConfigResources');
/**
* Security page (auth methods, users, roles...).
*/
private $user_config = [];
+ /**
+ * Store console ACL config.
+ */
+ private $console_config = [];
+
/**
* Initialize page.
*
return (($is_basic && $allow_manage_users) || $is_local);
}
+ /**
+ * Set and load console ACL list.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter callback parameter
+ * @return none
+ */
+ public function setConsoleList($sender, $param) {
+ $config = $this->getModule('api')->get(['config', 'dir', 'Console']);
+ $console_directives = [
+ 'Description' => '',
+ 'JobAcl' => '',
+ 'ClientAcl' => '',
+ 'StorageAcl' => '',
+ 'ScheduleAcl' => '',
+ 'RunAcl' => '',
+ 'PoolAcl' => '',
+ 'CommandAcl' => '',
+ 'FilesetAcl' => '',
+ 'CatalogAcl' => '',
+ 'WhereAcl' => '',
+ 'PluginOptionsAcl' => '',
+ 'BackupClientAcl' => '',
+ 'RestoreClientAcl' => '',
+ 'DirectoryAcl' => ''
+ ];
+ $consoles = [];
+ function join_cons($item) {
+ if (is_array($item)) {
+ $item = implode(',', $item);
+ }
+ return $item;
+ }
+ if ($config->error == 0) {
+ for ($i = 0; $i < count($config->output); $i++) {
+ $cons = (array)$config->output[$i]->Console;
+ $cons = array_map('join_cons', $cons);
+ $consoles[] = array_merge($console_directives, $cons);
+ }
+ }
+ $this->getCallbackClient()->callClientFunction('oConsoles.load_console_list_cb', [
+ $consoles
+ ]);
+ $this->console_config = $consoles;
+ }
+
+ /**
+ * Load data in console modal window.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function loadConsoleWindow($sender, $param) {
+ $name = $param->getCallbackParameter();
+ if (!empty($name)) {
+ // edit existing console
+ $this->ConsoleConfig->setResourceName($name);
+ $this->ConsoleConfig->setLoadValues(true);
+ } else {
+ // add new console
+ $this->ConsoleConfig->setLoadValues(false);
+ $this->getCallbackClient()->callClientFunction('oBaculaConfigSection.show_sections', [true]);
+ }
+ $this->ConsoleConfig->setHost($this->User->getAPIHosts());
+ $this->ConsoleConfig->setComponentName($_SESSION['dir']);
+ $this->ConsoleConfig->raiseEvent('OnDirectiveListLoad', $this, null);
+ }
+
+ /**
+ * Remove consoles action.
+ * Here is possible to remove one console or many.
+ * This action is linked with table bulk actions.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function removeConsoles($sender, $param) {
+ $consoles = explode('|', $param->getCallbackParameter());
+ $res = new BaculaConfigResources();
+ $config = $res->getConfigData($this->User->getAPIHosts(), 'dir');
+ for ($i = 0; $i < count($consoles); $i++) {
+ $res->removeResourceFromConfig(
+ $config,
+ 'Console',
+ $consoles[$i]
+ );
+ }
+ $this->getModule('api')->set(
+ array('config', 'dir'),
+ array('config' => json_encode($config)),
+ $this->User->getAPIHosts(),
+ false
+ );
+
+ // refresh console list
+ $this->setConsoleList(null, null);
+
+ // refresh OAuth2 client console combobox
+ $this->loadOAuth2ClientConsole(null, null);
+ }
+
+ public function setAllCommandAcls($sender, $param) {
+ $config = (object)[
+ "CommandAcl" => [
+ 'gui',
+ '.api',
+ '.jobs',
+ '.ls',
+ '.client',
+ '.fileset',
+ '.pool',
+ '.status',
+ '.storage',
+ '.bvfs_get_jobids',
+ '.bvfs_update',
+ '.bvfs_lsdirs',
+ '.bvfs_lsfiles',
+ '.bvfs_versions',
+ '.bvfs_restore',
+ '.bvfs_cleanup',
+ 'restore',
+ 'show',
+ 'estimate',
+ 'run',
+ 'delete',
+ 'cancel'
+ ]
+ ];
+ $this->ConsoleConfig->setData($config);
+ $this->ConsoleConfig->raiseEvent('OnDirectiveListLoad', $this, null);
+ $this->getCallbackClient()->callClientFunction('oBaculaConfigSection.show_sections', [true]);
+ }
+
+ /**
+ * Set and load OAuth2 client list.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter callback parameter
+ * @return none
+ */
+ public function setOAuth2ClientList($sender, $param) {
+ $oauth2_clients = $this->getModule('api')->get(['oauth2', 'clients']);
+ $this->getCallbackClient()->callClientFunction('oOAuth2Clients.load_oauth2_client_list_cb', [
+ $oauth2_clients->output,
+ $oauth2_clients->error
+ ]);
+ }
+
+ public function loadOAuth2ClientConsole($sender, $param) {
+ $cons = $this->getModule('api')->get(['config', 'dir', 'Console']);
+ $console = ['' => ''];
+ if ($cons->error == 0) {
+ for ($i = 0; $i < count($cons->output); $i++) {
+ $console[$cons->output[$i]->Console->Name] = $cons->output[$i]->Console->Name;
+ }
+ }
+ $this->OAuth2ClientConsole->DataSource = $console;
+ $this->OAuth2ClientConsole->dataBind();
+ }
+
+ /**
+ * Load data in OAuth2 client modal window.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function loadOAuth2ClientWindow($sender, $param) {
+ $client_id = $param->getCallbackParameter();
+ if (!empty($client_id)) {
+ $oauth2_cfg = $this->getModule('api')->get(['oauth2', 'clients', $client_id]);
+ if ($oauth2_cfg->error === 0 && is_object($oauth2_cfg->output)) {
+ // It is done only for existing OAuth2 client accounts
+ $this->OAuth2ClientClientId->Text = $oauth2_cfg->output->client_id;
+ $this->OAuth2ClientClientSecret->Text = $oauth2_cfg->output->client_secret;
+ $this->OAuth2ClientRedirectURI->Text = $oauth2_cfg->output->redirect_uri;
+ $this->OAuth2ClientScope->Text = $oauth2_cfg->output->scope;
+ $this->OAuth2ClientBconsoleCfgPath->Text = $oauth2_cfg->output->bconsole_cfg_path;
+ $this->OAuth2ClientName->Text = $oauth2_cfg->output->name;
+ }
+ }
+ $this->loadOAuth2ClientConsole(null, null);
+
+ $dirs = $this->getModule('api')->get(['config', 'bcons', 'Director']);
+ $dir_names = [];
+ if ($dirs->error == 0) {
+ for ($i = 0; $i < count($dirs->output); $i++) {
+ $dir_names[$dirs->output[$i]->Director->Name] = $dirs->output[$i]->Director->Name;
+ }
+ }
+ $this->OAuth2ClientDirector->DataSource = $dir_names;
+ $this->OAuth2ClientDirector->dataBind();
+ }
+
+ /**
+ * Save OAuth2 client.
+ * It works both for new OAuth2 client and for edited OAuth2 client.
+ * Saves values from modal popup.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function saveOAuth2Client($sender, $param) {
+ $client_id = $this->OAuth2ClientClientId->Text;
+ $cfg = [];
+ $cfg['client_id'] = $client_id;
+ $cfg['client_secret'] = $this->OAuth2ClientClientSecret->Text;
+ $cfg['redirect_uri'] = $this->OAuth2ClientRedirectURI->Text;
+ $cfg['scope'] = $this->OAuth2ClientScope->Text;
+ $cfg['bconsole_cfg_path'] = $this->OAuth2ClientBconsoleCfgPath->Text;
+ if ($this->OAuth2ClientBconsoleCreate->Checked) {
+ $cfg['console'] = $this->OAuth2ClientConsole->SelectedValue;
+ $cfg['director'] = $this->OAuth2ClientDirector->SelectedValue;
+ }
+ $cfg['name'] = $this->OAuth2ClientName->Text;
+
+ $win_type = $this->OAuth2ClientWindowType->Value;
+ $result = (object)['error' => -1];
+ if ($win_type === self::TYPE_ADD_WINDOW) {
+ $result = $this->getModule('api')->create(['oauth2', 'clients', $client_id], $cfg);
+ } elseif ($win_type === self::TYPE_EDIT_WINDOW) {
+ $result = $this->getModule('api')->set(['oauth2', 'clients', $client_id], $cfg);
+ }
+
+ if ($result->error === 0) {
+ // Refresh OAuth2 client list
+ $this->setOAuth2ClientList(null, null);
+ }
+ $this->getCallbackClient()->callClientFunction('oOAuth2Clients.save_oauth2_client_cb', [
+ $result
+ ]);
+ }
+
+ /**
+ * Remove OAuth2 client action.
+ * Here is possible to remove one OAuth2 client or many.
+ * This action is linked with table bulk actions.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function removeOAuth2Clients($sender, $param) {
+ $client_ids = explode('|', $param->getCallbackParameter());
+ for ($i = 0; $i < count($client_ids); $i++) {
+ $result = $this->getModule('api')->remove(['oauth2', 'clients', $client_ids[$i]]);
+ if ($result->error !== 0) {
+ break;
+ }
+ }
+
+ if (count($client_ids) > 0) {
+ // Refresh OAuth2 client list
+ $this->setOAuth2ClientList(null, null);
+ }
+ }
+
+ /**
+ * Set and load OAuth2 client settings to API host modal window.
+ *
+ * @param TActiveDropDownList $sender sender object
+ * @param TCallbackEventParameter callback parameter
+ * @return none
+ */
+ public function loadOAuth2ClientSettings($sender, $param) {
+ $client_id = $this->APIHostOAuth2ClientSettings->SelectedValue;
+ if (!empty($client_id)) {
+ $host = $this->APIHostSettings->SelectedValue ?: null;
+ $oauth2_cfg = $this->getModule('api')->get(['oauth2', 'clients', $client_id], $host);
+ if ($oauth2_cfg->error === 0 && is_object($oauth2_cfg->output)) {
+ $this->APIHostOAuth2ClientId->Text = $oauth2_cfg->output->client_id;
+ $this->APIHostOAuth2ClientSecret->Text = $oauth2_cfg->output->client_secret;
+ $this->APIHostOAuth2RedirectURI->Text = $oauth2_cfg->output->redirect_uri;
+ $this->APIHostOAuth2Scope->Text = $oauth2_cfg->output->scope;
+ }
+ }
+ }
+
+ /**
+ * Load OAuth2 client list to get OAuth2 client settings.
+ *
+ * @return none
+ */
+ private function loadOAuth2ClientList() {
+ $host = $this->APIHostSettings->SelectedValue ?: null;
+ $oauth2_clients = $this->getModule('api')->get(['oauth2', 'clients'], $host);
+ $oauth2_client_list = ['' => ''];
+ if ($oauth2_clients->error == 0 && is_array($oauth2_clients->output)) {
+ for ($i = 0; $i < count($oauth2_clients->output); $i++) {
+ $name = $oauth2_clients->output[$i]->name ?: $oauth2_clients->output[$i]->client_id;
+ $oauth2_client_list[$oauth2_clients->output[$i]->client_id] = $name;
+ }
+ }
+ $this->APIHostOAuth2ClientSettings->DataSource = $oauth2_client_list;
+ $this->APIHostOAuth2ClientSettings->dataBind();
+ }
+
+ /**
+ * Set and load API hosts list.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter callback parameter
+ * @return none
+ */
+ public function setAPIHostList($sender, $param) {
+ $api_hosts = $this->getModule('host_config')->getConfig();
+ $shortnames = array_keys($api_hosts);
+ $attributes = array_values($api_hosts);
+ for ($i = 0; $i < count($attributes); $i++) {
+ $attributes[$i]['name'] = $shortnames[$i];
+ }
+
+ $this->getCallbackClient()->callClientFunction('oAPIHosts.load_api_host_list_cb', [
+ $attributes
+ ]);
+ }
+
+ /**
+ * Load data in API host modal window.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function loadAPIHostWindow($sender, $param) {
+ $name = $param->getCallbackParameter();
+
+ // prepare API host combobox
+ $api_hosts = $this->getModule('host_config')->getConfig();
+
+ if (!empty($name) && key_exists($name, $api_hosts)) {
+ $this->APIHostAddress->Text = $api_hosts[$name]['address'];
+ $this->APIHostProtocol->SelectedValue = $api_hosts[$name]['protocol'];
+ $this->APIHostPort->Text = $api_hosts[$name]['port'];
+ $this->APIHostOAuth2ClientId->Text = $api_hosts[$name]['client_id'];
+ $this->APIHostOAuth2ClientSecret->Text = $api_hosts[$name]['client_secret'];
+ $this->APIHostOAuth2RedirectURI->Text = $api_hosts[$name]['redirect_uri'];
+ $this->APIHostOAuth2Scope->Text = $api_hosts[$name]['scope'];
+ $this->APIHostName->Text = $name;
+ $this->APIHostBasicLogin->Text = $api_hosts[$name]['login'];
+ $this->APIHostBasicPassword->Text = $api_hosts[$name]['password'];
+ if ($api_hosts[$name]['auth_type'] == 'basic') {
+ $this->APIHostAuthBasic->Checked = true;
+ $this->getCallbackClient()->hide('configure_oauth2_auth');
+ $this->getCallbackClient()->show('configure_basic_auth');
+ } elseif ($api_hosts[$name]['auth_type'] == 'oauth2') {
+ $this->APIHostAuthOAuth2->Checked = true;
+ $this->getCallbackClient()->hide('configure_basic_auth');
+ $this->getCallbackClient()->show('configure_oauth2_auth');
+ }
+ }
+
+ $shortnames = array_keys($api_hosts);
+
+ $api_host_names = array_combine($shortnames, $shortnames);
+ $this->APIHostSettings->DataSource = array_merge(['' => ''], $api_host_names);
+ $this->APIHostSettings->dataBind();
+
+ // prepare OAuth2 client combobox
+ $this->loadOAuth2ClientList();
+ }
+
+ /**
+ * Load API host settings to API host modal window.
+ *
+ * @param TActiveDropDownList $sender sender object
+ * @param TCallbackEventParameter callback parameter
+ * @return none
+ */
+ public function loadAPIHostSettings($sender, $param) {
+ $api_host = $this->APIHostSettings->SelectedValue;
+ if (!empty($api_host)) {
+ $config = $this->getModule('host_config')->getConfig();
+ if (key_exists($api_host, $config)) {
+ // load OAuth2 clients to combobox from selected API host
+ $this->loadOAuth2ClientList();
+
+ $this->APIHostProtocol->SelectedValue = $config[$api_host]['protocol'];
+ $this->APIHostAddress->Text = $config[$api_host]['address'];
+ $this->APIHostPort->Text = $config[$api_host]['port'];
+ if ($config[$api_host]['auth_type'] == 'basic') {
+ $this->APIHostAuthBasic->Checked = true;
+ $this->getCallbackClient()->hide('configure_oauth2_auth');
+ $this->getCallbackClient()->show('configure_basic_auth');
+ } elseif ($config[$api_host]['auth_type'] == 'oauth2') {
+ $this->APIHostAuthOAuth2->Checked = true;
+ $this->getCallbackClient()->hide('configure_basic_auth');
+ $this->getCallbackClient()->show('configure_oauth2_auth');
+ }
+ }
+ }
+ }
+
+ public function connectionAPITest($sender, $param) {
+ $host = $this->APIHostAddress->Text;
+ if (empty($host)) {
+ $host = false;
+ }
+ $host_params = array(
+ 'protocol' => $this->APIHostProtocol->SelectedValue,
+ 'address' => $this->APIHostAddress->Text,
+ 'port' => $this->APIHostPort->Text,
+ 'url_prefix' => ''
+ );
+
+ if ($this->APIHostAuthBasic->Checked) {
+ $host_params['auth_type'] = 'basic';
+ $host_params['login'] = $this->APIHostBasicLogin->Text;
+ $host_params['password'] = $this->APIHostBasicPassword->Text;
+ } elseif ($this->APIHostAuthOAuth2->Checked) {
+ $host_params['auth_type'] = 'oauth2';
+ $host_params['client_id'] = $this->APIHostOAuth2ClientId->Text;
+ $host_params['client_secret'] = $this->APIHostOAuth2ClientSecret->Text;
+ $host_params['redirect_uri'] = $this->APIHostOAuth2RedirectURI->Text;
+ $host_params['scope'] = $this->APIHostOAuth2Scope->Text;
+ }
+ $api = $this->getModule('api');
+
+ // Catalog test
+ OAuth2Record::deleteByPk($host);
+ $api->setHostParams($host, $host_params);
+ $catalog = $api->get(array('catalog'), $host, false);
+
+ // Console test
+ OAuth2Record::deleteByPk($host);
+ $api->setHostParams($host, $host_params);
+ $director = null;
+ if (array_key_exists('director', $_SESSION)) {
+ // Current director can't be passed to new remote host.
+ $director = $_SESSION['director'];
+ unset($_SESSION['director']);
+ }
+
+ $console = $api->set(array('console'), array('version'), $host, false);
+ if (!is_null($director)) {
+ // Revert director setting if any
+ $_SESSION['director'] = $director;
+ }
+
+ // Config test
+ OAuth2Record::deleteByPk($host);
+ $api->setHostParams($host, $host_params);
+ $config = $api->get(array('config'), $host, false);
+
+ $is_catalog = (is_object($catalog) && $catalog->error === 0);
+ $is_console = (is_object($console) && $console->error === 0);
+ $is_config = (is_object($config) && $config->error === 0);
+
+ $status_ok = $is_catalog;
+ if ($status_ok) {
+ $status_ok = $is_console;
+ }
+
+ if (!$is_catalog) {
+ $this->APIHostTestResultErr->Text .= $catalog->output . '<br />';
+ }
+ if (!$is_console) {
+ $this->APIHostTestResultErr->Text .= $console->output . '<br />';
+ }
+ if (!$is_config) {
+ $this->APIHostTestResultErr->Text .= $config->output . '<br />';
+ }
+
+ $this->APIHostTestResultOk->Display = ($status_ok === true) ? 'Dynamic' : 'None';
+ $this->APIHostTestResultErr->Display = ($status_ok === false) ? 'Dynamic' : 'None';
+ $this->APIHostCatalogSupportYes->Display = ($is_catalog === true) ? 'Dynamic' : 'None';
+ $this->APIHostCatalogSupportNo->Display = ($is_catalog === false) ? 'Dynamic' : 'None';
+ $this->APIHostConsoleSupportYes->Display = ($is_console === true) ? 'Dynamic' : 'None';
+ $this->APIHostConsoleSupportNo->Display = ($is_console === false) ? 'Dynamic' : 'None';
+ $this->APIHostConfigSupportYes->Display = ($is_config === true) ? 'Dynamic' : 'None';
+ $this->APIHostConfigSupportNo->Display = ($is_config === false) ? 'Dynamic' : 'None';
+ }
+
+ public function saveAPIHost($sender, $param) {
+ $cfg_host = array(
+ 'auth_type' => '',
+ 'login' => '',
+ 'password' => '',
+ 'client_id' => '',
+ 'client_secret' => '',
+ 'redirect_uri' => '',
+ 'scope' => ''
+ );
+ $cfg_host['protocol'] = $this->APIHostProtocol->Text;
+ $cfg_host['address'] = $this->APIHostAddress->Text;
+ $cfg_host['port'] = $this->APIHostPort->Text;
+ $cfg_host['url_prefix'] = '';
+ if ($this->APIHostAuthBasic->Checked == true) {
+ $cfg_host['auth_type'] = 'basic';
+ $cfg_host['login'] = $this->APIHostBasicLogin->Text;
+ $cfg_host['password'] = $this->APIHostBasicPassword->Text;
+ } elseif($this->APIHostAuthOAuth2->Checked == true) {
+ $cfg_host['auth_type'] = 'oauth2';
+ $cfg_host['client_id'] = $this->APIHostOAuth2ClientId->Text;
+ $cfg_host['client_secret'] = $this->APIHostOAuth2ClientSecret->Text;
+ $cfg_host['redirect_uri'] = $this->APIHostOAuth2RedirectURI->Text;
+ $cfg_host['scope'] = $this->APIHostOAuth2Scope->Text;
+ }
+ $hc = $this->getModule('host_config');
+ $config = $hc->getConfig();
+ $host_name = trim($this->APIHostName->Text);
+ if (empty($host_name)) {
+ $host_name = $cfg_host['address'];
+ }
+ $config[$host_name] = $cfg_host;
+ $hc->setConfig($config);
+ $this->setAPIHostList(null, null);
+ $this->getCallbackClient()->hide('api_host_window');
+
+ // refresh user window
+ $this->initUserWindow();
+ }
+
+ /**
+ * Remove API host action.
+ * Here is possible to remove one API host or many.
+ * This action is linked with table bulk actions.
+ *
+ * @param TCallback $sender sender object
+ * @param TCallbackEventParameter $param callback parameter
+ * @return none
+ */
+ public function removeAPIHosts($sender, $param) {
+ $names = explode('|', $param->getCallbackParameter());
+ $hc = $this->getModule('host_config');
+ $config = $hc->getConfig();
+ $cfg = [];
+ foreach ($config as $host => $opts) {
+ if (in_array($host, $names)) {
+ continue;
+ }
+ $cfg[$host] = $opts;
+ }
+ $hc->setConfig($cfg);
+ $this->setAPIHostList(null, null);
+ }
+
/**
* Validate IP restriction address value.
*
const SHOW_REMOVE_BUTTON = 'ShowRemoveButton';
const SHOW_CANCEL_BUTTON = 'ShowCancelButton';
const SHOW_ALL_DIRECTIVES = 'ShowAllDirectives';
+ const SHOW_BOTTOM_BUTTONS = 'ShowBottomButtons';
const SAVE_DIRECTIVE_ACTION_OK = 'SaveDirectiveActionOk';
private $show_all_directives = false;
$directives = array();
$parent_directives = array();
$config = new stdClass;
+ $predefined = false;
if ($load_values === true) {
$config = $this->getConfigData($host, array(
$component_type,
$config->JobDefs
));
}
+ } else {
+ // Pre-defined config for new resource can be provided in Data property.
+ $data = $this->getData();
+ if (!empty($data)) {
+ $config = $data;
+ $predefined = true;
+ }
}
$data_desc = $this->Application->getModule('data_desc');
}
$directive_value = null;
- if ($in_config === true && $load_values === true) {
+ if (($in_config === true && $load_values === true) || ($predefined && property_exists($config, $directive_name))) {
$directive_value = $config->{$directive_name};
}
if (is_object($directive_desc)) {
if (property_exists($directive_desc, 'Required')) {
$required = $directive_desc->Required;
- if ($load_values === true && array_key_exists($directive_name, $parent_directives)) {
+ if ($load_values === true && key_exists($directive_name, $parent_directives)) {
// values can be taken from JobDefs
$required = false;
}
$this->SaveDirectiveErrMsg->Display = 'Dynamic';
$this->SaveDirectiveErrMsg->Text = "Error {$result->error}: {$result->output}";
}
+ $this->onSave(null);
}
public function setShowAllDirectives($show_all_directives) {
public function getShowCancelButton() {
return $this->getViewState(self::SHOW_CANCEL_BUTTON, true);
}
+
+ /**
+ * Set if buttons should be flexible and available at the bottom of the page.
+ *
+ * @return none;
+ */
+ public function setShowBottomButtons($show) {
+ $show = TPropertyValue::ensureBoolean($show);
+ $this->setViewState(self::SHOW_BOTTOM_BUTTONS, $show);
+ }
+
+ /**
+ * Get if buttons should be flexible and available at the bottom of the page.
+ *
+ * @return bool true if buttons are available at the bottom of the page, otherwise false
+ */
+ public function getShowBottomButtons() {
+ return $this->getViewState(self::SHOW_BOTTOM_BUTTONS, true);
+ }
+
+ public function onSave($param) {
+ $this->raiseEvent('OnSave', $this, $param);
+ }
}
?>
ItemRenderer="Application.Web.Portlets.DirectiveRenderer"
>
</com:TActiveRepeater>
- <div class="w3-row w3-center w3-border bottom_buttons page_main_el" style="margin-left: 250px">
+ <div class="w3-row w3-center<%=$this->ShowBottomButtons ? ' w3-border bottom_buttons' : ''%> page_main_el"<%=$this->ShowBottomButtons ? ' style="margin-left: 250px"' : ''%>>
<com:Application.Web.Portlets.DirectiveSetting
ID="DirectiveSetting"
Resource="<%=$this->getResource()%>"
public $resource_names = array();
- private function getConfigData($host, $component_type) {
+ public function getConfigData($host, $component_type) {
$params = array('config', $component_type);
$result = $this->Application->getModule('api')->get($params, $host, false);
$config = array();
* @param string $resource_name resource name to remove
* @return none
*/
- private function removeResourceFromConfig(&$config, $resource_type, $resource_name) {
+ public function removeResourceFromConfig(&$config, $resource_type, $resource_name) {
for ($i = 0; $i < count($config); $i++) {
foreach ($config[$i] as $rtype => $resource) {
if (!property_exists($resource, 'Name')) {
if ($rtype === $resource_type && $resource->Name === $resource_name) {
// remove resource
array_splice($config, $i, 1);
- break;
+ break 2;
}
}
}