diff options
author | Artjoms Rimdjonoks <artjoms.rimdjonoks@zabbix.com> | 2021-02-08 21:52:36 +0300 |
---|---|---|
committer | Artjoms Rimdjonoks <artjoms.rimdjonoks@zabbix.com> | 2021-02-08 21:52:36 +0300 |
commit | 60c77a15aeef3fc9e32aa9f18f96b5563b38e438 (patch) | |
tree | 3fceed36fd25e19115937a5b01be8387eff3a777 /ui/app/controllers | |
parent | 897094a0045e4aff12e383f92b9a30b8a11cce2c (diff) | |
parent | 041720766868904c0bdace33ca4d77e536a6cb21 (diff) |
.......... [ZBXNEXT-6309] updated to the latest master branch (simple conflicts solved)
Diffstat (limited to 'ui/app/controllers')
31 files changed, 1406 insertions, 162 deletions
diff --git a/ui/app/controllers/CControllerAuditLogList.php b/ui/app/controllers/CControllerAuditLogList.php index 2f76a71c088..9b896b26314 100644 --- a/ui/app/controllers/CControllerAuditLogList.php +++ b/ui/app/controllers/CControllerAuditLogList.php @@ -219,7 +219,8 @@ class CControllerAuditLogList extends CController { AUDIT_RESOURCE_SETTINGS => _('Settings'), AUDIT_RESOURCE_HOUSEKEEPING => _('Housekeeping'), AUDIT_RESOURCE_AUTHENTICATION => _('Authentication'), - AUDIT_RESOURCE_TEMPLATE_DASHBOARD => _('Template dashboard') + AUDIT_RESOURCE_TEMPLATE_DASHBOARD => _('Template dashboard'), + AUDIT_RESOURCE_AUTH_TOKEN => _('API token') ]; } diff --git a/ui/app/controllers/CControllerAuthenticationUpdate.php b/ui/app/controllers/CControllerAuthenticationUpdate.php index c84f5b2ac62..5bd561b6923 100644 --- a/ui/app/controllers/CControllerAuthenticationUpdate.php +++ b/ui/app/controllers/CControllerAuthenticationUpdate.php @@ -31,8 +31,6 @@ class CControllerAuthenticationUpdate extends CController { ->setArgument('action', 'authentication.edit') ->getUrl() ); - - $this->disableSIDValidation(); } protected function checkInput() { diff --git a/ui/app/controllers/CControllerCorrelationList.php b/ui/app/controllers/CControllerCorrelationList.php index 145e3403a53..41f531113ba 100644 --- a/ui/app/controllers/CControllerCorrelationList.php +++ b/ui/app/controllers/CControllerCorrelationList.php @@ -88,7 +88,7 @@ class CControllerCorrelationList extends CController { 'selectFilter' => ['formula', 'conditions', 'evaltype', 'eval_formula'], 'selectOperations' => ['type'], 'search' => [ - 'name' => ($filter['name'] === '') ? null : $filter['name'], + 'name' => ($filter['name'] === '') ? null : $filter['name'] ], 'filter' => [ 'status' => ($filter['status'] == -1) ? null : $filter['status'] diff --git a/ui/app/controllers/CControllerHost.php b/ui/app/controllers/CControllerHost.php index c19a2c12946..cd25d7a5f71 100644 --- a/ui/app/controllers/CControllerHost.php +++ b/ui/app/controllers/CControllerHost.php @@ -154,11 +154,8 @@ abstract class CControllerHost extends CController { // Get additional data to limited host amount. $hosts = API::Host()->get([ - 'output' => ['hostid', 'name', 'status', 'maintenance_status', 'maintenanceid', 'maintenance_type', - 'available', 'snmp_available', 'jmx_available', 'ipmi_available', 'error', 'ipmi_error', 'snmp_error', - 'jmx_error' - ], - 'selectInterfaces' => ['ip', 'dns', 'port', 'main', 'type', 'useip'], + 'output' => ['hostid', 'name', 'status', 'maintenance_status', 'maintenanceid', 'maintenance_type'], + 'selectInterfaces' => ['ip', 'dns', 'port', 'main', 'type', 'useip', 'available', 'error', 'details'], 'selectGraphs' => API_OUTPUT_COUNT, 'selectHttpTests' => API_OUTPUT_COUNT, 'selectTags' => ['tag', 'value'], @@ -280,7 +277,7 @@ abstract class CControllerHost extends CController { $data = []; if ($filter['groupids']) { - $groups= API::HostGroup()->get([ + $groups = API::HostGroup()->get([ 'output' => ['groupid', 'name'], 'groupids' => $filter['groupids'] ]); diff --git a/ui/app/controllers/CControllerMenuPopup.php b/ui/app/controllers/CControllerMenuPopup.php index c73ad01a224..2dd1620b7ec 100644 --- a/ui/app/controllers/CControllerMenuPopup.php +++ b/ui/app/controllers/CControllerMenuPopup.php @@ -565,6 +565,7 @@ class CControllerMenuPopup extends CController { $can_be_closed = ($db_trigger['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED && CWebUser::checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) ); + $event = []; if (array_key_exists('eventid', $data)) { $menu_data['eventid'] = $data['eventid']; @@ -622,6 +623,32 @@ class CControllerMenuPopup extends CController { ); } + $scripts_by_hosts = CWebUser::checkAccess(CRoleHelper::ACTIONS_EXECUTE_SCRIPTS) + ? $event ? API::Script()->getScriptsByHosts(array_keys($hosts)) : [] + : []; + + $scripts = []; + foreach ($scripts_by_hosts as &$host_scripts) { + foreach ($host_scripts as &$host_script) { + if (!array_key_exists($host_script['scriptid'], $scripts)) { + $host_script['name'] = trimPath($host_script['name']); + $scripts[$host_script['scriptid']] = $host_script; + } + } + unset($host_script); + } + unset($host_scripts); + + CArrayHelper::sort($scripts, ['name']); + + foreach (array_values($scripts) as $script) { + $menu_data['scripts'][] = [ + 'name' => $script['name'], + 'scriptid' => $script['scriptid'], + 'confirmation' => $script['confirmation'] + ]; + } + return $menu_data; } diff --git a/ui/app/controllers/CControllerPopupGeneric.php b/ui/app/controllers/CControllerPopupGeneric.php index 04c405d1b7c..aad1e3c880e 100644 --- a/ui/app/controllers/CControllerPopupGeneric.php +++ b/ui/app/controllers/CControllerPopupGeneric.php @@ -377,8 +377,7 @@ class CControllerPopupGeneric extends CController { ], 'table_columns' => [ _('Name'), - _('Execute on'), - _('Commands') + _('Execute on') ] ], 'roles' => [ @@ -1298,7 +1297,7 @@ class CControllerPopupGeneric extends CController { case 'scripts': $options += [ - 'output' => ['scriptid', 'name', 'type', 'execute_on', 'command'], + 'output' => ['scriptid', 'name', 'type', 'execute_on'], 'groupids' => (!$this->hostids && $this->groupids) ? $this->groupids : null ]; diff --git a/ui/app/controllers/CControllerPopupItemTest.php b/ui/app/controllers/CControllerPopupItemTest.php index a209937f9c6..29b59609690 100644 --- a/ui/app/controllers/CControllerPopupItemTest.php +++ b/ui/app/controllers/CControllerPopupItemTest.php @@ -137,55 +137,56 @@ abstract class CControllerPopupItemTest extends CController { 'url' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'posts' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'http_proxy' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'ssl_cert_file' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'ssl_key_file' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'query_fields' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'headers' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}', '{HOST.PORT}'], - 'item' => ['{ITEM.ID}', '{ITEM.KEY}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], 'parameters' => [ 'host' => ['{HOSTNAME}', '{HOST.HOST}', '{HOST.NAME}'], 'interface' => ['{HOST.IP}', '{IPADDRESS}', '{HOST.DNS}', '{HOST.CONN}'], + 'item' => ['{ITEM.ID}', '{ITEM.KEY.ORIG}', '{ITEM.KEY}'], 'support_user_macros' => true, 'support_lld_macros' => true ], @@ -304,9 +305,8 @@ abstract class CControllerPopupItemTest extends CController { if ($ret && $hostid != 0) { $hosts = API::Host()->get([ - 'output' => ['hostid', 'host', 'name', 'status', 'available', 'proxy_hostid', 'tls_subject', - 'ipmi_available', 'jmx_available', 'snmp_available', 'maintenance_status', 'maintenance_type', - 'ipmi_authtype', 'ipmi_privilege', 'ipmi_username', 'ipmi_password', + 'output' => ['hostid', 'host', 'name', 'status', 'proxy_hostid', 'tls_subject', 'maintenance_status', + 'maintenance_type', 'ipmi_authtype', 'ipmi_privilege', 'ipmi_username', 'ipmi_password', 'tls_issuer', 'tls_connect' ], 'hostids' => [$hostid], @@ -315,7 +315,7 @@ abstract class CControllerPopupItemTest extends CController { if (!$hosts) { $hosts = API::Template()->get([ - 'output' => ['templateid', 'host', 'name', 'status', 'available', 'jmx_available'], + 'output' => ['templateid', 'host', 'name', 'status'], 'templateids' => [$hostid], 'editable' => true ]); @@ -427,7 +427,8 @@ abstract class CControllerPopupItemTest extends CController { $interface_input['address'] = $input['address']; } - if (array_key_exists('data', $input) && array_key_exists('interface_details', $input['data'])) { + if (array_key_exists('data', $input) && array_key_exists('interface_details', $input['data']) + && is_array($input['data']['interface_details'])) { $interface_input['details'] = $input['data']['interface_details']; } elseif (array_key_exists('interface', $input) && array_key_exists('details', $input['interface'])) { @@ -530,17 +531,13 @@ abstract class CControllerPopupItemTest extends CController { $data += [ 'key' => $input['key'], 'host' => [ - 'hostid' => $this->host['hostid'], - 'available' => $this->host['available'], - 'jmx_available' => $this->host['jmx_available'] + 'hostid' => $this->host['hostid'] ] ]; if ($this->host['status'] != HOST_STATUS_TEMPLATE) { $data['host'] += [ 'maintenance_status' => $this->host['maintenance_status'], - 'ipmi_available' => $this->host['ipmi_available'], - 'snmp_available' => $this->host['snmp_available'], 'maintenance_type' => $this->host['maintenance_type'] ]; } @@ -739,12 +736,39 @@ abstract class CControllerPopupItemTest extends CController { // Get values from database; resolve macros. if (($this->host['status'] == HOST_STATUS_MONITORED || $this->host['status'] == HOST_STATUS_NOT_MONITORED) && array_key_exists('interfaceid', $inputs)) { - $output_details = ($this->item_type == ITEM_TYPE_SNMP) ? ['details'] : []; - $interfaces = API::HostInterface()->get([ - 'output' => array_merge(['hostid', 'type', 'dns', 'ip', 'port', 'main', 'useip'], $output_details), - 'interfaceids' => $inputs['interfaceid'], - 'hostids' => $this->host['hostid'] - ]); + $output = ['hostid', 'type', 'dns', 'ip', 'port', 'main', 'useip']; + $interfaces = []; + + if ($this->item_type == ITEM_TYPE_SNMP) { + $output[] = 'details'; + } + + if (itemTypeInterface($this->item_type) === false) { + $host_interfaces = API::HostInterface()->get([ + 'output' => $output, + 'hostids' => $this->host['hostid'], + 'filter' => ['main' => INTERFACE_PRIMARY] + ]); + $host_interfaces = zbx_toHash($host_interfaces, 'type'); + + $ordered_interface_types = [INTERFACE_TYPE_AGENT, INTERFACE_TYPE_SNMP, INTERFACE_TYPE_JMX, + INTERFACE_TYPE_IPMI + ]; + + foreach ($ordered_interface_types as $interface_type) { + if (array_key_exists($interface_type, $host_interfaces)) { + $interfaces[] = $host_interfaces[$interface_type]; + break; + } + } + } + else { + $interfaces = API::HostInterface()->get([ + 'output' => $output, + 'interfaceids' => $inputs['interfaceid'], + 'hostids' => $this->host['hostid'] + ]); + } if (count($interfaces) != 0) { $interfaces = CMacrosResolverHelper::resolveHostInterfaces($interfaces); @@ -766,6 +790,10 @@ abstract class CControllerPopupItemTest extends CController { } } + if ($this->item_type == ITEM_TYPE_SCRIPT) { + return $interface_data; + } + // Apply client side cache. foreach ($inputs as $key => $value) { if (is_array($value)) { @@ -893,10 +921,31 @@ abstract class CControllerPopupItemTest extends CController { '{ITEM.ID}' => (array_key_exists('itemid', $inputs) && $inputs['itemid']) ? $inputs['itemid'] : UNRESOLVED_MACRO_STRING, - '{ITEM.KEY}' => array_key_exists('key', $inputs) ? $inputs['key'] : UNRESOLVED_MACRO_STRING + '{ITEM.KEY}' => array_key_exists('key', $inputs) ? $inputs['key'] : UNRESOLVED_MACRO_STRING, + '{ITEM.KEY.ORIG}' => array_key_exists('key', $inputs) ? $inputs['key'] : UNRESOLVED_MACRO_STRING ] ]; + if (array_key_exists('key', $inputs) && strstr($inputs['key'], '{') !== false) { + $usermacros = CMacrosResolverHelper::extractItemTestMacros([ + 'steps' => [], + 'delay' => '', + 'supported_macros' => array_diff_key($this->macros_by_item_props['key'], + ['support_user_macros' => true, 'support_lld_macros' => true] + ), + 'support_lldmacros' => ($this->preproc_item instanceof CItemPrototype), + 'texts_support_macros' => [$inputs['key']], + 'texts_support_lld_macros' => [$inputs['key']], + 'texts_support_user_macros' => [$inputs['key']], + 'hostid' => $this->host ? $this->host['hostid'] : 0, + 'macros_values' => array_intersect_key($macros, $this->macros_by_item_props['key']) + ]); + + foreach ($usermacros['macros'] as $macro => $value) { + $macros['item']['{ITEM.KEY}'] = str_replace($macro, $value, $macros['item']['{ITEM.KEY}']); + } + } + return $macros; } diff --git a/ui/app/controllers/CControllerPopupItemTestEdit.php b/ui/app/controllers/CControllerPopupItemTestEdit.php index 808c77fe8fb..abddd97d4ac 100644 --- a/ui/app/controllers/CControllerPopupItemTestEdit.php +++ b/ui/app/controllers/CControllerPopupItemTestEdit.php @@ -149,9 +149,9 @@ class CControllerPopupItemTestEdit extends CControllerPopupItemTest { $inputs = $this->getItemTestProperties($this->getInputAll()); // Work with preprocessing steps. - $preprocessing_steps_inpupt = $this->getInput('steps', []); + $preprocessing_steps_input = $this->getInput('steps', []); $preprocessing_steps = []; - foreach ($preprocessing_steps_inpupt as $preproc) { + foreach ($preprocessing_steps_input as $preproc) { if ($preproc['type'] == ZBX_PREPROC_VALIDATE_NOT_SUPPORTED) { array_unshift($preprocessing_steps, $preproc); } @@ -248,13 +248,13 @@ class CControllerPopupItemTestEdit extends CControllerPopupItemTest { // Extract macros and apply effective values for each of them. $usermacros = CMacrosResolverHelper::extractItemTestMacros([ 'steps' => $preprocessing_steps, - 'hostid' => $this->host ? $this->host['hostid'] : 0, 'delay' => $show_prev ? $this->getInput('delay', ZBX_ITEM_DELAY_DEFAULT) : '', - 'texts_support_macros' => $texts_support_macros, - 'texts_support_lld_macros' => $texts_support_lld_macros, - 'texts_support_user_macros' => $texts_support_user_macros, 'supported_macros' => $supported_macros, 'support_lldmacros' => $support_lldmacros, + 'texts_support_macros' => $texts_support_macros, + 'texts_support_user_macros' => $texts_support_user_macros, + 'texts_support_lld_macros' => $texts_support_lld_macros, + 'hostid' => $this->host ? $this->host['hostid'] : 0, 'macros_values' => $this->getSupportedMacros($inputs + ['interfaceid' => $this->getInput('interfaceid', 0)]) ]); diff --git a/ui/app/controllers/CControllerPopupMassupdateItem.php b/ui/app/controllers/CControllerPopupMassupdateItem.php index 67ff9890ec0..0701aedcb9c 100644 --- a/ui/app/controllers/CControllerPopupMassupdateItem.php +++ b/ui/app/controllers/CControllerPopupMassupdateItem.php @@ -450,7 +450,7 @@ class CControllerPopupMassupdateItem extends CController { 'multiple_interface_types' => false, 'initial_item_type' => null, 'preprocessing_test_type' => CControllerPopupItemTestEdit::ZBX_TEST_TYPE_ITEM, - 'preprocessing_types' => CItem::$supported_preprocessing_types, + 'preprocessing_types' => CItem::SUPPORTED_PREPROCESSING_TYPES, 'displayApplications' => true, 'display_interfaces' => true, 'displayMasteritems' => true, diff --git a/ui/app/controllers/CControllerPopupMassupdateItemPrototype.php b/ui/app/controllers/CControllerPopupMassupdateItemPrototype.php index a31f9c20b85..8936497b41a 100644 --- a/ui/app/controllers/CControllerPopupMassupdateItemPrototype.php +++ b/ui/app/controllers/CControllerPopupMassupdateItemPrototype.php @@ -216,7 +216,7 @@ class CControllerPopupMassupdateItemPrototype extends CController { if (is_array($application_prototype) && array_key_exists('new', $application_prototype)) { $new_application_prototypes[] = [ - 'name' => $application_prototype['new'], + 'name' => $application_prototype['new'] ]; } else { @@ -580,7 +580,7 @@ class CControllerPopupMassupdateItemPrototype extends CController { 'multiple_interface_types' => false, 'initial_item_type' => null, 'preprocessing_test_type' => CControllerPopupItemTestEdit::ZBX_TEST_TYPE_ITEM_PROTOTYPE, - 'preprocessing_types' => CItemPrototype::$supported_preprocessing_types, + 'preprocessing_types' => CItemPrototype::SUPPORTED_PREPROCESSING_TYPES, 'displayApplications' => true, 'display_interfaces' => true, 'displayMasteritems' => true, diff --git a/ui/app/controllers/CControllerPopupScriptExec.php b/ui/app/controllers/CControllerPopupScriptExec.php index 1abf588619a..9d7ab9742b1 100644 --- a/ui/app/controllers/CControllerPopupScriptExec.php +++ b/ui/app/controllers/CControllerPopupScriptExec.php @@ -23,8 +23,9 @@ class CControllerPopupScriptExec extends CController { protected function checkInput() { $fields = [ + 'scriptid' => 'db scripts.scriptid', 'hostid' => 'db hosts.hostid', - 'scriptid' => 'db scripts.scriptid' + 'eventid' => 'db events.eventid' ]; $ret = $this->validateInput($fields); @@ -48,62 +49,78 @@ class CControllerPopupScriptExec extends CController { return false; } - return (bool) API::Host()->get([ - 'output' => [], - 'hostids' => $this->getInput('hostid') - ]); + if ($this->hasInput('hostid')) { + return (bool) API::Host()->get([ + 'output' => [], + 'hostids' => $this->getInput('hostid') + ]); + } + + if ($this->hasInput('eventid')) { + return (bool) API::Event()->get([ + 'output' => [], + 'eventids' => $this->getInput('eventid') + ]); + } + + return false; } protected function doAction() { $scriptid = $this->getInput('scriptid'); - $hostid = $this->getInput('hostid'); + $hostid = $this->getInput('hostid', ''); + $eventid = $this->getInput('eventid', ''); $data = [ 'title' => _('Scripts'), - 'command' => '', - 'message' => '', - 'errors' => null, + 'type' => ZBX_SCRIPT_TYPE_WEBHOOK, + 'output' => '', + 'debug' => [], + 'messages' => null, + 'success' => false, 'user' => [ 'debug_mode' => $this->getDebugMode() ] ]; $scripts = API::Script()->get([ - 'output' => ['name', 'command'], + 'output' => ['name', 'type'], 'scriptids' => $scriptid ]); if ($scripts) { $script = $scripts[0]; - - $macros_data = CMacrosResolverHelper::resolve([ - 'config' => 'scriptConfirmation', - 'data' => [$hostid => [$scriptid => $script['command']]] - ]); - $data['title'] = $script['name']; - $data['command'] = $macros_data[$hostid][$scriptid]; + $data['type'] = $script['type']; - $result = API::Script()->execute([ - 'hostid' => $hostid, - 'scriptid' => $scriptid - ]); + $execution_params = ['scriptid' => $scriptid]; - if (!$result) { - error(_('Cannot execute script')); + if ($hostid) { + $execution_params['hostid'] = $hostid; } - elseif ($result['response'] === 'failed') { - error($result['value']); + elseif ($eventid) { + $execution_params['eventid'] = $eventid; } - else { - $data['message'] = $result['value']; + + $result = API::Script()->execute($execution_params); + + if ($result) { + if ($data['type'] == ZBX_SCRIPT_TYPE_WEBHOOK) { + $value = json_decode($result['value']); + $result['value'] = json_last_error() ? $result['value'] : json_encode($value, JSON_PRETTY_PRINT); + } + + $data['output'] = $result['value']; + $data['debug'] = $result['debug']; + $data['success'] = true; + info(_('Script execution successful.')); } } else { error(_('No permissions to referred object or it does not exist!')); } - $data['errors'] = getMessages(); + $data['messages'] = getMessages($data['success'], $data['success'] ? null : _('Cannot execute script.')); $this->setResponse(new CControllerResponseData($data)); } diff --git a/ui/app/controllers/CControllerProfileUpdate.php b/ui/app/controllers/CControllerProfileUpdate.php index 3a3ccc87c39..87148563b85 100644 --- a/ui/app/controllers/CControllerProfileUpdate.php +++ b/ui/app/controllers/CControllerProfileUpdate.php @@ -79,10 +79,12 @@ class CControllerProfileUpdate extends CController { case 'web.templates.httpconf.filter.active': case 'web.templates.items.filter.active': case 'web.templates.triggers.filter.active': + case 'web.token.filter.active': case 'web.toptriggers.filter.active': case 'web.tr_events.hats.'.WIDGET_HAT_EVENTACTIONS.'.state': case 'web.tr_events.hats.'.WIDGET_HAT_EVENTLIST.'.state': case 'web.user.filter.active': + case 'web.user.token.filter.active': case 'web.usergroup.filter.active': case 'web.web.filter.active': $ret = true; diff --git a/ui/app/controllers/CControllerScriptCreate.php b/ui/app/controllers/CControllerScriptCreate.php index 7c3d30d6061..f66cd39bcf1 100644 --- a/ui/app/controllers/CControllerScriptCreate.php +++ b/ui/app/controllers/CControllerScriptCreate.php @@ -24,17 +24,21 @@ class CControllerScriptCreate extends CController { protected function checkInput() { $fields = [ 'name' => 'db scripts.name', - 'type' => 'db scripts.type |in '.ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT.','.ZBX_SCRIPT_TYPE_IPMI, - 'execute_on' => 'db scripts.execute_on |in '.ZBX_SCRIPT_EXECUTE_ON_AGENT.','.ZBX_SCRIPT_EXECUTE_ON_SERVER.','.ZBX_SCRIPT_EXECUTE_ON_PROXY, - 'command' => 'db scripts.command |flags '.P_CRLF, - 'commandipmi' => 'db scripts.command |flags '.P_CRLF, + 'type' => 'db scripts.type|in '.ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT.','.ZBX_SCRIPT_TYPE_IPMI.','.ZBX_SCRIPT_TYPE_WEBHOOK, + 'execute_on' => 'db scripts.execute_on|in '.ZBX_SCRIPT_EXECUTE_ON_AGENT.','.ZBX_SCRIPT_EXECUTE_ON_SERVER.','.ZBX_SCRIPT_EXECUTE_ON_PROXY, + 'command' => 'db scripts.command|flags '.P_CRLF, + 'commandipmi' => 'db scripts.command|flags '.P_CRLF, + 'parameters' => 'array', + 'script' => 'db scripts.command|flags '.P_CRLF, + 'timeout' => 'db scripts.timeout|time_unit '.implode(':', [1, 60]), 'description' => 'db scripts.description', - 'host_access' => 'db scripts.host_access |in '.PERM_READ.','.PERM_READ_WRITE, + 'host_access' => 'db scripts.host_access|in '.PERM_READ.','.PERM_READ_WRITE, 'groupid' => 'db scripts.groupid', 'usrgrpid' => 'db scripts.usrgrpid', - 'hgstype' => ' in 0,1', + 'hgstype' => 'in 0,1', 'confirmation' => 'db scripts.confirmation|not_empty', - 'enable_confirmation' => ' in 1' + 'enable_confirmation' => 'in 1', + 'form_refresh' => 'int32' ]; $ret = $this->validateInput($fields); @@ -65,14 +69,27 @@ class CControllerScriptCreate extends CController { $this->getInputs($script, ['command', 'description', 'usrgrpid', 'groupid', 'host_access', 'confirmation']); $script['name'] = trimPath($this->getInput('name', '')); - $script['type'] = $this->getInput('type', ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT); - $script['execute_on'] = $this->getInput('execute_on', ZBX_SCRIPT_EXECUTE_ON_SERVER); + $script['type'] = $this->getInput('type', ZBX_SCRIPT_TYPE_WEBHOOK); + $script['execute_on'] = $this->getInput('execute_on', ZBX_SCRIPT_EXECUTE_ON_PROXY); + + if ($script['type'] != ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT) { + $script['execute_on'] = ZBX_SCRIPT_EXECUTE_ON_PROXY; + } if ($script['type'] == ZBX_SCRIPT_TYPE_IPMI) { - if ($this->hasInput('commandipmi')) { - $script['command'] = $this->getInput('commandipmi'); + $script['command'] = $this->getInput('commandipmi', ''); + } + elseif ($script['type'] == ZBX_SCRIPT_TYPE_WEBHOOK) { + $script['command'] = $this->getInput('script', ''); + $script['timeout'] = $this->getInput('timeout', DB::getDefault('scripts', 'timeout')); + $parameters = $this->getInput('parameters', []); + + if (array_key_exists('name', $parameters) && array_key_exists('value', $parameters)) { + $script['parameters'] = array_map(function ($name, $value) { + return compact('name', 'value'); + }, $parameters['name'], $parameters['value'] + ); } - $script['execute_on'] = ZBX_SCRIPT_EXECUTE_ON_SERVER; } if ($this->getInput('hgstype', 1) == 0) { @@ -90,9 +107,7 @@ class CControllerScriptCreate extends CController { CMessageHelper::setSuccessTitle(_('Script added')); } else { - $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) - ->setArgument('action', 'script.edit') - ); + $response = new CControllerResponseRedirect((new CUrl('zabbix.php'))->setArgument('action', 'script.edit')); $response->setFormData($this->getInputAll()); CMessageHelper::setErrorTitle(_('Cannot add script')); } diff --git a/ui/app/controllers/CControllerScriptEdit.php b/ui/app/controllers/CControllerScriptEdit.php index 03aade6d000..ea3d62092cf 100644 --- a/ui/app/controllers/CControllerScriptEdit.php +++ b/ui/app/controllers/CControllerScriptEdit.php @@ -29,17 +29,21 @@ class CControllerScriptEdit extends CController { $fields = [ 'scriptid' => 'db scripts.scriptid', 'name' => 'db scripts.name', - 'type' => 'db scripts.type |in '.ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT.','.ZBX_SCRIPT_TYPE_IPMI, - 'execute_on' => 'db scripts.execute_on |in '.ZBX_SCRIPT_EXECUTE_ON_AGENT.','.ZBX_SCRIPT_EXECUTE_ON_SERVER.','.ZBX_SCRIPT_EXECUTE_ON_PROXY, + 'type' => 'db scripts.type|in '.ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT.','.ZBX_SCRIPT_TYPE_IPMI.','.ZBX_SCRIPT_TYPE_WEBHOOK, + 'execute_on' => 'db scripts.execute_on|in '.ZBX_SCRIPT_EXECUTE_ON_AGENT.','.ZBX_SCRIPT_EXECUTE_ON_SERVER.','.ZBX_SCRIPT_EXECUTE_ON_PROXY, 'command' => 'db scripts.command', 'commandipmi' => 'db scripts.command', + 'parameters' => 'array', + 'script' => 'db scripts.command', + 'timeout' => 'db media_type.timeout', 'description' => 'db scripts.description', - 'host_access' => 'db scripts.host_access |in '.PERM_READ.','.PERM_READ_WRITE, + 'host_access' => 'db scripts.host_access|in '.PERM_READ.','.PERM_READ_WRITE, 'groupid' => 'db scripts.groupid', 'usrgrpid' => 'db scripts.usrgrpid', - 'hgstype' => ' in 0,1', + 'hgstype' => 'in 0,1', 'confirmation' => 'db scripts.confirmation', - 'enable_confirmation' => ' in 1' + 'enable_confirmation' => 'in 1', + 'form_refresh' => 'int32' ]; $ret = $this->validateInput($fields); @@ -73,68 +77,74 @@ class CControllerScriptEdit extends CController { 'sid' => $this->getUserSID(), 'scriptid' => 0, 'name' => '', - 'type' => ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT, + 'type' => ZBX_SCRIPT_TYPE_WEBHOOK, 'execute_on' => ZBX_SCRIPT_EXECUTE_ON_AGENT, 'command' => '', 'commandipmi' => '', + 'parameters' => [], + 'script' => '', + 'timeout' => DB::getDefault('scripts', 'timeout'), 'description' => '', 'usrgrpid' => 0, 'groupid' => 0, 'host_access' => PERM_READ, 'confirmation' => '', - 'enable_confirmation' => 0, + 'enable_confirmation' => false, 'hgstype' => 0 ]; // get values from the dabatase if ($this->hasInput('scriptid')) { $scripts = API::Script()->get([ - 'output' => ['scriptid', 'name', 'type', 'execute_on', 'command', 'description', 'usrgrpid', - 'groupid', 'host_access', 'confirmation' + 'output' => ['scriptid', 'name', 'type', 'execute_on', 'command', 'description', 'usrgrpid', 'groupid', + 'host_access', 'confirmation', 'timeout', 'parameters' ], 'scriptids' => $this->getInput('scriptid') ]); - $script = $scripts[0]; - - $data['scriptid'] = $script['scriptid']; - $data['name'] = $script['name']; - $data['type'] = $script['type']; - $data['execute_on'] = $script['execute_on']; - $data['command'] = ($script['type'] == ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT) ? $script['command'] : ''; - $data['commandipmi'] = ($script['type'] == ZBX_SCRIPT_TYPE_IPMI) ? $script['command'] : ''; - $data['description'] = $script['description']; - $data['usrgrpid'] = $script['usrgrpid']; - $data['groupid'] = $script['groupid']; - $data['host_access'] = $script['host_access']; - $data['confirmation'] = $script['confirmation']; - $data['enable_confirmation'] = ($script['confirmation'] !== ''); - $data['hgstype'] = ($script['groupid'] != 0) ? 1 : 0; + if ($scripts) { + $script = $scripts[0]; + + $data['scriptid'] = $script['scriptid']; + $data['name'] = $script['name']; + $data['type'] = $script['type']; + $data['execute_on'] = $script['execute_on']; + $data['command'] = ($script['type'] == ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT) ? $script['command'] : ''; + $data['commandipmi'] = ($script['type'] == ZBX_SCRIPT_TYPE_IPMI) ? $script['command'] : ''; + $data['parameters'] = $script['parameters']; + $data['script'] = ($script['type'] == ZBX_SCRIPT_TYPE_WEBHOOK) ? $script['command'] : ''; + $data['timeout'] = $script['timeout']; + $data['description'] = $script['description']; + $data['usrgrpid'] = $script['usrgrpid']; + $data['groupid'] = $script['groupid']; + $data['host_access'] = $script['host_access']; + $data['confirmation'] = $script['confirmation']; + $data['enable_confirmation'] = ($script['confirmation'] !== ''); + $data['hgstype'] = ($script['groupid'] != 0) ? 1 : 0; + } } // overwrite with input variables - $this->getInputs($data, [ - 'name', - 'type', - 'execute_on', - 'command', - 'commandipmi', - 'description', - 'usrgrpid', - 'groupid', - 'host_access', - 'confirmation', - 'enable_confirmation', + $this->getInputs($data, ['name', 'type', 'execute_on', 'command', 'commandipmi', 'parameters', 'script', + 'timeout', 'description', 'usrgrpid', 'groupid', 'host_access', 'confirmation', 'enable_confirmation', 'hgstype' ]); + if ($this->hasInput('form_refresh') && array_key_exists('name', $data['parameters']) + && array_key_exists('value', $data['parameters'])) { + $data['parameters'] = array_map(function ($name, $value) { + return compact('name', 'value'); + }, $data['parameters']['name'], $data['parameters']['value'] + ); + } + // get host group if ($data['groupid'] == 0) { $data['hostgroup'] = null; } else { $hostgroups = API::HostGroup()->get([ - 'groupids' => [$data['groupid']], - 'output' => ['groupid', 'name'] + 'output' => ['groupid', 'name'], + 'groupids' => [$data['groupid']] ]); $hostgroup = $hostgroups[0]; diff --git a/ui/app/controllers/CControllerScriptList.php b/ui/app/controllers/CControllerScriptList.php index c1bc759b98c..a9079b45061 100644 --- a/ui/app/controllers/CControllerScriptList.php +++ b/ui/app/controllers/CControllerScriptList.php @@ -102,6 +102,10 @@ class CControllerScriptList extends CController { $groupids = []; foreach ($data['scripts'] as &$script) { + if ($script['type'] == ZBX_SCRIPT_TYPE_WEBHOOK) { + $script['command'] = ''; + } + $script['userGroupName'] = null; // all user groups $script['hostGroupName'] = null; // all host groups diff --git a/ui/app/controllers/CControllerScriptUpdate.php b/ui/app/controllers/CControllerScriptUpdate.php index 96add398f86..5a5deb75e30 100644 --- a/ui/app/controllers/CControllerScriptUpdate.php +++ b/ui/app/controllers/CControllerScriptUpdate.php @@ -24,18 +24,22 @@ class CControllerScriptUpdate extends CController { protected function checkInput() { $fields = [ 'scriptid' => 'fatal|required|db scripts.scriptid', - 'name' => ' db scripts.name', - 'type' => ' db scripts.type |in '.ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT.','.ZBX_SCRIPT_TYPE_IPMI, - 'execute_on' => ' db scripts.execute_on |in '.ZBX_SCRIPT_EXECUTE_ON_AGENT.','.ZBX_SCRIPT_EXECUTE_ON_SERVER.','.ZBX_SCRIPT_EXECUTE_ON_PROXY, - 'command' => ' db scripts.command |flags '.P_CRLF, - 'commandipmi' => ' db scripts.command |flags '.P_CRLF, - 'description' => ' db scripts.description', - 'host_access' => ' db scripts.host_access |in '.PERM_READ.','.PERM_READ_WRITE, - 'groupid' => ' db scripts.groupid', - 'usrgrpid' => ' db scripts.usrgrpid', - 'hgstype' => ' in 0,1', - 'confirmation' => ' db scripts.confirmation|not_empty', - 'enable_confirmation' => ' in 1' + 'name' => 'db scripts.name', + 'type' => 'db scripts.type|in '.ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT.','.ZBX_SCRIPT_TYPE_IPMI.','.ZBX_SCRIPT_TYPE_WEBHOOK, + 'execute_on' => 'db scripts.execute_on|in '.ZBX_SCRIPT_EXECUTE_ON_AGENT.','.ZBX_SCRIPT_EXECUTE_ON_SERVER.','.ZBX_SCRIPT_EXECUTE_ON_PROXY, + 'command' => 'db scripts.command|flags '.P_CRLF, + 'commandipmi' => 'db scripts.command|flags '.P_CRLF, + 'parameters' => 'array', + 'script' => 'db scripts.command|flags '.P_CRLF, + 'timeout' => 'db scripts.timeout|time_unit '.implode(':', [1, 60]), + 'description' => 'db scripts.description', + 'host_access' => 'db scripts.host_access|in '.PERM_READ.','.PERM_READ_WRITE, + 'groupid' => 'db scripts.groupid', + 'usrgrpid' => 'db scripts.usrgrpid', + 'hgstype' => 'in 0,1', + 'confirmation' => 'db scripts.confirmation|not_empty', + 'enable_confirmation' => 'in 1', + 'form_refresh' => 'int32' ]; $ret = $this->validateInput($fields); @@ -74,15 +78,31 @@ class CControllerScriptUpdate extends CController { $this->getInputs($script, ['scriptid', 'command', 'description', 'usrgrpid', 'groupid', 'host_access']); $script['name'] = trimPath($this->getInput('name', '')); - $script['type'] = $this->getInput('type', ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT); - $script['execute_on'] = $this->getInput('execute_on', ZBX_SCRIPT_EXECUTE_ON_SERVER); + $script['type'] = $this->getInput('type', ZBX_SCRIPT_TYPE_WEBHOOK); + $script['execute_on'] = $this->getInput('execute_on', ZBX_SCRIPT_EXECUTE_ON_PROXY); $script['confirmation'] = $this->getInput('confirmation', ''); + if ($script['type'] != ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT) { + $script['execute_on'] = ZBX_SCRIPT_EXECUTE_ON_PROXY; + } + if ($script['type'] == ZBX_SCRIPT_TYPE_IPMI) { - if ($this->hasInput('commandipmi')) { - $script['command'] = $this->getInput('commandipmi'); + $script['command'] = $this->getInput('commandipmi', ''); + } + elseif ($script['type'] == ZBX_SCRIPT_TYPE_WEBHOOK) { + $script['command'] = $this->getInput('script', ''); + $script['timeout'] = $this->getInput('timeout', DB::getDefault('scripts', 'timeout')); + $script['parameters'] = []; + $parameters = $this->getInput('parameters', []); + + if (array_key_exists('name', $parameters) && array_key_exists('value', $parameters)) { + $script['parameters'] = array_map(function ($name, $value) { + return compact('name', 'value'); + }, + $parameters['name'], + $parameters['value'] + ); } - $script['execute_on'] = ZBX_SCRIPT_EXECUTE_ON_SERVER; } if ($this->getInput('hgstype', 1) == 0) { diff --git a/ui/app/controllers/CControllerTokenCreate.php b/ui/app/controllers/CControllerTokenCreate.php new file mode 100644 index 00000000000..b63b3bfccf7 --- /dev/null +++ b/ui/app/controllers/CControllerTokenCreate.php @@ -0,0 +1,110 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenCreate extends CController { + + protected function checkInput() { + $fields = [ + 'name' => 'db token.name|required|not_empty', + 'description' => 'db token.description', + 'userid' => 'db users.userid|required', + 'expires_state' => 'in 0,1|required', + 'expires_at' => 'range_time', + 'status' => 'db token.status|required|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED, + 'action_src' => 'fatal|required|in token.edit,user.token.edit', + 'action_dst' => 'fatal|required|in token.view,user.token.view' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + switch ($this->getValidationError()) { + case self::VALIDATION_ERROR: + $location = (new CUrl('zabbix.php'))->setArgument('action', $this->getInput('action_src')); + $response = new CControllerResponseRedirect($location); + $response->setFormData($this->getInputAll()); + CMessageHelper::setErrorTitle(_('Cannot add API token')); + $this->setResponse($response); + break; + case self::VALIDATION_FATAL_ERROR: + $this->setResponse(new CControllerResponseFatal()); + break; + } + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $this->getInputs($token, ['name', 'description', 'userid', 'expires_at', 'status']); + + $token['expires_at'] = $this->getInput('expires_state') + ? (new DateTime($token['expires_at']))->getTimestamp() + : 0; + + $result = API::Token()->create($token); + + if ($result) { + ['tokenids' => $tokenids] = $result; + [['token' => $auth_token]] = API::Token()->generate($tokenids); + + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgumentSID() + ->setArgument('action', $this->getInput('action_dst')) + ); + + [$user] = (CWebUser::$data['userid'] != $token['userid']) + ? API::User()->get([ + 'output' => ['alias', 'name', 'surname'], + 'userids' => $token['userid'] + ]) + : [CWebUser::$data]; + + $response->setFormData([ + 'name' => $token['name'], + 'user' => getUserFullname($user), + 'auth_token' => $auth_token, + 'expires_at' => $token['expires_at'], + 'description' => $token['description'], + 'status' => $token['status'] + ]); + + CMessageHelper::setSuccessTitle(_('API token added')); + } + else { + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgument('action', $this->getInput('action_src')) + ); + $response->setFormData($this->getInputAll()); + CMessageHelper::setErrorTitle(_('Cannot add API token')); + } + + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenDelete.php b/ui/app/controllers/CControllerTokenDelete.php new file mode 100644 index 00000000000..5763f0ceaa8 --- /dev/null +++ b/ui/app/controllers/CControllerTokenDelete.php @@ -0,0 +1,69 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenDelete extends CController { + + protected function checkInput() { + $fields = [ + 'tokenids' => 'required|array_db token.tokenid', + 'action_src' => 'required|in token.list,user.token.list' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $tokenids = $this->getInput('tokenids'); + + $result = API::Token()->delete($tokenids); + + $deleted = count($tokenids); + + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgument('action', $this->getInput('action_src')) + ->setArgument('page', CPagerHelper::loadPage($this->getInput('action_src'), null)) + ); + + if ($result) { + $response->setFormData(['uncheck' => '1']); + CMessageHelper::setSuccessTitle(_n('API token deleted', 'API tokens deleted', $deleted)); + } + else { + CMessageHelper::setErrorTitle(_n('Cannot delete API token', 'Cannot delete API tokens', $deleted)); + } + + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenDisable.php b/ui/app/controllers/CControllerTokenDisable.php new file mode 100644 index 00000000000..dc68bd3ec8a --- /dev/null +++ b/ui/app/controllers/CControllerTokenDisable.php @@ -0,0 +1,71 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenDisable extends CController { + + protected function checkInput() { + $fields = [ + 'tokenids' => 'required|array_db token.tokenid', + 'action_src' => 'required|in token.list,user.token.list' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $tokens = []; + + foreach ($this->getInput('tokenids') as $tokenid) { + $tokens[] = ['tokenid' => $tokenid, 'status' => ZBX_AUTH_TOKEN_DISABLED]; + } + + $result = API::Token()->update($tokens); + $updated = count($tokens); + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgument('action', $this->getInput('action_src')) + ->setArgument('page', CPagerHelper::loadPage($this->getInput('action_src'), null)) + ); + + if ($result) { + $response->setFormData(['uncheck' => '1']); + CMessageHelper::setSuccessTitle(_n('API token disabled', 'API tokens disabled', $updated)); + } + else { + CMessageHelper::setErrorTitle(_n('Cannot disable API token', 'Cannot disable API tokens', $updated)); + } + + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenEdit.php b/ui/app/controllers/CControllerTokenEdit.php new file mode 100644 index 00000000000..7fd13ae019a --- /dev/null +++ b/ui/app/controllers/CControllerTokenEdit.php @@ -0,0 +1,110 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenEdit extends CController { + + protected function init() { + $this->disableSIDValidation(); + } + + protected function checkInput() { + $fields = [ + 'tokenid' => 'db token.tokenid', + 'name' => 'db token.name', + 'description' => 'db token.description', + 'userid' => 'db users.userid', + 'expires_state' => 'in 0,1', + 'expires_at' => 'string', + 'status' => 'db token.status|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return ($this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS) + && $this->checkAccess(CRoleHelper::UI_ADMINISTRATION_GENERAL) + ); + } + + protected function doAction() { + if ($this->hasInput('tokenid')) { + $tokens = API::Token()->get([ + 'output' => ['tokenid', 'userid', 'name', 'description', 'expires_at', 'status'], + 'tokenids' => $this->getInput('tokenid') + ]); + + if (!$tokens) { + access_deny(ACCESS_DENY_PAGE); + } + + $data = $tokens[0]; + + if ($data['expires_at'] != 0) { + $data['expires_at'] = date(DATE_TIME_FORMAT_SECONDS, (int) $data['expires_at']); + $data['expires_state'] = '1'; + } + else { + $data['expires_at'] = null; + $data['expires_state'] = '0'; + } + } + else { + $data = [ + 'tokenid' => 0, + 'userid' => 0, + 'name' => '', + 'description' => '', + 'expires_at' => null, + 'expires_state' => '1', + 'status' => ZBX_AUTH_TOKEN_ENABLED + ]; + } + + $data['ms_user'] = []; + $this->getInputs($data, ['userid', 'name', 'description', 'expires_at', 'expires_state', 'status']); + + if ($data['userid'] != 0) { + [$user] = (CWebUser::$data['userid'] != $data['userid']) + ? API::User()->get([ + 'output' => ['alias', 'name', 'surname'], + 'userids' => $data['userid'] + ]) + : [CWebUser::$data]; + + $data['ms_user'] = [['id' => $user['userid'], 'name' => getUserFullname($user)]]; + } + + $response = new CControllerResponseData($data); + $response->setTitle(_('API tokens')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenEnable.php b/ui/app/controllers/CControllerTokenEnable.php new file mode 100644 index 00000000000..1f6381b2ba6 --- /dev/null +++ b/ui/app/controllers/CControllerTokenEnable.php @@ -0,0 +1,71 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenEnable extends CController { + + protected function checkInput() { + $fields = [ + 'tokenids' => 'required|array_db token.tokenid', + 'action_src' => 'required|in token.list,user.token.list' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $tokens = []; + + foreach ($this->getInput('tokenids') as $tokenid) { + $tokens[] = ['tokenid' => $tokenid, 'status' => ZBX_AUTH_TOKEN_ENABLED]; + } + + $result = API::Token()->update($tokens); + $updated = count($tokens); + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgument('action', $this->getInput('action_src')) + ->setArgument('page', CPagerHelper::loadPage($this->getInput('action_src'), null)) + ); + + if ($result) { + $response->setFormData(['uncheck' => '1']); + CMessageHelper::setSuccessTitle(_n('API token enabled', 'API tokens enabled', $updated)); + } + else { + CMessageHelper::setErrorTitle(_n('Cannot enable API token', 'Cannot enable API tokens', $updated)); + } + + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenList.php b/ui/app/controllers/CControllerTokenList.php new file mode 100644 index 00000000000..40ebae99564 --- /dev/null +++ b/ui/app/controllers/CControllerTokenList.php @@ -0,0 +1,196 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenList extends CController { + + protected function init() { + $this->disableSIDValidation(); + } + + protected function checkInput() { + $fields = [ + 'sort' => 'in name,user,expires_at,creator,lastaccess,status', + 'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP, + 'uncheck' => 'in 1', + 'filter_set' => 'in 1', + 'filter_rst' => 'in 1', + 'filter_name' => 'string', + 'filter_userids' => 'array_db users.userid', + 'filter_expires_state' => 'in 1', + 'filter_expires_days' => 'int32', + 'filter_creator_userids' => 'array_db users.userid', + 'filter_status' => 'in -1,'.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED, + 'page' => 'ge 1' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return ($this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS) + && $this->checkAccess(CRoleHelper::UI_ADMINISTRATION_GENERAL) + ); + } + + protected function doAction() { + $sort_field = $this->getInput('sort', CProfile::get('web.token.list.sort', 'name')); + $sort_order = $this->getInput('sortorder', CProfile::get('web.token.list.sortorder', ZBX_SORT_UP)); + + CProfile::update('web.token.list.sort', $sort_field, PROFILE_TYPE_STR); + CProfile::update('web.token.list.sortorder', $sort_order, PROFILE_TYPE_STR); + + if ($this->hasInput('filter_set')) { + CProfile::update('web.token.filter_name', $this->getInput('filter_name', ''), PROFILE_TYPE_STR); + CProfile::updateArray('web.token.filter_userids', $this->getInput('filter_userids', []), PROFILE_TYPE_ID); + CProfile::update('web.token.filter_expires_state', $this->getInput('filter_expires_state', 0), + PROFILE_TYPE_INT + ); + CProfile::update('web.token.filter_expires_days', $this->getInput('filter_expires_days', 14), + PROFILE_TYPE_INT + ); + CProfile::updateArray('web.token.filter_creator_userids', $this->getInput('filter_creator_userids', []), + PROFILE_TYPE_ID + ); + CProfile::update('web.token.filter_status', $this->getInput('filter_status', -1), PROFILE_TYPE_INT); + } + elseif ($this->hasInput('filter_rst')) { + CProfile::delete('web.token.filter_name'); + CProfile::deleteIdx('web.token.filter_userids'); + CProfile::delete('web.token.filter_expires_state'); + CProfile::delete('web.token.filter_expires_days'); + CProfile::deleteIdx('web.token.filter_creator_userids'); + CProfile::delete('web.token.filter_status'); + } + + $filter = [ + 'name' => CProfile::get('web.token.filter_name', ''), + 'userids' => CProfile::getArray('web.token.filter_userids', []), + 'expires_state' => CProfile::get('web.token.filter_expires_state', 0), + 'expires_days' => CProfile::get('web.token.filter_expires_days', 14), + 'creator_userids' => CProfile::getArray('web.token.filter_creator_userids', []), + 'status' => CProfile::get('web.token.filter_status', -1) + ]; + + $data = [ + 'ms_users' => [], + 'ms_creators' => [], + 'uncheck' => $this->hasInput('uncheck'), + 'sort' => $sort_field, + 'sortorder' => $sort_order, + 'filter' => $filter, + 'profileIdx' => 'web.token.filter', + 'active_tab' => CProfile::get('web.token.filter.active', 1) + ]; + + $limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1; + $data['tokens'] = API::Token()->get([ + 'output' => ['tokenid', 'name', 'userid', 'expires_at', 'created_at', 'creator_userid', 'lastaccess', + 'status' + ], + 'userids' => $filter['userids'] ? $filter['userids'] : null, + 'valid_at' => $filter['expires_state'] ? time() : null, + 'expired_at' => $filter['expires_state'] + ? bcadd((string) time(), bcmul($filter['expires_days'], (string) SEC_PER_DAY, 0), 0) + : null, + 'search' => [ + 'name' => ($filter['name'] === '') ? null : $filter['name'] + ], + 'filter' => [ + 'creator_userid' => $filter['creator_userids'] ? $filter['creator_userids'] : null, + 'status' => ($filter['status'] == -1) ? null : $filter['status'] + ], + 'limit' => $limit, + 'preservekeys' => true + ]); + + if ($data['tokens'] === false) { + $data['tokens'] = []; + } + + $userids = array_column($data['tokens'], 'userid', 'userid'); + $userids += array_column($data['tokens'], 'creator_userid', 'creator_userid'); + $userids += array_flip($filter['userids']); + $userids += array_flip($filter['creator_userids']); + + $users = $userids + ? API::User()->get([ + 'output' => ['alias', 'name', 'surname'], + 'userids' => array_keys($userids), + 'preservekeys' => true + ]) + : []; + + $now = time(); + array_walk($data['tokens'], function (array &$token) use ($users, $now) { + $token['user'] = getUserFullname($users[$token['userid']]); + + $token['creator'] = array_key_exists($token['creator_userid'], $users) + ? getUserFullname($users[$token['creator_userid']]) + : null; + + $token['is_expired'] = $token['expires_at'] + ? $now > $token['expires_at'] + : false; + }); + + CArrayHelper::sort($data['tokens'], [['field' => $sort_field, 'order' => $sort_order]]); + + foreach ($filter['userids'] as $userid) { + if (!array_key_exists($userid, $users)) { + continue; + } + + $data['ms_users'][] = ['id' => $userid, 'name' => getUserFullname($users[$userid])]; + } + + CArrayHelper::sort($data['ms_users'], ['name']); + + foreach ($filter['creator_userids'] as $userid) { + if (!array_key_exists($userid, $users)) { + continue; + } + + $data['ms_creators'][] = ['id' => $userid, 'name' => getUserFullname($users[$userid])]; + } + + CArrayHelper::sort($data['ms_creators'], ['name']); + + $page_num = $this->getInput('page', 1); + CPagerHelper::savePage('token.list', $page_num); + $data['paging'] = CPagerHelper::paginate($page_num, $data['tokens'], $sort_order, + (new CUrl('zabbix.php'))->setArgument('action', $this->getAction()) + ); + + $response = new CControllerResponseData($data); + $response->setTitle(_('API tokens')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenUpdate.php b/ui/app/controllers/CControllerTokenUpdate.php new file mode 100644 index 00000000000..c8fd67f925f --- /dev/null +++ b/ui/app/controllers/CControllerTokenUpdate.php @@ -0,0 +1,127 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenUpdate extends CController { + + protected function checkInput() { + $fields = [ + 'tokenid' => 'db token.tokenid|required|fatal', + 'name' => 'db token.name|required|not_empty', + 'description' => 'db token.description', + 'expires_state' => 'in 0,1|required', + 'expires_at' => 'range_time', + 'status' => 'db token.status|required|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED, + 'action_src' => 'fatal|required|in token.edit,user.token.edit', + 'action_dst' => 'fatal|required|in token.list,user.token.list,token.view,user.token.view', + 'regenerate' => 'in 1' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + switch ($this->getValidationError()) { + case self::VALIDATION_ERROR: + $location = (new CUrl('zabbix.php')) + ->setArgument('tokenid', $this->getInput('tokenid')) + ->setArgument('action', $this->getInput('action_src')); + $response = new CControllerResponseRedirect($location); + $response->setFormData($this->getInputAll()); + CMessageHelper::setErrorTitle(_('Cannot update API token')); + $this->setResponse($response); + break; + case self::VALIDATION_FATAL_ERROR: + $this->setResponse(new CControllerResponseFatal()); + break; + } + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $this->getInputs($token, ['tokenid', 'name', 'description', 'expires_at', 'status']); + + $token['expires_at'] = $this->getInput('expires_state') + ? (new DateTime($token['expires_at']))->getTimestamp() + : 0; + + $result = API::Token()->update($token); + + if ($result) { + if ($this->hasInput('regenerate')) { + ['tokenids' => $tokenids] = $result; + [['userid' => $userid]] = API::Token()->get([ + 'output' => ['userid'], + 'tokenids' => $tokenids + ]); + [['token' => $auth_token]] = API::Token()->generate($tokenids); + + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgumentSID() + ->setArgument('action', $this->getInput('action_dst')) + ); + + [$user] = (CWebUser::$data['userid'] != $userid) + ? API::User()->get([ + 'output' => ['alias', 'name', 'surname'], + 'userids' => $userid + ]) + : [CWebUser::$data]; + + $response->setFormData([ + 'name' => $token['name'], + 'user' => getUserFullname($user), + 'auth_token' => $auth_token, + 'expires_at' => $token['expires_at'], + 'description' => $token['description'], + 'status' => $token['status'] + ]); + } + else { + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgument('action', $this->getInput('action_dst')) + ->setArgument('page', CPagerHelper::loadPage($this->getInput('action_dst'), null)) + ); + $response->setFormData(['uncheck' => '1']); + } + + CMessageHelper::setSuccessTitle(_('API token updated')); + } + else { + $response = new CControllerResponseRedirect((new CUrl('zabbix.php')) + ->setArgument('action', $this->getInput('action_src')) + ->setArgument('tokenid', $this->getInput('tokenid')) + ); + $response->setFormData($this->getInputAll()); + CMessageHelper::setErrorTitle(_('Cannot update API token')); + } + + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerTokenView.php b/ui/app/controllers/CControllerTokenView.php new file mode 100644 index 00000000000..031fe34e772 --- /dev/null +++ b/ui/app/controllers/CControllerTokenView.php @@ -0,0 +1,59 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerTokenView extends CController { + + protected function checkInput() { + $fields = [ + 'name' => 'required', + 'user' => 'required', + 'auth_token' => 'required', + 'description' => 'required', + 'expires_at' => 'required', + 'status' => 'db token.status|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED.'|required' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return ($this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS) + && $this->checkAccess(CRoleHelper::UI_ADMINISTRATION_GENERAL) + ); + } + + protected function doAction() { + $data = $this->getInputAll(); + $response = new CControllerResponseData($data); + $response->setTitle(_('API tokens')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerUserTokenEdit.php b/ui/app/controllers/CControllerUserTokenEdit.php new file mode 100644 index 00000000000..5ed65e3c5d4 --- /dev/null +++ b/ui/app/controllers/CControllerUserTokenEdit.php @@ -0,0 +1,94 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerUserTokenEdit extends CController { + + protected function init() { + $this->disableSIDValidation(); + } + + protected function checkInput() { + $fields = [ + 'tokenid' => 'db token.tokenid', + 'name' => 'db token.name', + 'description' => 'db token.description', + 'expires_state' => 'in 0,1', + 'expires_at' => 'string', + 'status' => 'db token.status|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + if ($this->hasInput('tokenid')) { + $tokens = API::Token()->get([ + 'output' => ['tokenid', 'name', 'description', 'expires_at', 'status'], + 'tokenids' => $this->getInput('tokenid') + ]); + + if (!$tokens) { + access_deny(ACCESS_DENY_PAGE); + } + + $data = $tokens[0]; + + if ($data['expires_at'] != 0) { + $data['expires_at'] = date(DATE_TIME_FORMAT_SECONDS, (int) $data['expires_at']); + $data['expires_state'] = '1'; + } + else { + $data['expires_at'] = null; + $data['expires_state'] = '0'; + } + } + else { + $data = [ + 'tokenid' => 0, + 'name' => '', + 'description' => '', + 'expires_at' => null, + 'expires_state' => '1', + 'status' => ZBX_AUTH_TOKEN_ENABLED + ]; + } + + $this->getInputs($data, ['name', 'description', 'expires_at', 'expires_state', 'status']); + + $response = new CControllerResponseData($data); + $response->setTitle(_('API tokens')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerUserTokenList.php b/ui/app/controllers/CControllerUserTokenList.php new file mode 100644 index 00000000000..6f7e7b1be94 --- /dev/null +++ b/ui/app/controllers/CControllerUserTokenList.php @@ -0,0 +1,140 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerUserTokenList extends CController { + + protected function init() { + $this->disableSIDValidation(); + } + + protected function checkInput() { + $fields = [ + 'sort' => 'in name,expires_at,lastaccess,status', + 'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP, + 'uncheck' => 'in 1', + 'filter_set' => 'in 1', + 'filter_rst' => 'in 1', + 'filter_name' => 'string', + 'filter_expires_state' => 'in 1', + 'filter_expires_days' => 'int32', + 'filter_status' => 'in -1,'.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED, + 'page' => 'ge 1' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $sort_field = $this->getInput('sort', CProfile::get('web.user.token.list.sort', 'name')); + $sort_order = $this->getInput('sortorder', CProfile::get('web.user.token.list.sortorder', ZBX_SORT_UP)); + + CProfile::update('web.user.token.list.sort', $sort_field, PROFILE_TYPE_STR); + CProfile::update('web.user.token.list.sortorder', $sort_order, PROFILE_TYPE_STR); + + if ($this->hasInput('filter_set')) { + CProfile::update('web.user.token.filter_name', $this->getInput('filter_name', ''), PROFILE_TYPE_STR); + CProfile::update('web.user.token.filter_expires_state', $this->getInput('filter_expires_state', 0), + PROFILE_TYPE_INT + ); + CProfile::update('web.user.token.filter_expires_days', $this->getInput('filter_expires_days', 14), + PROFILE_TYPE_INT + ); + CProfile::update('web.user.token.filter_status', $this->getInput('filter_status', -1), PROFILE_TYPE_INT); + } + elseif ($this->hasInput('filter_rst')) { + CProfile::delete('web.user.token.filter_name'); + CProfile::delete('web.user.token.filter_expires_state'); + CProfile::delete('web.user.token.filter_expires_days'); + CProfile::delete('web.user.token.filter_status'); + } + + $filter = [ + 'name' => CProfile::get('web.user.token.filter_name', ''), + 'expires_state' => CProfile::get('web.user.token.filter_expires_state', 0), + 'expires_days' => CProfile::get('web.user.token.filter_expires_days', 14), + 'status' => CProfile::get('web.user.token.filter_status', -1) + ]; + + $data = [ + 'uncheck' => $this->hasInput('uncheck'), + 'sort' => $sort_field, + 'sortorder' => $sort_order, + 'filter' => $filter, + 'profileIdx' => 'web.user.token.filter', + 'active_tab' => CProfile::get('web.user.token.filter.active', 1) + ]; + + $limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1; + $data['tokens'] = API::Token()->get([ + 'output' => ['tokenid', 'name', 'expires_at', 'created_at', 'lastaccess', 'status'], + 'userids' => CWebUser::$data['userid'], + 'valid_at' => $filter['expires_state'] ? time() : null, + 'expired_at' => $filter['expires_state'] + ? bcadd((string) time(), bcmul($filter['expires_days'], (string) SEC_PER_DAY, 0), 0) + : null, + 'search' => [ + 'name' => ($filter['name'] === '') ? null : $filter['name'] + ], + 'filter' => [ + 'status' => ($filter['status'] == -1) ? null : $filter['status'] + ], + 'limit' => $limit, + 'preservekeys' => true + ]); + + if ($data['tokens'] === false) { + $data['tokens'] = []; + } + + $now = time(); + array_walk($data['tokens'], function (array &$token) use ($now) { + $token['is_expired'] = $token['expires_at'] + ? $now > $token['expires_at'] + : false; + }); + + CArrayHelper::sort($data['tokens'], [['field' => $sort_field, 'order' => $sort_order]]); + + $page_num = $this->getInput('page', 1); + CPagerHelper::savePage('user.token.list', $page_num); + $data['paging'] = CPagerHelper::paginate($page_num, $data['tokens'], $sort_order, + (new CUrl('zabbix.php'))->setArgument('action', $this->getAction()) + ); + + $response = new CControllerResponseData($data); + $response->setTitle(_('API tokens')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerUserTokenView.php b/ui/app/controllers/CControllerUserTokenView.php new file mode 100644 index 00000000000..d49d03f4419 --- /dev/null +++ b/ui/app/controllers/CControllerUserTokenView.php @@ -0,0 +1,56 @@ +<?php declare(strict_types=1); +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerUserTokenView extends CController { + + protected function checkInput() { + $fields = [ + 'name' => 'required', + 'auth_token' => 'required', + 'description' => 'required', + 'expires_at' => 'required', + 'status' => 'db token.status|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED.'|required' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + if (CWebUser::isGuest()) { + return false; + } + + return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS); + } + + protected function doAction() { + $data = $this->getInputAll(); + $response = new CControllerResponseData($data); + $response->setTitle(_('API tokens')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerUserroleCreate.php b/ui/app/controllers/CControllerUserroleCreate.php index c7fbdeda9ea..2b1128b2d33 100644 --- a/ui/app/controllers/CControllerUserroleCreate.php +++ b/ui/app/controllers/CControllerUserroleCreate.php @@ -74,6 +74,7 @@ class CControllerUserroleCreate extends CControllerUserroleEditGeneral { 'actions_change_severity' => 'in 0,1', 'actions_add_problem_comments' => 'in 0,1', 'actions_execute_scripts' => 'in 0,1', + 'actions_manage_api_tokens' => 'in 0,1', 'modules' => 'array', 'api_mode' => 'in 0,1', 'api_methods' => 'array' diff --git a/ui/app/controllers/CControllerUserroleEdit.php b/ui/app/controllers/CControllerUserroleEdit.php index 869049e32d0..03afaa57c41 100644 --- a/ui/app/controllers/CControllerUserroleEdit.php +++ b/ui/app/controllers/CControllerUserroleEdit.php @@ -77,6 +77,7 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral { 'actions_change_severity' => 'in 0,1', 'actions_add_problem_comments' => 'in 0,1', 'actions_execute_scripts' => 'in 0,1', + 'actions_manage_api_tokens' => 'in 0,1', 'ui_default_access' => 'in 0,1', 'modules_default_access' => 'in 0,1', 'actions_default_access' => 'in 0,1', diff --git a/ui/app/controllers/CControllerUserroleUpdate.php b/ui/app/controllers/CControllerUserroleUpdate.php index 4cc4519f1b1..c7821cf3144 100644 --- a/ui/app/controllers/CControllerUserroleUpdate.php +++ b/ui/app/controllers/CControllerUserroleUpdate.php @@ -73,6 +73,7 @@ class CControllerUserroleUpdate extends CControllerUserroleEditGeneral { 'actions_change_severity' => 'in 0,1', 'actions_add_problem_comments' => 'in 0,1', 'actions_execute_scripts' => 'in 0,1', + 'actions_manage_api_tokens' => 'in 0,1', 'ui_default_access' => 'in 0,1', 'modules_default_access' => 'in 0,1', 'actions_default_access' => 'in 0,1', diff --git a/ui/app/controllers/CControllerWidgetHostAvailView.php b/ui/app/controllers/CControllerWidgetHostAvailView.php index 43f7ae91124..20eb83c765a 100644 --- a/ui/app/controllers/CControllerWidgetHostAvailView.php +++ b/ui/app/controllers/CControllerWidgetHostAvailView.php @@ -34,14 +34,7 @@ class CControllerWidgetHostAvailView extends CControllerWidget { protected function doAction() { $fields = $this->getForm()->getFieldsData(); - $type_fields = [ - INTERFACE_TYPE_AGENT => 'available', - INTERFACE_TYPE_SNMP => 'snmp_available', - INTERFACE_TYPE_JMX => 'jmx_available', - INTERFACE_TYPE_IPMI => 'ipmi_available' - ]; - - $interface_types = array_keys($type_fields); + $interface_types = [INTERFACE_TYPE_AGENT, INTERFACE_TYPE_SNMP, INTERFACE_TYPE_JMX, INTERFACE_TYPE_IPMI]; // Sanitize non-existing interface types. $fields['interface_type'] = array_values(array_intersect($interface_types, $fields['interface_type'])); @@ -52,28 +45,34 @@ class CControllerWidgetHostAvailView extends CControllerWidget { $hosts_total = array_fill_keys($interface_types, 0); $hosts_count = array_fill_keys($interface_types, [ - HOST_AVAILABLE_UNKNOWN => 0, - HOST_AVAILABLE_TRUE => 0, - HOST_AVAILABLE_FALSE => 0 + INTERFACE_AVAILABLE_UNKNOWN => 0, + INTERFACE_AVAILABLE_TRUE => 0, + INTERFACE_AVAILABLE_FALSE => 0 ]); $db_hosts = API::Host()->get([ - 'output' => ['available', 'snmp_available', 'jmx_available', 'ipmi_available'], - 'selectInterfaces' => ['interfaceid', 'type'], + 'output' => [], + 'selectInterfaces' => ['type', 'available'], 'groupids' => $groupids, 'filter' => ($fields['maintenance'] == HOST_MAINTENANCE_STATUS_OFF) ? ['status' => HOST_STATUS_MONITORED, 'maintenance_status' => HOST_MAINTENANCE_STATUS_OFF] : ['status' => HOST_STATUS_MONITORED] ]); + $availability_priority = [INTERFACE_AVAILABLE_FALSE, INTERFACE_AVAILABLE_UNKNOWN, INTERFACE_AVAILABLE_TRUE]; foreach ($db_hosts as $host) { - $interfaces = []; - foreach ($host['interfaces'] as $val) { - $interfaces[$val['type']] = true; + $host_interfaces = array_fill_keys($interface_types, []); + + foreach ($host['interfaces'] as $interface) { + $host_interfaces[$interface['type']][] = $interface['available']; } - foreach (array_keys($interfaces) as $type) { - $hosts_count[$type][$host[$type_fields[$type]]]++; + $host_interfaces = array_filter($host_interfaces); + + foreach ($host_interfaces as $type => $interfaces) { + $interfaces_availability = array_intersect($availability_priority, $interfaces); + $available = reset($interfaces_availability); + $hosts_count[$type][$available]++; $hosts_total[$type]++; } } |