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 ($this->data['is_profile']) { 25 $userWidget = ($this->data['name'] !== '' || $this->data['surname'] !== '') 26 ? (new CWidget())->setTitle(_('User profile').NAME_DELIMITER.$this->data['name'].' '.$this->data['surname']) 27 : (new CWidget())->setTitle(_('User profile').NAME_DELIMITER.$this->data['alias']); 28} 29else { 30 $userWidget = (new CWidget())->setTitle(_('Users')); 31} 32 33// create form 34$userForm = (new CForm()) 35 ->setName('userForm') 36 ->addVar('form', $this->data['form']); 37 38if ($data['userid'] != 0) { 39 $userForm->addVar('userid', $data['userid']); 40} 41 42/* 43 * User tab 44 */ 45$userFormList = new CFormList('userFormList'); 46 47if (!$data['is_profile']) { 48 $userFormList->addRow(_('Alias'), (new CTextBox('alias', $this->data['alias'])) 49 ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 50 ->setAttribute('autofocus', 'autofocus') 51 ); 52 $userFormList->addRow(_x('Name', 'user first name'), 53 (new CTextBox('name', $this->data['name']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 54 ); 55 $userFormList->addRow(_('Surname'), 56 (new CTextBox('surname', $this->data['surname']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 57 ); 58} 59 60// append user groups to form list 61if (!$this->data['is_profile']) { 62 $user_groups = []; 63 64 foreach ($this->data['groups'] as $group) { 65 $user_groups[] = CArrayHelper::renameKeys($group, ['usrgrpid' => 'id']); 66 } 67 68 $userFormList->addRow( 69 _('Groups'), 70 (new CMultiSelect([ 71 'name' => 'user_groups[]', 72 'objectName' => 'usersGroups', 73 'data' => $user_groups, 74 'popup' => [ 75 'parameters' => 'srctbl=usrgrp&dstfrm='.$userForm->getName().'&dstfld1=user_groups_&srcfld1=usrgrpid'. 76 '&multiselect=1' 77 ] 78 ]))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 79 ); 80} 81 82// append password to form list 83if ($data['auth_type'] == ZBX_AUTH_INTERNAL) { 84 if ($data['userid'] == 0 || isset($this->data['change_password'])) { 85 $userFormList->addRow( 86 _('Password'), 87 (new CPassBox('password1', $this->data['password1']))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) 88 ); 89 $userFormList->addRow( 90 _('Password (once again)'), 91 (new CPassBox('password2', $this->data['password2']))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH) 92 ); 93 94 if (isset($this->data['change_password'])) { 95 $userForm->addVar('change_password', $this->data['change_password']); 96 } 97 } 98 else { 99 $passwdButton = (new CSimpleButton(_('Change password'))) 100 ->onClick('javascript: submitFormWithParam("'.$userForm->getName().'", "change_password", "1");') 101 ->addClass(ZBX_STYLE_BTN_GREY); 102 if ($this->data['alias'] == ZBX_GUEST_USER) { 103 $passwdButton->setAttribute('disabled', 'disabled'); 104 } 105 106 $userFormList->addRow(_('Password'), $passwdButton); 107 } 108} 109else { 110 $userFormList->addRow(_('Password'), 111 new CSpan(_s('Unavailable for users with %1$s.', authentication2str($data['auth_type']))) 112 ); 113} 114 115// append languages to form list 116$languageComboBox = new CComboBox('lang', $this->data['lang']); 117 118$allLocalesAvailable = true; 119foreach (getLocales() as $localeId => $locale) { 120 if ($locale['display']) { 121 // checking if this locale exists in the system. The only way of doing it is to try and set one 122 // trying to set only the LC_MONETARY locale to avoid changing LC_NUMERIC 123 $localeExists = ($localeId === 'en_GB' || setlocale(LC_MONETARY , zbx_locale_variants($localeId))); 124 125 $languageComboBox->addItem( 126 $localeId, 127 $locale['name'], 128 ($localeId == $this->data['lang']) ? true : null, 129 $localeExists 130 ); 131 132 $allLocalesAvailable &= $localeExists; 133 } 134} 135 136// restoring original locale 137setlocale(LC_MONETARY, zbx_locale_variants(CWebUser::$data['lang'])); 138 139$languageError = ''; 140if (!function_exists('bindtextdomain')) { 141 $languageError = 'Translations are unavailable because the PHP gettext module is missing.'; 142 $languageComboBox->setAttribute('disabled', 'disabled'); 143} 144elseif (!$allLocalesAvailable) { 145 $languageError = _('You are not able to choose some of the languages, because locales for them are not installed on the web server.'); 146} 147 148$userFormList->addRow( 149 _('Language'), 150 $languageError 151 ? [$languageComboBox, SPACE, (new CSpan($languageError))->addClass('red')->addClass('wrap')] 152 : $languageComboBox 153); 154 155// append themes to form list 156$themes = array_merge([THEME_DEFAULT => _('System default')], Z::getThemes()); 157$userFormList->addRow(_('Theme'), new CComboBox('theme', $this->data['theme'], null, $themes)); 158 159// append auto-login & auto-logout to form list 160$autologoutCheckBox = (new CCheckBox('autologout_visible'))->setChecked(isset($this->data['autologout'])); 161if (isset($this->data['autologout'])) { 162 $autologoutTextBox = (new CNumericBox('autologout', $this->data['autologout'], 4)) 163 ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH); 164} 165else { 166 $autologoutTextBox = (new CNumericBox('autologout', 900, 4)) 167 ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH) 168 ->setAttribute('disabled', 'disabled'); 169} 170 171if ($this->data['alias'] != ZBX_GUEST_USER) { 172 $userFormList->addRow(_('Auto-login'), (new CCheckBox('autologin'))->setChecked($this->data['autologin'])); 173 $userFormList->addRow(_('Auto-logout (min 90 seconds)'), [ 174 $autologoutCheckBox, 175 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 176 $autologoutTextBox 177 ]); 178} 179 180$userFormList 181 ->addRow(_('Refresh (in seconds)'), 182 (new CNumericBox('refresh', $this->data['refresh'], 4))->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH) 183 ) 184 ->addRow(_('Rows per page'), 185 (new CNumericBox('rows_per_page', $this->data['rows_per_page'], 6)) 186 ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH) 187 ) 188 ->addRow(_('URL (after login)'), 189 (new CTextBox('url', $this->data['url']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) 190 ); 191 192/* 193 * Media tab 194 */ 195if (uint_in_array(CWebUser::$data['type'], [USER_TYPE_ZABBIX_ADMIN, USER_TYPE_SUPER_ADMIN])) { 196 $userMediaFormList = new CFormList('userMediaFormList'); 197 $userForm->addVar('user_medias', $this->data['user_medias']); 198 199 $mediaTableInfo = (new CTable()) 200 ->setAttribute('style', 'width: 100%;') 201 ->setHeader([_('Type'), _('Send to'), _('When active'), _('Use if severity'), ('Status'), _('Action')]); 202 203 foreach ($this->data['user_medias'] as $id => $media) { 204 if (!isset($media['active']) || !$media['active']) { 205 $status = (new CLink(_('Enabled'), '#')) 206 ->addClass(ZBX_STYLE_LINK_ACTION) 207 ->addClass(ZBX_STYLE_GREEN) 208 ->onClick('return create_var("'.$userForm->getName().'","disable_media",'.$id.', true);'); 209 } 210 else { 211 $status = (new CLink(_('Disabled'), '#')) 212 ->addClass(ZBX_STYLE_LINK_ACTION) 213 ->addClass(ZBX_STYLE_RED) 214 ->onClick('return create_var("'.$userForm->getName().'","enable_media",'.$id.', true);'); 215 } 216 217 $mediaUrl = 'popup_media.php'. 218 '?dstfrm='.$userForm->getName(). 219 '&media='.$id. 220 '&mediatypeid='.$media['mediatypeid']. 221 '&sendto='.urlencode($media['sendto']). 222 '&period='.$media['period']. 223 '&severity='.$media['severity']. 224 '&active='.$media['active']; 225 226 $mediaSeverity = []; 227 228 for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) { 229 $severityName = getSeverityName($severity, $this->data['config']); 230 231 $mediaActive = ($media['severity'] & (1 << $severity)); 232 233 $mediaSeverity[$severity] = (new CSpan(mb_substr($severityName, 0, 1))) 234 ->setHint($severityName.' ('.($mediaActive ? _('on') : _('off')).')', '', false) 235 ->addClass($mediaActive ? ZBX_STYLE_GREEN : ZBX_STYLE_GREY); 236 } 237 238 $mediaTableInfo->addRow( 239 (new CRow([ 240 $media['description'], 241 $media['sendto'], 242 $media['period'], 243 $mediaSeverity, 244 $status, 245 (new CCol( 246 new CHorList([ 247 (new CButton(null, _('Edit'))) 248 ->addClass(ZBX_STYLE_BTN_LINK) 249 ->onClick('return PopUp("'.$mediaUrl.'");'), 250 (new CButton(null, _('Remove'))) 251 ->addClass(ZBX_STYLE_BTN_LINK) 252 ->onClick('javascript: removeMedia('.$id.');') 253 ]) 254 ))->addClass(ZBX_STYLE_NOWRAP) 255 ]))->setId('user_medias_'.$id) 256 ); 257 } 258 259 $userMediaFormList->addRow(_('Media'), 260 (new CDiv([ 261 $mediaTableInfo, 262 (new CButton(null, _('Add'))) 263 ->onClick('return PopUp("popup_media.php?dstfrm='.$userForm->getName().'");') 264 ->addClass(ZBX_STYLE_BTN_LINK), 265 ])) 266 ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) 267 ->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') 268 ); 269} 270 271/* 272 * Profile fields 273 */ 274if ($this->data['is_profile']) { 275 $zbxSounds = getSounds(); 276 277 $userMessagingFormList = new CFormList(); 278 $userMessagingFormList->addRow(_('Frontend messaging'), 279 (new CCheckBox('messages[enabled]'))->setChecked($this->data['messages']['enabled'] == 1) 280 ); 281 $userMessagingFormList->addRow(_('Message timeout (seconds)'), 282 (new CNumericBox('messages[timeout]', $this->data['messages']['timeout'], 5)) 283 ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH), 284 'timeout_row' 285 ); 286 287 $repeatSound = new CComboBox('messages[sounds.repeat]', $this->data['messages']['sounds.repeat'], 288 'if (IE) { submit() }', 289 [ 290 1 => _('Once'), 291 10 => '10 '._('Seconds'), 292 -1 => _('Message timeout') 293 ] 294 ); 295 $userMessagingFormList->addRow(_('Play sound'), $repeatSound, 'repeat_row'); 296 297 $soundList = new CComboBox('messages[sounds.recovery]', $this->data['messages']['sounds.recovery']); 298 foreach ($zbxSounds as $filename => $file) { 299 $soundList->addItem($file, $filename); 300 } 301 302 $triggersTable = (new CTable()) 303 ->addRow([ 304 new CLabel([ 305 (new CCheckBox('messages[triggers.recovery]')) 306 ->setChecked($this->data['messages']['triggers.recovery'] == 1), 307 _('Recovery')], 'messages[triggers.recovery]' 308 ), 309 [ 310 $soundList, 311 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 312 (new CButton('start', _('Play'))) 313 ->addClass(ZBX_STYLE_BTN_GREY) 314 ->onClick("javascript: testUserSound('messages_sounds.recovery');"), 315 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 316 (new CButton('stop', _('Stop'))) 317 ->addClass(ZBX_STYLE_BTN_GREY) 318 ->onClick('javascript: AudioControl.stop();') 319 ] 320 ]); 321 322 $msgVisibility = ['1' => [ 323 'messages[timeout]', 324 'messages[sounds.repeat]', 325 'messages[sounds.recovery]', 326 'messages[triggers.recovery]', 327 'timeout_row', 328 'repeat_row', 329 'triggers_row' 330 ]]; 331 332 // trigger sounds 333 for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) { 334 $soundList = new CComboBox('messages[sounds.'.$severity.']', $this->data['messages']['sounds.'.$severity]); 335 foreach ($zbxSounds as $filename => $file) { 336 $soundList->addItem($file, $filename); 337 } 338 339 $triggersTable->addRow([ 340 new CLabel([ 341 (new CCheckBox('messages[triggers.severities]['.$severity.']')) 342 ->setChecked(isset($this->data['messages']['triggers.severities'][$severity])), 343 getSeverityName($severity, $this->data['config'])], 'messages[triggers.severities]['.$severity.']' 344 ), 345 [ 346 $soundList, 347 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 348 (new CButton('start', _('Play'))) 349 ->addClass(ZBX_STYLE_BTN_GREY) 350 ->onClick( "javascript: testUserSound('messages_sounds.".$severity."');"), 351 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 352 (new CButton('stop', _('Stop'))) 353 ->addClass(ZBX_STYLE_BTN_GREY) 354 ->onClick('javascript: AudioControl.stop();') 355 ] 356 ]); 357 358 zbx_subarray_push($msgVisibility, 1, 'messages[triggers.severities]['.$severity.']'); 359 zbx_subarray_push($msgVisibility, 1, 'messages[sounds.'.$severity.']'); 360 } 361 362 $userMessagingFormList->addRow(_('Trigger severity'), $triggersTable, 'triggers_row'); 363} 364 365// append form lists to tab 366$userTab = new CTabView(); 367if (!$this->data['form_refresh']) { 368 $userTab->setSelected(0); 369} 370$userTab->addTab('userTab', _('User'), $userFormList); 371if (isset($userMediaFormList)) { 372 $userTab->addTab('mediaTab', _('Media'), $userMediaFormList); 373} 374 375if (!$this->data['is_profile']) { 376 /* 377 * Permissions tab 378 */ 379 $permissionsFormList = new CFormList('permissionsFormList'); 380 381 $userTypeComboBox = new CComboBox('user_type', $this->data['user_type'], 'submit();', [ 382 USER_TYPE_ZABBIX_USER => user_type2str(USER_TYPE_ZABBIX_USER), 383 USER_TYPE_ZABBIX_ADMIN => user_type2str(USER_TYPE_ZABBIX_ADMIN), 384 USER_TYPE_SUPER_ADMIN => user_type2str(USER_TYPE_SUPER_ADMIN) 385 ]); 386 387 if ($data['userid'] != 0 && bccomp(CWebUser::$data['userid'], $data['userid']) == 0) { 388 $userTypeComboBox->setEnabled(false); 389 $permissionsFormList->addRow(_('User type'), [$userTypeComboBox, SPACE, new CSpan(_('User can\'t change type for himself'))]); 390 $userForm->addVar('user_type', $this->data['user_type']); 391 } 392 else { 393 $permissionsFormList->addRow(_('User type'), $userTypeComboBox); 394 } 395 396 $permissionsFormList = getPermissionsFormList($this->data['user_rights'], $this->data['user_type'], $permissionsFormList); 397 $permissionsFormList->addInfo(_('Permissions can be assigned for user groups only.')); 398 399 $userTab->addTab('permissionsTab', _('Permissions'), $permissionsFormList); 400} 401if (isset($userMessagingFormList)) { 402 $userTab->addTab('messagingTab', _('Messaging'), $userMessagingFormList); 403} 404 405// append buttons to form 406if ($data['userid'] != 0) { 407 $buttons = [ 408 new CButtonCancel() 409 ]; 410 411 if (!$this->data['is_profile']) { 412 $deleteButton = new CButtonDelete(_('Delete selected user?'), url_param('form').url_param('userid')); 413 if (bccomp(CWebUser::$data['userid'], $data['userid']) == 0) { 414 $deleteButton->setAttribute('disabled', 'disabled'); 415 } 416 417 array_unshift($buttons, $deleteButton); 418 } 419 420 $userTab->setFooter(makeFormFooter(new CSubmit('update', _('Update')), $buttons)); 421} 422else { 423 $userTab->setFooter(makeFormFooter( 424 new CSubmit('add', _('Add')), 425 [new CButtonCancel()] 426 )); 427} 428 429// append tab to form 430$userForm->addItem($userTab); 431 432// append form to widget 433$userWidget->addItem($userForm); 434 435return $userWidget; 436