1<?php declare(strict_types=1); 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22class CControllerActionOperationGet extends CController { 23 24 protected function checkInput() { 25 $fields = [ 26 'eventsource' => 'required|in '.implode(',', [EVENT_SOURCE_TRIGGERS, EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION, EVENT_SOURCE_INTERNAL]), 27 'recovery' => 'required|in '.implode(',', [ACTION_OPERATION, ACTION_RECOVERY_OPERATION, ACTION_ACKNOWLEDGE_OPERATION]), 28 'actionid' => 'db actions.actionid', 29 'operation' => 'array' 30 ]; 31 32 $ret = $this->validateInput($fields) && $this->validateInputConstraints(); 33 34 if (!$ret) { 35 $output = []; 36 if (($messages = getMessages()) !== null) { 37 $output['errors'] = $messages->toString(); 38 } 39 40 $this->setResponse(new CControllerResponseData(['main_block' => json_encode($output)])); 41 } 42 43 return $ret; 44 } 45 46 protected function validateInputConstraints(): bool { 47 $eventsource = $this->getInput('eventsource'); 48 $recovery = $this->getInput('recovery'); 49 50 $allowed_operations = getAllowedOperations($eventsource); 51 52 if (!array_key_exists($recovery, $allowed_operations)) { 53 error(_('Unsupported operation.')); 54 return false; 55 } 56 57 return true; 58 } 59 60 protected function checkPermissions() { 61 if ($this->getUserType() >= USER_TYPE_ZABBIX_ADMIN) { 62 if (!$this->getInput('actionid', '0')) { 63 return true; 64 } 65 66 return (bool) API::Action()->get([ 67 'output' => [], 68 'actionids' => $this->getInput('actionid'), 69 'editable' => true 70 ]); 71 } 72 73 return false; 74 } 75 76 protected function doAction() { 77 $operation = $this->getInput('operation', []) + $this->defaultOperationObject(); 78 79 $eventsource = (int) $this->getInput('eventsource'); 80 $recovery = (int) $this->getInput('recovery'); 81 82 $data = [ 83 'popup_config' => $this->popupConfig($operation, $eventsource, $recovery), 84 'debug' => null 85 ]; 86 87 if ($this->getDebugMode() == GROUP_DEBUG_MODE_ENABLED) { 88 CProfiler::getInstance()->stop(); 89 $data['debug'] = CProfiler::getInstance()->make()->toString(); 90 } 91 92 $this->setResponse(new CControllerResponseData(['main_block' => json_encode($data)])); 93 } 94 95 /** 96 * Returns empty default operation object. 97 * 98 * @return array 99 */ 100 private function defaultOperationObject(): array { 101 return [ 102 'opmessage_usr' => [], 103 'opmessage_grp' => [], 104 'opmessage' => [ 105 'subject' => '', 106 'message' => '', 107 'mediatypeid' => '0', 108 'default_msg' => '1' 109 ], 110 'operationtype' => '0', 111 'esc_step_from' => '1', 112 'esc_step_to' => '1', 113 'esc_period' => '0', 114 'opcommand_hst' => [], 115 'opcommand_grp' => [], 116 'evaltype' => (string) CONDITION_EVAL_TYPE_AND_OR, 117 'opconditions' => [], 118 'opgroup' => [], 119 'optemplate' => [], 120 'opinventory' => [ 121 'inventory_mode' => (string) HOST_INVENTORY_MANUAL 122 ], 123 'opcommand' => [ 124 'type' => (string) ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT, 125 'scriptid' => '0', 126 'execute_on' => (string) ZBX_SCRIPT_EXECUTE_ON_AGENT, 127 'port' => '', 128 'authtype' => (string) ITEM_AUTHTYPE_PASSWORD, 129 'username' => '', 130 'password' => '', 131 'publickey' => '', 132 'privatekey' => '', 133 'command' => '' 134 ] 135 ]; 136 } 137 138 /** 139 * Transforms operation object into operation config object. Needed meta data is queried. 140 * 141 * @param array $operation Operation object. 142 * @param int $eventsource Action event source. 143 * @param int $recovery Action event phase. 144 * 145 * @return array Each of fields is nullable, meaning given operation may not have particular configuration domain. 146 */ 147 private function popupConfig(array $operation, int $eventsource, int $recovery): array { 148 $operation_type = $this->popupConfigOperationType($operation, $eventsource, $recovery); 149 $operation_steps = $this->popupConfigOperationSteps($operation, $eventsource, $recovery); 150 $operation_message = $this->popupConfigOperationMessage($operation, $eventsource); 151 $operation_command = $this->popupConfigOperationCommand($operation, $eventsource); 152 $operation_attr = $this->popupConfigOperationAttr($operation, $eventsource); 153 $operation_condition = $this->popupConfigOperationCondition($operation, $eventsource, $recovery); 154 155 return [ 156 'operation_type' => $operation_type, 157 'operation_steps' => $operation_steps, 158 'operation_message' => $operation_message, 159 'operation_command' => $operation_command, 160 'operation_attr' => $operation_attr, 161 'operation_condition' => $operation_condition 162 ]; 163 } 164 165 /** 166 * Returns "operation type" configuration fields for given operation in given source. 167 * 168 * @param array $operation Operation object. 169 * @param int $eventsource Action event source. 170 * @param int $recovery Action event phase. 171 * 172 * @return array 173 */ 174 private function popupConfigOperationType(array $operation, int $eventsource, int $recovery): array { 175 $operation_type_options = []; 176 177 foreach (getAllowedOperations($eventsource)[$recovery] as $operation_type) { 178 $operation_type_options[] = [ 179 'value' => $operation_type, 180 'name' => operation_type2str($operation_type) 181 ]; 182 } 183 184 return [ 185 'options' => $operation_type_options, 186 'selected' => $operation['operationtype'] 187 ]; 188 } 189 190 /** 191 * Returns populated "escalation steps" domain configuration fields for given operation in given source. 192 * 193 * @param array $operation Operation object. 194 * @param int $eventsource Action event source. 195 * @param int $recovery Action event phase. 196 * 197 * @return array|null 198 */ 199 private function popupConfigOperationSteps(array $operation, int $eventsource, int $recovery): ?array { 200 if ($eventsource == EVENT_SOURCE_TRIGGERS || $eventsource == EVENT_SOURCE_INTERNAL) { 201 if ($recovery == ACTION_OPERATION) { 202 return [ 203 'from' => $operation['esc_step_from'], 204 'to' => $operation['esc_step_to'], 205 'duration' => $operation['esc_period'] 206 ]; 207 } 208 } 209 210 return null; 211 } 212 213 /** 214 * Returns populated "message" domain configuration fields for given operation in given source. 215 * 216 * @param array $operation Operation object. 217 * @param int $eventsource Action event source. 218 * 219 * @return array|null 220 */ 221 private function popupConfigOperationMessage(array $operation, int $eventsource): ?array { 222 if ($eventsource == EVENT_SOURCE_TRIGGERS || $eventsource == EVENT_SOURCE_DISCOVERY 223 || $eventsource == EVENT_SOURCE_AUTOREGISTRATION || $eventsource == EVENT_SOURCE_INTERNAL) { 224 $usergroups = []; 225 if ($operation['opmessage_grp']) { 226 $usergroups = API::UserGroup()->get([ 227 'output' => ['usergroupid', 'name'], 228 'usrgrpids' => array_column($operation['opmessage_grp'], 'usrgrpid') 229 ]); 230 } 231 232 $users = []; 233 if ($operation['opmessage_usr']) { 234 $db_users = API::User()->get([ 235 'output' => ['userid', 'alias', 'name', 'surname'], 236 'userids' => array_column($operation['opmessage_usr'], 'userid') 237 ]); 238 CArrayHelper::sort($db_users, ['alias']); 239 240 foreach ($db_users as $db_user) { 241 $users[] = [ 242 'id' => $db_user['userid'], 243 'name' => getUserFullname($db_user) 244 ]; 245 } 246 } 247 248 $mediatypes = API::MediaType()->get(['output' => ['mediatypeid', 'name', 'status']]); 249 CArrayHelper::sort($mediatypes, ['name']); 250 $mediatypes = array_values($mediatypes); 251 252 return [ 253 'custom_message' => $operation['opmessage']['default_msg'] === '0', 254 'subject' => $operation['opmessage']['subject'], 255 'body' => $operation['opmessage']['message'], 256 'mediatypeid' => $operation['opmessage']['mediatypeid'], 257 'mediatypes' => $mediatypes, 258 'usergroups' => $usergroups, 259 'users' => $users 260 ]; 261 } 262 263 return null; 264 } 265 266 /** 267 * Returns populated "command" domain configuration fields for given operation in given context (eventsource). 268 * 269 * @param array $operation Operation object. 270 * @param int $eventsource Action event source. 271 * 272 * @return array|null 273 */ 274 private function popupConfigOperationCommand(array $operation, int $eventsource): ?array { 275 if ($eventsource == EVENT_SOURCE_TRIGGERS || $eventsource == EVENT_SOURCE_DISCOVERY 276 || $eventsource == EVENT_SOURCE_AUTOREGISTRATION) { 277 $current_host = false; 278 279 $hostids = []; 280 foreach ($operation['opcommand_hst'] as $hostid) { 281 if ($hostid == '0') { 282 $current_host = true; 283 } 284 else { 285 $hostids[] = $hostid; 286 } 287 } 288 289 $operation_command = [ 290 'type' => $operation['opcommand']['type'], 291 'current_host' => $current_host, 292 'execute_on' => $operation['opcommand']['execute_on'], 293 'command' => $operation['opcommand']['command'], 294 'username' => $operation['opcommand']['username'], 295 'password' => $operation['opcommand']['password'], 296 'privatekey' => $operation['opcommand']['privatekey'], 297 'publickey' => $operation['opcommand']['publickey'], 298 'port' => $operation['opcommand']['port'], 299 'authtype' => $operation['opcommand']['authtype'], 300 'global_script' => ['scriptid' => '0', 'name' => ''], 301 'hosts' => [], 302 'groups' => [] 303 ]; 304 305 if ($operation['opcommand']['scriptid']) { 306 $db_scrpt = API::Script()->get([ 307 'output' => ['name', 'scriptid'], 308 'scriptids' => (array) $operation['opcommand']['scriptid'] 309 ]); 310 311 if ($db_scrpt) { 312 $operation_command['global_script'] = $db_scrpt[0]; 313 } 314 } 315 316 if ($hostids) { 317 $operation_command['hosts'] = CArrayHelper::renameObjectsKeys(API::Host()->get([ 318 'output' => ['hostid', 'name'], 319 'hostids' => $hostids 320 ]), ['hostid' => 'id']); 321 } 322 323 if ($operation['opcommand_grp']) { 324 $operation_command['groups'] = CArrayHelper::renameObjectsKeys(API::HostGroup()->get([ 325 'output' => ['groupid', 'name'], 326 'groupids' => $operation['opcommand_grp'] 327 ]), ['groupid' => 'id']); 328 } 329 330 return $operation_command; 331 } 332 333 return null; 334 } 335 336 /** 337 * Returns populated "attributes" domain configuration fields for given operation in given source. 338 * 339 * @param array $operation Operation object. 340 * @param int $eventsource Action event source. 341 * 342 * @return array|null 343 */ 344 private function popupConfigOperationAttr(array $operation, int $eventsource): ?array { 345 if ($eventsource == EVENT_SOURCE_DISCOVERY || $eventsource == EVENT_SOURCE_AUTOREGISTRATION) { 346 $operation_attr = [ 347 'hostgroups' => [], 348 'templates' => [] 349 ]; 350 351 if ($operation['opgroup']) { 352 $operation_attr['hostgroups'] = CArrayHelper::renameObjectsKeys(API::HostGroup()->get([ 353 'output' => ['groupid', 'name'], 354 'groupids' => array_column($operation['opgroup'], 'groupid') 355 ]), ['groupid' => 'id']); 356 } 357 358 if ($operation['optemplate']) { 359 $operation_attr['templates'] = CArrayHelper::renameObjectsKeys(API::Template()->get([ 360 'output' => ['templateid', 'name'], 361 'templateids' => array_column($operation['optemplate'], 'templateid'), 362 'editable' => true 363 ]), ['templateid' => 'id']); 364 } 365 366 if ($operation['opinventory']) { 367 $operation_attr['inventory_mode'] = $operation['opinventory']['inventory_mode']; 368 } 369 370 return $operation_attr; 371 } 372 373 return null; 374 } 375 376 /** 377 * Returns populated "conditions" domain configuration fields for given operation in given source. 378 * 379 * @param array $operation Operation object. 380 * @param int $eventsource Action event source. 381 * 382 * @return array|null 383 */ 384 private function popupConfigOperationCondition(array $operation, int $eventsource, int $recovery): ?array { 385 if ($eventsource == EVENT_SOURCE_TRIGGERS) { 386 if ($recovery == ACTION_OPERATION) { 387 $operation_condition = [ 388 'conditions' => [], 389 'evaltype' => $operation['evaltype'] 390 ]; 391 392 foreach ($operation['opconditions'] as $index => $opcondition) { 393 $name = getConditionDescription($opcondition['conditiontype'], $opcondition['operator'], 394 $opcondition['value'], '' 395 ); 396 397 $operation_condition['conditions'][] = [ 398 'formulaid' => num2letter($index), 399 'name' => $name, 400 'conditiontype' => $opcondition['conditiontype'], 401 'operator' => $opcondition['operator'], 402 'value' => $opcondition['value'] 403 ]; 404 } 405 406 return $operation_condition; 407 } 408 } 409 410 return null; 411 } 412} 413