1<?php 2if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied'); 3 4$info = $qs = array(); 5 6if ($_REQUEST['a']=='add'){ 7 if (!$staff) { 8 $staff = Staff::create(array( 9 'isactive' => true, 10 )); 11 // Set some default permissions 12 $staff->updatePerms(array( 13 User::PERM_CREATE, 14 User::PERM_EDIT, 15 User::PERM_DELETE, 16 User::PERM_MANAGE, 17 User::PERM_DIRECTORY, 18 Organization::PERM_CREATE, 19 Organization::PERM_EDIT, 20 Organization::PERM_DELETE, 21 FAQ::PERM_MANAGE, 22 Dept::PERM_DEPT, 23 Staff::PERM_STAFF, 24 )); 25 } 26 $title=__('Add New Agent'); 27 $action='create'; 28 $submit_text=__('Create'); 29} 30else { 31 //Editing Department. 32 $title=__('Manage Agent'); 33 $action='update'; 34 $submit_text=__('Save Changes'); 35 $info['id'] = $staff->getId(); 36 $qs += array('id' => $staff->getId()); 37} 38 39$extras = new ArrayObject(); 40?> 41 42<form action="staff.php?<?php echo Http::build_query($qs); ?>" method="post" class="save" autocomplete="off"> 43 <?php csrf_token(); ?> 44 <input type="hidden" name="do" value="<?php echo $action; ?>"> 45 <input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>"> 46 <input type="hidden" name="id" value="<?php echo $info['id']; ?>"> 47 48 <h2><?php echo $title; ?> 49 <?php if (isset($staff->staff_id)) { ?><small> 50 — <?php echo $staff->getName(); ?></small> 51 <?php } ?> 52</h2> 53 54 <ul class="clean tabs"> 55 <li class="active"><a href="#account"><i class="icon-user"></i> <?php echo __('Account'); ?></a></li> 56 <li><a href="#access"><?php echo __('Access'); ?></a></li> 57 <li><a href="#permissions"><?php echo __('Permissions'); ?></a></li> 58 <li><a href="#teams"><?php echo __('Teams'); ?></a></li> 59 <?php Signal::send('agenttab.audit', $staff, $extras); ?> 60 </ul> 61 62 <div class="tab_content" id="account"> 63 <table class="table two-column" width="940" border="0" cellspacing="0" cellpadding="2"> 64 <tbody> 65 <tr><td colspan="2"><div> 66 <div class="avatar pull-left" style="width: 100px; margin: 10px;"> 67 <?php echo $staff->getAvatar(); ?> 68 </div> 69 <table class="table two-column" border="0" cellspacing="2" cellpadding="2" style="width: 760px"> 70 <tr> 71 <td class="required"><?php echo __('Name'); ?>:</td> 72 <td> 73 <input type="text" size="20" maxlength="64" style="width: 145px" name="firstname" class="auto first" 74 autofocus value="<?php echo Format::htmlchars($staff->firstname); ?>" 75 placeholder="<?php echo __("First Name"); ?>" /> 76 <input type="text" size="20" maxlength="64" style="width: 145px" name="lastname" class="auto last" 77 value="<?php echo Format::htmlchars($staff->lastname); ?>" 78 placeholder="<?php echo __("Last Name"); ?>" /> 79 <div class="error"><?php echo $errors['firstname']; ?></div> 80 <div class="error"><?php echo $errors['lastname']; ?></div> 81 </td> 82 </tr> 83 <tr> 84 <td class="required"><?php echo __('Email Address'); ?>:</td> 85 <td> 86 <input type="email" size="40" maxlength="64" style="width: 300px" name="email" class="auto email" 87 value="<?php echo Format::htmlchars($staff->email); ?>" 88 placeholder="<?php echo __('e.g. me@mycompany.com'); ?>" /> 89 <div class="error"><?php echo $errors['email']; ?></div> 90 </td> 91 </tr> 92 <tr> 93 <td><?php echo __('Phone Number');?>:</td> 94 <td> 95 <input type="tel" size="18" name="phone" class="auto phone" 96 value="<?php echo Format::htmlchars($staff->phone); ?>" /> 97 <?php echo __('Ext');?> 98 <input type="text" size="5" name="phone_ext" 99 value="<?php echo Format::htmlchars($staff->phone_ext); ?>"> 100 <div class="error"><?php echo $errors['phone']; ?></div> 101 <div class="error"><?php echo $errors['phone_ext']; ?></div> 102 </td> 103 </tr> 104 <tr> 105 <td><?php echo __('Mobile Number');?>:</td> 106 <td> 107 <input type="tel" size="18" name="mobile" class="auto phone" 108 value="<?php echo Format::htmlchars($staff->mobile); ?>" /> 109 <div class="error"><?php echo $errors['mobile']; ?></div> 110 </td> 111 </tr> 112 </table></div></td></tr> 113 </tbody> 114 <!-- ================================================ --> 115 <tbody> 116 <tr class="header"> 117 <th colspan="2"> 118 <?php echo __('Authentication'); ?> 119 </th> 120 </tr> 121 <tr> 122 <td class="required"><?php echo __('Username'); ?>: 123 <span class="error">*</span></td> 124 <td> 125 <input type="text" size="40" style="width:300px" 126 class="staff-username typeahead" 127 name="username" value="<?php echo Format::htmlchars($staff->username); ?>" /> 128<?php if (!($bk = $staff->getAuthBackend()) || $bk->supportsPasswordChange()) { ?> 129 <button type="button" class="action-button" onclick="javascript: 130 $.dialog('ajax.php/staff/'+<?php echo $info['id'] ?: '0'; ?>+'/set-password', 201);"> 131 <i class="icon-refresh"></i> <?php echo __('Set Password'); ?> 132 </button> 133<?php } ?> 134 <i class="offset help-tip icon-question-sign" href="#username"></i> 135 <div class="error"><?php echo $errors['username']; ?></div> 136 </td> 137 </tr> 138<?php 139$bks = array(); 140foreach (StaffAuthenticationBackend::allRegistered() as $ab) { 141 if (!$ab->supportsInteractiveAuthentication()) continue; 142 $bks[] = $ab; 143} 144if (count($bks) > 1) { 145?> 146 <tr> 147 <td><?php echo __('Authentication Backend'); ?>:</td> 148 <td> 149 <select name="backend" id="backend-selection" 150 style="width:300px" onchange="javascript: 151 if (this.value != '' && this.value != 'local') 152 $('#password-fields').hide(); 153 else if (!$('#welcome-email').is(':checked')) 154 $('#password-fields').show(); 155 "> 156 <option value="">— <?php echo __('Use any available backend'); ?> —</option> 157<?php foreach ($bks as $ab) { ?> 158 <option value="<?php echo $ab::$id; ?>" <?php 159 if ($staff->backend == $ab::$id) 160 echo 'selected="selected"'; ?>><?php 161 echo $ab->getName(); ?></option> 162<?php } ?> 163 </select> 164 </td> 165 </tr> 166<?php 167} ?> 168<?php 169if ($bks=Staff2FABackend::allRegistered() && $current = $staff->get2FABackend()) { 170 $_config = $staff->getConfig(); 171?> 172 <tr> 173 <td><?php echo __('Default 2FA'); ?>:</td> 174 <td> 175 <input type="text" size="40" style="width:300px" 176 name="default_2fa" disabled value="<?php echo $current->getName(); ?>" /> 177 178 <button type="button" id="reset-2fa" class="action-button" onclick="javascript: 179 if (confirm('<?php echo __('You sure?'); ?>')) { 180 $.ajax({ 181 url: 'ajax.php/staff/'+<?php echo $staff->getId(); ?>+'/reset-2fa', 182 type: 'POST', 183 data: {'staffId':<?php echo $staff->getId(); ?>}, 184 success: function(data) { 185 location.reload(); 186 } 187 }); 188 } 189 return false;"> 190 <i class="icon-gear"></i> <?php echo __('Reset 2FA'); ?> 191 </button> 192 <i class="offset help-tip icon-question-sign" href="#reset2fa"></i> 193 </td> 194 </tr> 195<?php 196} ?> 197 </tbody> 198 <!-- ================================================ --> 199 <tbody> 200 <tr class="header"> 201 <th colspan="2"> 202 <?php echo __('Status and Settings'); ?> 203 </th> 204 </tr> 205 <tr> 206 <td colspan="2"> 207 <div class="error"><?php echo $errors['isadmin']; ?></div> 208 <div class="error"><?php echo $errors['isactive']; ?></div> 209 <label class="checkbox"> 210 <input type="checkbox" name="islocked" value="1" 211 <?php echo (!$staff->isactive) ? 'checked="checked"' : ''; ?> /> 212 <?php echo __('Locked'); ?> 213 </label> 214 <label class="checkbox"> 215 <input type="checkbox" name="isadmin" value="1" 216 <?php echo ($staff->isadmin) ? 'checked="checked"' : ''; ?> /> 217 <?php echo __('Administrator'); ?> 218 </label> 219 <label class="checkbox"> 220 <input type="checkbox" name="assigned_only" 221 <?php echo ($staff->assigned_only) ? 'checked="checked"' : ''; ?> /> 222 <?php echo __('Limit ticket access to ONLY assigned tickets'); ?> 223 </label> 224 <label class="checkbox"> 225 <input type="checkbox" name="onvacation" 226 <?php echo ($staff->onvacation) ? 'checked="checked"' : ''; ?> /> 227 <?php echo __('Vacation Mode'); ?> 228 </label> 229 <br/> 230 </tr> 231 </tbody> 232 </table> 233 234 <div style="padding:8px 3px; margin-top: 1.6em"> 235 <strong class="big"><?php echo __('Internal Notes');?>: </strong> 236 <?php echo __("Be liberal, they're internal");?> 237 </div> 238 239 <textarea name="notes" class="richtext"> 240 <?php echo Format::viewableImages($staff->notes); ?> 241 </textarea> 242 </div> 243 244 <!-- ============== DEPARTMENT ACCESS =================== --> 245 246 <div class="hidden tab_content" id="access"> 247 <table class="table two-column" width="940" border="0" cellspacing="0" cellpadding="2"> 248 <tbody> 249 <tr class="header"> 250 <th colspan="3"> 251 <?php echo __('Access'); ?> 252 <div><small><?php echo __( 253 "Select the departments the agent is allowed to access and the corresponding effective role." 254 ); ?> 255 </small></div><br> 256 <div><?php echo __('Primary Department'); ?> <span 257 class="error">*</span></div> 258 </th> 259 </tr> 260 <tr> 261 <td style="vertical-align:top"> 262 <select name="dept_id" id="dept_id" data-quick-add="department"> 263 <option value="0">— <?php echo __('Select Department');?> —</option> 264 <?php 265 if($depts = Dept::getPublicDepartments()) { 266 if($staff->dept_id && !array_key_exists($staff->dept_id, $depts)) 267 { 268 $depts[$staff->dept_id] = $staff->dept; 269 $warn = sprintf(__('%s selected must be active'), __('Department')); 270 } 271 foreach($depts as $id =>$name) { 272 $sel=($staff->dept_id==$id)?'selected="selected"':''; 273 echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); 274 } 275 } 276 ?> 277 <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> 278 </select> 279 <i class="offset help-tip icon-question-sign" href="#primary_department"></i> 280 <?php 281 if($warn) { ?> 282 <span class="error">* <?php echo $warn; ?></span> 283 <?php } ?> 284 </td> 285 <td style="vertical-align:top"> 286 <select name="role_id" data-quick-add="role"> 287 <option value="0">— <?php echo __('Select Role');?> —</option> 288 <?php 289 foreach (Role::getRoles() as $id=>$name) { 290 $sel=($staff->role_id==$id)?'selected="selected"':''; 291 echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); 292 } 293 ?> 294 <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> 295 </select> 296 <i class="offset help-tip icon-question-sign" href="#primary_role"></i> 297 </td> 298 <td> 299 <label class="inline checkbox"> 300 <input type="checkbox" name="assign_use_pri_role" <?php 301 if ($staff->usePrimaryRoleOnAssignment()) 302 echo 'checked="checked"'; 303 ?> /> 304 <?php echo __('Fall back to primary role on assignments'); ?> 305 <i class="icon-question-sign help-tip" 306 href="#primary_role_on_assign"></i> 307 </label> 308 309 <div class="error"><?php echo $errors['role_id']; ?></div> 310 </td> 311 </tr> 312 </tbody> 313 <tbody> 314 <tr id="extended_access_template" class="hidden"> 315 <td> 316 <input type="hidden" data-name="dept_access[]" value="" /> 317 </td> 318 <td> 319 <select data-name="dept_access_role" data-quick-add="role"> 320 <option value="0">— <?php echo __('Select Role');?> —</option> 321 <?php 322 foreach (Role::getRoles() as $id=>$name) { 323 echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); 324 } 325 ?> 326 <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> 327 </select> 328 </td> 329 <td> 330 <label class="inline checkbox"> 331 <input type="checkbox" data-name="dept_access_alerts" value="1" /> 332 <?php echo __('Alerts'); ?> 333 </label> 334 <a href="#" class="pull-right drop-access" title="<?php echo __('Delete'); 335 ?>"><i class="icon-trash"></i></a> 336 </td> 337 </tr> 338 </tbody> 339 <tbody> 340 <tr class="header"> 341 <th colspan="3"> 342 <?php echo __('Extended Access'); ?> 343 </th> 344 </tr> 345<?php 346$depts = Dept::getDepartments(); 347foreach ($staff->dept_access as $dept_access) { 348 unset($depts[$dept_access->dept_id]); 349} 350?> 351 <tr id="add_extended_access"> 352 <td colspan="2"> 353 <i class="icon-plus-sign"></i> 354 <select id="add_access" data-quick-add="department"> 355 <option value="0">— <?php echo __('Select Department');?> —</option> 356 <?php 357 foreach ($depts as $id=>$name) { 358 echo sprintf('<option value="%d">%s</option>',$id,Format::htmlchars($name)); 359 } 360 ?> 361 <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> 362 </select> 363 <button type="button" class="green button"> 364 <?php echo __('Add'); ?> 365 </button> 366 </td> 367 </tr> 368 </tbody> 369 </table> 370 </div> 371 372 <!-- ================= PERMISSIONS ====================== --> 373 374 <div id="permissions" class="hidden"> 375<?php 376 $permissions = array(); 377 foreach (RolePermission::allPermissions() as $g => $perms) { 378 foreach ($perms as $k=>$P) { 379 if (!$P['primary']) 380 continue; 381 if (!isset($permissions[$g])) 382 $permissions[$g] = array(); 383 $permissions[$g][$k] = $P; 384 } 385 } 386?> 387 <ul class="alt tabs"> 388<?php 389 $first = true; 390 foreach ($permissions as $g => $perms) { ?> 391 <li <?php if ($first) { echo 'class="active"'; $first=false; } ?>> 392 <a href="#<?php echo Format::slugify($g); ?>"><?php echo Format::htmlchars(__($g));?></a> 393 </li> 394<?php } ?> 395 </ul> 396<?php 397 $first = true; 398 foreach ($permissions as $g => $perms) { ?> 399 <div class="tab_content <?php if (!$first) { echo 'hidden'; } else { $first = false; } 400 ?>" id="<?php echo Format::slugify($g); ?>"> 401 <table class="table"> 402<?php foreach ($perms as $k => $v) { ?> 403 <tr> 404 <td> 405 <label> 406 <?php 407 echo sprintf('<input type="checkbox" name="perms[]" value="%s" %s />', 408 $k, ($staff->hasPerm($k)) ? 'checked="checked"' : ''); 409 ?> 410 411 <?php echo Format::htmlchars(__($v['title'])); ?> 412 — 413 <em><?php echo Format::htmlchars(__($v['desc'])); ?></em> 414 </label> 415 </td> 416 </tr> 417<?php } ?> 418 </table> 419 </div> 420<?php } ?> 421 </div> 422 423 <!-- ============== TEAM MEMBERSHIP =================== --> 424 425 <div class="hidden tab_content" id="teams"> 426 <table class="table two-column" width="100%"> 427 <tbody> 428 <tr class="header"> 429 <th colspan="2"> 430 <?php echo __('Assigned Teams'); ?> 431 <div><small><?php echo __( 432 "Agent will have access to tickets assigned to a team they belong to regardless of the ticket's department. Alerts can be enabled for each associated team." 433 ); ?> 434 </small></div> 435 </th> 436 </tr> 437<?php 438$teams = Team::getTeams(); 439foreach ($staff->teams as $TM) { 440 unset($teams[$TM->team_id]); 441} 442?> 443 <tr id="join_team"> 444 <td colspan="2"> 445 <i class="icon-plus-sign"></i> 446 <select id="add_team" data-quick-add="team"> 447 <option value="0">— <?php echo __('Select Team');?> —</option> 448 <?php 449 foreach ($teams as $id=>$name) { 450 echo sprintf('<option value="%d">%s</option>',$id,Format::htmlchars($name)); 451 } 452 ?> 453 <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> 454 </select> 455 <button type="button" class="green button"> 456 <?php echo __('Add'); ?> 457 </button> 458 </td> 459 </tr> 460 </tbody> 461 <tbody> 462 <tr id="team_member_template" class="hidden"> 463 <td> 464 <input type="hidden" data-name="teams[]" value="" /> 465 </td> 466 <td> 467 <label> 468 <input type="checkbox" data-name="team_alerts" value="1" /> 469 <?php echo __('Alerts'); ?> 470 </label> 471 <a href="#" class="pull-right drop-membership" title="<?php echo __('Delete'); 472 ?>"><i class="icon-trash"></i></a> 473 </td> 474 </tr> 475 </tbody> 476 </table> 477 </div> 478 479 <!-- ============== Audits =================== --> 480<?php Signal::send('agent.audit', $staff, $extras); ?> 481 482 <p style="text-align:center;"> 483 <input type="submit" name="submit" value="<?php echo $submit_text; ?>"> 484 <input type="reset" name="reset" value="<?php echo __('Reset');?>"> 485 <input type="button" name="cancel" value="<?php echo __('Cancel');?>" onclick="window.history.go(-1);"> 486 </p> 487</form> 488 489<script type="text/javascript"> 490var addAccess = function(daid, name, role, alerts, error) { 491 if (!daid) return; 492 var copy = $('#extended_access_template').clone(); 493 494 copy.find('[data-name=dept_access\\[\\]]') 495 .attr('name', 'dept_access[]') 496 .val(daid); 497 copy.find('[data-name^=dept_access_role]') 498 .attr('name', 'dept_access_role['+daid+']') 499 .val(role || 0); 500 copy.find('[data-name^=dept_access_alerts]') 501 .attr('name', 'dept_access_alerts['+daid+']') 502 .prop('checked', alerts); 503 copy.find('td:first').append(document.createTextNode(name)); 504 copy.attr('id', '').show().insertBefore($('#add_extended_access')); 505 copy.removeClass('hidden') 506 if (error) 507 $('<div class="error">').text(error).appendTo(copy.find('td:last')); 508 copy.find('a.drop-access').click(function() { 509 $('#add_access').append( 510 $('<option>') 511 .attr('value', copy.find('input[name^=dept_access][type=hidden]').val()) 512 .text(copy.find('td:first').text()) 513 ); 514 copy.fadeOut(function() { $(this).remove(); }); 515 return false; 516 }); 517}; 518 519$('#add_extended_access').find('button').on('click', function() { 520 var selected = $('#add_access').find(':selected'), 521 id = parseInt(selected.val()); 522 if (!id) 523 return; 524 addAccess(id, selected.text(), 0, true); 525 selected.remove(); 526 return false; 527}); 528 529var joinTeam = function(teamid, name, alerts, error) { 530 if (!teamid) return; 531 var copy = $('#team_member_template').clone(); 532 533 copy.find('[data-name=teams\\[\\]]') 534 .attr('name', 'teams[]') 535 .val(teamid); 536 copy.find('[data-name^=team_alerts]') 537 .attr('name', 'team_alerts['+teamid+']') 538 .prop('checked', alerts); 539 copy.find('td:first').append(document.createTextNode(name)); 540 copy.attr('id', '').show().insertBefore($('#join_team')); 541 copy.removeClass('hidden'); 542 if (error) 543 $('<div class="error">').text(error).appendTo(copy.find('td:last')); 544 copy.find('a.drop-membership').click(function() { 545 $('#add_team').append( 546 $('<option>') 547 .attr('value', copy.find('input[name^=teams][type=hidden]').val()) 548 .text(copy.find('td:first').text()) 549 ); 550 copy.fadeOut(function() { $(this).remove(); }); 551 return false; 552 }); 553}; 554 555$('#join_team').find('button').on('click', function() { 556 var selected = $('#add_team').find(':selected'), 557 id = parseInt(selected.val()); 558 if (!id) 559 return; 560 joinTeam(id, selected.text(), true); 561 selected.remove(); 562 return false; 563}); 564 565 566<?php 567foreach ($staff->dept_access as $dept_access) { 568 if (!$dept_access->dept_id) continue; 569 echo sprintf('addAccess(%d, %s, %d, %d, %s);', $dept_access->dept_id, 570 JsonDataEncoder::encode($dept_access->dept->getName()), 571 $dept_access->role_id, 572 $dept_access->isAlertsEnabled(), 573 JsonDataEncoder::encode(@$errors['dept_access'][$dept_access->dept_id]) 574 ); 575} 576 577foreach ($staff->teams as $member) { 578 if (!$member->team) continue; 579 echo sprintf('joinTeam(%d, %s, %d, %s);', $member->team_id, 580 JsonDataEncoder::encode($member->team->getName()), 581 $member->isAlertsEnabled(), 582 JsonDataEncoder::encode(@$errors['teams'][$member->team_id]) 583 ); 584} 585 586?> 587</script> 588