diff options
author | Andrejs Kozlovs <andrejs.kozlovs@zabbix.com> | 2020-12-01 12:11:01 +0300 |
---|---|---|
committer | Andrejs Kozlovs <andrejs.kozlovs@zabbix.com> | 2020-12-01 12:11:01 +0300 |
commit | 44b054e5a20955a7c702f22830fa8e71877f90b3 (patch) | |
tree | e2931902925c9a5d76ea384dfc0be8e17ec1758c /ui/app | |
parent | f37addd9700a4ed7c1849e9d3eb58c4766a1775d (diff) | |
parent | 59f798d09c38a717446b04eee081e54d2c46268f (diff) |
.......PS. [ZBXNEXT-6311] update from branch 'master' of https://git.zabbix.com/scm/zbx/zabbix into feature/ZBXNEXT-6311-5.3
Diffstat (limited to 'ui/app')
67 files changed, 814 insertions, 192 deletions
diff --git a/ui/app/controllers/CControllerAuthenticationUpdate.php b/ui/app/controllers/CControllerAuthenticationUpdate.php index f14a2335f36..b24396a9ee9 100644 --- a/ui/app/controllers/CControllerAuthenticationUpdate.php +++ b/ui/app/controllers/CControllerAuthenticationUpdate.php @@ -169,7 +169,8 @@ class CControllerAuthenticationUpdate extends CController { 'bind_dn' => $ldap_auth['ldap_bind_dn'], 'bind_password' => $ldap_auth['ldap_bind_password'], 'search_attribute' => $ldap_auth['ldap_search_attribute'] - ] + ], + 'detailed_errors' => true ]); $login = $ldap_validator->validate([ diff --git a/ui/app/controllers/CControllerDashboardWidgetCheck.php b/ui/app/controllers/CControllerDashboardWidgetCheck.php index 7bb881e3b80..41a02c77a64 100644 --- a/ui/app/controllers/CControllerDashboardWidgetCheck.php +++ b/ui/app/controllers/CControllerDashboardWidgetCheck.php @@ -28,7 +28,7 @@ class CControllerDashboardWidgetCheck extends CController { 'templateid' => 'db dashboard.templateid', 'type' => 'required|string', 'name' => 'required|string', - 'fields' => 'json', + 'fields' => 'json' ]; $ret = $this->validateInput($fields); diff --git a/ui/app/controllers/CControllerDiscoveryView.php b/ui/app/controllers/CControllerDiscoveryView.php index 403392382ad..ef7556c6d97 100644 --- a/ui/app/controllers/CControllerDiscoveryView.php +++ b/ui/app/controllers/CControllerDiscoveryView.php @@ -80,7 +80,7 @@ class CControllerDiscoveryView extends CController { 'druleids' => $filter_druleids, 'filter' => ['status' => DRULE_STATUS_ACTIVE] ]), ['druleid' => 'id']) - : [], + : [] ], 'profileIdx' => 'web.discovery.filter', 'active_tab' => CProfile::get('web.discovery.filter.active', 1) diff --git a/ui/app/controllers/CControllerGuiEdit.php b/ui/app/controllers/CControllerGuiEdit.php index 27870f8b82c..0ee67a22f5f 100644 --- a/ui/app/controllers/CControllerGuiEdit.php +++ b/ui/app/controllers/CControllerGuiEdit.php @@ -21,14 +21,23 @@ class CControllerGuiEdit extends CController { + /** + * @var array + */ + protected $timezones; + protected function init() { $this->disableSIDValidation(); + + $this->timezones = [ + ZBX_DEFAULT_TIMEZONE => CDateTimeZoneHelper::getSystemDateTimeZone() + ] + (new CDateTimeZoneHelper())->getAllDateTimeZones(); } protected function checkInput() { $fields = [ 'default_lang' => 'db config.default_lang', - 'default_timezone' => 'db config.default_timezone', + 'default_timezone' => 'db config.default_timezone|in '.implode(',', array_keys($this->timezones)), 'default_theme' => 'db config.default_theme', 'search_limit' => 'db config.search_limit', 'max_overview_table_size' => 'db config.max_overview_table_size', @@ -60,6 +69,7 @@ class CControllerGuiEdit extends CController { 'default_timezone' => $this->getInput('default_timezone', CSettingsHelper::get( CSettingsHelper::DEFAULT_TIMEZONE )), + 'timezones' => $this->timezones, 'default_theme' => $this->getInput('default_theme', CSettingsHelper::get(CSettingsHelper::DEFAULT_THEME)), 'search_limit' => $this->getInput('search_limit', CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT)), 'max_overview_table_size' => $this->getInput('max_overview_table_size', CSettingsHelper::get( diff --git a/ui/app/controllers/CControllerGuiUpdate.php b/ui/app/controllers/CControllerGuiUpdate.php index df0b6905d5b..ad093a75aec 100644 --- a/ui/app/controllers/CControllerGuiUpdate.php +++ b/ui/app/controllers/CControllerGuiUpdate.php @@ -23,9 +23,11 @@ class CControllerGuiUpdate extends CController { protected function checkInput() { $themes = array_keys(APP::getThemes()); + $timezones = array_keys((new CDateTimeZoneHelper())->getAllDateTimeZones()); + $fields = [ 'default_lang' => 'db config.default_lang|in '.implode(',', array_keys(getLocales())), - 'default_timezone' => 'required|in '.ZBX_DEFAULT_TIMEZONE.','.implode(',', DateTimeZone::listIdentifiers()).'|db config.default_timezone', + 'default_timezone' => 'required|in '.ZBX_DEFAULT_TIMEZONE.','.implode(',', $timezones).'|db config.default_timezone', 'default_theme' => 'required|db config.default_theme|in '.implode(',', $themes), 'search_limit' => 'required|db config.search_limit|ge 1|le 999999', 'max_overview_table_size' => 'required|db config.max_overview_table_size|ge 5|le 999999', diff --git a/ui/app/controllers/CControllerHost.php b/ui/app/controllers/CControllerHost.php index ad8ff8fc88b..cdd7a6d3bc4 100644 --- a/ui/app/controllers/CControllerHost.php +++ b/ui/app/controllers/CControllerHost.php @@ -137,7 +137,7 @@ abstract class CControllerHost extends CController { 'port' => ($filter['port'] === '') ? null : $filter['port'], 'maintenance_status' => ($filter['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) ? null - : HOST_MAINTENANCE_STATUS_OFF, + : HOST_MAINTENANCE_STATUS_OFF ], 'sortfield' => 'name', 'limit' => $limit, diff --git a/ui/app/controllers/CControllerHostView.php b/ui/app/controllers/CControllerHostView.php index 71c840c5a44..1c5cf2e8b3c 100644 --- a/ui/app/controllers/CControllerHostView.php +++ b/ui/app/controllers/CControllerHostView.php @@ -115,7 +115,7 @@ class CControllerHostView extends CControllerHost { 'support_custom_time' => 0, 'expanded' => $profile->expanded, 'page' => $filter['page'] - ], + ] ] + $this->getData($filter); $response = new CControllerResponseData($data); diff --git a/ui/app/controllers/CControllerHousekeepingUpdate.php b/ui/app/controllers/CControllerHousekeepingUpdate.php index 93d6c60d273..874b67d81a7 100644 --- a/ui/app/controllers/CControllerHousekeepingUpdate.php +++ b/ui/app/controllers/CControllerHousekeepingUpdate.php @@ -62,7 +62,7 @@ class CControllerHousekeepingUpdate extends CController { 'hk_history_global' => '0', 'hk_trends_mode' => '0', 'hk_trends_global' => '0', - 'compression_status' => '0', + 'compression_status' => '0' ]); CMessageHelper::setErrorTitle(_('Cannot update configuration')); $this->setResponse($response); diff --git a/ui/app/controllers/CControllerMediatypeList.php b/ui/app/controllers/CControllerMediatypeList.php index 2bdf3da097f..98d09ccb317 100644 --- a/ui/app/controllers/CControllerMediatypeList.php +++ b/ui/app/controllers/CControllerMediatypeList.php @@ -33,7 +33,7 @@ class CControllerMediatypeList extends CController { 'filter_set' => 'in 1', 'filter_rst' => 'in 1', 'filter_name' => 'string', - 'filter_status' => 'in -1,'.MEDIA_TYPE_STATUS_ACTIVE.','.MEDIA_TYPE_STATUS_DISABLED, + 'filter_status' => 'in -1,'.MEDIA_TYPE_STATUS_ACTIVE.','.MEDIA_TYPE_STATUS_DISABLED ]; $ret = $this->validateInput($fields); diff --git a/ui/app/controllers/CControllerMenuPopup.php b/ui/app/controllers/CControllerMenuPopup.php index 42f96a46539..a98c5f30da6 100644 --- a/ui/app/controllers/CControllerMenuPopup.php +++ b/ui/app/controllers/CControllerMenuPopup.php @@ -434,7 +434,7 @@ class CControllerMenuPopup extends CController { case SYSMAP_ELEMENT_TYPE_IMAGE: $menu_data = [ - 'type' => 'map_element_image', + 'type' => 'map_element_image' ]; if ($selement['urls']) { $menu_data['urls'] = $selement['urls']; @@ -492,7 +492,7 @@ class CControllerMenuPopup extends CController { */ private static function getMenuDataTrigger(array $data) { $db_triggers = API::Trigger()->get([ - 'output' => ['expression', 'url', 'comments'], + 'output' => ['expression', 'url', 'comments', 'manual_close'], 'selectHosts' => ['hostid', 'name', 'status'], 'selectItems' => ['itemid', 'hostid', 'name', 'key_', 'value_type'], 'triggerids' => $data['triggerid'], @@ -551,10 +551,6 @@ class CControllerMenuPopup extends CController { 'items' => $items, 'showEvents' => $show_events, 'allowed_ui_problems' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_PROBLEMS), - 'allowed_ack' => CWebUser::checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS) - || CWebUser::checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) - || CWebUser::checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY) - || CWebUser::checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS), 'allowed_ui_conf_hosts' => CWebUser::checkAccess(CRoleHelper::UI_CONFIGURATION_HOSTS), 'allowed_ui_latest_data' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_LATEST_DATA) ]; @@ -566,16 +562,35 @@ class CControllerMenuPopup extends CController { ]; } + $can_be_closed = ($db_trigger['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED + && CWebUser::checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) + ); + if (array_key_exists('eventid', $data)) { $menu_data['eventid'] = $data['eventid']; $events = API::Event()->get([ - 'output' => ['urls'], + 'output' => ['r_eventid', 'urls'], + 'select_acknowledges' => ['action'], 'eventids' => $data['eventid'] ]); if ($events) { - foreach ($events[0]['urls'] as $url) { + $event = $events[0]; + + if ($event['r_eventid'] != 0) { + $can_be_closed = false; + } + else { + foreach ($event['acknowledges'] as $acknowledge) { + if (($acknowledge['action'] & ZBX_PROBLEM_UPDATE_CLOSE) == ZBX_PROBLEM_UPDATE_CLOSE) { + $can_be_closed = false; + break; + } + } + } + + foreach ($event['urls'] as $url) { $menu_data['urls'][] = [ 'label' => $url['name'], 'url' => $url['url'], @@ -598,7 +613,13 @@ class CControllerMenuPopup extends CController { } if (array_key_exists('acknowledge', $data)) { - $menu_data['acknowledge'] = (bool) $data['acknowledge']; + $menu_data['acknowledge'] = ((bool) $data['acknowledge'] + && (CWebUser::checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS) + || CWebUser::checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY) + || CWebUser::checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS) + || $can_be_closed + ) + ); } return $menu_data; @@ -644,18 +665,26 @@ class CControllerMenuPopup extends CController { $menu_data['params'] = $data['params']; } - if ($data['widgetType'] == WIDGET_GRAPH && array_key_exists('graphid', $data) && $data['graphid']) { - $menu_data['download'] = (bool) API::Graph()->get([ - 'output' => ['graphid'], - 'graphids' => $data['graphid'] - ]); - } - elseif ($data['widgetType'] == WIDGET_GRAPH && array_key_exists('itemid', $data) && $data['itemid']) { - $menu_data['download'] = (bool) API::Item()->get([ - 'output' => ['itemid'], - 'itemids' => $data['itemid'], - 'webitems' => true - ]); + if ($data['widgetType'] == WIDGET_GRAPH) { + $options = []; + + if (array_key_exists('dynamic_hostid', $data)) { + $options['hostids'] = $data['dynamic_hostid']; + } + + if (array_key_exists('graphid', $data) && $data['graphid']) { + $menu_data['download'] = (bool) API::Graph()->get($options + [ + 'output' => ['graphid'], + 'graphids' => $data['graphid'] + ]); + } + elseif (array_key_exists('itemid', $data) && $data['itemid']) { + $menu_data['download'] = (bool) API::Item()->get($options + [ + 'output' => ['itemid'], + 'itemids' => $data['itemid'], + 'webitems' => true + ]); + } } return $menu_data; diff --git a/ui/app/controllers/CControllerModuleEdit.php b/ui/app/controllers/CControllerModuleEdit.php index d5918bfb550..bf2d722f543 100644 --- a/ui/app/controllers/CControllerModuleEdit.php +++ b/ui/app/controllers/CControllerModuleEdit.php @@ -91,7 +91,7 @@ class CControllerModuleEdit extends CController { ? $this->hasInput('status') ? MODULE_STATUS_ENABLED : MODULE_STATUS_DISABLED - : $this->module['status'], + : $this->module['status'] ]; $response = new CControllerResponseData($data); diff --git a/ui/app/controllers/CControllerModuleList.php b/ui/app/controllers/CControllerModuleList.php index 12f67a62468..73d32319289 100644 --- a/ui/app/controllers/CControllerModuleList.php +++ b/ui/app/controllers/CControllerModuleList.php @@ -115,7 +115,7 @@ class CControllerModuleList extends CController { 'modules' => $modules, 'paging' => $paging, 'filter_profile' => 'web.modules.filter', - 'filter_active_tab' => CProfile::get('web.modules.filter.active', 1), + 'filter_active_tab' => CProfile::get('web.modules.filter.active', 1) ]; $response = new CControllerResponseData($data); diff --git a/ui/app/controllers/CControllerNotificationsGet.php b/ui/app/controllers/CControllerNotificationsGet.php index d3700e64a65..cf8f13c7c09 100644 --- a/ui/app/controllers/CControllerNotificationsGet.php +++ b/ui/app/controllers/CControllerNotificationsGet.php @@ -98,18 +98,43 @@ class CControllerNotificationsGet extends CController { $events = API::Problem()->get($options); // Select latest status for already known events that are no longer available in problems table. - $resolved_events = $this->settings['show_recovered'] + $other_still_shown_eventids = $this->settings['show_recovered'] ? array_diff(array_keys($this->known_eventids), array_keys($events)) : []; - if ($resolved_events) { - $events += API::Event()->get([ + if ($other_still_shown_eventids) { + $resolved_events = API::Event()->get([ 'output' => ['eventid', 'r_eventid', 'clock', 'severity'], - 'eventids' => $resolved_events, + 'eventids' => $other_still_shown_eventids, 'sortfield' => 'clock', 'sortorder' => ZBX_SORT_DOWN, 'preservekeys' => true ]); + + $r_eventids = []; + + foreach ($resolved_events as $eventid => $resolved_event) { + if ($resolved_event['r_eventid'] != 0) { + $r_eventids[$eventid] = $resolved_event['r_eventid']; + } + } + + if ($r_eventids) { + $r_clocks = API::Event()->get([ + 'output' => ['clock'], + 'eventids' => array_values($r_eventids), + 'sortfield' => 'clock', + 'sortorder' => ZBX_SORT_DOWN, + 'preservekeys' => true + ]); + + foreach ($r_eventids as $eventid => &$r_eventid) { + $resolved_events[$eventid]['r_clock'] = $r_clocks[$r_eventid]['clock']; + } + unset($r_eventid); + } + + $events += $resolved_events; } // Append selected events to notifications array. @@ -132,7 +157,7 @@ class CControllerNotificationsGet extends CController { */ } // Filter by problem start time, because that is not done by API if show_recovered is enabled. - elseif ($event['clock'] < $this->time_from && !in_array($eventid, $resolved_events)) { + elseif ($event['clock'] < $this->time_from && !in_array($eventid, $other_still_shown_eventids)) { continue; } } @@ -193,7 +218,7 @@ class CControllerNotificationsGet extends CController { '[url='.$url_events.']'.CHtml::encode($notification['name']).'[/url]', '[url='.$url_trigger_events.']'. zbx_date2str(DATE_TIME_FORMAT_SECONDS, $notification['clock']). - '[/url]', + '[/url]' ] ]; } diff --git a/ui/app/controllers/CControllerPopupAcknowledgeEdit.php b/ui/app/controllers/CControllerPopupAcknowledgeEdit.php index e3a1aa88c87..0ff72e119ec 100644 --- a/ui/app/controllers/CControllerPopupAcknowledgeEdit.php +++ b/ui/app/controllers/CControllerPopupAcknowledgeEdit.php @@ -137,7 +137,7 @@ class CControllerPopupAcknowledgeEdit extends CController { $can_be_closed = false; $data['related_problems_count']++; // Count selected but closed events. } - // Not allowed to close events generated by non-writtable and non-closable triggers. + // Not allowed to close events generated by non-writable and non-closable triggers. elseif (!array_key_exists($event['objectid'], $editable_triggers) || $editable_triggers[$event['objectid']]['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_NOT_ALLOWED) { $can_be_closed = false; diff --git a/ui/app/controllers/CControllerPopupGeneric.php b/ui/app/controllers/CControllerPopupGeneric.php index acba6fed524..d54114cbaaa 100644 --- a/ui/app/controllers/CControllerPopupGeneric.php +++ b/ui/app/controllers/CControllerPopupGeneric.php @@ -394,7 +394,7 @@ class CControllerPopupGeneric extends CController { ] ], 'api_methods' => [ - 'title' => _('Api methods'), + 'title' => _('API methods'), 'min_user_type' => USER_TYPE_SUPER_ADMIN, 'allowed_src_fields' => 'name', 'form' => [ @@ -404,7 +404,7 @@ class CControllerPopupGeneric extends CController { 'table_columns' => [ _('Name') ] - ], + ] ]; } diff --git a/ui/app/controllers/CControllerPopupImport.php b/ui/app/controllers/CControllerPopupImport.php new file mode 100644 index 00000000000..4f333e9934e --- /dev/null +++ b/ui/app/controllers/CControllerPopupImport.php @@ -0,0 +1,205 @@ +<?php +/* +** 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 CControllerPopupImport extends CController { + + protected function checkInput() { + $fields = [ + 'import' => 'in 1', + 'rules_preset' => 'in host,template,mediatype,valuemap,screen,map', + 'rules' => 'array' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $output = []; + if (($messages = getMessages()) !== null) { + $output['errors'] = $messages->toString(); + } + + $this->setResponse( + (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView() + ); + } + + return $ret; + } + + protected function checkPermissions() { + $user_type = $this->getUserType(); + + switch ($this->getInput('rules_preset', '')) { + case 'map' : + return $this->checkAccess(CRoleHelper::ACTIONS_EDIT_MAPS); + + case 'screen': + return $this->checkAccess(CRoleHelper::ACTIONS_EDIT_DASHBOARDS); + + case 'host': + case 'template': + case 'mediatype': + case 'valuemap': + return ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN); + + default: + return false; + } + } + + protected function doAction() { + $rules = [ + 'groups' => ['createMissing' => false], + 'hosts' => ['updateExisting' => false, 'createMissing' => false], + 'templates' => ['updateExisting' => false, 'createMissing' => false], + 'templateDashboards' => ['updateExisting' => false, 'createMissing' => false, 'deleteMissing' => false], + 'templateLinkage' => ['createMissing' => false, 'deleteMissing' => false], + 'applications' => ['createMissing' => false, 'deleteMissing' => false], + 'items' => ['updateExisting' => false, 'createMissing' => false, 'deleteMissing' => false], + 'discoveryRules' => ['updateExisting' => false, 'createMissing' => false, 'deleteMissing' => false], + 'triggers' => ['updateExisting' => false, 'createMissing' => false, 'deleteMissing' => false], + 'graphs' => ['updateExisting' => false, 'createMissing' => false, 'deleteMissing' => false], + 'httptests' => ['updateExisting' => false, 'createMissing' => false, 'deleteMissing' => false], + 'screens' => ['updateExisting' => false, 'createMissing' => false], + 'maps' => ['updateExisting' => false, 'createMissing' => false], + 'images' => ['updateExisting' => false, 'createMissing' => false], + 'mediaTypes' => ['updateExisting' => false, 'createMissing' => false], + 'valueMaps' => ['updateExisting' => false, 'createMissing' => false] + ]; + + // Adjust defaults for given rule preset, if specified. + switch ($this->getInput('rules_preset')) { + case 'host': + $rules['groups'] = ['createMissing' => true]; + $rules['hosts'] = ['updateExisting' => true, 'createMissing' => true]; + $rules['applications'] = ['createMissing' => true, 'deleteMissing' => false]; + $rules['items'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['discoveryRules'] = ['updateExisting' => true, 'createMissing' => true, + 'deleteMissing' => false + ]; + $rules['triggers'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['graphs'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['httptests'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['templateLinkage'] = ['createMissing' => true, 'deleteMissing' => false]; + $rules['valueMaps'] = ['updateExisting' => false, 'createMissing' => true]; + break; + + case 'template': + $rules['groups'] = ['createMissing' => true]; + $rules['templates'] = ['updateExisting' => true, 'createMissing' => true]; + $rules['templateDashboards'] = ['updateExisting' => true, 'createMissing' => true, + 'deleteMissing' => false + ]; + $rules['applications'] = ['createMissing' => true, 'deleteMissing' => false]; + $rules['items'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['discoveryRules'] = ['updateExisting' => true, 'createMissing' => true, + 'deleteMissing' => false + ]; + $rules['triggers'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['graphs'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['httptests'] = ['updateExisting' => true, 'createMissing' => true, 'deleteMissing' => false]; + $rules['templateLinkage'] = ['createMissing' => true, 'deleteMissing' => false]; + $rules['valueMaps'] = ['updateExisting' => false, 'createMissing' => true]; + break; + + case 'mediatype': + $rules['mediaTypes'] = ['updateExisting' => false, 'createMissing' => true]; + break; + + case 'valuemap': + $rules['valueMaps'] = ['updateExisting' => false, 'createMissing' => true]; + break; + + case 'map': + $rules['maps'] = [ + 'updateExisting' => CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_MAPS), + 'createMissing' => CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_MAPS) + ]; + $rules['images'] = ['updateExisting' => false, 'createMissing' => true]; + break; + + case 'screen': + $rules['screens'] = [ + 'updateExisting' => CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_DASHBOARDS), + 'createMissing' => CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_DASHBOARDS) + ]; + break; + } + + if ($this->hasInput('import')) { + $request_rules = array_intersect_key($this->getInput('rules', []), $rules); + $request_rules += array_fill_keys(array_keys($rules), []); + $options = array_fill_keys(['updateExisting', 'createMissing', 'deleteMissing'], false); + + foreach ($request_rules as $rule_name => &$rule) { + $rule = array_map('boolval', array_intersect_key($rule + $options, $rules[$rule_name])); + } + unset($rule); + + $result = false; + + if (!isset($_FILES['import_file'])) { + error(_('No file was uploaded.')); + } else { + // CUploadFile throws exceptions, so we need to catch them + try { + $file = new CUploadFile($_FILES['import_file']); + + $result = API::Configuration()->import([ + 'format' => CImportReaderFactory::fileExt2ImportFormat($file->getExtension()), + 'source' => $file->getContent(), + 'rules' => $request_rules + ]); + } + catch (Exception $e) { + error($e->getMessage()); + } + } + + $output = []; + + if ($result) { + $output = ['message' => _('Imported successfully')]; + } + else { + if (($messages = getMessages()) !== null) { + $output['errors'] = $messages->toString(); + } + } + + $this->setResponse( + (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView() + ); + } + else { + $this->setResponse(new CControllerResponseData([ + 'title' => _('Import'), + 'rules' => $rules, + 'rules_preset' => $this->getInput('rules_preset'), + 'allowed_edit_maps' => CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_MAPS), + 'allowed_edit_screens' => CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_DASHBOARDS), + 'user' => [ + 'debug_mode' => $this->getDebugMode() + ] + ])); + } + } +} diff --git a/ui/app/controllers/CControllerPopupItemTest.php b/ui/app/controllers/CControllerPopupItemTest.php index d029d670759..6fe2f86e3a0 100644 --- a/ui/app/controllers/CControllerPopupItemTest.php +++ b/ui/app/controllers/CControllerPopupItemTest.php @@ -211,6 +211,14 @@ abstract class CControllerPopupItemTest extends CController { 'password' => [ 'support_user_macros' => true, 'support_lld_macros' => true + ], + 'http_username' => [ + 'support_user_macros' => true, + 'support_lld_macros' => true + ], + 'http_password' => [ + 'support_user_macros' => true, + 'support_lld_macros' => true ] ]; diff --git a/ui/app/controllers/CControllerPopupMaintenancePeriod.php b/ui/app/controllers/CControllerPopupMaintenancePeriod.php index bd0a954cc32..548a7fd5c1c 100644 --- a/ui/app/controllers/CControllerPopupMaintenancePeriod.php +++ b/ui/app/controllers/CControllerPopupMaintenancePeriod.php @@ -101,7 +101,7 @@ class CControllerPopupMaintenancePeriod extends CController { case TIMEPERIOD_TYPE_WEEKLY: $rules = [ 'every' => 'required|ge 1', - 'days' => 'required|not_empty', + 'days' => 'required|not_empty' ]; break; diff --git a/ui/app/controllers/CControllerPopupMediatypeTestEdit.php b/ui/app/controllers/CControllerPopupMediatypeTestEdit.php index 9ab726edf2e..c844191b3db 100644 --- a/ui/app/controllers/CControllerPopupMediatypeTestEdit.php +++ b/ui/app/controllers/CControllerPopupMediatypeTestEdit.php @@ -49,7 +49,7 @@ class CControllerPopupMediatypeTestEdit extends CController { protected function doAction() { $mediatype = API::MediaType()->get([ 'output' => ['type', 'name', 'status', 'parameters'], - 'mediatypeids' => $this->getInput('mediatypeid'), + 'mediatypeids' => $this->getInput('mediatypeid') ]); if (!$mediatype) { diff --git a/ui/app/controllers/CControllerPopupMediatypeTestSend.php b/ui/app/controllers/CControllerPopupMediatypeTestSend.php index e5882c6ebf0..ff21f64af8c 100644 --- a/ui/app/controllers/CControllerPopupMediatypeTestSend.php +++ b/ui/app/controllers/CControllerPopupMediatypeTestSend.php @@ -66,7 +66,7 @@ class CControllerPopupMediatypeTestSend extends CController { protected function validateMediaType() { $mediatypes = API::MediaType()->get([ 'output' => ['type', 'status'], - 'mediatypeids' => $this->getInput('mediatypeid'), + 'mediatypeids' => $this->getInput('mediatypeid') ]); if (!$mediatypes) { diff --git a/ui/app/controllers/CControllerPopupServices.php b/ui/app/controllers/CControllerPopupServices.php index 6fb4c8ec0c0..73f5a875e75 100644 --- a/ui/app/controllers/CControllerPopupServices.php +++ b/ui/app/controllers/CControllerPopupServices.php @@ -123,7 +123,7 @@ class CControllerPopupServices extends CController { 'output' => ['serviceid', 'name', 'algorithm'], 'selectTrigger' => ['description'], 'preservekeys' => true, - 'sortfield' => ['name'], + 'sortfield' => ['name'] ]); if ($service) { diff --git a/ui/app/controllers/CControllerPopupTabFilterEdit.php b/ui/app/controllers/CControllerPopupTabFilterEdit.php index f78c488f77e..5607b88f314 100644 --- a/ui/app/controllers/CControllerPopupTabFilterEdit.php +++ b/ui/app/controllers/CControllerPopupTabFilterEdit.php @@ -65,7 +65,7 @@ class CControllerPopupTabFilterEdit extends CController { $rules = [ 'tabfilter_from' => 'range_time|required', - 'tabfilter_to' => 'range_time|required', + 'tabfilter_to' => 'range_time|required' ]; $validator = new CNewValidator($this->getInputAll(), $rules); diff --git a/ui/app/controllers/CControllerPopupTabFilterUpdate.php b/ui/app/controllers/CControllerPopupTabFilterUpdate.php index d6d863c7c72..8f469a5b630 100644 --- a/ui/app/controllers/CControllerPopupTabFilterUpdate.php +++ b/ui/app/controllers/CControllerPopupTabFilterUpdate.php @@ -63,7 +63,7 @@ class CControllerPopupTabFilterUpdate extends CController { $rules = [ 'tabfilter_from' => 'range_time|required', - 'tabfilter_to' => 'range_time|required', + 'tabfilter_to' => 'range_time|required' ]; $validator = new CNewValidator($this->getInputAll(), $rules); diff --git a/ui/app/controllers/CControllerPopupTestTriggerExpr.php b/ui/app/controllers/CControllerPopupTestTriggerExpr.php index ff15e71ce01..6ce3dec0a95 100644 --- a/ui/app/controllers/CControllerPopupTestTriggerExpr.php +++ b/ui/app/controllers/CControllerPopupTestTriggerExpr.php @@ -40,8 +40,6 @@ class CControllerPopupTestTriggerExpr extends CController { $this->disableSIDvalidation(); define('ZBX_PAGE_NO_MENU', true); - define('COMBO_PATTERN', 'str_in_array({},array('); - define('COMBO_PATTERN_LENGTH', strlen(COMBO_PATTERN)); define('NO_LINK_IN_TESTING', true); $this->defined_error_phrases = [ diff --git a/ui/app/controllers/CControllerPopupTriggerExpr.php b/ui/app/controllers/CControllerPopupTriggerExpr.php index d0a89985e53..c808a8586c9 100644 --- a/ui/app/controllers/CControllerPopupTriggerExpr.php +++ b/ui/app/controllers/CControllerPopupTriggerExpr.php @@ -668,7 +668,7 @@ class CControllerPopupTriggerExpr extends CController { 'itemValueType' => $item_value_type, 'selectedFunction' => null, 'groupid' => $this->getInput('groupid', 0), - 'hostid' => $this->getInput('hostid', 0), + 'hostid' => $this->getInput('hostid', 0) ]; // Check if submitted function is usable with selected item. diff --git a/ui/app/controllers/CControllerProblemView.php b/ui/app/controllers/CControllerProblemView.php index 166b0b9ff31..494a6a94e1b 100644 --- a/ui/app/controllers/CControllerProblemView.php +++ b/ui/app/controllers/CControllerProblemView.php @@ -149,11 +149,7 @@ class CControllerProblemView extends CControllerProblem { 'sort' => $filter['sort'], 'sortorder' => $filter['sortorder'], 'uncheck' => $this->hasInput('filter_reset'), - 'page' => $this->getInput('page', 1), - 'allowed_ack' => $this->checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS) - || $this->checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) - || $this->checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY) - || $this->checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS) + 'page' => $this->getInput('page', 1) ]; $response = new CControllerResponseData($data); diff --git a/ui/app/controllers/CControllerTimeSelectorUpdate.php b/ui/app/controllers/CControllerTimeSelectorUpdate.php index ef0ed19c835..32830fdfa11 100644 --- a/ui/app/controllers/CControllerTimeSelectorUpdate.php +++ b/ui/app/controllers/CControllerTimeSelectorUpdate.php @@ -201,7 +201,7 @@ class CControllerTimeSelectorUpdate extends CController { 'from_date' => $date->setTimestamp($ts['from'])->format(ZBX_FULL_DATE_TIME), 'to' => $value['to'], 'to_ts' => $ts['to'], - 'to_date' => $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME), + 'to_date' => $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME) ] + getTimeselectorActions($value['from'], $value['to']))])); } diff --git a/ui/app/controllers/CControllerUserCreate.php b/ui/app/controllers/CControllerUserCreate.php index d4b257e9c79..d52dafa13b4 100644 --- a/ui/app/controllers/CControllerUserCreate.php +++ b/ui/app/controllers/CControllerUserCreate.php @@ -24,8 +24,6 @@ class CControllerUserCreate extends CControllerUserUpdateGeneral { protected function checkInput() { $locales = array_keys(getLocales()); $locales[] = LANG_DEFAULT; - $timezones = DateTimeZone::listIdentifiers(); - $timezones[] = TIMEZONE_DEFAULT; $themes = array_keys(APP::getThemes()); $themes[] = THEME_DEFAULT; @@ -38,7 +36,7 @@ class CControllerUserCreate extends CControllerUserUpdateGeneral { 'user_groups' => 'required|array_id|not_empty', 'medias' => 'array', 'lang' => 'db users.lang|in '.implode(',', $locales), - 'timezone' => 'db users.timezone|in '.implode(',', $timezones), + 'timezone' => 'db users.timezone|in '.implode(',', $this->timezones), 'theme' => 'db users.theme|in '.implode(',', $themes), 'autologin' => 'db users.autologin|in 0,1', 'autologout' => 'db users.autologout|not_empty', diff --git a/ui/app/controllers/CControllerUserEdit.php b/ui/app/controllers/CControllerUserEdit.php index 49e8e9d2158..6423959aef1 100644 --- a/ui/app/controllers/CControllerUserEdit.php +++ b/ui/app/controllers/CControllerUserEdit.php @@ -27,8 +27,6 @@ class CControllerUserEdit extends CControllerUserEditGeneral { protected function checkInput() { $locales = array_keys(getLocales()); $locales[] = LANG_DEFAULT; - $timezones = DateTimeZone::listIdentifiers(); - $timezones[] = TIMEZONE_DEFAULT; $themes = array_keys(APP::getThemes()); $themes[] = THEME_DEFAULT; @@ -42,7 +40,7 @@ class CControllerUserEdit extends CControllerUserEditGeneral { 'password1' => 'string', 'password2' => 'string', 'lang' => 'db users.lang|in '.implode(',', $locales), - 'timezone' => 'db users.timezone|in '.implode(',', $timezones), + 'timezone' => 'db users.timezone|in '.implode(',', array_keys($this->timezones)), 'theme' => 'db users.theme|in '.implode(',', $themes), 'autologin' => 'db users.autologin|in 0,1', 'autologout' => 'db users.autologout', @@ -105,6 +103,7 @@ class CControllerUserEdit extends CControllerUserEditGeneral { 'password2' => '', 'lang' => $db_defaults['lang'], 'timezone' => $db_defaults['timezone'], + 'timezones' => $this->timezones, 'theme' => $db_defaults['theme'], 'autologin' => $db_defaults['autologin'], 'autologout' => '0', diff --git a/ui/app/controllers/CControllerUserEditGeneral.php b/ui/app/controllers/CControllerUserEditGeneral.php index 9182cbf7345..77d47bfcfc3 100644 --- a/ui/app/controllers/CControllerUserEditGeneral.php +++ b/ui/app/controllers/CControllerUserEditGeneral.php @@ -31,8 +31,17 @@ abstract class CControllerUserEditGeneral extends CController { */ protected $user = []; + /** + * @var array + */ + protected $timezones = []; + protected function init() { $this->disableSIDValidation(); + + $this->timezones = [ + TIMEZONE_DEFAULT => CDateTimeZoneHelper::getDefaultDateTimeZone() + ] + (new CDateTimeZoneHelper())->getAllDateTimeZones(); } /** diff --git a/ui/app/controllers/CControllerUserProfileEdit.php b/ui/app/controllers/CControllerUserProfileEdit.php index 1c6a4b78d0a..1036cdcfa53 100644 --- a/ui/app/controllers/CControllerUserProfileEdit.php +++ b/ui/app/controllers/CControllerUserProfileEdit.php @@ -27,8 +27,6 @@ class CControllerUserProfileEdit extends CControllerUserEditGeneral { protected function checkInput() { $locales = array_keys(getLocales()); $locales[] = LANG_DEFAULT; - $timezones = DateTimeZone::listIdentifiers(); - $timezones[] = TIMEZONE_DEFAULT; $themes = array_keys(APP::getThemes()); $themes[] = THEME_DEFAULT; @@ -37,7 +35,7 @@ class CControllerUserProfileEdit extends CControllerUserEditGeneral { 'password1' => 'string', 'password2' => 'string', 'lang' => 'db users.lang|in '.implode(',', $locales), - 'timezone' => 'db users.timezone|in '.implode(',', $timezones), + 'timezone' => 'db users.timezone|in '.implode(',', array_keys($this->timezones)), 'theme' => 'db users.theme|in '.implode(',', $themes), 'autologin' => 'db users.autologin|in 0,1', 'autologout' => 'db users.autologout', @@ -106,6 +104,7 @@ class CControllerUserProfileEdit extends CControllerUserEditGeneral { 'password2' => '', 'lang' => $this->user['lang'], 'timezone' => $this->user['timezone'], + 'timezones' => $this->timezones, 'theme' => $this->user['theme'], 'autologin' => $this->user['autologin'], 'autologout' => $this->user['autologout'], diff --git a/ui/app/controllers/CControllerUserProfileUpdate.php b/ui/app/controllers/CControllerUserProfileUpdate.php index 9afa3dba921..74ab38af511 100644 --- a/ui/app/controllers/CControllerUserProfileUpdate.php +++ b/ui/app/controllers/CControllerUserProfileUpdate.php @@ -27,8 +27,6 @@ class CControllerUserProfileUpdate extends CControllerUserUpdateGeneral { protected function checkInput() { $locales = array_keys(getLocales()); $locales[] = LANG_DEFAULT; - $timezones = DateTimeZone::listIdentifiers(); - $timezones[] = TIMEZONE_DEFAULT; $themes = array_keys(APP::getThemes()); $themes[] = THEME_DEFAULT; @@ -38,7 +36,7 @@ class CControllerUserProfileUpdate extends CControllerUserUpdateGeneral { 'password2' => 'string', 'medias' => 'array', 'lang' => 'db users.lang|in '.implode(',', $locales), - 'timezone' => 'db users.timezone|in '.implode(',', $timezones), + 'timezone' => 'db users.timezone|in '.implode(',', $this->timezones), 'theme' => 'db users.theme|in '.implode(',', $themes), 'autologin' => 'db users.autologin|in 0,1', 'autologout' => 'db users.autologout|not_empty', diff --git a/ui/app/controllers/CControllerUserUpdate.php b/ui/app/controllers/CControllerUserUpdate.php index 21f7ebaed03..9d038613cd5 100644 --- a/ui/app/controllers/CControllerUserUpdate.php +++ b/ui/app/controllers/CControllerUserUpdate.php @@ -27,8 +27,6 @@ class CControllerUserUpdate extends CControllerUserUpdateGeneral { protected function checkInput() { $locales = array_keys(getLocales()); $locales[] = LANG_DEFAULT; - $timezones = DateTimeZone::listIdentifiers(); - $timezones[] = TIMEZONE_DEFAULT; $themes = array_keys(APP::getThemes()); $themes[] = THEME_DEFAULT; @@ -42,7 +40,7 @@ class CControllerUserUpdate extends CControllerUserUpdateGeneral { 'password2' => 'string', 'medias' => 'array', 'lang' => 'db users.lang|in '.implode(',', $locales), - 'timezone' => 'db users.timezone|in '.implode(',', $timezones), + 'timezone' => 'db users.timezone|in '.implode(',', $this->timezones), 'theme' => 'db users.theme|in '.implode(',', $themes), 'autologin' => 'db users.autologin|in 0,1', 'autologout' => 'db users.autologout|not_empty', diff --git a/ui/app/controllers/CControllerUserUpdateGeneral.php b/ui/app/controllers/CControllerUserUpdateGeneral.php index 53a110ed006..590264fa596 100644 --- a/ui/app/controllers/CControllerUserUpdateGeneral.php +++ b/ui/app/controllers/CControllerUserUpdateGeneral.php @@ -31,6 +31,19 @@ abstract class CControllerUserUpdateGeneral extends CController { */ protected $allow_empty_password; + + /** + * @var array + */ + protected $timezones; + + protected function init() { + parent::init(); + + $this->timezones = array_keys((new CDateTimeZoneHelper())->getAllDateTimeZones()); + $this->timezones[] = TIMEZONE_DEFAULT; + } + /** * Get groups gui access. * diff --git a/ui/app/controllers/CControllerUsergroupTagfilterAdd.php b/ui/app/controllers/CControllerUsergroupTagfilterAdd.php index ac27f68b399..b338d5138ea 100644 --- a/ui/app/controllers/CControllerUsergroupTagfilterAdd.php +++ b/ui/app/controllers/CControllerUsergroupTagfilterAdd.php @@ -81,7 +81,7 @@ class CControllerUsergroupTagfilterAdd extends CController { $tag_filters[] = [ 'groupid' => $groupid, 'tag' => $new_tag_filter['tag'], - 'value' => $new_tag_filter['value'], + 'value' => $new_tag_filter['value'] ]; } diff --git a/ui/app/controllers/CControllerUserroleEdit.php b/ui/app/controllers/CControllerUserroleEdit.php index 0e7e3bc3dad..2815a489d6e 100644 --- a/ui/app/controllers/CControllerUserroleEdit.php +++ b/ui/app/controllers/CControllerUserroleEdit.php @@ -135,38 +135,6 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral { 'rules' => $rules_labels, 'modules' => $module_labels, 'actions' => $actions_labels - ], - 'rules' => [ - CRoleHelper::UI_DEFAULT_ACCESS => true, - CRoleHelper::ACTIONS_DEFAULT_ACCESS => true, - CRoleHelper::MODULES_DEFAULT_ACCESS => true, - CRoleHelper::SECTION_UI => [ - CRoleHelper::UI_MONITORING_DASHBOARD => true, - CRoleHelper::UI_MONITORING_PROBLEMS => true, - CRoleHelper::UI_MONITORING_HOSTS => true, - CRoleHelper::UI_MONITORING_OVERVIEW => true, - CRoleHelper::UI_MONITORING_LATEST_DATA => true, - CRoleHelper::UI_MONITORING_SCREENS => true, - CRoleHelper::UI_MONITORING_MAPS => true, - CRoleHelper::UI_MONITORING_SERVICES => true, - CRoleHelper::UI_INVENTORY_OVERVIEW => true, - CRoleHelper::UI_INVENTORY_HOSTS => true, - CRoleHelper::UI_REPORTS_AVAILABILITY_REPORT => true, - CRoleHelper::UI_REPORTS_TOP_TRIGGERS => true - ], - CRoleHelper::SECTION_ACTIONS => [ - CRoleHelper::ACTIONS_EDIT_DASHBOARDS => true, - CRoleHelper::ACTIONS_EDIT_MAPS => true, - CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS => true, - CRoleHelper::ACTIONS_CLOSE_PROBLEMS => true, - CRoleHelper::ACTIONS_CHANGE_SEVERITY => true, - CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS => true, - CRoleHelper::ACTIONS_EXECUTE_SCRIPTS => true - ], - CRoleHelper::SECTION_MODULES => [], - CRoleHelper::API_ACCESS => true, - CRoleHelper::API_MODE => CRoleHelper::API_MODE_DENY, - CRoleHelper::SECTION_API => [] ] ]; @@ -176,11 +144,28 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral { $data['type'] = $this->role['type']; $data['readonly'] = $this->role['readonly']; } + else { + // The input value will be set in case of read-only role cloning. + $data['type'] = $this->getInput('type', $data['type']); + } + + $data['rules'] = [ + CRoleHelper::UI_DEFAULT_ACCESS => true, + CRoleHelper::ACTIONS_DEFAULT_ACCESS => true, + CRoleHelper::MODULES_DEFAULT_ACCESS => true, + CRoleHelper::SECTION_UI => array_fill_keys(CRoleHelper::getAllUiElements((int) $data['type']), true), + CRoleHelper::SECTION_ACTIONS => array_fill_keys(CRoleHelper::getAllActions((int) $data['type']), true), + CRoleHelper::SECTION_MODULES => [], + CRoleHelper::API_ACCESS => true, + CRoleHelper::API_MODE => CRoleHelper::API_MODE_DENY, + CRoleHelper::SECTION_API => [] + ]; if ($this->getInput('roleid', 0) != 0) { $data['rules'] = array_merge($data['rules'], $this->getRulesValue((int) $this->role['roleid'])); } + $data['is_own_role'] = ($data['roleid'] == CWebUser::$data['roleid']); $data = $this->overwriteInputs($data); $response = new CControllerResponseData($data); diff --git a/ui/app/controllers/CControllerUserroleEditGeneral.php b/ui/app/controllers/CControllerUserroleEditGeneral.php index 4eb4dcd46f3..fd34bff5aa7 100644 --- a/ui/app/controllers/CControllerUserroleEditGeneral.php +++ b/ui/app/controllers/CControllerUserroleEditGeneral.php @@ -28,7 +28,7 @@ abstract class CControllerUserroleEditGeneral extends CController { $rules = [ CRoleHelper::UI_DEFAULT_ACCESS => $this->getInput('ui_default_access'), CRoleHelper::ACTIONS_DEFAULT_ACCESS => $this->getInput('actions_default_access'), - CRoleHelper::MODULES_DEFAULT_ACCESS => $this->getInput('modules_default_access'), + CRoleHelper::MODULES_DEFAULT_ACCESS => $this->getInput('modules_default_access') ]; $rules += $this->getUiSectionRules($user_type); diff --git a/ui/app/controllers/CControllerWidgetDataOverView.php b/ui/app/controllers/CControllerWidgetDataOverView.php index bcf3708c6aa..7407fa87175 100644 --- a/ui/app/controllers/CControllerWidgetDataOverView.php +++ b/ui/app/controllers/CControllerWidgetDataOverView.php @@ -27,7 +27,7 @@ class CControllerWidgetDataOverView extends CControllerWidget { $this->setType(WIDGET_DATA_OVER); $this->setValidationRules([ 'name' => 'string', - 'fields' => 'json', + 'fields' => 'json' ]); } diff --git a/ui/app/controllers/CControllerWidgetGraphView.php b/ui/app/controllers/CControllerWidgetGraphView.php index 126ba3c7762..291b0a9874a 100644 --- a/ui/app/controllers/CControllerWidgetGraphView.php +++ b/ui/app/controllers/CControllerWidgetGraphView.php @@ -416,7 +416,7 @@ class CControllerWidgetGraphView extends CControllerWidget { 'item_graph_url' => $unavailable_object ? null : $item_graph_url, 'widget' => [ 'uniqueid' => $uniqueid, - 'initial_load' => (int) $this->getInput('initial_load', 0), + 'initial_load' => (int) $this->getInput('initial_load', 0) ], 'time_control_data' => $time_control_data, 'timeline' => $timeline, diff --git a/ui/app/controllers/CControllerWidgetHostAvailView.php b/ui/app/controllers/CControllerWidgetHostAvailView.php index fdbd4dcc01b..3defee59135 100644 --- a/ui/app/controllers/CControllerWidgetHostAvailView.php +++ b/ui/app/controllers/CControllerWidgetHostAvailView.php @@ -27,7 +27,7 @@ class CControllerWidgetHostAvailView extends CControllerWidget { $this->setType(WIDGET_HOST_AVAIL); $this->setValidationRules([ 'name' => 'string', - 'fields' => 'json', + 'fields' => 'json' ]); } diff --git a/ui/app/controllers/CControllerWidgetProblemsView.php b/ui/app/controllers/CControllerWidgetProblemsView.php index 2f171e2351c..a2454f0e33d 100644 --- a/ui/app/controllers/CControllerWidgetProblemsView.php +++ b/ui/app/controllers/CControllerWidgetProblemsView.php @@ -105,10 +105,10 @@ class CControllerWidgetProblemsView extends CControllerWidget { 'blink_period' => CSettingsHelper::get(CSettingsHelper::BLINK_PERIOD) ], 'allowed_ui_problems' => $this->checkAccess(CRoleHelper::UI_MONITORING_PROBLEMS), - 'allowed_ack' => $this->checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS) - || $this->checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) - || $this->checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY) - || $this->checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS) + 'allowed_add_comments' => $this->checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS), + 'allowed_change_severity' => $this->checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY), + 'allowed_acknowledge' => $this->checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS), + 'allowed_close' => $this->checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) ])); } diff --git a/ui/app/partials/layout.htmlpage.aside.php b/ui/app/partials/layout.htmlpage.aside.php index 3dfc022b58c..91c4172793b 100644 --- a/ui/app/partials/layout.htmlpage.aside.php +++ b/ui/app/partials/layout.htmlpage.aside.php @@ -71,8 +71,8 @@ $search = (new CForm('get', 'zabbix.php')) (new CVar('action', 'search'))->removeId(), (new CTextBox('search', getRequest('search', ''), false, 255)) ->addClass(ZBX_STYLE_SEARCH) - ->setAttribute('autocomplete', 'off') - ->setAttribute('aria-label', _('type here to search')), + ->setAttribute('aria-label', _('type here to search')) + ->disableAutocomplete(), $search_icon ]); diff --git a/ui/app/partials/monitoring.host.filter.php b/ui/app/partials/monitoring.host.filter.php index 61c8bcc2cc5..d03dd449855 100644 --- a/ui/app/partials/monitoring.host.filter.php +++ b/ui/app/partials/monitoring.host.filter.php @@ -136,7 +136,7 @@ $right_column = (new CFormList()) ->setId('show_suppressed_#{uniqid}') ->setChecked($data['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE) ->setUncheckedValue(ZBX_PROBLEM_SUPPRESSED_FALSE) - ->setEnabled($data['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON), + ->setEnabled($data['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN) ]); diff --git a/ui/app/partials/monitoring.problem.filter.php b/ui/app/partials/monitoring.problem.filter.php index 8c16eaec5da..14517d5912e 100644 --- a/ui/app/partials/monitoring.problem.filter.php +++ b/ui/app/partials/monitoring.problem.filter.php @@ -269,7 +269,7 @@ $right_column = (new CFormList()) ->setChecked($data['show_timeline'] == 1) ->setEnabled($data['compact_view'] == 0) ->setUncheckedValue(0) - ->setId('show_timeline_#{uniqid}'), + ->setId('show_timeline_#{uniqid}') ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN) ]) ->addRow(_('Show details'), [ diff --git a/ui/app/partials/popup.operations.php b/ui/app/partials/popup.operations.php index ac395dbca8e..ce24580a284 100644 --- a/ui/app/partials/popup.operations.php +++ b/ui/app/partials/popup.operations.php @@ -258,7 +258,8 @@ $form_list->addRow( $form_list->addRow((new CLabel(_('User name'), 'operation_opcommand_username'))->setAsteriskMark(), (new CTextBox('operation[opcommand][username]')) ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) - ->setAriaRequired(), + ->setAriaRequired() + ->disableAutocomplete(), 'operation-command-username' ); @@ -286,7 +287,8 @@ $form_list->addRow((new CLabel(_('Private key file'), 'operation_opcommand_priva * Command password row. */ $form_list->addRow(_('Password'), (new CTextBox('operation[opcommand][password]')) - ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH), + ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) + ->disableAutocomplete(), 'operation-command-password' ); @@ -295,7 +297,8 @@ $form_list->addRow(_('Password'), (new CTextBox('operation[opcommand][password]' */ $form_list->addRow(_('Key passphrase'), (new CTextBox('operation[opcommand][password]')) ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) - ->setId('opcommand_passphrase'), + ->setId('opcommand_passphrase') + ->disableAutocomplete(), 'operation-command-passphrase' ); diff --git a/ui/app/views/administration.autoreg.edit.php b/ui/app/views/administration.autoreg.edit.php index e432c77d9cb..ed5e8e866f1 100644 --- a/ui/app/views/administration.autoreg.edit.php +++ b/ui/app/views/administration.autoreg.edit.php @@ -58,8 +58,8 @@ if ($data['change_psk']) { DB::getFieldLength('config_autoreg_tls', 'tls_psk_identity') )) ->setWidth(ZBX_TEXTAREA_BIG_WIDTH) - ->setAttribute('autocomplete', 'off') - ->setAriaRequired(), + ->setAriaRequired() + ->disableAutocomplete(), null, 'tls_psk' ) @@ -67,8 +67,8 @@ if ($data['change_psk']) { (new CLabel(_('PSK'), 'tls_psk'))->setAsteriskMark(), (new CTextBox('tls_psk', $data['tls_psk'], false, DB::getFieldLength('config_autoreg_tls', 'tls_psk'))) ->setWidth(ZBX_TEXTAREA_BIG_WIDTH) - ->setAttribute('autocomplete', 'off') - ->setAriaRequired(), + ->setAriaRequired() + ->disableAutocomplete(), null, 'tls_psk' ); diff --git a/ui/app/views/administration.gui.edit.php b/ui/app/views/administration.gui.edit.php index 4d369a79097..ed61ac4344b 100644 --- a/ui/app/views/administration.gui.edit.php +++ b/ui/app/views/administration.gui.edit.php @@ -24,6 +24,7 @@ */ $this->includeJsFile('administration.gui.edit.js.php'); +$this->addJsFile('multiselect.js'); $widget = (new CWidget()) ->setTitle(_('GUI')) @@ -62,18 +63,18 @@ elseif ($all_locales_available == 0) { $language_error = _('You are not able to choose some of the languages, because locales for them are not installed on the web server.'); } -$timezones = DateTimeZone::listIdentifiers(); - $gui_tab = (new CFormList()) ->addRow(_('Default language'), ($language_error !== '') ? [$lang_combobox, (makeErrorIcon($language_error))->addStyle('margin-left: 5px;')] : $lang_combobox ) - ->addRow(_('Default time zone'), - new CComboBox('default_timezone', $data['default_timezone'], null, - [ZBX_DEFAULT_TIMEZONE => _('System')] + array_combine($timezones, $timezones) - ) + ->addRow(new CLabel(_('Default time zone'), 'default-timezone-select'), + (new CSelect('default_timezone')) + ->addOptions(CSelect::createOptionsFromArray($data['timezones'])) + ->setValue($data['default_timezone']) + ->setFocusableElementId('default-timezone-select') + ->setId('default_timezone') ) ->addRow(_('Default theme'), new CComboBox('default_theme', $data['default_theme'], null, APP::getThemes()) diff --git a/ui/app/views/administration.image.list.php b/ui/app/views/administration.image.list.php index c36e06e3a8e..490bb03d2a2 100644 --- a/ui/app/views/administration.image.list.php +++ b/ui/app/views/administration.image.list.php @@ -43,7 +43,7 @@ $widget = (new CWidget()) ->getUrl() => _('Icon'), $page_url ->setArgument('imagetype', IMAGE_TYPE_BACKGROUND) - ->getUrl() => _('Background'), + ->getUrl() => _('Background') ]) ]) ->addItem( diff --git a/ui/app/views/administration.mediatype.list.php b/ui/app/views/administration.mediatype.list.php index 6f8aa6cec7e..e1055947dd1 100644 --- a/ui/app/views/administration.mediatype.list.php +++ b/ui/app/views/administration.mediatype.list.php @@ -32,7 +32,13 @@ $widget = (new CWidget()) ->setControls((new CTag('nav', true, (new CList()) ->addItem(new CRedirectButton(_('Create media type'), 'zabbix.php?action=mediatype.edit')) - ->addItem(new CRedirectButton(_('Import'), 'conf.import.php?rules_preset=mediatype')) + ->addItem( + (new CButton('', _('Import'))) + ->onClick('return PopUp("popup.import", jQuery.extend('. + json_encode(['rules_preset' => 'mediatype']).', null), null, this);' + ) + ->removeId() + ) )) ->setAttribute('aria-label', _('Content controls')) ) diff --git a/ui/app/views/administration.proxy.edit.php b/ui/app/views/administration.proxy.edit.php index 4120068ad7f..e07ce9057fd 100644 --- a/ui/app/views/administration.proxy.edit.php +++ b/ui/app/views/administration.proxy.edit.php @@ -112,6 +112,7 @@ $encryption_form_list = (new CFormList('encryption')) (new CTextBox('tls_psk', $data['tls_psk'], false, 512)) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ->setAriaRequired() + ->disableAutocomplete() ) ->addRow(_('Issuer'), (new CTextBox('tls_issuer', $data['tls_issuer'], false, 1024))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) diff --git a/ui/app/views/administration.user.edit.php b/ui/app/views/administration.user.edit.php index 960bde94aeb..f6c0335b952 100644 --- a/ui/app/views/administration.user.edit.php +++ b/ui/app/views/administration.user.edit.php @@ -103,7 +103,6 @@ if ($data['change_password']) { $password1 = (new CPassBox('password1', $data['password1'])) ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) - ->setAttribute('autocomplete', 'off') ->setAriaRequired(); if ($data['action'] !== 'user.edit') { @@ -121,7 +120,6 @@ if ($data['change_password']) { ->addRow((new CLabel(_('Password (once again)'), 'password2'))->setAsteriskMark(), (new CPassBox('password2', $data['password2'])) ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) - ->setAttribute('autocomplete', 'off') ->setAriaRequired() ) ->addRow('', _('Password is not mandatory for non internal authentication type.')); @@ -138,12 +136,15 @@ else { // Append languages, timezones & themes to form list. $lang_combobox = (new CComboBox('lang', $data['lang']))->addItem(LANG_DEFAULT, _('System default')); -$timezone_combobox = (new CComboBox('timezone', $data['timezone']))->addItem(TIMEZONE_DEFAULT, _('System default')); +$timezone_combobox = new CSelect('timezone'); $theme_combobox = (new CComboBox('theme', $data['theme']))->addItem(THEME_DEFAULT, _('System default')); if ($data['action'] === 'user.edit' && $data['db_user']['alias'] === ZBX_GUEST_USER) { $lang_combobox->setEnabled(false); - $timezone_combobox->setEnabled(false); + $timezone_combobox + ->addOptions(CSelect::createOptionsFromArray([TIMEZONE_DEFAULT => $data['timezones'][TIMEZONE_DEFAULT]])) + ->setValue(TIMEZONE_DEFAULT) + ->setDisabled(); $theme_combobox->setEnabled(false); } else { @@ -181,14 +182,16 @@ else { $lang_combobox = [$lang_combobox, (makeErrorIcon($language_error))->addStyle('margin-left: 5px;')]; } - $timezones = DateTimeZone::listIdentifiers(); - $timezone_combobox->addItems(array_combine($timezones, $timezones)); + $timezone_combobox + ->addOptions(CSelect::createOptionsFromArray($data['timezones'])) + ->setValue($data['timezone']) + ->setFocusableElementId('timezone-select'); $theme_combobox->addItems(APP::getThemes()); } $user_form_list ->addRow(_('Language'), $lang_combobox) - ->addRow(_('Time zone'), $timezone_combobox) + ->addRow(new CLabel(_('Time zone'), 'timezone-select'), $timezone_combobox) ->addRow(_('Theme'), $theme_combobox); // Append auto-login & auto-logout to form list. @@ -313,7 +316,7 @@ if ($data['action'] === 'user.edit' || CWebUser::$data['type'] > USER_TYPE_ZABBI 'dstfrm' => $user_form->getName() ]).', null, this);' ) - ->addClass(ZBX_STYLE_BTN_LINK), + ->addClass(ZBX_STYLE_BTN_LINK) ])) ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) ->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') @@ -346,7 +349,7 @@ if ($data['action'] === 'user.edit') { $permissions_form_list->addRow((new CLabel(_('Role')))->setAsteriskMark(), (new CDiv([ $role_multiselect, - new CDiv(_('User can\'t change role for himself')) + new CDiv(_('User cannot change own role.')) ])) ->setWidth(ZBX_TEXTAREA_BIG_WIDTH) ->addClass('multiselect-description-container') diff --git a/ui/app/views/administration.userrole.edit.php b/ui/app/views/administration.userrole.edit.php index 4e5df81b84a..008ecd25449 100644 --- a/ui/app/views/administration.userrole.edit.php +++ b/ui/app/views/administration.userrole.edit.php @@ -50,12 +50,19 @@ $form_grid->addItem([ ))->addClass(CFormField::ZBX_STYLE_FORM_FIELD_FLUID) ]); -if ($data['readonly']) { +if ($data['readonly'] || $data['is_own_role']) { $form_grid->addItem([ (new CLabel(_('User type'), 'type')), - (new CFormField( - (new CTextBox('type', user_type2str()[$data['type']]))->setAttribute('readonly', true) - ))->addClass(CFormField::ZBX_STYLE_FORM_FIELD_FLUID) + (new CFormField([ + (new CTextBox('type', user_type2str()[$data['type']])) + ->setId('type_readonly') + ->setAttribute('readonly', true), + new CVar('type', $data['type']), + ' ', + $data['is_own_role'] + ? new CSpan(_('User cannot change the user type of own role.')) + : null + ]))->addClass(CFormField::ZBX_STYLE_FORM_FIELD_FLUID) ]); } else { @@ -262,6 +269,29 @@ $form_grid->addItem([ ))->addClass(CFormField::ZBX_STYLE_FORM_FIELD_FLUID) ]); +$cancel_button = (new CRedirectButton(_('Cancel'), + (new CUrl('zabbix.php')) + ->setArgument('action', 'userrole.list') + ->setArgument('page', CPagerHelper::loadPage('userrole.list', null)) +))->setId('cancel'); + +$buttons = [$cancel_button]; + +if ($data['roleid'] != 0) { + $buttons = [ + (new CSimpleButton(_('Clone')))->setId('clone'), + (new CRedirectButton(_('Delete'), + (new CUrl('zabbix.php'))->setArgument('action', 'userrole.delete') + ->setArgument('roleids', [$data['roleid']]) + ->setArgumentSID(), + _('Delete selected role?') + )) + ->setId('delete') + ->setEnabled(!$data['readonly']), + $cancel_button + ]; +} + $form_grid->addItem( (new CFormActions( ($data['roleid'] != 0) @@ -269,13 +299,7 @@ $form_grid->addItem( ->setId('update') ->setEnabled(!$data['readonly']) : (new CSubmitButton(_('Add'), 'action', 'userrole.create'))->setId('add'), - [ - (new CRedirectButton(_('Cancel'), - (new CUrl('zabbix.php')) - ->setArgument('action', 'userrole.list') - ->setArgument('page', CPagerHelper::loadPage('userrole.list', null)) - ))->setId('cancel') - ] + $buttons )) ->addClass(CFormField::ZBX_STYLE_FORM_FIELD_FLUID) ->addClass(CFormField::ZBX_STYLE_FORM_FIELD_OFFSET_1) diff --git a/ui/app/views/administration.valuemap.list.php b/ui/app/views/administration.valuemap.list.php index 1184af2060a..fe0aa27f9f3 100644 --- a/ui/app/views/administration.valuemap.list.php +++ b/ui/app/views/administration.valuemap.list.php @@ -37,9 +37,13 @@ $widget = (new CWidget()) ->addItem(new CRedirectButton(_('Create value map'), (new CUrl('zabbix.php')) ->setArgument('action', 'valuemap.edit') )) - ->addItem(new CRedirectButton(_('Import'), (new CUrl('conf.import.php')) - ->setArgument('rules_preset', 'valuemap') - )) + ->addItem( + (new CButton('', _('Import'))) + ->onClick('return PopUp("popup.import", jQuery.extend('. + json_encode(['rules_preset' => 'valuemap']).', null), null, this);' + ) + ->removeId() + ) ) )) ->setAttribute('aria-label', _('Content controls')) diff --git a/ui/app/views/js/administration.iconmap.edit.js.php b/ui/app/views/js/administration.iconmap.edit.js.php index aed2943ef56..a339f624e12 100644 --- a/ui/app/views/js/administration.iconmap.edit.js.php +++ b/ui/app/views/js/administration.iconmap.edit.js.php @@ -32,16 +32,14 @@ ))->addClass(ZBX_STYLE_TD_DRAG_ICON), (new CSpan('#0:'))->addClass('rowNum'), (new CComboBox('iconmap[mappings][#{iconmappingid}][inventory_link]', null, null, $data['inventory_list'])) - ->setId('iconmap_mappings_#{iconmappingid}_inventory_link') - ->setAttribute('autocomplete', 'off'), + ->setId('iconmap_mappings_#{iconmappingid}_inventory_link'), (new CTextBox('iconmap[mappings][#{iconmappingid}][expression]', '', false, 64)) ->setId('iconmap_mappings_#{iconmappingid}_expression') ->setAriaRequired() ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH), (new CComboBox('iconmap[mappings][#{iconmappingid}][iconid]', null, null, $data['icon_list'])) ->setId('iconmap_mappings_#{iconmappingid}_iconid') - ->addClass('mappingIcon') - ->setAttribute('autocomplete', 'off'), + ->addClass('mappingIcon'), (new CCol( (new CImg('imgstore.php?iconid='.$data['default_imageid'].'&width='.ZBX_ICON_PREVIEW_WIDTH. '&height='.ZBX_ICON_PREVIEW_HEIGHT, _('Preview')) diff --git a/ui/app/views/js/administration.mediatype.edit.js.php b/ui/app/views/js/administration.mediatype.edit.js.php index b557eb922ae..46bcf3d76ce 100644 --- a/ui/app/views/js/administration.mediatype.edit.js.php +++ b/ui/app/views/js/administration.mediatype.edit.js.php @@ -42,7 +42,7 @@ new CInput('hidden', 'message_templates[#{message_type}][eventsource]', '#{eventsource}'), new CInput('hidden', 'message_templates[#{message_type}][recovery]', '#{recovery}'), new CInput('hidden', 'message_templates[#{message_type}][subject]', '#{subject}'), - new CInput('hidden', 'message_templates[#{message_type}][message]', '#{message}'), + new CInput('hidden', 'message_templates[#{message_type}][message]', '#{message}') ])) ->addClass(ZBX_STYLE_OVERFLOW_ELLIPSIS) ->addStyle('max-width: '.ZBX_TEXTAREA_MEDIUM_WIDTH.'px;'), diff --git a/ui/app/views/js/administration.userrole.edit.js.php b/ui/app/views/js/administration.userrole.edit.js.php index d62b004b18a..6bac9d140c5 100644 --- a/ui/app/views/js/administration.userrole.edit.js.php +++ b/ui/app/views/js/administration.userrole.edit.js.php @@ -112,14 +112,42 @@ } document.addEventListener('DOMContentLoaded', () => { - const ui_manager = new UserRoleUiManager(<?php echo (bool) $this->data['readonly']; ?>); + const clone_btn = document.getElementById('clone'); + const ui_manager = new UserRoleUiManager(<?= $this->data['readonly'] ? 'true' : 'false'; ?>); const type_elem = document.querySelector('.js-userrole-usertype'); + if (clone_btn !== null) { + clone_btn.addEventListener('click', () => { + if (ui_manager.readonly) { + var url = new Curl('zabbix.php?action=userrole.edit'); + + document + .querySelectorAll('#name, #type') + .forEach((element) => { + url.setArgument(element.getAttribute('name'), element.getAttribute('value')); + }); + + redirect(url.getUrl(), 'post', 'action', undefined, false, true); + } + + document + .querySelectorAll('#roleid, #delete, #clone') + .forEach((element) => { element.remove(); }); + + const update_btn = document.querySelector('#update'); + update_btn.innerHTML = <?= json_encode(_('Add')) ?>; + update_btn.setAttribute('value', 'userrole.create'); + update_btn.setAttribute('id', 'add'); + + document.querySelector('#name').focus(); + }); + } + if (!type_elem) { return false; } - type_elem.addEventListener('change', (event) => { + type_elem.addEventListener('change', () => { ui_manager.disableUiCheckbox(); let user_type = type_elem.options[type_elem.selectedIndex].value, @@ -144,7 +172,7 @@ document .querySelector('.js-userrole-apiaccess') - .addEventListener('change', (event) => { + .addEventListener('change', () => { ui_manager.disableApiSection(); }); diff --git a/ui/app/views/js/dashboard/class.dashboard-share.js.php b/ui/app/views/js/dashboard/class.dashboard-share.js.php index c7bb3fb3a52..bc13b438fd3 100644 --- a/ui/app/views/js/dashboard/class.dashboard-share.js.php +++ b/ui/app/views/js/dashboard/class.dashboard-share.js.php @@ -52,7 +52,7 @@ <?= (new CRow([ new CCol([ (new CTextBox('users[#{id}][userid]', '#{id}'))->setAttribute('type', 'hidden'), - '#{name}', + '#{name}' ]), new CCol( (new CRadioButtonList('users[#{id}][permission]', PERM_READ)) diff --git a/ui/app/views/js/popup.import.js.php b/ui/app/views/js/popup.import.js.php new file mode 100644 index 00000000000..63015347484 --- /dev/null +++ b/ui/app/views/js/popup.import.js.php @@ -0,0 +1,116 @@ +<?php +/* +** 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. +**/ + + +/** + * @var CView $this + */ +?> + +function confirmSubmit(overlay) { + if (document.querySelectorAll('.deleteMissing:checked').length === 0) { + return submitPopup(overlay); + } + else { + overlayDialogue({ + 'content': jQuery('<span>').text(<?= json_encode(_('Delete all elements that are not present in the import file?')) ?>), + 'buttons': [ + { + 'title': <?= json_encode(_('OK')) ?>, + 'focused': true, + 'action': function() { + return submitPopup(overlay); + } + }, + { + 'title': <?= json_encode(_('Cancel')) ?>, + 'cancel': true, + 'class': '<?= ZBX_STYLE_BTN_ALT ?>', + 'action': function() { + overlay.unsetLoading(); + return true; + } + } + ] + }, overlay); + } +} + +function submitPopup(overlay) { + const form = document.querySelector('#import-form'); + const file = form.querySelector('#import_file'); + const formData = new FormData(); + + // Remove error message. + overlay.$dialogue.find('.<?= ZBX_STYLE_MSG_BAD ?>').remove(); + + // Append import file. + formData.append('import_file', file.files.length ? file.files[0] : ''); + + // Append all checkboxes to form. + [...form.querySelectorAll('input[type=checkbox]:checked, input[type=hidden]')].map( + (elem) => formData.append(elem.name, elem.value) + ); + + url = new Curl('zabbix.php', false), + url.setArgument('action', 'popup.import'); + url.setArgument('output', 'ajax'); + + fetch(url.getUrl(), { + method: 'post', + body: formData + }) + .then((response) => response.json()) + .then((response) => { + if ('errors' in response) { + overlay.unsetLoading(); + $(response.errors).insertBefore(form); + form.querySelector('#import_file').value = ''; + } + else { + postMessageOk(response['message']); + overlayDialogueDestroy(overlay.dialogueid); + location.href = location.href; + } + }); +} + +function updateWarning(obj, content) { + if (jQuery(obj).is(':checked')) { + overlayDialogue({ + 'content': jQuery('<span>').text(content), + 'buttons': [ + { + 'title': <?= json_encode(_('OK')) ?>, + 'focused': true, + 'action': function() {} + }, + { + 'title': <?= json_encode(_('Cancel')) ?>, + 'cancel': true, + 'class': '<?= ZBX_STYLE_BTN_ALT ?>', + 'action': function() { + jQuery(obj).prop('checked', false); + } + } + ] + }, obj); + } +} diff --git a/ui/app/views/js/popup.mediatypetest.edit.js.php b/ui/app/views/js/popup.mediatypetest.edit.js.php index e77a9056979..84f2f38dbd2 100644 --- a/ui/app/views/js/popup.mediatypetest.edit.js.php +++ b/ui/app/views/js/popup.mediatypetest.edit.js.php @@ -93,23 +93,23 @@ function openLogPopup(opener) { } var debug = JSON.parse(sessionStorage.getItem('mediatypetest')||'null'), - $content = $('<div id="mediatype_testlog"/>'), - $logitems = $('<div class="logitems"/>'), - $footer = $('<pre/>'); + $content = $('<div/>'), + $logitems = $('<div/>', {class: 'logitems'}), + $footer = $('<div/>', {class: 'logtotalms'}); if (debug) { debug.log.forEach(function (entry) { $('<pre/>').text(entry.ms + ' ' + entry.level + ' ' + entry.message).appendTo($logitems); }); $footer.text(<?= json_encode(_('Time elapsed:')) ?> + " " + debug.ms + 'ms'); - $content.append($logitems).append($footer); + $content.append($logitems); } overlayDialogue({ - 'dialogueid': '', 'title': <?= json_encode(_('Media type test log')) ?>, - 'content': $content.wrap('<p/>').parent().html(), - 'class': 'modal-popup modal-popup-generic', + 'content': $content, + 'class': 'modal-popup modal-popup-generic mediatypetest-modal', + 'footer': $footer, 'buttons': [ { 'title': <?= json_encode(_('Ok')) ?>, @@ -117,10 +117,8 @@ function openLogPopup(opener) { 'focused': true, 'action': () => {} } - ], - 'element': opener, - 'type': 'popup' - }); + ] + }, opener); } sessionStorage.removeItem('mediatypetest'); diff --git a/ui/app/views/monitoring.problem.view.php b/ui/app/views/monitoring.problem.view.php index 0c90ea3feab..4e0d3e341c8 100644 --- a/ui/app/views/monitoring.problem.view.php +++ b/ui/app/views/monitoring.problem.view.php @@ -53,9 +53,8 @@ $options = [ 'details' => $data['filter']['details'], 'highlight_row' => $data['filter']['highlight_row'], 'show_opdata' => $data['filter']['show_opdata'] - ], - 'allowed_ack' => (int) $data['allowed_ack'] - ], + ] + ] ]; switch ($data['filter']['show']) { diff --git a/ui/app/views/monitoring.widget.problems.view.php b/ui/app/views/monitoring.widget.problems.view.php index 9258d5e1d2a..c726920c44b 100644 --- a/ui/app/views/monitoring.widget.problems.view.php +++ b/ui/app/views/monitoring.widget.problems.view.php @@ -75,13 +75,24 @@ if ($data['data']['problems']) { $triggers_hosts = makeTriggersHostsList($data['data']['triggers_hosts']); } +$allowed = [ + 'ui_problems' => $data['allowed_ui_problems'], + 'add_comments' => $data['allowed_add_comments'], + 'change_severity' => $data['allowed_change_severity'], + 'acknowledge' => $data['allowed_acknowledge'] +]; + foreach ($data['data']['problems'] as $eventid => $problem) { $trigger = $data['data']['triggers'][$problem['objectid']]; + $allowed['close'] = ($trigger['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED && $data['allowed_close']); + $can_be_closed = $allowed['close']; + if ($problem['r_eventid'] != 0) { $value = TRIGGER_VALUE_FALSE; $value_str = _('RESOLVED'); $value_clock = $problem['r_clock']; + $can_be_closed = false; } else { $in_closing = false; @@ -89,6 +100,7 @@ foreach ($data['data']['problems'] as $eventid => $problem) { foreach ($problem['acknowledges'] as $acknowledge) { if (($acknowledge['action'] & ZBX_PROBLEM_UPDATE_CLOSE) == ZBX_PROBLEM_UPDATE_CLOSE) { $in_closing = true; + $can_be_closed = false; break; } } @@ -189,14 +201,6 @@ foreach ($data['data']['problems'] as $eventid => $problem) { } } - $allowed = [ - 'ui_problems' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_PROBLEMS), - 'ack' => CWebUser::checkAccess(CRoleHelper::ACTIONS_ACKNOWLEDGE_PROBLEMS) - || CWebUser::checkAccess(CRoleHelper::ACTIONS_CLOSE_PROBLEMS) - || CWebUser::checkAccess(CRoleHelper::ACTIONS_CHANGE_SEVERITY) - || CWebUser::checkAccess(CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS) - ]; - $problem_link = [ (new CLinkAction($problem['name'])) ->setHint( @@ -260,7 +264,8 @@ foreach ($data['data']['problems'] as $eventid => $problem) { } // Create acknowledge link. - $problem_update_link = $data['allowed_ack'] + $problem_update_link = ($allowed['add_comments'] || $allowed['change_severity'] || $allowed['acknowledge'] + || $can_be_closed) ? (new CLink($is_acknowledged ? _('Yes') : _('No'))) ->addClass($is_acknowledged ? ZBX_STYLE_GREEN : ZBX_STYLE_RED) ->addClass(ZBX_STYLE_LINK_ALT) diff --git a/ui/app/views/popup.discovery.check.php b/ui/app/views/popup.discovery.check.php index 878757640ab..3f79ae65416 100644 --- a/ui/app/views/popup.discovery.check.php +++ b/ui/app/views/popup.discovery.check.php @@ -103,7 +103,8 @@ $form_list = (new CFormList()) ->addRow(new CLabel(_('Authentication passphrase'), 'snmpv3_authpassphrase'), (new CTextBox('snmpv3_authpassphrase', $data['params']['snmpv3_authpassphrase'])) ->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH) - ->setAttribute('maxlength', 64), + ->setAttribute('maxlength', 64) + ->disableAutocomplete(), 'row_dcheck_snmpv3_authpassphrase' ) ->addRow(new CLabel(_('Privacy protocol'), 'snmpv3_privprotocol'), @@ -117,7 +118,8 @@ $form_list = (new CFormList()) (new CTextBox('snmpv3_privpassphrase', $data['params']['snmpv3_privpassphrase'])) ->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH) ->setAriaRequired() - ->setAttribute('maxlength', 64), + ->setAttribute('maxlength', 64) + ->disableAutocomplete(), 'row_dcheck_snmpv3_privpassphrase' ); diff --git a/ui/app/views/popup.generic.php b/ui/app/views/popup.generic.php index 41eb0768c2b..584b4a043bf 100644 --- a/ui/app/views/popup.generic.php +++ b/ui/app/views/popup.generic.php @@ -616,7 +616,7 @@ switch ($data['popup_type']) { $check_box, $description, $script_execute_on, - zbx_nl2br(htmlspecialchars($script['command'], ENT_COMPAT, 'UTF-8')), + zbx_nl2br(htmlspecialchars($script['command'], ENT_COMPAT, 'UTF-8')) ]); } unset($data['table_records']); diff --git a/ui/app/views/popup.httpstep.php b/ui/app/views/popup.httpstep.php index 4835ac8286b..6661c2491f5 100644 --- a/ui/app/views/popup.httpstep.php +++ b/ui/app/views/popup.httpstep.php @@ -24,7 +24,7 @@ */ $output = [ - 'header' => $data['title'], + 'header' => $data['title'] ]; $options = $data['options']; diff --git a/ui/app/views/popup.import.php b/ui/app/views/popup.import.php new file mode 100644 index 00000000000..766f9a62d31 --- /dev/null +++ b/ui/app/views/popup.import.php @@ -0,0 +1,161 @@ +<?php +/* +** 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. +**/ + + +/** + * @var CView $this + */ + +$rulesTable = (new CTable()) + ->setHeader(['', _('Update existing'), _('Create new'), _('Delete missing')]); + +$titles = [ + 'groups' => _('Groups'), + 'hosts' => _('Hosts'), + 'templates' => _('Templates'), + 'templateDashboards' => _('Template dashboards'), + 'templateLinkage' => _('Template linkage'), + 'applications' => _('Applications'), + 'items' => _('Items'), + 'discoveryRules' => _('Discovery rules'), + 'triggers' => _('Triggers'), + 'graphs' => _('Graphs'), + 'httptests' => _('Web scenarios'), + 'screens' => _('Screens'), + 'maps' => _('Maps') +]; + +$user_type = CWebUser::getType(); + +if ($user_type == USER_TYPE_SUPER_ADMIN) { + $titles['images'] = _('Images'); + $titles['mediaTypes'] = _('Media types'); + $titles['valueMaps'] = _('Value mappings'); +} + +foreach ($titles as $key => $title) { + $cbExist = null; + $cbMissed = null; + $cbDeleted = null; + + if (array_key_exists('updateExisting', $data['rules'][$key])) { + $cbExist = (new CCheckBox('rules['.$key.'][updateExisting]')) + ->setChecked($data['rules'][$key]['updateExisting']); + + if ($key !== 'maps' && $key !== 'screens' && $user_type != USER_TYPE_SUPER_ADMIN + && $user_type != USER_TYPE_ZABBIX_ADMIN) { + $cbExist->setAttribute('disabled', 'disabled'); + } + elseif ($key === 'maps') { + $cbExist->setAttribute('disabled', $data['allowed_edit_maps'] ? null : true); + } + elseif ($key === 'screens') { + $cbExist->setAttribute('disabled', $data['allowed_edit_screens'] ? null : true); + } + + if ($key === 'images') { + $cbExist->onClick('updateWarning(this, '.json_encode(_('Images for all maps will be updated!')).')'); + } + + if ($key === 'valueMaps') { + $cbExist->onClick( + 'updateWarning(this, '.json_encode(_('Value mappings for value maps will be updated!')).')' + ); + } + } + + if (array_key_exists('createMissing', $data['rules'][$key])) { + $cbMissed = (new CCheckBox('rules['.$key.'][createMissing]')) + ->setChecked($data['rules'][$key]['createMissing']); + } + + if ($key !== 'maps' && $key !== 'screens' && $user_type != USER_TYPE_SUPER_ADMIN + && $user_type != USER_TYPE_ZABBIX_ADMIN) { + $cbMissed->setAttribute('disabled', 'disabled'); + } + elseif ($key === 'maps') { + $cbMissed->setAttribute('disabled', $data['allowed_edit_maps'] ? null : true); + } + elseif ($key === 'screens') { + $cbMissed->setAttribute('disabled', $data['allowed_edit_screens'] ? null : true); + } + + if (array_key_exists('deleteMissing', $data['rules'][$key])) { + $cbDeleted = (new CCheckBox('rules['.$key.'][deleteMissing]')) + ->setChecked($data['rules'][$key]['deleteMissing']) + ->addClass('deleteMissing'); + + if ($key !== 'maps' && $key !== 'screens' && $user_type != USER_TYPE_SUPER_ADMIN + && $user_type != USER_TYPE_ZABBIX_ADMIN) { + $cbDeleted->setAttribute('disabled', 'disabled'); + } + + if ($key === 'templateLinkage') { + $cbDeleted->onClick('updateWarning(this, '.json_encode( + _('Template and host properties that are inherited through template linkage will be unlinked and cleared.') + ).')'); + } + } + + $rulesTable->addRow([ + $title, + (new CCol($cbExist))->addClass(ZBX_STYLE_CENTER), + (new CCol($cbMissed))->addClass(ZBX_STYLE_CENTER), + (new CCol($cbDeleted))->addClass(ZBX_STYLE_CENTER) + ]); +} + +$form_list = (new CFormList()) + ->addRow((new CLabel(_('Import file'), 'import_file'))->setAsteriskMark(), + (new CFile('import_file')) + ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) + ->setAriaRequired() + ->setAttribute('autofocus', 'autofocus') + ) + ->addRow(_('Rules'), new CDiv($rulesTable)); + +$form = (new CForm('post', null, 'multipart/form-data')) + ->setId('import-form') + ->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE) + ->addVar('import', 1) + ->addVar('rules_preset', $data['rules_preset']) + ->addItem($form_list); + +$output = [ + 'header' => $data['title'], + 'script_inline' => trim($this->readJsFile('popup.import.js.php')), + 'body' => $form->toString(), + 'buttons' => [ + [ + 'title' => _('Import'), + 'class' => '', + 'keepOpen' => true, + 'isSubmit' => true, + 'action' => 'return confirmSubmit(overlay);' + ] + ] +]; + +if ($data['user']['debug_mode'] == GROUP_DEBUG_MODE_ENABLED) { + CProfiler::getInstance()->stop(); + $output['debug'] = CProfiler::getInstance()->make()->toString(); +} + +echo json_encode($output); diff --git a/ui/app/views/popup.lldoperation.php b/ui/app/views/popup.lldoperation.php index 265029cbf66..7528480734a 100644 --- a/ui/app/views/popup.lldoperation.php +++ b/ui/app/views/popup.lldoperation.php @@ -67,7 +67,7 @@ $operations_popup_form_list = (new CFormList()) (new CTextBox('value', $options['value'], $options['templated'], DB::getFieldLength('lld_override_operation', 'value'))) ->setWidth(ZBX_TEXTAREA_MACRO_VALUE_WIDTH) - ->setAttribute('placeholder', _('pattern')), + ->setAttribute('placeholder', _('pattern')) ]) ->addRow( (new CVisibilityBox('visible[opstatus]', 'opstatus_status', _('Original'))) diff --git a/ui/app/views/popup.media.php b/ui/app/views/popup.media.php index 0139aa1aceb..3a121d898b9 100644 --- a/ui/app/views/popup.media.php +++ b/ui/app/views/popup.media.php @@ -106,7 +106,7 @@ $form = (new CForm()) (new CCol((new CButton('sendto_emails[#{rowNum}][remove]', _('Remove'))) ->addClass(ZBX_STYLE_BTN_LINK) ->addClass('element-table-remove') - )), + )) ])) ->addClass('form_row') ->addClass('dynamic-row')) |