1<?php 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 22include('include/views/js/administration.users.edit.js.php'); 23 24if ($data['is_profile']) { 25 $userWidget = ($data['name'] !== '' || $data['surname'] !== '') 26 ? (new CWidget())->setTitle(_('User profile').NAME_DELIMITER.$data['name'].' '.$data['surname']) 27 : (new CWidget())->setTitle(_('User profile').NAME_DELIMITER.$data['alias']); 28} 29else { 30 $userWidget = (new CWidget())->setTitle(_('Users')); 31} 32 33// create form 34$userForm = (new CForm()) 35 ->setName('userForm') 36 ->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE) 37 ->addVar('form', $data['form']); 38 39if ($data['userid'] != 0) { 40 $userForm->addVar('userid', $data['userid']); 41} 42 43/* 44 * User tab 45 */ 46$userFormList = new CFormList('userFormList'); 47$form_autofocus = false; 48 49if (!$data['is_profile']) { 50 $userFormList->addRow( 51 (new CLabel(_('Alias'), 'alias'))->setAsteriskMark(), 52 (new CTextBox('alias', $data['alias'])) 53 ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 54 ->setAriaRequired() 55 ->setAttribute('autofocus', 'autofocus') 56 ->setAttribute('maxlength', DB::getFieldLength('users', 'alias')) 57 ); 58 $form_autofocus = true; 59 $userFormList->addRow(_x('Name', 'user first name'), 60 (new CTextBox('name', $data['name'])) 61 ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 62 ->setAttribute('maxlength', DB::getFieldLength('users', 'name')) 63 ); 64 $userFormList->addRow(_('Surname'), 65 (new CTextBox('surname', $data['surname'])) 66 ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 67 ->setAttribute('maxlength', DB::getFieldLength('users', 'surname')) 68 ); 69} 70 71// append user groups to form list 72if (!$data['is_profile']) { 73 $user_groups = []; 74 75 foreach ($data['groups'] as $group) { 76 $user_groups[] = CArrayHelper::renameKeys($group, ['usrgrpid' => 'id']); 77 } 78 79 $userFormList->addRow( 80 (new CLabel(_('Groups'), 'user_groups__ms'))->setAsteriskMark(), 81 (new CMultiSelect([ 82 'name' => 'user_groups[]', 83 'object_name' => 'usersGroups', 84 'data' => $user_groups, 85 'popup' => [ 86 'parameters' => [ 87 'srctbl' => 'usrgrp', 88 'srcfld1' => 'usrgrpid', 89 'dstfrm' => $userForm->getName(), 90 'dstfld1' => 'user_groups_' 91 ] 92 ] 93 ])) 94 ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 95 ->setAriaRequired() 96 ); 97} 98 99// append password to form list 100if ($data['userid'] == 0 || $data['change_password']) { 101 $userForm->disablePasswordAutofill(); 102 103 $password1 = (new CPassBox('password1', $data['password1'])) 104 ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) 105 ->setAriaRequired(); 106 107 if (!$form_autofocus) { 108 $form_autofocus = true; 109 $password1->setAttribute('autofocus', 'autofocus'); 110 } 111 112 $userFormList 113 ->addRow((new CLabel(_('Password'), 'password1'))->setAsteriskMark(), [ 114 // Hidden dummy login field for protection against chrome error when password autocomplete. 115 (new CInput('text', null, null)) 116 ->setAttribute('tabindex', '-1') 117 ->addStyle('position: absolute; left: -100vw;'), 118 $password1 119 ]) 120 ->addRow((new CLabel(_('Password (once again)'), 'password2'))->setAsteriskMark(), 121 (new CPassBox('password2', $data['password2'])) 122 ->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) 123 ->setAriaRequired() 124 ) 125 ->addRow('', _('Password is not mandatory for non internal authentication type.')); 126 127 if ($data['change_password']) { 128 $userForm->addVar('change_password', $data['change_password']); 129 } 130} 131else { 132 $passwdButton = (new CSimpleButton(_('Change password'))) 133 ->onClick('javascript: submitFormWithParam("'.$userForm->getName().'", "change_password", "1");') 134 ->addClass(ZBX_STYLE_BTN_GREY); 135 if ($data['alias'] == ZBX_GUEST_USER) { 136 $passwdButton->setAttribute('disabled', 'disabled'); 137 } 138 139 if (!$form_autofocus) { 140 $form_autofocus = true; 141 $passwdButton->setAttribute('autofocus', 'autofocus'); 142 } 143 144 $userFormList->addRow(_('Password'), $passwdButton); 145} 146 147// append languages to form list 148$languageComboBox = new CComboBox('lang', $data['lang']); 149 150$allLocalesAvailable = true; 151foreach (getLocales() as $localeId => $locale) { 152 if ($locale['display']) { 153 // checking if this locale exists in the system. The only way of doing it is to try and set one 154 // trying to set only the LC_MONETARY locale to avoid changing LC_NUMERIC 155 $localeExists = ($localeId === 'en_GB' || setlocale(LC_MONETARY , zbx_locale_variants($localeId))); 156 157 $languageComboBox->addItem( 158 $localeId, 159 $locale['name'], 160 ($localeId == $data['lang']) ? true : null, 161 $localeExists 162 ); 163 164 $allLocalesAvailable &= $localeExists; 165 } 166} 167 168// restoring original locale 169setlocale(LC_MONETARY, zbx_locale_variants(CWebUser::$data['lang'])); 170 171$languageError = ''; 172if (!function_exists('bindtextdomain')) { 173 $languageError = 'Translations are unavailable because the PHP gettext module is missing.'; 174 $languageComboBox->setAttribute('disabled', 'disabled'); 175} 176elseif (!$allLocalesAvailable) { 177 $languageError = _('You are not able to choose some of the languages, because locales for them are not installed on the web server.'); 178} 179 180if (!$form_autofocus && $languageComboBox->getAttribute('disabled') === null) { 181 $languageComboBox->setAttribute('autofocus', 'autofocus'); 182 $form_autofocus = true; 183} 184 185$userFormList->addRow( 186 _('Language'), 187 $languageError 188 ? [$languageComboBox, SPACE, (new CSpan($languageError))->addClass('red')->addClass('wrap')] 189 : $languageComboBox 190); 191 192// append themes to form list 193$themes = array_merge([THEME_DEFAULT => _('System default')], Z::getThemes()); 194$themes_combobox = new CComboBox('theme', $data['theme'], null, $themes); 195 196if (!$form_autofocus) { 197 $themes_combobox->setAttribute('autofocus', 'autofocus'); 198 $form_autofocus = true; 199} 200 201$userFormList->addRow(_('Theme'), $themes_combobox); 202 203// append auto-login & auto-logout to form list 204$autologoutCheckBox = (new CCheckBox('autologout_visible'))->setChecked($data['autologout_visible']); 205if ($data['autologout_visible']) { 206 $autologoutTextBox = (new CTextBox('autologout', $data['autologout']))->setWidth(ZBX_TEXTAREA_TINY_WIDTH); 207} 208else { 209 $autologoutTextBox = (new CTextBox('autologout', DB::getDefault('users', 'autologout'))) 210 ->setWidth(ZBX_TEXTAREA_TINY_WIDTH) 211 ->setAttribute('disabled', 'disabled'); 212} 213 214if ($data['alias'] != ZBX_GUEST_USER) { 215 $userFormList->addRow(_('Auto-login'), (new CCheckBox('autologin'))->setChecked($data['autologin'])); 216 $userFormList->addRow(_('Auto-logout'), [ 217 $autologoutCheckBox, 218 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 219 $autologoutTextBox 220 ]); 221} 222 223$userFormList 224 ->addRow((new CLabel(_('Refresh'), 'refresh'))->setAsteriskMark(), 225 (new CTextBox('refresh', $data['refresh'])) 226 ->setWidth(ZBX_TEXTAREA_TINY_WIDTH) 227 ->setAriaRequired() 228 ) 229 ->addRow((new CLabel(_('Rows per page'), 'rows_per_page'))->setAsteriskMark(), 230 (new CNumericBox('rows_per_page', $data['rows_per_page'], 6)) 231 ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH) 232 ->setAriaRequired() 233 ) 234 ->addRow(_('URL (after login)'), 235 (new CTextBox('url', $data['url']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 236 ); 237 238/* 239 * Media tab 240 */ 241if (uint_in_array(CWebUser::$data['type'], [USER_TYPE_ZABBIX_ADMIN, USER_TYPE_SUPER_ADMIN])) { 242 $userMediaFormList = new CFormList('userMediaFormList'); 243 $userForm->addVar('user_medias', $data['user_medias']); 244 245 $mediaTableInfo = (new CTable()) 246 ->setAttribute('style', 'width: 100%;') 247 ->setHeader([_('Type'), _('Send to'), _('When active'), _('Use if severity'), ('Status'), _('Action')]); 248 249 foreach ($data['user_medias'] as $id => $media) { 250 if (!array_key_exists('active', $media) || !$media['active']) { 251 $status = (new CLink(_('Enabled'), '#')) 252 ->addClass(ZBX_STYLE_LINK_ACTION) 253 ->addClass(ZBX_STYLE_GREEN) 254 ->onClick('return create_var("'.$userForm->getName().'","disable_media",'.$id.', true);'); 255 } 256 else { 257 $status = (new CLink(_('Disabled'), '#')) 258 ->addClass(ZBX_STYLE_LINK_ACTION) 259 ->addClass(ZBX_STYLE_RED) 260 ->onClick('return create_var("'.$userForm->getName().'","enable_media",'.$id.', true);'); 261 } 262 263 $popup_options = [ 264 'dstfrm' => $userForm->getName(), 265 'media' => $id, 266 'mediatypeid' => $media['mediatypeid'], 267 'period' => $media['period'], 268 'severity' => $media['severity'], 269 'active' => $media['active'] 270 ]; 271 272 if ($media['mediatype'] == MEDIA_TYPE_EMAIL) { 273 foreach ($media['sendto'] as $email) { 274 $popup_options['sendto_emails'][] = $email; 275 } 276 } 277 else { 278 $popup_options['sendto'] = $media['sendto']; 279 } 280 281 $mediaSeverity = []; 282 283 for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) { 284 $severityName = getSeverityName($severity, $data['config']); 285 $severity_status_style = getSeverityStatusStyle($severity); 286 287 $mediaActive = ($media['severity'] & (1 << $severity)); 288 289 $mediaSeverity[$severity] = (new CSpan(mb_substr($severityName, 0, 1))) 290 ->setHint($severityName.' ('.($mediaActive ? _('on') : _('off')).')', '', false) 291 ->addClass($mediaActive ? $severity_status_style : ZBX_STYLE_STATUS_DISABLED_BG); 292 } 293 294 if ($media['mediatype'] == MEDIA_TYPE_EMAIL) { 295 $media['sendto'] = implode(', ', $media['sendto']); 296 } 297 298 if (mb_strlen($media['sendto']) > 50) { 299 $media['sendto'] = (new CSpan(mb_substr($media['sendto'], 0, 50).'...'))->setHint($media['sendto']); 300 } 301 302 $mediaTableInfo->addRow( 303 (new CRow([ 304 $media['description'], 305 $media['sendto'], 306 (new CDiv($media['period'])) 307 ->setAttribute('style', 'max-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;') 308 ->addClass(ZBX_STYLE_OVERFLOW_ELLIPSIS), 309 (new CDiv($mediaSeverity))->addClass(ZBX_STYLE_STATUS_CONTAINER), 310 $status, 311 (new CCol( 312 new CHorList([ 313 (new CButton(null, _('Edit'))) 314 ->addClass(ZBX_STYLE_BTN_LINK) 315 ->onClick('return PopUp("popup.media",'.CJs::encodeJson($popup_options).', null, this);'), 316 (new CButton(null, _('Remove'))) 317 ->addClass(ZBX_STYLE_BTN_LINK) 318 ->onClick('javascript: removeMedia('.$id.');') 319 ]) 320 ))->addClass(ZBX_STYLE_NOWRAP) 321 ]))->setId('user_medias_'.$id) 322 ); 323 } 324 325 $userMediaFormList->addRow(_('Media'), 326 (new CDiv([ 327 $mediaTableInfo, 328 (new CButton(null, _('Add'))) 329 ->onClick('return PopUp("popup.media",'. 330 CJs::encodeJson([ 331 'dstfrm' => $userForm->getName() 332 ]).', null, this);' 333 ) 334 ->addClass(ZBX_STYLE_BTN_LINK) 335 ])) 336 ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) 337 ->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') 338 ); 339} 340else { 341 $userMediaFormList = null; 342} 343 344/* 345 * Profile fields 346 */ 347if ($data['is_profile']) { 348 $zbxSounds = getSounds(); 349 350 $userMessagingFormList = new CFormList(); 351 $userMessagingFormList->addRow(_('Frontend messaging'), 352 (new CCheckBox('messages[enabled]')) 353 ->setChecked($data['messages']['enabled'] == 1) 354 ->setUncheckedValue(0) 355 ); 356 $userMessagingFormList->addRow(_('Message timeout'), 357 (new CTextBox('messages[timeout]', $data['messages']['timeout'])) 358 ->setWidth(ZBX_TEXTAREA_TINY_WIDTH), 359 'timeout_row' 360 ); 361 362 $repeatSound = new CComboBox('messages[sounds.repeat]', $data['messages']['sounds.repeat'], 363 'if (IE) { submit() }', 364 [ 365 1 => _('Once'), 366 10 => '10 '._('Seconds'), 367 -1 => _('Message timeout') 368 ] 369 ); 370 $userMessagingFormList->addRow(_('Play sound'), $repeatSound, 'repeat_row'); 371 372 $soundList = new CComboBox('messages[sounds.recovery]', $data['messages']['sounds.recovery']); 373 foreach ($zbxSounds as $filename => $file) { 374 $soundList->addItem($file, $filename); 375 } 376 377 $triggersTable = (new CTable()) 378 ->addRow([ 379 (new CCheckBox('messages[triggers.recovery]')) 380 ->setLabel(_('Recovery')) 381 ->setChecked($data['messages']['triggers.recovery'] == 1) 382 ->setUncheckedValue(0), 383 [ 384 $soundList, 385 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 386 (new CButton('start', _('Play'))) 387 ->addClass(ZBX_STYLE_BTN_GREY) 388 ->onClick("javascript: testUserSound('messages_sounds.recovery');") 389 ->removeId(), 390 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 391 (new CButton('stop', _('Stop'))) 392 ->addClass(ZBX_STYLE_BTN_GREY) 393 ->onClick('javascript: AudioControl.stop();') 394 ->removeId() 395 ] 396 ]); 397 398 $msgVisibility = ['1' => [ 399 'messages[timeout]', 400 'messages[sounds.repeat]', 401 'messages[sounds.recovery]', 402 'messages[triggers.recovery]', 403 'timeout_row', 404 'repeat_row', 405 'triggers_row' 406 ]]; 407 408 // trigger sounds 409 for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) { 410 $soundList = new CComboBox('messages[sounds.'.$severity.']', $data['messages']['sounds.'.$severity]); 411 foreach ($zbxSounds as $filename => $file) { 412 $soundList->addItem($file, $filename); 413 } 414 415 $triggersTable->addRow([ 416 (new CCheckBox('messages[triggers.severities]['.$severity.']')) 417 ->setLabel(getSeverityName($severity, $data['config'])) 418 ->setChecked(array_key_exists($severity, $data['messages']['triggers.severities'])) 419 ->setUncheckedValue(0), 420 [ 421 $soundList, 422 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 423 (new CButton('start', _('Play'))) 424 ->addClass(ZBX_STYLE_BTN_GREY) 425 ->onClick("javascript: testUserSound('messages_sounds.".$severity."');") 426 ->removeId(), 427 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 428 (new CButton('stop', _('Stop'))) 429 ->addClass(ZBX_STYLE_BTN_GREY) 430 ->onClick('javascript: AudioControl.stop();') 431 ->removeId() 432 ] 433 ]); 434 435 zbx_subarray_push($msgVisibility, 1, 'messages[triggers.severities]['.$severity.']'); 436 zbx_subarray_push($msgVisibility, 1, 'messages[sounds.'.$severity.']'); 437 } 438 439 $userMessagingFormList 440 ->addRow(_('Trigger severity'), $triggersTable, 'triggers_row') 441 ->addRow(_('Show suppressed problems'), 442 (new CCheckBox('messages[show_suppressed]')) 443 ->setChecked($data['messages']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE) 444 ->setUncheckedValue(ZBX_PROBLEM_SUPPRESSED_FALSE) 445 ); 446} 447else { 448 $userMessagingFormList = null; 449} 450 451// append form lists to tab 452$userTab = new CTabView(); 453if (!$data['form_refresh']) { 454 $userTab->setSelected(0); 455} 456$userTab->addTab('userTab', _('User'), $userFormList); 457if ($userMediaFormList) { 458 $userTab->addTab('mediaTab', _('Media'), $userMediaFormList); 459} 460 461// Permissions tab. 462if (!$data['is_profile']) { 463 $permissionsFormList = new CFormList('permissionsFormList'); 464 465 $userTypeComboBox = new CComboBox('user_type', $data['user_type'], 'submit();', [ 466 USER_TYPE_ZABBIX_USER => user_type2str(USER_TYPE_ZABBIX_USER), 467 USER_TYPE_ZABBIX_ADMIN => user_type2str(USER_TYPE_ZABBIX_ADMIN), 468 USER_TYPE_SUPER_ADMIN => user_type2str(USER_TYPE_SUPER_ADMIN) 469 ]); 470 471 if ($data['userid'] != 0 && bccomp(CWebUser::$data['userid'], $data['userid']) == 0) { 472 $userTypeComboBox->setEnabled(false); 473 $permissionsFormList->addRow(_('User type'), [$userTypeComboBox, SPACE, new CSpan(_('User can\'t change type for himself'))]); 474 $userForm->addItem((new CVar('user_type', $data['user_type']))->removeId()); 475 } 476 else { 477 $permissionsFormList->addRow(_('User type'), $userTypeComboBox); 478 } 479 480 $permissions_table = (new CTable()) 481 ->setAttribute('style', 'width: 100%;') 482 ->setHeader([_('Host group'), _('Permissions')]); 483 484 if ($data['user_type'] == USER_TYPE_SUPER_ADMIN) { 485 $permissions_table->addRow([italic(_('All groups')), permissionText(PERM_READ_WRITE)]); 486 } 487 else { 488 foreach ($data['groups_rights'] as $groupid => $group_rights) { 489 if (array_key_exists('grouped', $group_rights) && $group_rights['grouped']) { 490 $group_name = ($groupid == 0) 491 ? italic(_('All groups')) 492 : [$group_rights['name'], SPACE, italic('('._('including subgroups').')')]; 493 } 494 else { 495 $group_name = $group_rights['name']; 496 } 497 $permissions_table->addRow([$group_name, permissionText($group_rights['permission'])]); 498 } 499 } 500 501 $permissionsFormList 502 ->addRow(_('Permissions'), 503 (new CDiv($permissions_table)) 504 ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) 505 ->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') 506 ) 507 ->addInfo(_('Permissions can be assigned for user groups only.')); 508 509 $userTab->addTab('permissionsTab', _('Permissions'), $permissionsFormList); 510} 511 512if ($userMessagingFormList) { 513 $userTab->addTab('messagingTab', _('Messaging'), $userMessagingFormList); 514} 515 516// append buttons to form 517if ($data['userid'] != 0) { 518 $buttons = [ 519 new CButtonCancel() 520 ]; 521 522 if (!$data['is_profile']) { 523 $deleteButton = new CButtonDelete(_('Delete selected user?'), url_param('form').url_param('userid')); 524 if (bccomp(CWebUser::$data['userid'], $data['userid']) == 0) { 525 $deleteButton->setAttribute('disabled', 'disabled'); 526 } 527 528 array_unshift($buttons, $deleteButton); 529 } 530 531 $userTab->setFooter(makeFormFooter(new CSubmit('update', _('Update')), $buttons)); 532} 533else { 534 $userTab->setFooter(makeFormFooter( 535 new CSubmit('add', _('Add')), 536 [new CButtonCancel()] 537 )); 538} 539 540// append tab to form 541$userForm->addItem($userTab); 542 543// append form to widget 544$userWidget->addItem($userForm); 545 546return $userWidget; 547