diff --git a/bootstrap.php b/bootstrap.php index c7ba0a41575eab6fc47ed3b566359303ab4f1795..6fa05aa508dc48443d1235f8fb3f1a5a09aa755b 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -81,7 +81,7 @@ class Bootstrap { define('TEAM_MEMBER_TABLE',$prefix.'team_member'); define('DEPT_TABLE',$prefix.'department'); define('GROUP_TABLE', $prefix.'group'); - define('GROUP_DEPT_TABLE', $prefix.'group_dept_access'); + define('STAFF_DEPT_TABLE', $prefix.'staff_dept_access'); define('ROLE_TABLE', $prefix.'role'); define('FAQ_TABLE',$prefix.'faq'); diff --git a/include/ajax.admin.php b/include/ajax.admin.php index 0cee34e4c6b522e8a07371913c927f108a007128..ca34433480a46eb6091730a9d9068de46d6bdc1f 100644 --- a/include/ajax.admin.php +++ b/include/ajax.admin.php @@ -44,7 +44,7 @@ class AdminAjaxAPI extends AjaxController { } $title = __("Add New Department"); - $path = $ost->get_path_info(); + $path = ltrim($ost->get_path_info(), '/'); include STAFFINC_DIR . 'templates/quick-add.tmpl.php'; } @@ -88,7 +88,7 @@ class AdminAjaxAPI extends AjaxController { } $title = __("Add New Team"); - $path = $ost->get_path_info(); + $path = ltrim($ost->get_path_info(), '/'); include STAFFINC_DIR . 'templates/quick-add.tmpl.php'; } diff --git a/include/ajax.kbase.php b/include/ajax.kbase.php index 30575ac22b05ee80bcf3aa07d1e52ed9fe5d3b0a..10266e242d680d7fb231831dab3c95c54ef05f9c 100644 --- a/include/ajax.kbase.php +++ b/include/ajax.kbase.php @@ -55,7 +55,7 @@ class KbaseAjaxAPI extends AjaxController { $faq->getId(), $faq->getNumAttachments()); if($thisstaff - && $thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) { + && $thisstaff->hasPerm(FAQ::PERM_MANAGE)) { $resp.=sprintf(' | <a href="faq.php?id=%d&a=edit">'.__('Edit').'</a>',$faq->getId()); } diff --git a/include/ajax.orgs.php b/include/ajax.orgs.php index b6a4002feac751e5a2bbf1a3a6ac34f38ee2db45..c4d73187bf6d2c85c2bf1dc4a7c0f6650174e233 100644 --- a/include/ajax.orgs.php +++ b/include/ajax.orgs.php @@ -54,7 +54,7 @@ class OrgsAjaxAPI extends AjaxController { if(!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(Organization::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif(!($org = Organization::lookup($id))) Http::response(404, 'Unknown organization'); @@ -74,7 +74,7 @@ class OrgsAjaxAPI extends AjaxController { if(!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(Organization::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif(!($org = Organization::lookup($id))) Http::response(404, 'Unknown organization'); @@ -101,7 +101,7 @@ class OrgsAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_DELETE)) + elseif (!$thisstaff->hasPerm(Organization::PERM_DELETE)) Http::response(403, 'Permission Denied'); elseif (!($org = Organization::lookup($id))) Http::response(404, 'Unknown organization'); @@ -122,7 +122,7 @@ class OrgsAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(User::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif (!($org = Organization::lookup($id))) Http::response(404, 'Unknown organization'); @@ -145,7 +145,7 @@ class OrgsAjaxAPI extends AjaxController { Format::htmlchars($user->getName())); } else { //Creating new user $form = UserForm::getUserForm()->getForm($_POST); - $can_create = $thisstaff->getRole()->hasPerm(User::PERM_CREATE); + $can_create = $thisstaff->hasPerm(User::PERM_CREATE); if (!($user = User::fromForm($form, $can_create))) $info['error'] = __('Error adding user - try again!'); } @@ -184,7 +184,7 @@ class OrgsAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_CREATE)) + elseif (!$thisstaff->hasPerm(Organization::PERM_CREATE)) Http::response(403, 'Permission Denied'); elseif (!($org = Organization::lookup($org_id))) Http::response(404, 'No such organization'); @@ -211,7 +211,7 @@ class OrgsAjaxAPI extends AjaxController { function addOrg() { global $thisstaff; - if (!$thisstaff->getRole()->hasPerm(Organization::PERM_CREATE)) + if (!$thisstaff->hasPerm(Organization::PERM_CREATE)) Http::response(403, 'Permission Denied'); $info = array(); @@ -285,7 +285,7 @@ class OrgsAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, "Login required"); - elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(Organization::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif (!($org = Organization::lookup($org_id))) Http::response(404, "No such ticket"); diff --git a/include/ajax.users.php b/include/ajax.users.php index e00e811a93dffae117d092cf037405e1cd1b2d1f..4b3c64fd2ffa67e7b2b6cda925eb1e1b3ff6add9 100644 --- a/include/ajax.users.php +++ b/include/ajax.users.php @@ -110,7 +110,7 @@ class UsersAjaxAPI extends AjaxController { if(!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(User::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif(!($user = User::lookup($id))) Http::response(404, 'Unknown user'); @@ -128,7 +128,7 @@ class UsersAjaxAPI extends AjaxController { if(!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(User::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif(!($user = User::lookup($id))) Http::response(404, 'Unknown user'); @@ -146,7 +146,7 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_MANAGE)) + elseif (!$thisstaff->hasPerm(User::PERM_MANAGE)) Http::response(403, 'Permission Denied'); elseif (!($user = User::lookup($id))) Http::response(404, 'Unknown user'); @@ -175,7 +175,7 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_MANAGE)) + elseif (!$thisstaff->hasPerm(User::PERM_MANAGE)) Http::response(403, 'Permission Denied'); elseif (!($user = User::lookup($id))) Http::response(404, 'Unknown user'); @@ -209,7 +209,7 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_DELETE)) + elseif (!$thisstaff->hasPerm(User::PERM_DELETE)) Http::response(403, 'Permission Denied'); elseif (!($user = User::lookup($id))) Http::response(404, 'Unknown user'); @@ -257,7 +257,7 @@ class UsersAjaxAPI extends AjaxController { $info['lookup'] = 'local'; if ($_POST) { - if (!$thisstaff->getRole()->hasPerm(User::PERM_CREATE)) + if (!$thisstaff->hasPerm(User::PERM_CREATE)) Http::response(403, 'Permission Denied'); $info['title'] = __('Add New User'); @@ -276,7 +276,7 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_CREATE)) + elseif (!$thisstaff->hasPerm(User::PERM_CREATE)) Http::response(403, 'Permission Denied'); elseif (!$bk || !$id) Http::response(422, 'Backend and user id required'); @@ -299,7 +299,7 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_CREATE)) + elseif (!$thisstaff->hasPerm(User::PERM_CREATE)) Http::response(403, 'Permission Denied'); $info = array( @@ -340,7 +340,7 @@ class UsersAjaxAPI extends AjaxController { global $thisstaff; if (!$info or !$info['title']) { - if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE)) + if ($thisstaff->hasPerm(User::PERM_CREATE)) $info += array('title' => __('Lookup or create a user')); else $info += array('title' => __('Lookup a user')); @@ -445,7 +445,7 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, "Login required"); - elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT)) + elseif (!$thisstaff->hasPerm(User::PERM_EDIT)) Http::response(403, 'Permission Denied'); elseif (!($user = User::lookup($user_id))) Http::response(404, "No such user"); diff --git a/include/class.dept.php b/include/class.dept.php index 473dca73bc5b4389c800510341e62d8daf619fcb..f09ad0587370b9adfac33298c2f9ed2a1b0c7df2 100644 --- a/include/class.dept.php +++ b/include/class.dept.php @@ -42,10 +42,10 @@ implements TemplateVariable { 'list' => true, 'reverse' => 'Staff.dept', ), - 'groups' => array( + 'extended' => array( 'null' => true, 'list' => true, - 'reverse' => 'GroupDeptAccess.dept' + 'reverse' => 'StaffDeptAccess.dept' ), ), ); @@ -155,15 +155,14 @@ implements TemplateVariable { ->filter(Q::any(array( 'dept_id' => $this->getId(), new Q(array( - 'group__depts__dept_id' => $this->getId(), - 'group__depts__dept__group_membership' => self::ALERTS_DEPT_AND_GROUPS, + 'dept_access__dept_id' => $this->getId(), + 'dept_access__dept__group_membership' => self::ALERTS_DEPT_AND_GROUPS, )), 'staff_id' => $this->manager_id ))); if ($criteria && $criteria['available']) $members->filter(array( - 'group__flags__hasbit' => Group::FLAG_ENABLED, 'isactive' => 1, 'onvacation' => 0, )); @@ -314,53 +313,7 @@ implements TemplateVariable { return $this->getHashtable(); } - function getAllowedGroups() { - - if (!isset($this->_groupids)) { - $this->_groupids = array(); - $groups = GroupDeptAccess::objects() - ->filter(array('dept_id' => $this->getId())) - ->values_flat('group_id'); - - foreach ($groups as $row) - $this->_groupids[] = $row[0]; - } - - return $this->_groupids; - } - - function updateGroups($groups_ids, $vars) { - - // Groups allowed to access department - if (is_array($groups_ids)) { - $groups = GroupDeptAccess::objects() - ->filter(array('dept_id' => $this->getId())); - foreach ($groups as $group) { - if ($idx = array_search($group->group_id, $groups_ids)) { - unset($groups_ids[$idx]); - $roleId = $vars['group'.$group->group_id.'_role_id']; - if ($roleId != $group->role_id) { - $group->set('role_id', $roleId ?: 0); - $group->save(); - } - } else { - $group->delete(); - } - } - foreach ($groups_ids as $id) { - $roleId = $vars['group'.$id.'_role_id']; - GroupDeptAccess::create(array( - 'dept_id' => $this->getId(), - 'group_id' => $id, - 'role_id' => $roleId ?: 0, - ))->save(); - } - } - - } - function updateSettings($vars) { - $this->updateGroups($vars['groups'] ?: array(), $vars); $this->path = $this->getFullPath(); $this->save(); return true; @@ -391,10 +344,11 @@ implements TemplateVariable { db_query('UPDATE '.EMAIL_TABLE.' SET dept_id=0 WHERE dept_id='.db_input($id)); db_query('UPDATE '.FILTER_TABLE.' SET dept_id=0 WHERE dept_id='.db_input($id)); - //Delete group access - db_query('DELETE FROM '.GROUP_DEPT_TABLE.' WHERE dept_id='.db_input($id)); + // Delete extended access + StaffDeptAccess::objects() + ->filter(array('dept_id' => $id)) + ->delete(); } - return true; } @@ -607,24 +561,6 @@ implements TemplateVariable { } -class GroupDeptAccess extends VerySimpleModel { - static $meta = array( - 'table' => GROUP_DEPT_TABLE, - 'pk' => array('dept_id', 'group_id'), - 'joins' => array( - 'dept' => array( - 'constraint' => array('dept_id' => 'Dept.id'), - ), - 'group' => array( - 'constraint' => array('group_id' => 'Group.id'), - ), - 'role' => array( - 'constraint' => array('role_id' => 'Role.id'), - ), - ), - ); -} - class DepartmentQuickAddForm extends Form { function getFields() { diff --git a/include/class.export.php b/include/class.export.php index 68b907282853cbf55b5ebde39f367230905d4ebc..d12dd3bf4762ca9456c56ae31a270bf249264549 100644 --- a/include/class.export.php +++ b/include/class.export.php @@ -341,7 +341,7 @@ class DatabaseExporter { var $options; var $tables = array(CONFIG_TABLE, SYSLOG_TABLE, FILE_TABLE, FILE_CHUNK_TABLE, STAFF_TABLE, DEPT_TABLE, TOPIC_TABLE, GROUP_TABLE, - GROUP_DEPT_TABLE, TEAM_TABLE, TEAM_MEMBER_TABLE, FAQ_TABLE, + STAFF_DEPT_TABLE, TEAM_TABLE, TEAM_MEMBER_TABLE, FAQ_TABLE, FAQ_TOPIC_TABLE, FAQ_CATEGORY_TABLE, DRAFT_TABLE, CANNED_TABLE, TICKET_TABLE, ATTACHMENT_TABLE, THREAD_TABLE, THREAD_ENTRY_TABLE, THREAD_ENTRY_EMAIL_TABLE, diff --git a/include/class.group.php b/include/class.group.php deleted file mode 100644 index c8b8e6ef76c36ab51faf0fc1d4e88f75d37f48f3..0000000000000000000000000000000000000000 --- a/include/class.group.php +++ /dev/null @@ -1,314 +0,0 @@ -<?php -/********************************************************************* - class.group.php - - User Group - Everything about a group! - - Peter Rotich <peter@osticket.com> - Copyright (c) 2006-2013 osTicket - http://www.osticket.com - - Released under the GNU General Public License WITHOUT ANY WARRANTY. - See LICENSE.TXT for details. - - vim: expandtab sw=4 ts=4 sts=4: -**********************************************************************/ - -class Group extends VerySimpleModel { - - static $meta = array( - 'table' => GROUP_TABLE, - 'pk' => array('id'), - 'joins' => array( - 'members' => array( - 'null' => true, - 'list' => true, - 'reverse' => 'Staff.group', - ), - 'depts' => array( - 'null' => true, - 'list' => true, - 'reverse' => 'GroupDeptAccess.group', - ), - 'role' => array( - 'constraint' => array('role_id' => 'Role.id') - ), - ), - ); - - const FLAG_ENABLED = 0X0001; - - var $departments; - - function getHashtable() { - $base = $this->ht; - $base['name'] = $base['name']; - $base['isactive'] = $base['flags']; - return $base; - } - - function getInfo() { - return $this->getHashtable(); - } - - function getId() { - return $this->id; - } - - function getRoleId() { - return $this->role_id; - } - - function getRole($deptId=0) { - - if ($deptId // Department specific role. - && ($roles=$this->getDepartmentsAccess()) - && isset($roles[$deptId]) - && $roles[$deptId] - && ($role=Role::lookup($roles[$deptId])) - && $role->isEnabled()) - return $role; - - // Default role for this group. - return $this->role; - } - - function getName() { - return $this->name; - } - - function getCreateDate() { - return $this->created; - } - - function getUpdateDate() { - return $this->updated; - } - - function getNumMembers() { - return $this->members ? $this->members->count() : 0; - } - - function isEnabled() { - return ($this->get('flags') & self::FLAG_ENABLED !== 0); - } - - function isActive(){ - return $this->isEnabled(); - } - - function getTranslateTag($subtag) { - return _H(sprintf('group.%s.%s', $subtag, $this->getId())); - } - function getLocal($subtag) { - $tag = $this->getTranslateTag($subtag); - $T = CustomDataTranslation::translate($tag); - return $T != $tag ? $T : $this->ht[$subtag]; - } - static function getLocalById($id, $subtag, $default) { - $tag = _H(sprintf('group.%s.%s', $subtag, $id)); - $T = CustomDataTranslation::translate($tag); - return $T != $tag ? $T : $default; - } - - //Get members of the group. - function getMembers() { - - if (!$this->members) { - $this->members = Staff::objects() - ->filter(array('group_id'=>$this->getId())) - ->order_by('lastname', 'firstname') - ->all(); - } - return $this->members; - } - - //Get departments & roles the group is allowed to access. - function getDepartments() { - return array_keys($this->getDepartmentsAccess()); - } - - function getDepartmentsAccess() { - if (!isset($this->departments)) { - $this->departments = array(); - foreach (GroupDeptAccess::objects() - ->filter(array('group_id'=>$this->getId())) - ->values_flat('dept_id', 'role_id') as $gda - ) { - $this->departments[$gda[0]] = $gda[1]; - } - } - - return $this->departments; - } - - function updateDeptAccess($dept_ids, $vars=array()) { - if (is_array($dept_ids)) { - $groups = GroupDeptAccess::objects() - ->filter(array('group_id' => $this->getId())); - foreach ($groups as $group) { - if ($idx = array_search($group->dept_id, $dept_ids)) { - unset($dept_ids[$idx]); - $roleId = $vars['dept'.$group->dept_id.'_role_id']; - if ($roleId != $group->role_id) { - $group->set('role_id', $roleId ?: 0); - $group->save(); - } - } else { - $group->delete(); - } - } - foreach ($dept_ids as $id) { - $roleId = $vars['dept'.$id.'_role_id']; - GroupDeptAccess::create(array( - 'group_id' => $this->getId(), - 'dept_id' => $id, - 'role_id' => $roleId ?: 0 - ))->save(); - } - } - return true; - } - - function delete() { - - // Can't delete with members - if ($this->getNumMembers()) - return false; - - if (!parent::delete()) - return false; - - // Remove dept access entries - GroupDeptAccess::objects() - ->filter(array('group_id'=>$this->getId())) - ->delete(); - - return true; - } - - function __toString() { - return $this->getName(); - } - - function save($refetch=false) { - if ($this->dirty) { - $this->updated = SqlFunction::NOW(); - } - return parent::save($refetch || $this->dirty); - } - - function update($vars,&$errors) { - if (isset($this->id) && $this->getId() != $vars['id']) - $errors['err'] = __('Missing or invalid group ID'); - - if (!$vars['name']) { - $errors['name'] = __('Group name required'); - } elseif(strlen($vars['name'])<3) { - $errors['name'] = __('Group name must be at least 3 chars.'); - } elseif (($gid=static::getIdByName($vars['name'])) - && (!isset($this->id) || $gid!=$this->getId())) { - $errors['name'] = __('Group name already exists'); - } - - if (!$vars['role_id']) - $errors['role_id'] = __('Role selection required'); - - if ($errors) - return false; - - $this->name = Format::striptags($vars['name']); - $this->role_id = $vars['role_id']; - $this->notes = Format::sanitize($vars['notes']); - - if ($vars['isactive']) - $this->flags = ($this->flags | self::FLAG_ENABLED); - else - $this->flags = ($this->flags & ~self::FLAG_ENABLED); - - if ($this->save()) - return $this->updateDeptAccess($vars['depts'] ?: array(), $vars); - - if (isset($this->id)) { - $errors['err']=sprintf(__('Unable to update %s.'), __('this group')) - .' '.__('Internal error occurred'); - } - else { - $errors['err']=sprintf(__('Unable to create %s.'), __('this group')) - .' '.__('Internal error occurred'); - } - return false; - } - - /*** Static functions ***/ - static function getIdByName($name){ - $id = static::objects()->filter(array('name'=>trim($name))) - ->values_flat('id')->first(); - - return $id ? $id[0] : 0; - } - - static function create($vars=false) { - - if (!isset($vars['flags'])) - $vars['flags'] = 0; - - $group = parent::create($vars); - $group->created = SqlFunction::NOW(); - return $group; - } - - static function __create($vars, &$errors) { - $g = self::create($vars); - $g->save(); - if ($vars['depts']) - $g->updateDeptAccess($vars['depts'], $vars); - - return $g; - } - - static function getGroups($criteria=array()) { - static $groups = null; - if (!isset($groups) || $criteria) { - $groups = array(); - $query = static::objects() - ->values_flat('id', 'name', 'flags') - ->order_by('name'); - - $filters = array(); - if (isset($criteria['active'])) - $filters += array( - 'isactive' => $criteria['active'] ? 1 : 0); - - if ($filters) - $query->filter($filters); - - $names = array(); - foreach ($query as $row) { - list($id, $name, $flags) = $row; - $names[$id] = sprintf('%s%s', - self::getLocalById($id, 'name', $name), - $flags ? '' : ' ' . __('(disabled)')); - } - - //TODO: sort if $criteria['localize']; - if ($criteria) - return $names; - - $groups = $names; - } - - return $groups; - } - - static function getActiveGroups() { - static $groups = null; - - if (!isset($groups)) - $groups = self::getGroups(array('active'=>true)); - - return $groups; - } - -} -?> diff --git a/include/class.nav.php b/include/class.nav.php index 867f34623c541ac6191cc6c4843221b7a63b7899..94f7a7ca44dad7fdec96723d9ee6b29ee9751545 100644 --- a/include/class.nav.php +++ b/include/class.nav.php @@ -118,7 +118,7 @@ class StaffNav { $this->tabs['dashboard'] = array( 'desc'=>__('Dashboard'),'href'=>'dashboard.php','title'=>__('Agent Dashboard'), "class"=>"no-pjax" ); - if ($thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) { + if ($thisstaff->hasPerm(User::PERM_DIRECTORY)) { $this->tabs['users'] = array( 'desc' => __('Users'), 'href' => 'users.php', 'title' => __('User Directory') ); @@ -175,7 +175,7 @@ class StaffNav { case 'kbase': $subnav[]=array('desc'=>__('FAQs'),'href'=>'kb.php', 'urls'=>array('faq.php'), 'iconclass'=>'kb'); if($staff) { - if ($staff->getRole()->hasPerm(FAQ::PERM_MANAGE)) + if ($staff->hasPerm(FAQ::PERM_MANAGE)) $subnav[]=array('desc'=>__('Categories'),'href'=>'categories.php','iconclass'=>'faq-categories'); if ($cfg->isCannedResponseEnabled() && $staff->getRole()->hasPerm(CannedModel::PERM_MANAGE)) $subnav[]=array('desc'=>__('Canned Responses'),'href'=>'canned.php','iconclass'=>'canned'); @@ -273,7 +273,6 @@ class AdminNav extends StaffNav{ case 'staff': $subnav[]=array('desc'=>__('Agents'),'href'=>'staff.php','iconclass'=>'users'); $subnav[]=array('desc'=>__('Teams'),'href'=>'teams.php','iconclass'=>'teams'); - $subnav[]=array('desc'=>__('Groups'),'href'=>'groups.php','iconclass'=>'groups'); $subnav[]=array('desc'=>__('Roles'),'href'=>'roles.php','iconclass'=>'lists'); $subnav[]=array('desc'=>__('Departments'),'href'=>'departments.php','iconclass'=>'departments'); break; diff --git a/include/class.orm.php b/include/class.orm.php index b0aa78eaac87d714b708be1e2e541cf60f996aef..6fbdf0ae45b12fdc5b7bd4dd0d787f71b3f58893 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -308,7 +308,6 @@ class VerySimpleModel { if (in_array($field, static::getMeta('fields'))) return null; - // TODO: Inspect fields from database before throwing this error throw new OrmException(sprintf(__('%s: %s: Field not defined'), get_class($this), $field)); } @@ -316,6 +315,15 @@ class VerySimpleModel { return $this->get($field, null); } + function getByPath($path) { + if (is_string($path)) + $path = explode('__', $path); + $root = $this; + foreach ($path as $P) + $root = $root->get($P); + return $root; + } + function __isset($field) { return array_key_exists($field, $this->ht) || isset(static::$meta['joins'][$field]); @@ -1556,6 +1564,34 @@ class InstrumentedList extends ModelInstanceManager { return new static(array($this->model, $key), $this->filter($constraint)); } + /** + * Find the first item in the current set which matches the given criteria. + * This would be used in favor of ::filter() which might trigger another + * database query. The criteria is intended to be quite simple and should + * not traverse relationships which have not already been fetched. + * Otherwise, the ::filter() or ::window() methods would provide better + * performance. + * + * Example: + * >>> $a = new User(); + * >>> $a->roles->add(Role::lookup(['name' => 'administator'])); + * >>> $a->roles->findFirst(['roles__name__startswith' => 'admin']); + * <Role: administrator> + */ + function findFirst(array $criteria) { + foreach ($this as $record) { + $matches = true; + foreach ($criteria as $field=>$check) { + if (!SqlCompiler::evaluate($record, $field, $check)) { + $matches = false; + break; + } + } + if ($matches) + return $record; + } + } + // QuerySet delegates function count() { return $this->objects()->count(); @@ -1614,6 +1650,56 @@ class SqlCompiler { return $this->options['parent']; } + /** + * Split a criteria item into the identifying pieces: path, field, and + * operator. + */ + static function splitCriteria($criteria) { + static $operators = array( + 'exact' => 1, 'isnull' => 1, + 'gt' => 1, 'lt' => 1, 'gte' => 1, 'lte' => 1, + 'contains' => 1, 'like' => 1, 'startswith' => 1, 'endswith' => 1, + 'in' => 1, 'intersect' => 1, + 'hasbit' => 1, + ); + $path = explode('__', $criteria); + if (!isset($options['table'])) { + $field = array_pop($path); + if (isset($operators[$field])) { + $operator = $field; + $field = array_pop($path); + } + } + return array($field, $path, $operator ?: 'exact'); + } + + /** + * Check if the values match given the operator. + * + * Throws: + * OrmException - if $operator is not supported + */ + static function evaluate($record, $field, $check) { + static $ops; if (!isset($ops)) { $ops = array( + 'exact' => function($a, $b) { return is_string($a) ? strcasecmp($a, $b) == 0 : $a == $b; }, + 'isnull' => function($a, $b) { return is_null($a) == $b; }, + 'gt' => function($a, $b) { return $a > $b; }, + 'gte' => function($a, $b) { return $a >= $b; }, + 'lt' => function($a, $b) { return $a < $b; }, + 'lte' => function($a, $b) { return $a <= $b; }, + 'contains' => function($a, $b) { return stripos($a, $b) !== false; }, + 'startswith' => function($a, $b) { return stripos($a, $b) === 0; }, + 'hasbit' => function($a, $b) { return $a & $b == $b; }, + ); } + list($field, $path, $operator) = self::splitCriteria($field); + if (!isset($ops[$operator])) + throw new OrmException($operator.': Unsupported operator'); + + if ($path) + $record = $record->getByPath($path); + return $ops[$operator]($record->get($field), $check); + } + /** * Handles breaking down a field or model search descriptor into the * model search path, field, and operator parts. When used in a queryset @@ -1680,16 +1766,8 @@ class SqlCompiler { // The parts after each of the __ pieces are links to other tables. // The last item (after the last __) is allowed to be an operator // specifiction. - $parts = explode('__', $field); - $operator = static::$operators['exact']; - if (!isset($options['table'])) { - $field = array_pop($parts); - if (isset(static::$operators[$field])) { - $operator = static::$operators[$field]; - $field = array_pop($parts); - } - } - + list($field, $parts, $op) = static::splitCriteria($field); + $operator = static::$operators[$op]; $path = ''; $rootModel = $model; diff --git a/include/class.role.php b/include/class.role.php index ce4256c5ba75da5a0c67eac8b51319a040758562..5f73d8d5684b23584d7d2a949424a3cc049b1191 100644 --- a/include/class.role.php +++ b/include/class.role.php @@ -19,10 +19,10 @@ class RoleModel extends VerySimpleModel { 'table' => ROLE_TABLE, 'pk' => array('id'), 'joins' => array( - 'groups' => array( + 'extensions' => array( 'null' => true, 'list' => true, - 'reverse' => 'Group.role', + 'reverse' => 'StaffDeptAccess.role', ), 'agents' => array( 'reverse' => 'Staff.role', @@ -70,7 +70,7 @@ class RoleModel extends VerySimpleModel { } function isDeleteable() { - return $this->groups->count() + $this->agents->count() == 0; + return $this->extensions->count() + $this->agents->count() == 0; } } diff --git a/include/class.staff.php b/include/class.staff.php index be5ea3562a664d6693cdc9983a2f4e87de8e67e4..5d686dc113914a35f02d45de77728a38c4677450 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -18,7 +18,6 @@ include_once(INCLUDE_DIR.'class.dept.php'); include_once(INCLUDE_DIR.'class.error.php'); include_once(INCLUDE_DIR.'class.team.php'); include_once(INCLUDE_DIR.'class.role.php'); -include_once(INCLUDE_DIR.'class.group.php'); include_once(INCLUDE_DIR.'class.passwd.php'); include_once(INCLUDE_DIR.'class.user.php'); include_once(INCLUDE_DIR.'class.auth.php'); @@ -29,6 +28,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { static $meta = array( 'table' => STAFF_TABLE, 'pk' => array('staff_id'), + 'select_related' => array('dept'), 'joins' => array( 'dept' => array( 'constraint' => array('dept_id' => 'Dept.id'), @@ -36,8 +36,8 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { 'role' => array( 'constraint' => array('role_id' => 'Role.id'), ), - 'group' => array( - 'constraint' => array('group_id' => 'Group.id'), + 'dept_access' => array( + 'reverse' => 'StaffDeptAccess.staff', ), 'teams' => array( 'reverse' => 'TeamMember.staff', @@ -52,7 +52,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { var $passwd_change; var $_roles = null; var $_teams = null; - var $_perms = null; + var $_perm; function __onload() { @@ -101,8 +101,8 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { function getHashtable() { $base = $this->ht; - $base['group'] = $base['group_id']; unset($base['teams']); + unset($base['dept_access']); return $base; } @@ -311,7 +311,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { // Departments the staff is "allowed" to access... // based on the group they belong to + user's primary dept + user's managed depts. $sql='SELECT DISTINCT d.id FROM '.STAFF_TABLE.' s ' - .' LEFT JOIN '.GROUP_DEPT_TABLE.' g ON (s.group_id=g.group_id) ' + .' LEFT JOIN '.STAFF_DEPT_TABLE.' g ON (s.staff_id=g.staff_id) ' .' INNER JOIN '.DEPT_TABLE.' d ON (LOCATE(CONCAT("/", s.dept_id, "/"), d.path) OR d.manager_id=s.staff_id OR LOCATE(CONCAT("/", g.dept_id, "/"), d.path)) ' .' WHERE s.staff_id='.db_input($this->getId()); $depts = array(); @@ -325,8 +325,8 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { 'path__contains' => '/'.$this->dept_id.'/', 'manager_id' => $this->getId(), )); - // Add in group access - foreach ($this->group->depts->values_flat('dept_id') as $row) { + // Add in extended access + foreach ($this->dept_access->depts->values_flat('dept_id') as $row) { // Skip primary dept if ($row[0] == $this->dept_id) continue; @@ -342,10 +342,6 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { $depts[] = $row[0]; */ - if (!$depts) { //Neptune help us! (fallback) - $depts = array_merge($this->getGroup()->getDepartments(), array($this->getDeptId())); - } - $this->departments = $depts; } @@ -363,14 +359,6 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { ))?array_keys($depts):array(); } - function getGroupId() { - return $this->group_id; - } - - function getGroup() { - return $this->group; - } - function getDeptId() { return $this->dept_id; } @@ -400,25 +388,15 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { if (isset($this->_roles[$deptId])) return $this->_roles[$deptId]; - if (($role = $this->group->getRole($deptId))) - return $this->_roles[$deptId] = $role; + if ($access = $this->dept_access->findFirst(array('dept_id' => $deptId))) + return $this->_roles[$deptId] = $access->role; } // For the primary department, use the primary role return $this->role; } function hasPerm($perm) { - if (!isset($this->_perms)) { - $this->_perms = array(); - foreach ($this->getDepartments() as $deptId) { - if (($role = $this->getRole($deptId))) { - foreach ($role->getPermission()->getInfo() as $perm=>$v) { - $this->_perms[$perm] |= $v; - } - } - } - } - return @$this->_perms[$perm] ?: false; + return $this->getPermission()->has($perm); } function canManageTickets() { @@ -435,10 +413,6 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { return TRUE; } - function isGroupActive() { - return $this->group->isEnabled(); - } - function isactive() { return $this->isactive; } @@ -452,7 +426,7 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { } function isAvailable() { - return ($this->isactive() && $this->isGroupActive() && !$this->onVacation()); + return ($this->isactive() && !$this->onVacation()); } function showAssignedOnly() { @@ -545,6 +519,17 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { } } + function getPermission() { + if (!isset($this->_perm)) { + $this->_perm = new RolePermission($this->permissions); + } + return $this->_perm; + } + + function getPermissionInfo() { + return $this->getPermission()->getInfo(); + } + function onLogin($bk) { // Update last apparent language preference $this->setExtraAttr('browser_lang', @@ -648,31 +633,29 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { return $this->save(); } - function updateTeams($team_ids) { + function updateTeams($membership, &$errors) { + $dropped = array(); + foreach ($this->teams as $TM) + $dropped[$TM->team_id] = 1; - if (is_array($team_ids)) { - $members = TeamMember::objects() - ->filter(array('staff_id' => $this->getId())); - foreach ($members as $member) { - if ($idx = array_search($member->team_id, $team_ids)) { - unset($team_ids[$idx]); - } else { - $member->delete(); - } + reset($membership); + while(list(, list($team_id, $alerts)) = each($membership)) { + $member = $this->teams->findFirst(array('team_id' => $team_id)); + if (!$member) { + $this->teams->add($member = TeamMember::create(array( + 'team_id' => $team_id, + ))); } - - foreach ($team_ids as $id) { - TeamMember::create(array( - 'staff_id'=>$this->getId(), - 'team_id'=>$id - ))->save(); - } - } else { - TeamMember::objects() - ->filter(array('staff_id'=>$this->getId())) + $member->setAlerts($alerts); + if (!$errors) + $member->save(); + unset($dropped[$member->team_id]); + } + if (!$errors && $dropped) { + $member = $this->teams + ->filter(array('team_id__in' => array_keys($dropped))) ->delete(); } - return true; } @@ -685,22 +668,24 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { if (!parent::delete()) return false; - //Update the poster and clear staff_id on ticket thread table. - db_query('UPDATE '.THREAD_ENTRY_TABLE - .' SET staff_id=0, poster= '.db_input($this->getName()->getOriginal()) - .' WHERE staff_id='.db_input($this->getId())); - // DO SOME HOUSE CLEANING //Move remove any ticket assignments...TODO: send alert to Dept. manager? - db_query('UPDATE '.TICKET_TABLE.' SET staff_id=0 WHERE staff_id='.db_input($this->getId())); + Ticket::objects() + ->filter(array('staff_id' => $this->getId())) + ->update(array('staff_id' => 0)); //Update the poster and clear staff_id on ticket thread table. - db_query('UPDATE '.TICKET_THREAD_TABLE - .' SET staff_id=0, poster= '.db_input($this->getName()->getOriginal()) - .' WHERE staff_id='.db_input($this->getId())); + ThreadEntry::objects() + ->filter(array('staff_id' => $this->getId())) + ->update(array( + 'staff_id' => 0, + 'poster' => $this->getName()->getOriginal(), + )); // Cleanup Team membership table. - $this->updateTeams(array()); + TeamMember::objects() + ->filter(array('staff_id'=>$this->getId())) + ->delete(); return true; } @@ -726,7 +711,6 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { if (isset($criteria['available'])) { $members = $members->filter(array( - 'group__flags__hasbit' => Group::FLAG_ENABLED, 'onvacation' => 0, 'isactive' => 1, )); @@ -896,11 +880,8 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { if(!$vars['role_id']) $errors['role_id']=__('Role for primary department is required'); - if(!$vars['group_id']) - $errors['group_id']=__('Group is required'); - // Ensure we will still have an administrator with access - if ($vars['isadmin'] !== '1' || $vars['isactive'] !== '1') { + if ($vars['isadmin'] !== '1' || $vars['islocked'] === '1') { $sql = 'select count(*), max(staff_id) from '.STAFF_TABLE .' WHERE isadmin=1 and isactive=1'; if (($res = db_query($sql)) @@ -913,17 +894,55 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { } } - if ($errors) - return false; + // Update the user's password if requested + if ($vars['passwd1']) { + try { + $this->setPassword($vars['passwd1'], null); + } + catch (BadPassword $ex) { + $errors['passwd1'] = $ex->getMessage(); + } + catch (PasswordUpdateFailed $ex) { + // TODO: Add a warning banner or crash the update + } + if (isset($vars['change_passwd'])) + $this->change_passwd = 1; + } + elseif (!isset($vars['change_passwd'])) { + $this->change_passwd = 0; + } + + // Update some things for ::updateAccess to inspect + $this->dept_id = $vars['dept_id']; + + // Format access update as [array(dept_id, role_id, alerts?)] + $access = array(); + if (isset($vars['dept_access'])) { + foreach (@$vars['dept_access'] as $dept_id) { + $access[] = array($dept_id, $vars['dept_access_role'][$dept_id], + @$vars['dept_access_alerts'][$dept_id]); + } + } + $this->updateAccess($access, $errors); + + // Format team membership as [array(team_id, alerts?)] + $teams = array(); + if (isset($vars['teams'])) { + foreach (@$vars['teams'] as $team_id) { + $teams[] = array($team_id, @$vars['team_alerts'][$team_id]); + } + } + $this->updateTeams($teams, $errors); + + // Update the local permissions + $this->updatePerms($vars['perms'], $errors); $this->isadmin = $vars['isadmin']; - $this->isactive = $vars['isactive']; + $this->isactive = isset($vars['islocked']) ? 0 : 1; $this->isvisible = isset($vars['isvisible'])?1:0; $this->onvacation = isset($vars['onvacation'])?1:0; $this->assigned_only = isset($vars['assigned_only'])?1:0; - $this->dept_id = $vars['dept_id']; $this->role_id = $vars['role_id']; - $this->group_id = $vars['group_id']; $this->timezone = $vars['timezone']; $this->username = $vars['username']; $this->firstname = $vars['firstname']; @@ -936,25 +955,10 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { $this->signature = Format::sanitize($vars['signature']); $this->notes = Format::sanitize($vars['notes']); - // Update the user's password if requested - if ($vars['passwd1']) { - try { - $this->setPassword($vars['passwd1'], null); - } - catch (BadPassword $ex) { - $errors['passwd1'] = $ex->getMessage(); - } - catch (PasswordUpdateFailed $ex) { - // TODO: Add a warning banner or crash the update - } - if (isset($vars['change_passwd'])) - $this->change_passwd = 1; - } - elseif (!isset($vars['change_passwd'])) { - $this->change_passwd = 0; - } + if ($errors) + return false; - if ($this->save() && $this->updateTeams($vars['teams'])) { + if ($this->save()) { if ($vars['welcome_email']) $this->sendResetEmail('registration-staff', false); return true; @@ -969,9 +973,98 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { } return false; } + + /** + * Parameters: + * $access - (<array($dept_id, $role_id, $alerts)>) a list of the complete, + * extended access for this agent. Any the agent currently has, which + * is not listed will be removed. + * $errors - (<array>) list of error messages from the process, which will + * be indexed by the dept_id number. + */ + function updateAccess($access, &$errors) { + reset($access); + $dropped = array(); + foreach ($this->dept_access as $DA) + $dropped[$DA->dept_id] = 1; + while (list(, list($dept_id, $role_id, $alerts)) = each($access)) { + unset($dropped[$dept_id]); + if (!$role_id || !Role::lookup($role_id)) + $errors['dept_access'][$dept_id] = __('Select a valid role'); + if (!$dept_id || !Dept::lookup($dept_id)) + $errors['dept_access'][$dept_id] = __('Select a valid departent'); + if ($dept_id == $this->getDeptId()) + $errors['dept_access'][$dept_id] = __('Agent already has access to this department'); + $da = $this->dept_access->findFirst(array('dept_id' => $dept_id)); + if (!isset($da)) { + $da = StaffDeptAccess::create(array( + 'dept_id' => $dept_id, 'role_id' => $role_id + )); + $this->dept_access->add($da); + } + else { + $da->role_id = $role_id; + } + $da->setAlerts($alerts); + if (!$errors) + $da->save(); + } + if (!$errors && $dropped) + $this->dept_access + ->filter(array('dept_id__in' => array_keys($dropped))) + ->delete(); + return !$errors; + } + + private function updatePerms($vars, &$errors) { + $permissions = $this->getPermission(); + foreach (RolePermission::allPermissions() as $g => $perms) { + foreach($perms as $k => $v) { + $permissions->set($k, in_array($k, $vars) ? 1 : 0); + } + } + $this->permissions = $permissions->toJson(); + } + } interface RestrictedAccess { function checkStaffPerm($staff); } + +class StaffDeptAccess extends VerySimpleModel { + static $meta = array( + 'table' => STAFF_DEPT_TABLE, + 'pk' => array('staff_id', 'dept_id'), + 'select_related' => array('dept', 'role'), + 'joins' => array( + 'dept' => array( + 'constraint' => array('dept_id' => 'Dept.id'), + ), + 'staff' => array( + 'constraint' => array('staff_id' => 'Staff.staff_id'), + ), + 'role' => array( + 'constraint' => array('role_id' => 'Role.id'), + ), + ), + ); + + const FLAG_ALERTS = 0x0001; + + function isAlertsEnabled() { + return $this->flags & self::FLAG_ALERTS != 0; + } + + function setFlag($flag, $value) { + if ($value) + $this->flags |= $flag; + else + $this->flags &= ~$flag; + } + + function setAlerts($value) { + $this->setFlag(self::FLAG_ALERTS, $value); + } +} ?> diff --git a/include/class.team.php b/include/class.team.php index 1e397d684263d6a1c32e7cb6b86bf4b11b0d2dee..0d5e7013f2864eccd13d8fcec7450d3e09d0cd66 100644 --- a/include/class.team.php +++ b/include/class.team.php @@ -238,7 +238,6 @@ implements TemplateVariable { 'flags__hasbit'=>self::FLAG_ENABLED, 'members__staff__isactive'=>1, 'members__staff__onvacation'=>0, - 'members__staff__group__flags__hasbit'=>Group::FLAG_ENABLED, )) ->filter(array('members_count__gt'=>0)); } @@ -298,6 +297,23 @@ class TeamMember extends VerySimpleModel { ), ), ); + + const FLAG_ALERTS = 0x0001; + + function isAlertsEnabled() { + return $this->flags & self::FLAG_ALERTS != 0; + } + + function setFlag($flag, $value) { + if ($value) + $this->flags |= $flag; + else + $this->flags &= ~$flag; + } + + function setAlerts($value) { + $this->setFlag(self::FLAG_ALERTS, $value); + } } class TeamQuickAddForm @@ -314,9 +330,10 @@ extends AbstractForm { ), )), 'lead_id' => new ChoiceField(array( + 'label' => __('Optionally select a leader for the team'), 'default' => 0, 'choices' => array_merge( - array(0 => '— '.__('No Leader').' —'), + array(0 => '— '.__('None').' —'), Staff::getStaffMembers() ), 'configuration' => array( diff --git a/include/class.ticket.php b/include/class.ticket.php index 9eb714dc45235412d33b1a2ccbd3a07e203077ea..bcacc0dd3c7363b12ce202acf9caee4df18fe460 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -2951,7 +2951,7 @@ implements RestrictedAccess, Threadable { } $user_form = UserForm::getUserForm()->getForm($vars); - $can_create = !$thisstaff || $thisstaff->getRole()->hasPerm(User::PERM_CREATE); + $can_create = !$thisstaff || $thisstaff->hasPerm(User::PERM_CREATE); if (!$user_form->isValid($field_filter('user')) || !($user=User::fromVars($user_form->getClean(), $can_create)) ) { diff --git a/include/staff/category.inc.php b/include/staff/category.inc.php index a506b90ab1bde45edd2015cee18d5e5112e0fc9a..c1b4dcda8f8534268408a8a04958bbb21b1e4a6d 100644 --- a/include/staff/category.inc.php +++ b/include/staff/category.inc.php @@ -1,6 +1,6 @@ <?php if (!defined('OSTSCPINC') || !$thisstaff - || !$thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) + || !$thisstaff->hasPerm(FAQ::PERM_MANAGE)) die('Access Denied'); $info=array(); diff --git a/include/staff/department.inc.php b/include/staff/department.inc.php index 82653e9b4e54ef7fd8d9147d661e8745787c2b7c..c5ea4cda2e884ce36a971fa43e414f2fb558c6e8 100644 --- a/include/staff/department.inc.php +++ b/include/staff/department.inc.php @@ -8,7 +8,6 @@ if($dept && $_REQUEST['a']!='add') { $submit_text=__('Save Changes'); $info = $dept->getInfo(); $info['id'] = $dept->getId(); - $info['groups'] = $dept->getAllowedGroups(); $qs += array('id' => $dept->getId()); } else { $title=__('Add New Department'); @@ -34,8 +33,6 @@ $info = Format::htmlchars(($errors && $_POST) ? $_POST : $info); <ul class="clean tabs"> <li class="active"><a href="#settings"> <i class="icon-file"></i> <?php echo __('Settings'); ?></a></li> - <li><a href="#access"> - <i class="icon-lock"></i> <?php echo __('Access'); ?></a></li> </ul> <div id="settings" class="tab_content"> <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2"> @@ -290,87 +287,6 @@ $info = Format::htmlchars(($errors && $_POST) ? $_POST : $info); </tbody> </table> </div> -<div id="access" class="tab_content" style="display:none"> - <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2"> - <thead> - <tr> - <th colspan=2> - <em><?php echo __('Primary department members have access to this department by default'); ?></em> - </th> - </tr> - <tr> - <th width="40%"><?php echo __('Group'); ?></th> - <th><?php echo __('Role'); ?></th> - </tr> - </thead> - <tbody> - <?php - $deptId = $dept ? $dept->getId() : 0; - $roles = Role::getRoles(); - $groups = Group::objects() - ->annotate(array( - 'isenabled'=>new SqlExpr(array( - 'flags__hasbit' => Group::FLAG_ENABLED)) - )) - ->order_by('name'); - foreach ($groups as $group) { - $DeptAccess = $group->getDepartmentsAccess(); - ?> - <tr> - <td> - - <label> - <?php - $ck = ($info['groups'] && in_array($group->getId(), $info['groups'])) ? 'checked="checked"' : ''; - echo sprintf('%s %s', - sprintf('<input type="checkbox" class="grp-ckb" - name="groups[]" value="%s" %s />', - $group->getId(), $ck), - Format::htmlchars($group->getName())); - ?> - </label> - </td> - <td> - <?php - $_name = 'group'.$group->getId().'_role_id'; - ?> - <select name="<?php echo $_name; ?>"> - <option value="0">— <?php - echo sprintf('%s (%s)', - __('Group Default'), - $group->getRole()); - ?> - —</option> - <?php - foreach ($roles as $rid => $role) { - $sel = ''; - if (isset($info[$_name])) - $sel = ($info[$_name] == $rid) ? 'selected="selected"' : ''; - elseif ($deptId && isset($DeptAccess[$deptId])) - $sel = ($DeptAccess[$deptId] == $rid) ? 'selected="selected"' : ''; - - echo sprintf('<option value="%d" %s>%s</option>', - $rid, $sel, $role); - } ?> - </select> - <i class="help-tip icon-question-sign" href="#dept-role"></i> - </td> - </tr> - <?php - } ?> - </tbody> - <tfoot> - <tr> - <td colspan="2"> - <?php echo __('Select');?>: - <a id="selectAll" href="#grp-ckb"><?php echo __('All');?></a> - <a id="selectNone" href="#grp-ckb"><?php echo __('None');?></a> - <a id="selectToggle" href="#grp-ckb"><?php echo __('Toggle');?></a> - </td> - </tr> - </tfoot> - </table> -</div> <p style="text-align:center"> <input type="submit" name="submit" value="<?php echo $submit_text; ?>"> <input type="reset" name="reset" value="<?php echo __('Reset');?>"> diff --git a/include/staff/faq-category.inc.php b/include/staff/faq-category.inc.php index b6287bcb9eb3779a9aab6aa5a49dc244683e1856..9f2ff86dd3f548ab34a9064e18fabc8be2ab750c 100644 --- a/include/staff/faq-category.inc.php +++ b/include/staff/faq-category.inc.php @@ -17,7 +17,7 @@ if(!defined('OSTSTAFFINC') || !$category || !$thisstaff) die('Access Denied'); <?php echo Format::display($category->getDescription()); ?> </div> <?php -if ($thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) { +if ($thisstaff->hasPerm(FAQ::PERM_MANAGE)) { echo sprintf('<div class="cat-manage-bar"><a href="categories.php?id=%d" class="Icon editCategory">'.__('Edit Category').'</a> <a href="categories.php" class="Icon deleteCategory">'.__('Delete Category').'</a> <a href="faq.php?cid=%d&a=add" class="Icon newFAQ">'.__('Add New FAQ').'</a></div>', diff --git a/include/staff/faq-view.inc.php b/include/staff/faq-view.inc.php index 05a6b0f48cf50d15087677dcb286707f0003c944..d3a4402fd8b607ace6fcc35c047937647f1b49e1 100644 --- a/include/staff/faq-view.inc.php +++ b/include/staff/faq-view.inc.php @@ -78,7 +78,7 @@ $query = http_build_query($query); ?> <?php echo __('Print'); ?> </a> <?php -if ($thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) { ?> +if ($thisstaff->hasPerm(FAQ::PERM_MANAGE)) { ?> <a href="faq.php?id=<?php echo $faq->getId(); ?>&a=edit" class="action-button"> <i class="icon-edit"></i> <?php echo __('Edit FAQ'); ?> @@ -102,7 +102,7 @@ if ($thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) { ?> <hr> <?php -if ($thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) { ?> +if ($thisstaff->hasPerm(FAQ::PERM_MANAGE)) { ?> <form action="faq.php?id=<?php echo $faq->getId(); ?>" method="post"> <?php csrf_token(); ?> <input type="hidden" name="do" value="manage-faq"> diff --git a/include/staff/faq.inc.php b/include/staff/faq.inc.php index 89584be75d0c313e9e74bc7811076bd000e5e764..fa2f9316bf6e3fb5586b1663e66d8ebe536ad3ac 100644 --- a/include/staff/faq.inc.php +++ b/include/staff/faq.inc.php @@ -1,6 +1,6 @@ <?php if (!defined('OSTSCPINC') || !$thisstaff - || !$thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) + || !$thisstaff->hasPerm(FAQ::PERM_MANAGE)) die('Access Denied'); $info = $qs = array(); diff --git a/include/staff/group.inc.php b/include/staff/group.inc.php deleted file mode 100644 index 032d0b3f05d5652ae8370449cb7a21373a81f9f6..0000000000000000000000000000000000000000 --- a/include/staff/group.inc.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied'); -$info = $qs = array(); -if ($group) { - $title = __('Update Group'); - $action = 'update'; - $submit_text = __('Save Changes'); - $info = $group->getInfo(); - $info['id'] = $group->getId(); - $info['depts'] = $group->getDepartments(); - $trans['name'] = $group->getTranslateTag('name'); - $qs += array('id' => $group->getId()); -} else { - $title = __('Add New Group'); - $action = 'add'; - $submit_text = __('Create Group'); - $info['isactive'] = isset($info['isactive']) ? $info['isactive'] : 1; - $qs += array('a' => $_REQUEST['a']); -} - -$info = Format::htmlchars(($errors && $_POST) ? array_merge($info, $_POST) : $info); -$roles = Role::getActiveRoles(); - -?> -<form action="groups.php?<?php echo Http::build_query($qs); ?>" method="post" id="save" name="group"> - <?php csrf_token(); ?> - <input type="hidden" name="do" value="<?php echo $action; ?>"> - <input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>"> - <input type="hidden" name="id" value="<?php echo $info['id']; ?>"> -<h2> <?php echo $group ?: __('New Group'); ?></h2> -<ul class="clean tabs"> - <li class="active"><a href="#group"> - <i class="icon-file"></i> <?php echo __('Group'); ?></a></li> - <li><a href="#departments"> - <i class="icon-lock"></i> <?php echo __('Departments Access'); ?></a></li> -</ul> -<div id="group" class="tab_content"> - <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2"> - <thead> - <tr> - <th colspan="2"> - <h4><?php echo $title; ?></h4> - <em><?php echo __( - 'Roles are used to define agents\' permissions' - ); ?> <i class="help-tip icon-question-sign" - href="#roles"></i></em> - </th> - </tr> - </thead> - <tbody> - <tr> - <td width="180" class="required"><?php echo __('Name'); ?>:</td> - <td> - <input size="50" type="text" name="name" value="<?php echo $info['name']; ?>" - autofocus data-translate-tag="<?php echo $trans['name']; ?>"/> - <span class="error">* <?php echo $errors['name']; ?></span> - </td> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Status');?>: - </td> - <td> - <input type="radio" name="isactive" value="1" <?php - echo $info['isactive'] ? 'checked="checked"' : ''; ?>><strong><?php echo __('Active');?></strong> - - <input type="radio" name="isactive" value="0" <?php - echo !$info['isactive'] ? 'checked="checked"' : ''; ?>><strong><?php echo __('Disabled');?></strong> - <span class="error">* <?php echo $errors['status']; ?></span> - <i class="help-tip icon-question-sign" href="#status"></i> - </td> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Default Role');?>: - </td> - <td> - <select name="role_id"> - <option value="0"><?php echo __('Select One'); ?></option> - <?php - foreach ($roles as $id => $role) { - $sel = ($info['role_id'] == $id) ? 'selected="selected"' : ''; - echo sprintf('<option value="%d" %s>%s</option>', - $id, $sel, $role); - } ?> - </select> - <span class="error">* <?php echo $errors['role_id']; ?></span> - <i class="help-tip icon-question-sign" href="#role"></i> - </td> - </tr> - </tbody> - <tbody> - <tr> - <th colspan="7"> - <em><strong><?php echo __('Internal Notes'); ?></strong> </em> - </th> - </tr> - <tr> - <td colspan="7"><textarea name="notes" class="richtext no-bar" - rows="6" cols="80"><?php - echo $info['notes']; ?></textarea> - </td> - </tr> - </tbody> - </table> -</div> -<div id="departments" class="tab_content" style="display:none"> - <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2"> - <thead> - <tr> - <th colspan=2> - <em><?php echo __('Check departments the group is allowed to access and optionally select an effective role.') ?></em> - </th> - </tr> - <tr> - <th width="40%"><?php echo __('Department'); ?></th> - <th><?php echo __('Group Role'); ?></th> - </tr> - </thead> - <tbody> - <?php - foreach (Dept::getDepartments() as $deptId => $name) { ?> - <tr> - <td> - - <label> - <?php - $ck = ($info['depts'] && in_array($deptId, $info['depts'])) ? 'checked="checked"' : ''; - echo sprintf('%s %s', - sprintf('<input type="checkbox" class="dept-ckb" - name="depts[]" value="%s" %s />', - $deptId, $ck), - Format::htmlchars($name)); - ?> - </label> - </td> - <td> - <?php - $DeptAccess = $group ? $group->getDepartmentsAccess() : array(); - $_name = 'dept'.$deptId.'_role_id'; - ?> - <select name="<?php echo $_name; ?>"> - <option value="0">— <?php - echo __('Group Default'); ?><?php - if (isset($group)) echo ' ('.$group->role->getName().')'; - ?> —</option> - <?php - foreach ($roles as $rid => $role) { - $sel = ''; - if (isset($info[$_name])) - $sel = ($info[$_name] == $rid) ? 'selected="selected"' : ''; - elseif ($DeptAccess && isset($DeptAccess[$deptId])) - $sel = ($DeptAccess[$deptId] == $rid) ? 'selected="selected"' : ''; - - echo sprintf('<option value="%d" %s>%s</option>', - $rid, $sel, $role); - } ?> - </select> - <i class="help-tip icon-question-sign" href="#dept-role"></i> - </td> - </tr> - <?php - } ?> - </tbody> - <tfoot> - <tr> - <td colspan="2"> - <?php echo __('Select');?>: - <a id="selectAll" href="#dept-ckb"><?php echo __('All');?></a> - <a id="selectNone" href="#dept-ckb"><?php echo __('None');?></a> - <a id="selectToggle" href="#dept-ckb"><?php echo __('Toggle');?></a> - </td> - </tr> - </tfoot> - </table> -</div> -<p class="centered"> - <input type="submit" name="submit" value="<?php echo $submit_text; ?>"> - <input type="reset" name="reset" value="<?php echo __('Reset'); ?>"> - <input type="button" name="cancel" value="<?php echo __('Cancel'); ?>" - onclick='window.location.href="?"'> -</p> -</form> diff --git a/include/staff/groups.inc.php b/include/staff/groups.inc.php deleted file mode 100644 index c1ec406f9510422ae1d5bfac84e9f4c3d55cdeae..0000000000000000000000000000000000000000 --- a/include/staff/groups.inc.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php -if (!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) - die('Access Denied'); - -$qs = array(); -$sortOptions = array( - 'name' => 'name', - 'users' => 'members_count', - 'depts' => 'depts_count', - 'status' => 'isenabled', - 'created'=> 'created', - 'updated'=> 'updated'); - -$orderWays = array('DESC'=>'DESC', 'ASC'=>'ASC'); -$sort = ($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])]) ? strtolower($_REQUEST['sort']) : 'name'; - -//Sorting options... -if ($sort && $sortOptions[$sort]) { - $order_column = $sortOptions[$sort]; -} - -$order_column = $order_column ? $order_column : 'name'; - -if ($_REQUEST['order'] && isset($orderWays[strtoupper($_REQUEST['order'])])) { - $order = $orderWays[strtoupper($_REQUEST['order'])]; -} else { - $order = 'ASC'; -} - -if ($order_column && strpos($order_column,',')) { - $order_column=str_replace(','," $order,",$order_column); -} -$x=$sort.'_sort'; -$$x=' class="'.strtolower($order).'" '; -$page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1; -$count = Group::objects()->count(); -$pageNav = new Pagenate($count, $page, PAGE_LIMIT); -$qstr = '&'. Http::build_query($qs); -$qstr .= '&order='.($order=='DESC' ? 'ASC' : 'DESC'); -$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']); -$pageNav->setURL('pages.php', $qs); -$showing = $pageNav->showing().' '._N('group', 'groups', $count); -?> -<div class="pull-left" style="width:700px;padding-top:5px;"> - <h2><?php echo __('Agent Groups');?> - <i class="help-tip icon-question-sign" href="#groups"></i> - </h2> - </div> -<div class="pull-right flush-right" style="padding-top:5px;padding-right:5px;"> - <b><a href="groups.php?a=add" class="Icon newgroup"><?php echo __('Add New Group');?></a></b></div> -<div class="clear"></div> -<form action="groups.php" method="POST" name="groups"> - <?php csrf_token(); ?> - <input type="hidden" name="do" value="mass_process" > - <input type="hidden" id="action" name="a" value="" > - <table class="list" border="0" cellspacing="1" cellpadding="0" width="940"> - <caption><?php echo $showing; ?></caption> - <thead> - <tr> - <th width="7px"> </th> - <th width="200"><a <?php echo $name_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=name"><?php echo __('Group Name');?></a></th> - <th width="80"><a <?php echo $status_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=status"><?php echo __('Status');?></a></th> - <th width="80" style="text-align:center;"><a <?php echo $users_sort; ?>href="groups.php?<?php echo $qstr; ?>&sort=users"><?php echo __('Members');?></a></th> - <th width="80" style="text-align:center;"><a <?php echo $depts_sort; ?>href="groups.php?<?php echo $qstr; ?>&sort=depts"><?php echo __('Departments');?></a></th> - <th width="100"><a <?php echo $created_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=created"><?php echo __('Created On');?></a></th> - <th width="120"><a <?php echo $updated_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=updated"><?php echo __('Last Updated');?></a></th> - </tr> - </thead> - <tbody> - <?php - $total=0; - $ids = ($errors && is_array($_POST['ids'])) ? $_POST['ids'] : null; - if ($count) { - $groups= Group::objects() - ->annotate(array( - 'members_count'=>SqlAggregate::COUNT('members__staff_id', true), - 'depts_count'=>SqlAggregate::COUNT('depts', true), - 'isenabled'=>new SqlExpr(array( - 'flags__hasbit' => Group::FLAG_ENABLED)) - )) - ->order_by(sprintf('%s%s', - strcasecmp($order, 'DESC') ? '' : '-', - $order_column)) - ->limit($pageNav->getLimit()) - ->offset($pageNav->getStart()); - - foreach ($groups as $group) { - $sel=false; - $id = $group->getId(); - if($ids && in_array($id, $ids)) - $sel=true; - ?> - <tr id="<?php echo $id; ?>"> - <td width=7px> - <input type="checkbox" class="ckb" name="ids[]" - value="<?php echo $id; ?>" - <?php echo $sel?'checked="checked"':''; ?>> </td> - <td><a href="groups.php?id=<?php echo $id; ?>"><?php echo - $group->getName(); ?></a> </td> - <td> <?php echo $group->isenabled ? __('Active') : '<b>'.__('Disabled').'</b>'; ?></td> - <td style="text-align:right;padding-right:30px"> - <?php if ($num=$group->members_count) { ?> - <a href="staff.php?gid=<?php echo $id; ?>"><?php echo $num; ?></a> - <?php } else { ?> 0 - <?php } ?> - - </td> - <td style="text-align:right;padding-right:30px"> - <?php echo $group->depts_count; ?> - </td> - <td><?php echo Format::date($group->getCreateDate()); ?> </td> - <td><?php echo Format::datetime($group->getUpdateDate()); ?> </td> - </tr> - <?php - } //end of while. - } ?> - <tfoot> - <tr> - <td colspan="7"> - <?php if ($count) { ?> - <?php echo __('Select');?>: - <a id="selectAll" href="#ckb"><?php echo __('All');?></a> - <a id="selectNone" href="#ckb"><?php echo __('None');?></a> - <a id="selectToggle" href="#ckb"><?php echo __('Toggle');?></a> - <?php }else{ - echo __('No groups found!'); - } ?> - </td> - </tr> - </tfoot> -</table> -<?php -if ($count): - echo '<div> '.__('Page').':'.$pageNav->getPageLinks().' </div>'; -?> -<p class="centered" id="actions"> - <input class="button" type="submit" name="enable" value="<?php echo __('Enable');?>" > - <input class="button" type="submit" name="disable" value="<?php echo __('Disable');?>" > - <input class="button" type="submit" name="delete" value="<?php echo __('Delete');?>"> -</p> -<?php -endif; -?> -</form> - -<div style="display:none;" class="dialog" id="confirm-action"> - <h3><?php echo __('Please Confirm');?></h3> - <a class="close" href=""><i class="icon-remove-circle"></i></a> - <hr/> - <p class="confirm-action" style="display:none;" id="enable-confirm"> - <?php echo sprintf(__('Are you sure you want to <b>enable</b> %s?'), - _N('selected group', 'selected groups', 2));?> - </p> - <p class="confirm-action" style="display:none;" id="disable-confirm"> - <?php echo sprintf(__('Are you sure you want to <b>disable</b> %s?'), - _N('selected group', 'selected groups', 2));?> - </p> - <p class="confirm-action" style="display:none;" id="delete-confirm"> - <font color="red"><strong><?php echo sprintf(__('Are you sure you want to DELETE %s?'), - _N('selected group', 'selected groups', 2));?></strong></font> - <br><br><?php echo __("Deleted data CANNOT be recovered and might affect agents' access.");?> - </p> - <div><?php echo __('Please confirm to continue.');?></div> - <hr style="margin-top:1em"/> - <p class="full-width"> - <span class="buttons pull-left"> - <input type="button" value="<?php echo __('No, Cancel');?>" class="close"> - </span> - <span class="buttons pull-right"> - <input type="button" value="<?php echo __('Yes, Do it!');?>" class="confirm"> - </span> - </p> - <div class="clear"></div> -</div> - diff --git a/include/staff/org-view.inc.php b/include/staff/org-view.inc.php index 94e658d24c39cb02253dfb2d2538be5d6f369421..becfd7adbe80894e81f77e3fae0b7baff9b24680 100644 --- a/include/staff/org-view.inc.php +++ b/include/staff/org-view.inc.php @@ -9,20 +9,20 @@ if(!defined('OSTSCPINC') || !$thisstaff || !is_object($org)) die('Invalid path') title="Reload"><i class="icon-refresh"></i> <?php echo $org->getName(); ?></a></h2> </td> <td width="50%" class="right_align has_bottom_border"> -<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) { ?> +<?php if ($thisstaff->hasPerm(Organization::PERM_EDIT)) { ?> <span class="action-button pull-right" data-dropdown="#action-dropdown-more"> <i class="icon-caret-down pull-right"></i> <span ><i class="icon-cog"></i> <?php echo __('More'); ?></span> </span> <?php } ?> -<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_DELETE)) { ?> +<?php if ($thisstaff->hasPerm(Organization::PERM_DELETE)) { ?> <a id="org-delete" class="action-button pull-right org-action" href="#orgs/<?php echo $org->getId(); ?>/delete"><i class="icon-trash"></i> <?php echo __('Delete Organization'); ?></a> <?php } ?> <div id="action-dropdown-more" class="action-dropdown anchor-right"> <ul> -<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) { ?> +<?php if ($thisstaff->hasPerm(Organization::PERM_EDIT)) { ?> <li><a href="#ajax.php/orgs/<?php echo $org->getId(); ?>/forms/manage" onclick="javascript: $.dialog($(this).attr('href').substr(1), 201); @@ -42,13 +42,13 @@ if(!defined('OSTSCPINC') || !$thisstaff || !is_object($org)) die('Invalid path') <tr> <th width="150"><?php echo __('Name'); ?>:</th> <td> -<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) { ?> +<?php if ($thisstaff->hasPerm(Organization::PERM_EDIT)) { ?> <b><a href="#orgs/<?php echo $org->getId(); ?>/edit" class="org-action"><i class="icon-edit"></i> <?php } echo $org->getName(); - if ($thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) { ?> + if ($thisstaff->hasPerm(Organization::PERM_EDIT)) { ?> </a></b> <?php } ?> </td> diff --git a/include/staff/orgs.inc.php b/include/staff/orgs.inc.php index bc41711ff8b59016163c65248071aef835107011..b614eb84c460f61399144151fdc6350ad7ff1b42 100644 --- a/include/staff/orgs.inc.php +++ b/include/staff/orgs.inc.php @@ -89,14 +89,14 @@ $_SESSION['orgs_qs_'.$qhash] = $query; </div> <div class="pull-right"> -<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_CREATE)) { ?> +<?php if ($thisstaff->hasPerm(Organization::PERM_CREATE)) { ?> <a class="action-button add-org" href="#"> <i class="icon-plus-sign"></i> <?php echo __('Add Organization'); ?> </a> <?php } -if ($thisstaff->getRole()->hasPerm(Organization::PERM_DELETE)) { ?> +if ($thisstaff->hasPerm(Organization::PERM_DELETE)) { ?> <span class="action-button" data-dropdown="#action-dropdown-more" style="/*DELME*/ vertical-align:top; margin-bottom:0"> <i class="icon-caret-down pull-right"></i> diff --git a/include/staff/role.inc.php b/include/staff/role.inc.php index 0e982e044bc04cd69ea92d9568f3ef51ef7ba68b..de2eecb2ba4583b396b2c8bd324f424d8baff2f9 100644 --- a/include/staff/role.inc.php +++ b/include/staff/role.inc.php @@ -80,13 +80,22 @@ $info = Format::htmlchars(($errors && $_POST) ? array_merge($info, $_POST) : $in </thead> <tbody> <?php - $setting = $role ? $role->getPermissionInfo() : array(); - foreach (RolePermission::allPermissions() as $g => $perms) { ?> - <tr><th><?php + + // Eliminate groups without any department-specific permissions + $buckets = array(); + foreach (RolePermission::allPermissions() as $g => $perms) { + foreach ($perms as $k => $v) { + if ($v['primary']) + continue; + $buckets[$g][$k] = $v; + } + } + foreach ($buckets as $g => $perms) { ?> + <tr><th><?php echo Format::htmlchars(__($g)); ?></th></tr> - <?php - foreach($perms as $k => $v) { ?> +<?php + foreach ($perms as $k => $v) { ?> <tr> <td> <label> @@ -98,11 +107,6 @@ $info = Format::htmlchars(($errors && $_POST) ? array_merge($info, $_POST) : $in <?php echo Format::htmlchars(__($v['title'])); ?> — - <?php - if ($v['primary']) { ?> - <i class="icon-globe faded" title="<?php echo - __('This permission only applies to the staff primary role'); ?>"></i> -<?php } ?> <em><?php echo Format::htmlchars(__($v['desc'])); ?></em> </label> diff --git a/include/staff/staff.inc.php b/include/staff/staff.inc.php index babf07db01da01030d2625fa3592a2807a9f1b19..659ab6873c2ba23f7d68ac8de189a95143ca58d4 100644 --- a/include/staff/staff.inc.php +++ b/include/staff/staff.inc.php @@ -2,360 +2,476 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied'); $info = $qs = array(); -if($staff && $_REQUEST['a']!='add'){ +if ($staff && $_REQUEST['a']!='add'){ //Editing Department. - $title=__('Update Agent'); + $title=__('Manage Agent'); $action='update'; $submit_text=__('Save Changes'); - $passwd_text=__('To reset the password enter a new one below'); - $info=$staff->getInfo(); - $info['id']=$staff->getId(); + $info = $staff->getInfo(); + $info['id'] = $staff->getId(); $info['teams'] = $staff->getTeams(); $info['signature'] = Format::viewableImages($info['signature']); $qs += array('id' => $staff->getId()); -}else { - $title=__('Add New Agent'); - $action='create'; - $submit_text=__('Add Agent'); - $passwd_text=__('Temporary password required only for "Local" authentication'); - //Some defaults for new staff. - $info['change_passwd']=1; - $info['welcome_email']=1; - $info['isactive']=1; - $info['isvisible']=1; - $info['isadmin']=0; - $qs += array('a' => 'add'); } -$info=Format::htmlchars(($errors && $_POST)?$_POST:$info); +$info = Format::htmlchars($info); ?> + <form action="staff.php?<?php echo Http::build_query($qs); ?>" method="post" id="save" autocomplete="off"> - <?php csrf_token(); ?> - <input type="hidden" name="do" value="<?php echo $action; ?>"> - <input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>"> - <input type="hidden" name="id" value="<?php echo $info['id']; ?>"> - <h2><?php echo __('Agent Account');?></h2> - <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2"> - <thead> - <tr> - <th colspan="2"> - <h4><?php echo $title; ?></h4> - <em><strong><?php echo __('User Information');?></strong></em> - </th> - </tr> - </thead> - <tbody> - <tr> - <td width="180" class="required"> - <?php echo __('Username');?>: - </td> - <td> - <input type="text" size="30" class="staff-username typeahead" - autofocus name="username" value="<?php echo $info['username']; ?>"> - <span class="error">* <?php echo $errors['username']; ?></span> <i class="help-tip icon-question-sign" href="#username"></i> - </td> - </tr> + <?php csrf_token(); ?> + <input type="hidden" name="do" value="<?php echo $action; ?>"> + <input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>"> + <input type="hidden" name="id" value="<?php echo $info['id']; ?>"> + <h2><?php echo $title; ?> + <div> + <small><?php echo $info['firstname'].' '.$info['lastname'];?></small> + </div> + </h2> + + <ul class="clean tabs"> + <li class="active"><a href="#account"><?php echo __('Account'); ?></a></li> + <li><a href="#access"><?php echo __('Access'); ?></a></li> + <li><a href="#permissions"><?php echo __('Permisions'); ?></a></li> + <li><a href="#teams"><?php echo __('Teams'); ?></a></li> + </ul> + + <div class="tab_content" id="account"> + <table class="table two-column" width="940" border="0" cellspacing="0" cellpadding="2"> + <tbody> <tr> - <td width="180" class="required"> - <?php echo __('First Name');?>: - </td> - <td> - <input type="text" size="30" name="firstname" class="auto first" - value="<?php echo $info['firstname']; ?>"> - <span class="error">* <?php echo $errors['firstname']; ?></span> - </td> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Last Name');?>: - </td> - <td> - <input type="text" size="30" name="lastname" class="auto last" - value="<?php echo $info['lastname']; ?>"> - <span class="error">* <?php echo $errors['lastname']; ?></span> - </td> + <td class="required"><?php echo __('Name'); ?>:</td> + <td> + <input type="text" size="20" maxlength="64" style="width: 145px" name="firstname" + autofocus value="<?php echo $info['firstname']; ?>" + placeholder="<?php echo __("First Name"); ?>" /> + <input type="text" size="20" maxlength="64" style="width: 145px" name="lastname" + value="<?php echo $info['lastname']; ?>" + placeholder="<?php echo __("Last Name"); ?>" /> + <div class="error"><?php echo $errors['firstname']; ?></div> + <div class="error"><?php echo $errors['lastname']; ?></div> + </td> </tr> <tr> - <td width="180" class="required"> - <?php echo __('Email Address');?>: - </td> - <td> - <input type="text" size="30" name="email" class="auto email" - value="<?php echo $info['email']; ?>"> - <span class="error">* <?php echo $errors['email']; ?></span> <i class="help-tip icon-question-sign" href="#email_address"></i> - </td> + <td class="required"><?php echo __('Email Address'); ?>:</td> + <td> + <input type="email" size="40" maxlength="64" style="width: 300px" name="email" + value="<?php echo $info['email']; ?>" + placeholder="<?php echo __('e.g. me@mycompany.com'); ?>" /> + <div class="error"><?php echo $errors['email']; ?></div> + </td> </tr> <tr> - <td width="180"> - <?php echo __('Phone Number');?>: - </td> - <td> - <input type="text" size="18" name="phone" class="auto phone" - value="<?php echo $info['phone']; ?>"> - <span class="error"> <?php echo $errors['phone']; ?></span> - <?php echo __('Ext');?> <input type="text" size="5" name="phone_ext" value="<?php echo $info['phone_ext']; ?>"> - <span class="error"> <?php echo $errors['phone_ext']; ?></span> - </td> + <td><?php echo __('Phone Number');?>:</td> + <td> + <input type="tel" size="18" name="phone" class="auto phone" + value="<?php echo $info['phone']; ?>" /> + <?php echo __('Ext');?> + <input type="text" size="5" name="phone_ext" + value="<?php echo $info['phone_ext']; ?>"> + <div class="error"><?php echo $errors['phone']; ?></div> + <div class="error"><?php echo $errors['phone_ext']; ?></div> + </td> </tr> <tr> - <td width="180"> - <?php echo __('Mobile Number');?>: - </td> - <td> - <input type="text" size="18" name="mobile" class="auto mobile" - value="<?php echo $info['mobile']; ?>"> - <span class="error"> <?php echo $errors['mobile']; ?></span> - </td> + <td><?php echo __('Mobile Number');?>:</td> + <td> + <input type="tel" size="18" name="mobile" class="auto phone" + value="<?php echo $info['mobile']; ?>" /> + <div class="error"><?php echo $errors['mobile']; ?></div> + </td> </tr> -<?php if (!$staff) { ?> - <tr> - <td width="180"><?php echo __('Welcome Email'); ?></td> - <td><input type="checkbox" name="welcome_email" id="welcome-email" <?php - if ($info['welcome_email']) echo 'checked="checked"'; - ?> onchange="javascript: - var sbk = $('#backend-selection'); - if ($(this).is(':checked')) - $('#password-fields').hide(); - else if (sbk.val() == '' || sbk.val() == 'local') - $('#password-fields').show(); - " /> - <?php echo __('Send sign in information'); ?> - <i class="help-tip icon-question-sign" href="#welcome_email"></i> - </td> + </tbody> + <!-- ================================================ --> + <tbody> + <tr class="header"> + <th colspan="2"> + <?php echo __('Authentication'); ?> + </th> </tr> -<?php } ?> <tr> - <th colspan="2"> - <em><strong><?php echo __('Authentication'); ?></strong>: <?php echo $passwd_text; ?> <span class="error"> <?php echo $errors['temppasswd']; ?></span> <i class="help-tip icon-question-sign" href="#account_password"></i></em> - </th> + <td class="required"><?php echo __('Username'); ?>: + <span class="error">*</span></td> + <td> + <input type="text" size="40" style="width:300px" + class="staff-username typeahead" + name="username" value="<?php echo $info['username']; ?>" /> + <button type="button" class="action-button"> + <i class="icon-refresh"></i> <?php echo __('Set Password'); ?> + </button> + <i class="offset help-tip icon-question-sign" href="#username"></i> + <div class="error"><?php echo $errors['username']; ?></div> + </td> </tr> +<?php +$bks = array(); +foreach (StaffAuthenticationBackend::allRegistered() as $ab) { + if (!$ab->supportsInteractiveAuthentication()) continue; + $bks[] = $ab; +} +if (count($bks) > 1) { +?> <tr> - <td><?php echo __('Authentication Backend'); ?></td> - <td> - <select name="backend" id="backend-selection" onchange="javascript: + <td><?php echo __('Authentication Backend'); ?>:</td> + <td> + <select name="backend" id="backend-selection" + style="width:300px" onchange="javascript: if (this.value != '' && this.value != 'local') $('#password-fields').hide(); else if (!$('#welcome-email').is(':checked')) $('#password-fields').show(); "> - <option value="">— <?php echo __('Use any available backend'); ?> —</option> - <?php foreach (StaffAuthenticationBackend::allRegistered() as $ab) { - if (!$ab->supportsInteractiveAuthentication()) continue; ?> - <option value="<?php echo $ab::$id; ?>" <?php - if ($info['backend'] == $ab::$id) - echo 'selected="selected"'; ?>><?php - echo $ab->getName(); ?></option> - <?php } ?> + <option value="">— <?php echo __('Use any available backend'); ?> —</option> +<?php foreach ($bks as $ab) { ?> + <option value="<?php echo $ab::$id; ?>" <?php + if ($info['backend'] == $ab::$id) + echo 'selected="selected"'; ?>><?php + echo $ab->getName(); ?></option> +<?php } ?> </select> - </td> + </td> </tr> - </tbody> - <tbody id="password-fields" style="<?php - if ($info['welcome_email'] || ($info['backend'] && $info['backend'] != 'local')) - echo 'display:none;'; ?>"> - <tr> - <td width="180"> - <?php echo __('Password');?>: - </td> - <td> - <input type="password" size="18" name="passwd1" value="<?php echo $info['passwd1']; ?>"> - <span class="error"> <?php echo $errors['passwd1']; ?></span> - </td> +<?php +} ?> + </tbody> + <!-- ================================================ --> + <tbody> + <tr class="header"> + <th colspan="2"> + <?php echo __('Status and Settings'); ?> + </th> </tr> <tr> - <td width="180"> - <?php echo __('Confirm Password');?>: - </td> - <td> - <input type="password" size="18" name="passwd2" value="<?php echo $info['passwd2']; ?>"> - <span class="error"> <?php echo $errors['passwd2']; ?></span> - </td> + <td colspan="2"> + <div class="error"><?php echo $errors['isadmin']; ?></div> + <div class="error"><?php echo $errors['isactive']; ?></div> + <label> + <input type="checkbox" name="islocked" value="1" + <?php echo (!$staff->isactive) ? 'checked="checked"' : ''; ?> /> + <?php echo __('Locked'); ?> + </label> + <br/> + <label> + <input type="checkbox" name="isadmin" value="1" + <?php echo ($info['isadmin']) ? 'checked="checked"' : ''; ?> /> + <?php echo __('Administrator'); ?> + </label> + <br/> + <label> + <input type="checkbox" name="assigned_only" + <?php echo ($info['assigned_only']) ? 'checked="checked"' : ''; ?> /> + <?php echo __('Limit ticket access to ONLY assigned tickets'); ?> + </label> + <br/> + <label> + <input type="checkbox" name="onvacation" + <?php echo ($info['onvacation']) ? 'checked="checked"' : ''; ?> /> + <?php echo __('Vacation Mode'); ?> + </label> + <br/> </tr> + </tbody> + </table> - <tr> - <td width="180"> - <?php echo __('Forced Password Change');?>: - </td> - <td> - <input type="checkbox" name="change_passwd" value="0" <?php echo $info['change_passwd']?'checked="checked"':''; ?>> - <?php echo __('<strong>Force</strong> password change on next login.');?> - <i class="help-tip icon-question-sign" href="#forced_password_change"></i> - </td> - </tr> - </tbody> - <tbody> - <tr> - <th colspan="2"> - <em><strong><?php echo __("Agent's Signature");?></strong>: - <?php echo __('Optional signature used on outgoing emails.');?> - <span class="error"> <?php echo $errors['signature']; ?></span></em> - <i class="help-tip icon-question-sign" href="#agents_signature"></i></em> - </th> - </tr> - <tr> - <td colspan=2> - <textarea class="richtext no-bar" name="signature" cols="21" - rows="5" style="width: 60%;"><?php echo $info['signature']; ?></textarea> - <br><em><?php echo __('Signature is made available as a choice, on ticket reply.');?></em> - </td> - </tr> - <tr> - <th colspan="2"> - <em><strong><?php echo __('Account Status & Settings');?></strong>: <?php echo __('Department and group assigned control access permissions.');?></em> - </th> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Account Type');?>: - </td> - <td> - <input type="radio" name="isadmin" value="1" <?php echo $info['isadmin']?'checked="checked"':''; ?>> - <font color="red"><strong><?php echo __('Admin');?></strong></font> - <input type="radio" name="isadmin" value="0" <?php echo !$info['isadmin']?'checked="checked"':''; ?>><strong><?php echo __('Agent');?></strong> - <span class="error"> <?php echo $errors['isadmin']; ?></span> - </td> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Account Status');?>: - </td> - <td> - <input type="radio" name="isactive" value="1" <?php echo $info['isactive']?'checked="checked"':''; ?>><strong><?php echo __('Active');?></strong> - <input type="radio" name="isactive" value="0" <?php echo !$info['isactive']?'checked="checked"':''; ?>><strong><?php echo __('Locked');?></strong> - <span class="error"> <?php echo $errors['isactive']; ?></span> <i class="help-tip icon-question-sign" href="#account_status"></i> - </td> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Primary Department');?>: - </td> - <td> - <select name="dept_id" id="dept_id" data-quick-add="department"> - <option value="0">— <?php echo __('Select Department');?> —</option> - <?php - foreach (Dept::getDepartments() as $id=>$name) { - $sel=($info['dept_id']==$id)?'selected="selected"':''; - echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); - } - ?> - <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> - </select> - <span class="error">*</span> - <i class="help-tip icon-question-sign" href="#primary_department"></i> - <div class="error"><?php echo $errors['dept_id']; ?></div> - </td> - </tr> - <tr> - <td width="180" class="required"> - <?php echo __('Primary Role');?>: - </td> - <td> - <select name="role_id"> - <option value="0">— <?php echo __('Select Role');?> —</option> - <?php - foreach (Role::getRoles() as $id=>$name) { - $sel=($info['role_id']==$id)?'selected="selected"':''; - echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); - } - ?> - </select> - <span class="error">*</span> - <i class="help-tip icon-question-sign" href="#primary_role"></i> - <div class="error"><?php echo $errors['role_id']; ?></div> - </td> + <div style="padding:8px 3px; margin-top: 1.6em"> + <strong class="big"><?php echo __('Internal Notes');?></strong><br/> + <?php echo __("be liberal, they're internal.");?> + </div> + + <textarea name="notes" class="richtext"> + <?php echo $info['notes']; ?> + </textarea> + </div> + + <!-- ============== DEPARTMENT ACCESS =================== --> + + <div class="hidden tab_content" id="access"> + <table class="table two-column" width="940" border="0" cellspacing="0" cellpadding="2"> + <tbody> + <tr class="header"> + <th colspan="2"> + <?php echo __('Primary Department and Role'); ?> + <span class="error">*</span> + <div><small><?php echo __( + "Select the departments the agent is allowed to access and optionally select an effective role." + ); ?> + </small></div> + </th> </tr> <tr> - <td width="180" class="required"> - <?php echo __('Assigned Group');?>: - </td> - <td> - <select name="group_id" id="group_id"> - <option value="0">— <?php echo __('Select Group');?> —</option> - <?php - foreach (Group::getGroups() as $id=>$name) { - $sel=($info['group_id']==$id)?'selected="selected"':''; - echo sprintf('<option value="%d" %s>%s</option>', - $id, $sel, $name); - } - ?> - </select> - <span class="error">* <?php echo $errors['group_id']; ?></span> <i class="help-tip icon-question-sign" href="#assigned_group"></i> - </td> + <td> + <select name="dept_id" id="dept_id" data-quick-add="department"> + <option value="0">— <?php echo __('Select Department');?> —</option> + <?php + foreach (Dept::getDepartments() as $id=>$name) { + $sel=($info['dept_id']==$id)?'selected="selected"':''; + echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); + } + ?> + <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> + </select> + <i class="offset help-tip icon-question-sign" href="#primary_department"></i> + <div class="error"><?php echo $errors['dept_id']; ?></div> + <div class="error"><?php echo $errors['role_id']; ?></div> + </td> + <td> + <select name="role_id"> + <option value="0">— <?php echo __('Select Role');?> —</option> + <?php + foreach (Role::getRoles() as $id=>$name) { + $sel=($info['role_id']==$id)?'selected="selected"':''; + echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); + } + ?> + </select> + <i class="offset help-tip icon-question-sign" href="#primary_role"></i> + </td> </tr> - <tr> - <td width="180"> - <?php echo __('Time Zone');?>: - </td> - <td> - <?php - $TZ_NAME = 'timezone'; - $TZ_TIMEZONE = $info['timezone']; - include STAFFINC_DIR.'templates/timezone.tmpl.php'; ?> - <div class="error"><?php echo $errors['timezone']; ?></div> - </td> + </tbody> + <tbody> + <tr id="extended_access_template" class="hidden"> + <td> + <input type="hidden" data-name="dept_access[]" value="" /> + </td> + <td> + <select data-name="dept_access_role"> + <option value="0">— <?php echo __('Select Role');?> —</option> + <?php + foreach (Role::getRoles() as $id=>$name) { + echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); + } + ?> + </select> + <span style="display:inline-block;width:20px"> </span> + <input type="checkbox" data-name="dept_access_alerts" value="1" /> + <?php echo __('Alerts'); ?> + <a href="#" class="pull-right drop-access" title="<?php echo __('Delete'); + ?>"><i class="icon-trash"></i></a> + </td> </tr> - <tr> - <td width="180"> - <?php echo __('Limited Access');?>: - </td> - <td> - <input type="checkbox" name="assigned_only" value="1" <?php echo $info['assigned_only']?'checked="checked"':''; ?>><?php echo __('Limit ticket access to ONLY assigned tickets.');?> - <i class="help-tip icon-question-sign" href="#limited_access"></i> - </td> + </tbody> + <tbody> + <tr class="header"> + <th colspan="2"> + <?php echo __('Extended Access'); ?> + </th> </tr> - <tr> - <td width="180"> - <?php echo __('Directory Listing');?>: - </td> - <td> - <input type="checkbox" name="isvisible" value="1" <?php echo $info['isvisible']?'checked="checked"':''; ?>> <?php - echo __('Make visible in the Agent Directory'); ?> - <i class="help-tip icon-question-sign" href="#directory_listing"></i> - </td> +<?php +$depts = Dept::getDepartments(); +foreach ($staff->dept_access as $dept_access) { + unset($depts[$dept_access->dept_id]); +} +?> + <tr id="add_extended_access"> + <td colspan="2"> + <i class="icon-plus-sign"></i> + <select id="add_access" data-quick-add="department"> + <option value="0">— <?php echo __('Select Department');?> —</option> + <?php + foreach ($depts as $id=>$name) { + echo sprintf('<option value="%d">%s</option>',$id,$name); + } + ?> + <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> + </select> + <button type="button" class="action-button"> + <?php echo __('Add'); ?> + </button> + </td> </tr> + </tbody> + </table> + </div> + + <!-- ================= PERMISSIONS ====================== --> + + <div id="permissions" class="hidden"> +<?php + $permissions = array(); + foreach (RolePermission::allPermissions() as $g => $perms) { + foreach ($perms as $k=>$P) { + if (!$P['primary']) + continue; + if (!isset($permissions[$g])) + $permissions[$g] = array(); + $permissions[$g][$k] = $P; + } + } +?> + <ul class="alt tabs"> +<?php + $first = true; + foreach ($permissions as $g => $perms) { ?> + <li <?php if ($first) { echo 'class="active"'; $first=false; } ?>> + <a href="#<?php echo Format::slugify($g); ?>"><?php echo Format::htmlchars(__($g));?></a> + </li> +<?php } ?> + </ul> +<?php + $first = true; + foreach ($permissions as $g => $perms) { ?> + <div class="tab_content <?php if (!$first) { echo 'hidden'; } else { $first = false; } + ?>" id="<?php echo Format::slugify($g); ?>"> + <table class="table"> +<?php foreach ($perms as $k => $v) { ?> <tr> - <td width="180"> - <?php echo __('Vacation Mode');?>: - </td> - <td> - <input type="checkbox" name="onvacation" value="1" <?php echo $info['onvacation']?'checked="checked"':''; ?>> - <?php echo __('Change Status to Vacation Mode'); ?> - <i class="help-tip icon-question-sign" href="#vacation_mode"></i> - </td> + <td> + <label> + <?php + echo sprintf('<input type="checkbox" name="perms[]" value="%s" %s />', + $k, ($staff->hasPerm($k)) ? 'checked="checked"' : ''); + ?> + + <?php echo Format::htmlchars(__($v['title'])); ?> + — + <em><?php echo Format::htmlchars(__($v['desc'])); ?></em> + </label> + </td> </tr> - <?php - // List team assignments. - $teams = Team::getTeams(); - if (count($teams)) { ?> - <tr> - <th colspan="2"> - <em><strong><?php echo __('Assigned Teams');?></strong>: <?php echo __("Agent will have access to tickets assigned to a team they belong to regardless of the ticket's department.");?> </em> - </th> +<?php } ?> + </table> + </div> +<?php } ?> + </div> + + <!-- ============== TEAM MEMBERSHIP =================== --> + + <div class="hidden tab_content" id="teams"> + <table class="table two-column" width="100%"> + <tbody> + <tr class="header"> + <th colspan="2"> + <?php echo __('Assigned Teams'); ?> + <div><small><?php echo __( + "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." + ); ?> + </small></div> + </th> </tr> - <?php - foreach ($teams as $id=>$name) { - $checked=($info['teams'] && in_array($id,$info['teams'])) - ? 'checked="checked"' : ''; - echo sprintf('<tr><td colspan=2><input type="checkbox" name="teams[]" value="%d" %s> %s</td></tr>', - $id,$checked,$name); - } - } ?> - <tr> - <th colspan="2"> - <em><strong><?php echo __('Internal Notes'); ?></strong></em> - </th> +<?php +$teams = Team::getTeams(); +foreach ($staff->teams as $TM) { + unset($teams[$TM->team_id]); +} +?> + <tr id="join_team"> + <td colspan="2"> + <i class="icon-plus-sign"></i> + <select id="add_team" data-quick-add="team"> + <option value="0">— <?php echo __('Select Team');?> —</option> + <?php + foreach ($teams as $id=>$name) { + echo sprintf('<option value="%d">%s</option>', $id, $name); + } + ?> + <option value="0" data-quick-add>— <?php echo __('Add New');?> —</option> + </select> + <button type="button" class="action-button"> + <?php echo __('Add'); ?> + </button> + </td> </tr> - <tr> - <td colspan=2> - <textarea class="richtext no-bar" name="notes" cols="28" - rows="7" style="width: 80%;"><?php echo $info['notes']; ?></textarea> - </td> + </tbody> + <tbody> + <tr id="team_member_template" class="hidden"> + <td> + <input type="hidden" data-name="teams[]" value="" /> + </td> + <td> + <input type="checkbox" data-name="team_alerts" value="1" /> + <?php echo __('Alerts'); ?> + <a href="#" class="pull-right drop-membership" title="<?php echo __('Delete'); + ?>"><i class="icon-trash"></i></a> + </td> </tr> - </tbody> -</table> -<p style="padding-left:250px;"> - <input type="submit" name="submit" value="<?php echo $submit_text; ?>"> - <input type="reset" name="reset" value="<?php echo __('Reset');?>"> - <input type="button" name="cancel" value="<?php echo __('Cancel');?>" onclick='window.location.href="staff.php"'> -</p> + </tbody> + </table> + </div> + + <p style="text-align:center;"> + <input type="submit" name="submit" value="<?php echo $submit_text; ?>"> + <input type="reset" name="reset" value="<?php echo __('Reset');?>"> + <input type="button" name="cancel" value="<?php echo __('Cancel');?>" onclick='window.location.href="helptopics.php"'> + </p> </form> + +<script type="text/javascript"> +var addAccess = function(daid, name, role, alerts, error) { + var copy = $('#extended_access_template').clone(); + + copy.find('[data-name=dept_access\\[\\]]') + .attr('name', 'dept_access[]') + .val(daid); + copy.find('[data-name^=dept_access_role]') + .attr('name', 'dept_access_role['+daid+']') + .val(role || 0); + copy.find('[data-name^=dept_access_alerts]') + .attr('name', 'dept_access_alerts['+daid+']') + .prop('checked', alerts); + copy.find('td:first').append(document.createTextNode(name)); + copy.attr('id', '').show().insertBefore($('#add_extended_access')); + copy.removeClass('hidden') + if (error) + $('<div class="error">').text(error).appendTo(copy.find('td:last')); +}; + +$('#add_extended_access').find('button').on('click', function() { + var selected = $('#add_access').find(':selected'); + addAccess(selected.val(), selected.text(), 0, true); + selected.remove(); + return false; +}); + +$(document).on('click', 'a.drop-access', function() { + var tr = $(this).closest('tr'); + $('#add_access').append( + $('<option>') + .attr('value', tr.find('input[name^=dept_access][type=hidden]').val()) + .text(tr.find('td:first').text()) + ); + tr.fadeOut(function() { $(this).remove(); }); + return false; +}); + +var joinTeam = function(teamid, name, alerts, error) { + var copy = $('#team_member_template').clone(); + + copy.find('[data-name=teams\\[\\]]') + .attr('name', 'teams[]') + .val(teamid); + copy.find('[data-name^=team_alerts]') + .attr('name', 'team_alerts['+teamid+']') + .prop('checked', alerts); + copy.find('td:first').append(document.createTextNode(name)); + copy.attr('id', '').show().insertBefore($('#join_team')); + copy.removeClass('hidden'); + if (error) + $('<div class="error">').text(error).appendTo(copy.find('td:last')); +}; + +$('#join_team').find('button').on('click', function() { + var selected = $('#add_team').find(':selected'); + joinTeam(selected.val(), selected.text(), true); + selected.remove(); + return false; +}); + +<?php +foreach ($staff->dept_access as $dept_access) { + echo sprintf('addAccess(%d, %s, %d, %d, %s);', $dept_access->dept_id, + JsonDataEncoder::encode($dept_access->dept->getName()), + $dept_access->role_id, + $dept_access->isAlertsEnabled(), + JsonDataEncoder::encode(@$errors['dept_access'][$dept_access->dept_id]) + ); +} + +foreach ($staff->teams as $member) { + echo sprintf('joinTeam(%d, %s, %d, %s);', $member->team_id, + JsonDataEncoder::encode($member->team->getName()), + $member->isAlertsEnabled(), + JsonDataEncoder::encode(@$errors['teams'][$member->team_id]) + ); +} + +?> +</script> diff --git a/include/staff/staffmembers.inc.php b/include/staff/staffmembers.inc.php index d57258241a521e135a479b44fb23119804c92a37..b83c532c06104f4e1560ff0a88c1e32f6b61fd70 100644 --- a/include/staff/staffmembers.inc.php +++ b/include/staff/staffmembers.inc.php @@ -8,7 +8,6 @@ $sortOptions = array( 'name' => array('firstname', 'lastname'), 'username' => 'username', 'status' => 'isactive', - 'group' => 'group__name', 'dept' => 'dept__name', 'created' => 'created', 'login' => 'lastlogin' @@ -48,11 +47,6 @@ if ($_REQUEST['did'] && is_numeric($_REQUEST['did'])) { $qs += array('did' => $_REQUEST['did']); } -if ($_REQUEST['gid'] && is_numeric($_REQUEST['gid'])) { - $filters += array('group_id' => $_REQUEST['gid']); - $qs += array('gid' => $_REQUEST['gid']); -} - if ($_REQUEST['tid'] && is_numeric($_REQUEST['tid'])) { $filters += array('teams__team_id' => $_REQUEST['tid']); $qs += array('tid' => $_REQUEST['tid']); @@ -102,17 +96,6 @@ $agents->limit($pageNav->getLimit())->offset($pageNav->getStart()); } ?> </select> - <select name="gid" id="gid"> - <option value="0">— <?php echo __('All Groups');?> —</option> - <?php - if (($groups=Group::getGroups())) { - foreach ($groups as $id => $name) { - $sel=($_REQUEST['gid'] && $_REQUEST['gid']==$id)?'selected="selected"':''; - echo sprintf('<option value="%d" %s>%s</option>',$id,$sel,$name); - } - } - ?> - </select> <select name="tid" id="tid"> <option value="0">— <?php echo __('All Teams');?> —</option> <?php @@ -142,7 +125,6 @@ $agents->limit($pageNav->getLimit())->offset($pageNav->getStart()); <th width="200"><a <?php echo $name_sort; ?> href="staff.php?<?php echo $qstr; ?>&sort=name"><?php echo __('Name');?></a></th> <th width="100"><a <?php echo $username_sort; ?> href="staff.php?<?php echo $qstr; ?>&sort=username"><?php echo __('Username');?></a></th> <th width="100"><a <?php echo $status_sort; ?> href="staff.php?<?php echo $qstr; ?>&sort=status"><?php echo __('Status');?></a></th> - <th width="120"><a <?php echo $group_sort; ?>href="staff.php?<?php echo $qstr; ?>&sort=group"><?php echo __('Group');?></a></th> <th width="150"><a <?php echo $dept_sort; ?>href="staff.php?<?php echo $qstr; ?>&sort=dept"><?php echo __('Department');?></a></th> <th width="100"><a <?php echo $created_sort; ?> href="staff.php?<?php echo $qstr; ?>&sort=created"><?php echo __('Created');?></a></th> <th width="145"><a <?php echo $login_sort; ?> href="staff.php?<?php echo $qstr; ?>&sort=login"><?php echo __('Last Login');?></a></th> @@ -167,8 +149,7 @@ $agents->limit($pageNav->getLimit())->offset($pageNav->getStart()); <td><?php echo $agent->getUserName(); ?></td> <td><?php echo $agent->isActive() ? __('Active') :'<b>'.__('Locked').'</b>'; ?> <?php echo $agent->onvacation ? '<small>(<i>'.__('vacation').'</i>)</small>' : ''; ?></td> - <td><a href="groups.php?id=<?php echo $agent->group_id; ?>"><?php - echo Format::htmlchars($agent->group->getName()); ?></a></td> + <td><a href="departments.php?id=<?php echo $agent->getDeptId(); ?>"><?php echo Format::htmlchars((string) $agent->dept); ?></a></td> @@ -239,4 +220,3 @@ endif; </p> <div class="clear"></div> </div> - diff --git a/include/staff/templates/thread-entry-view.tmpl.php b/include/staff/templates/thread-entry-view.tmpl.php index 0b5a542bae73f87eadfa31a810487042c05e54f5..06f73f4188f8930845e08af8aaae938508a496c4 100644 --- a/include/staff/templates/thread-entry-view.tmpl.php +++ b/include/staff/templates/thread-entry-view.tmpl.php @@ -7,7 +7,7 @@ <?php $E = $entry; $i = 0; -$omniscient = $thisstaff->getRole()->hasPerm(ThreadEntry::PERM_EDIT); +$omniscient = $thisstaff->hasPerm(ThreadEntry::PERM_EDIT); do { $i++; if (!$omniscient diff --git a/include/staff/templates/tickets.tmpl.php b/include/staff/templates/tickets.tmpl.php index 57ced36e88cb1db5f1867a7454f1cf06764c3ce6..d7ee6521b612e7e19a5944fbc2bb7b78c11f165b 100644 --- a/include/staff/templates/tickets.tmpl.php +++ b/include/staff/templates/tickets.tmpl.php @@ -9,7 +9,7 @@ elseif ($org) { $tickets->filter(array('user__org' => $org)); } -if (!$thisstaff->getRole()->hasPerm(SearchBackend::PERM_EVERYTHING)) { +if (!$thisstaff->hasPerm(SearchBackend::PERM_EVERYTHING)) { // -- Open and assigned to me $visibility = array( new Q(array('status__state'=>'open', 'staff_id' => $thisstaff->getId())) diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php index 4a8e1c505bf782b04fec58c0b8a606958e10a6d2..3e55a4cb3280c10a606519043d75675365011e21 100644 --- a/include/staff/templates/user-lookup.tmpl.php +++ b/include/staff/templates/user-lookup.tmpl.php @@ -5,7 +5,7 @@ <?php if (!isset($info['lookup']) || $info['lookup'] !== false) { ?> <div><p id="msg_info"><i class="icon-info-sign"></i> <?php echo - $thisstaff->getRole()->hasPerm(User::PERM_CREATE) + $thisstaff->hasPerm(User::PERM_CREATE) ? __('Search existing users or add a new user.') : __('Search existing users.'); ?></p></div> @@ -28,7 +28,7 @@ if ($info['error']) { <form method="post" class="user" action="<?php echo $info['action'] ? $info['action'] : '#users/lookup'; ?>"> <input type="hidden" id="user-id" name="id" value="<?php echo $user ? $user->getId() : 0; ?>"/> <i class="icon-user icon-4x pull-left icon-border"></i> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_CREATE)) { ?> <a class="action-button pull-right" style="overflow:inherit" id="unselect-user" href="#"><i class="icon-remove"></i> <?php echo __('Add New User'); ?></a> @@ -69,7 +69,7 @@ if ($user) { ?> </form> </div> <div id="new-user-form" style="display:<?php echo $user ? 'none' :'block'; ?>;"> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_CREATE)) { ?> <form method="post" class="user" action="<?php echo $info['action'] ?: '#users/lookup/form'; ?>"> <table width="100%" class="fixed"> <?php diff --git a/include/staff/templates/user.tmpl.php b/include/staff/templates/user.tmpl.php index 5add6b0824d389ff454ded25c57e9b83ce49717c..9400e4f93de8ed5ea0f96d5ffca19ba6a170f0a4 100644 --- a/include/staff/templates/user.tmpl.php +++ b/include/staff/templates/user.tmpl.php @@ -50,10 +50,10 @@ if ($info['error']) { <div id="user_tabs_container"> <div class="tab_content" id="info-tab"> <div class="floating-options"> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_EDIT)) { ?> <a href="<?php echo $info['useredit'] ?: '#'; ?>" id="edituser" class="action" title="<?php echo __('Edit'); ?>"><i class="icon-edit"></i></a> <?php } - if ($thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) { ?> + if ($thisstaff->hasPerm(User::PERM_DIRECTORY)) { ?> <a href="users.php?id=<?php echo $user->getId(); ?>" title="<?php echo __('Manage User'); ?>" class="action"><i class="icon-share"></i></a> <?php } ?> @@ -76,7 +76,7 @@ if ($info['error']) { <?php if ($org) { ?> <div class="hidden tab_content" id="org-tab"> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_DIRECTORY)) { ?> <div class="floating-options"> <a href="orgs.php?id=<?php echo $org->getId(); ?>" title="<?php echo __('Manage Organization'); ?>" class="action"><i class="icon-share"></i></a> diff --git a/include/staff/templates/users.tmpl.php b/include/staff/templates/users.tmpl.php index a2111414b06683a14453e8998cd9dc5c0ac9706f..636e3999c49459738d201b1827d853ec4c85e087 100644 --- a/include/staff/templates/users.tmpl.php +++ b/include/staff/templates/users.tmpl.php @@ -57,7 +57,7 @@ else ?> <div style="width:700px;" class="pull-left"><b><?php echo $showing; ?></b></div> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_EDIT)) { ?> <div class="pull-right flush-right" style="padding-right:5px;"> <b><a href="#orgs/<?php echo $org->getId(); ?>/add-user" class="Icon newstaff add-user" ><?php echo __('Add User'); ?></a></b> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index ecad25ee7d8a79e59575551cef4790ecf459da8a..1e0266b105cebdf38e0380135526b66baa37b2c2 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -231,7 +231,7 @@ if($ticket->isOverdue()) $user->getId(), sprintf(_N('%d Closed Ticket', '%d Closed Tickets', $closed), $closed)); ?> <li><a href="tickets.php?a=search&uid=<?php echo $ticket->getOwnerId(); ?>"><i class="icon-double-angle-right icon-fixed-width"></i> <?php echo __('All Tickets'); ?></a></li> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_DIRECTORY)) { ?> <li><a href="users.php?id=<?php echo $user->getId(); ?>"><i class="icon-user icon-fixed-width"></i> <?php echo __('Manage User'); ?></a></li> @@ -268,7 +268,7 @@ if($ticket->isOverdue()) 'a' => 'search', 'orgid' => $user->getOrgId() )); ?>"><i class="icon-double-angle-right icon-fixed-width"></i> <?php echo __('All Tickets'); ?></a></li> <?php } - if ($thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) { ?> + if ($thisstaff->hasPerm(User::PERM_DIRECTORY)) { ?> <li><a href="orgs.php?id=<?php echo $user->getOrgId(); ?>"><i class="icon-building icon-fixed-width"></i> <?php echo __('Manage Organization'); ?></a></li> @@ -770,7 +770,7 @@ $tcount = $ticket->getThreadEntries($types)->count(); echo sprintf('<span class="faded">'.__('Ticket is currently in <b>%s</b> department.').'</span>', $ticket->getDeptName()); ?> <br> - <select id="deptId" name="deptId"> + <select id="deptId" name="deptId" data-quick-add="department"> <option value="0" selected="selected">— <?php echo __('Select Target Department');?> —</option> <?php if($depts=Dept::getDepartments()) { @@ -781,6 +781,7 @@ $tcount = $ticket->getThreadEntries($types)->count(); } } ?> + <option value="0" data-quick-add>— <?php echo __('Add New'); ?> —</option> </select> <span class='error'>* <?php echo $errors['deptId']; ?></span> </td> </tr> diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php index 6c74947473fcdbc92390ac242538a6ff93cf36a0..ce0858e99f06f7834f8c49d1a2de68fd0b9d729b 100644 --- a/include/staff/tickets.inc.php +++ b/include/staff/tickets.inc.php @@ -107,7 +107,7 @@ case 'search': } elseif (isset($_SESSION['advsearch'])) { $form = $search->getFormFromSession('advsearch'); $tickets = $search->mangleQuerySet($tickets, $form); - $view_all_tickets = $thisstaff->getRole()->hasPerm(SearchBackend::PERM_EVERYTHING); + $view_all_tickets = $thisstaff->hasPerm(SearchBackend::PERM_EVERYTHING); $results_type=__('Advanced Search') . '<a class="action-button" href="?clear_filter"><i style="top:0" class="icon-ban-circle"></i> <em>' . __('clear') . '</em></a>'; $has_relevance = false; @@ -174,7 +174,7 @@ if (!$view_all_tickets) { if ($teams = array_filter($thisstaff->getTeams())) $assigned->add(array('team_id__in' => $teams)); - $visibility = Q::any(array('status__state'=>'open', $assigned)); + $visibility = Q::any(new Q(array('status__state'=>'open', $assigned))); // -- Routed to a department of mine if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts())) diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php index 256654d42816ec1d803c589dce7c00aa1dfde781..7c894ca6dc2fc6ad74657bc3c99f3c5c4cb6ae9b 100644 --- a/include/staff/user-view.inc.php +++ b/include/staff/user-view.inc.php @@ -14,18 +14,18 @@ $org = $user->getOrganization(); </td> <td width="50%" class="right_align has_bottom_border"> <?php if (($account && $account->isConfirmed()) - || $thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> + || $thisstaff->hasPerm(User::PERM_EDIT)) { ?> <span class="action-button pull-right" data-dropdown="#action-dropdown-more"> <i class="icon-caret-down pull-right"></i> <span><i class="icon-cog"></i> <?php echo __('More'); ?></span> </span> <?php } - if ($thisstaff->getRole()->hasPerm(User::PERM_DELETE)) { ?> + if ($thisstaff->hasPerm(User::PERM_DELETE)) { ?> <a id="user-delete" class="action-button pull-right user-action" href="#users/<?php echo $user->getId(); ?>/delete"><i class="icon-trash"></i> <?php echo __('Delete User'); ?></a> <?php } ?> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_MANAGE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_MANAGE)) { ?> <?php if ($account) { ?> <a id="user-manage" class="action-button pull-right user-action" @@ -55,7 +55,7 @@ $org = $user->getOrganization(); <?php echo __('Send Password Reset Email'); ?></a></li> <?php } ?> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_MANAGE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_MANAGE)) { ?> <li><a class="user-action" href="#users/<?php echo $user->getId(); ?>/manage/access"><i class="icon-lock"></i> @@ -63,7 +63,7 @@ $org = $user->getOrganization(); <?php } } ?> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_EDIT)) { ?> <li><a href="#ajax.php/users/<?php echo $user->getId(); ?>/forms/manage" onclick="javascript: $.dialog($(this).attr('href').substr(1), 201); @@ -85,13 +85,13 @@ $org = $user->getOrganization(); <th width="150"><?php echo __('Name'); ?>:</th> <td> <?php -if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> +if ($thisstaff->hasPerm(User::PERM_EDIT)) { ?> <b><a href="#users/<?php echo $user->getId(); ?>/edit" class="user-action"><i class="icon-edit"></i> <?php } echo Format::htmlchars($user->getName()->getOriginal()); -if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> +if ($thisstaff->hasPerm(User::PERM_EDIT)) { ?> </a> <?php } ?> </td> @@ -110,7 +110,7 @@ if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> if ($org) echo sprintf('<a href="#users/%d/org" class="user-action">%s</a>', $user->getId(), $org->getName()); - elseif ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { + elseif ($thisstaff->hasPerm(User::PERM_EDIT)) { echo sprintf( '<a href="#users/%d/org" class="user-action">%s</a>', $user->getId(), diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php index 5ff926b64d4e00c450f282efebfcca884ae0186a..746ac3683dac1fe0a815d844223389ff3465be92 100644 --- a/include/staff/users.inc.php +++ b/include/staff/users.inc.php @@ -74,7 +74,7 @@ $users->order_by($order . $order_column); </div> <div class="pull-right"> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_CREATE)) { ?> <a class="action-button popup-dialog" href="#users/add"> <i class="icon-plus-sign"></i> @@ -93,12 +93,12 @@ $users->order_by($order . $order_column); </span> <div id="action-dropdown-more" class="action-dropdown anchor-right"> <ul> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_DELETE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_DELETE)) { ?> <li><a class="users-action" href="#delete"> <i class="icon-trash icon-fixed-width"></i> <?php echo __('Delete'); ?></a></li> <?php } -if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?> +if ($thisstaff->hasPerm(User::PERM_EDIT)) { ?> <li><a href="#orgs/lookup/form" onclick="javascript: $.dialog('ajax.php/orgs/lookup/form', 201); return false;"> @@ -110,7 +110,7 @@ if ('disabled' != $cfg->getClientRegistrationMode()) { ?> <li><a class="users-action" href="#reset"> <i class="icon-envelope icon-fixed-width"></i> <?php echo __('Send Password Reset Email'); ?></a></li> -<?php if ($thisstaff->getRole()->hasPerm(User::PERM_MANAGE)) { ?> +<?php if ($thisstaff->hasPerm(User::PERM_MANAGE)) { ?> <li><a class="users-action" href="#register"> <i class="icon-smile icon-fixed-width"></i> <?php echo __('Register'); ?></a></li> diff --git a/include/upgrader/streams/core/435c62c3-2e7531a2.task.php b/include/upgrader/streams/core/435c62c3-2e7531a2.task.php index d80bc23a2e616248409c3c3780e3eedfca975799..6a3832f08d960deeb0600ad56e3c62ec4855f52f 100644 --- a/include/upgrader/streams/core/435c62c3-2e7531a2.task.php +++ b/include/upgrader/streams/core/435c62c3-2e7531a2.task.php @@ -1,6 +1,9 @@ <?php require_once INCLUDE_DIR.'class.migrater.php'; +// Replaced in v1.10 for STAFF_DEPT_TABLE +define('GROUP_DEPT_TABLE', TABLE_PREFIX.'group_dept_access'); + class MigrateGroupDeptAccess extends MigrationTask { var $description = "Migrate department access for groups from v1.6"; diff --git a/scp/categories.php b/scp/categories.php index d4e6125b4bca4d3fee6d40544d1ec173c408ff17..3e25c1d672e14f017b26c9da44863cc98f70455b 100644 --- a/scp/categories.php +++ b/scp/categories.php @@ -18,7 +18,7 @@ include_once(INCLUDE_DIR.'class.category.php'); /* check permission */ if(!$thisstaff || - !$thisstaff->getRole()->hasPerm(FAQ::PERM_MANAGE)) { + !$thisstaff->hasPerm(FAQ::PERM_MANAGE)) { header('Location: kb.php'); exit; } diff --git a/scp/css/scp.css b/scp/css/scp.css index af77ddc9812e4638fc59334ea2f0a72639588ec3..42afb11c70fda8aa85eda07d8931f75a0f1955d9 100644 --- a/scp/css/scp.css +++ b/scp/css/scp.css @@ -643,18 +643,30 @@ input[type=search] { .table tr.header td, .table th { - font-weight: bold; + font-weight: normal; + font-size: 1.3em; text-align: left; - height: 24px; - background: #f0f0f0; + min-height: 24px; +} +.table tbody:not(:first-child) th { + padding-top: 1.4em; } -.table tr { +.table tr:not(:last-child):not(.header) { border-bottom:1px dotted #ddd; } +.table tr.header { + border-bottom: 1px dotted #777; +} .table td:not(:empty) { height: 24px; } +.table.two-column tbody tr td:first-child { + width: 25%; +} +.table > tbody > tr.header + tr td { + padding-top: 10px; +} .form_table { margin-top:3px; @@ -1062,6 +1074,22 @@ ul.tabs li.active { bottom: 0; box-shadow: 4px -1px 6px -3px rgba(0,0,0,0.2); } +li.error { + border-top: 2px solid rgba(255, 0, 0, 0.3) !important; +} +li.error.active { + border-top-color: rgba(255, 0, 0, 0.7) !important; + +} +li.error a:before { + background-color: rgba(255,0,0,0.06); + top: 0; + left: 0; + bottom: 0; + right: 0; + content: ""; + position: absolute; +} ul.tabs li:not(.active) { box-shadow: inset 0 -5px 10px -9px rgba(0,0,0,0.2); } @@ -1073,6 +1101,7 @@ ul.tabs li a { font-weight: normal; line-height: 20px; color: #444; + color: rgba(0,0,0,0.6); display: block; outline: none; padding: 5px 10px; @@ -1083,6 +1112,8 @@ ul.tabs li a:hover { ul.tabs li.active a { font-weight: bold; + color: #222; + color: rgba(0,0,0,0.8); } ul.tabs li.empty { @@ -1141,6 +1172,29 @@ ul.tabs.vertical li a { padding: 5px; } +ul.tabs.alt { + background-color:initial; + border-bottom:2px solid #ccc; + border-bottom-color: rgba(0,0,0,0.1); + box-shadow:none; +} + +ul.tabs.alt li { + width:auto; + border:none; + min-width:0; + box-shadow:none; + bottom: 1px; + height: auto; +} + +ul.tabs.alt li.active { + border:none; + box-shadow:none; + background-color: transparent; + border-bottom:2px solid #81a9d7; +} + #response_options .reply_tab.tell { color:#a00 !important; background-image:url(../images/reminder.png); diff --git a/scp/groups.php b/scp/groups.php deleted file mode 100644 index 494824bb108c2c83b5477ab56ed95d073f772361..0000000000000000000000000000000000000000 --- a/scp/groups.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php -/********************************************************************* - groups.php - - User Groups. - - Peter Rotich <peter@osticket.com> - Copyright (c) 2006-2013 osTicket - http://www.osticket.com - - Released under the GNU General Public License WITHOUT ANY WARRANTY. - See LICENSE.TXT for details. - - vim: expandtab sw=4 ts=4 sts=4: -**********************************************************************/ -require('admin.inc.php'); - -$group=null; -if($_REQUEST['id'] && !($group=Group::lookup($_REQUEST['id']))) - $errors['err']=sprintf(__('%s: Unknown or invalid ID.'), __('group')); - -if($_POST){ - switch(strtolower($_POST['do'])){ - case 'update': - if (!$group) { - $errors['err']=sprintf(__('%s: Unknown or invalid'), __('group')); - } elseif (!$_POST['isactive'] - && ($thisstaff->getGroupId() == $group->getId())) { - $errors['err'] = sprintf( - __("As an admin, you cannot %s a group you belong to - you might lockout all admins!"), - __('disable')); - } elseif ($group->update($_POST, $errors)) { - $msg=sprintf(__('Successfully updated %s'), - __('this group')); - } elseif (!$errors['err']) { - $errors['err']=sprintf(__('Unable to update %s. Correct error(s) below and try again!'), - __('this group')); - } - break; - case 'add': - $_group = Group::create(); - if (($_group->update($_POST,$errors))) { - $msg=sprintf(__('Successfully added %s'),Format::htmlchars($_POST['name'])); - $_REQUEST['a']=null; - } elseif(!$errors['err']) { - $errors['err']=sprintf(__('Unable to add %s. Correct error(s) below and try again.'), - __('this group')); - } - break; - case 'mass_process': - $action = strtolower($_POST['a']); - if (!$_POST['ids'] || !is_array($_POST['ids']) || !count($_POST['ids'])) { - $errors['err'] = sprintf(__('You must select at least %s.'), __('one group')); - } elseif(in_array($thisstaff->getGroupId(), $_POST['ids']) - && in_array($action, array('disable', 'delete'))) { - $errors['err'] = sprintf( - __("As an admin, you cannot %s a group you belong to - you might lockout all admins!"), - __('disable or delete')); - } else { - $count = count($_POST['ids']); - switch($action) { - case 'enable': - $num = Group::objects()->filter(array( - 'id__in' => $_POST['ids'] - ))->update(array( - 'flags'=> SqlExpression::bitor( - new SqlField('flags'), - Group::FLAG_ENABLED) - )); - if ($num) { - if($num==$count) - $msg = sprintf(__('Successfully activated %s'), - _N('selected group', 'selected groups', $count)); - else - $warn = sprintf(__('%1$d of %2$d %3$s activated'), $num, $count, - _N('selected group', 'selected groups', $count)); - } else { - $errors['err'] = sprintf(__('Unable to activate %s'), - _N('selected group', 'selected groups', $count)); - } - break; - case 'disable': - $num = Group::objects()->filter(array( - 'id__in' => $_POST['ids'] - ))->update(array( - 'flags'=> SqlExpression::bitand( - new SqlField('flags'), - (~Group::FLAG_ENABLED)) - )); - - if ($num) { - if($num==$count) - $msg = sprintf(__('Successfully disabled %s'), - _N('selected group', 'selected groups', $count)); - else - $warn = sprintf(__('%1$d of %2$d %3$s disabled'), $num, $count, - _N('selected group', 'selected groups', $count)); - } else { - $errors['err'] = sprintf(__('Unable to disable %s'), - _N('selected group', 'selected groups', $count)); - } - break; - case 'delete': - foreach($_POST['ids'] as $k=>$v) { - if(($g=Group::lookup($v)) && $g->delete()) - $i++; - } - - if($i && $i==$count) - $msg = sprintf(__('Successfully deleted %s'), - _N('selected group', 'selected groups', $count)); - elseif($i>0) - $warn = sprintf(__('%1$d of %2$d %3$s deleted'), $i, $count, - _N('selected group', 'selected groups', $count)); - elseif(!$errors['err']) - $errors['err'] = sprintf(__('Unable to delete %s'), - _N('selected group', 'selected groups', $count)); - break; - default: - $errors['err'] = __('Unknown action - get technical help.'); - } - } - break; - default: - $errors['err']=__('Unknown action'); - break; - } -} - -$page='groups.inc.php'; -$tip_namespace = 'staff.groups'; -if($group || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add'))) { - $page='group.inc.php'; -} - -$nav->setTabActive('staff'); -$ost->addExtraHeader('<meta name="tip-namespace" content="' . $tip_namespace . '" />', - "$('#content').data('tipNamespace', '".$tip_namespace."');"); -require(STAFFINC_DIR.'header.inc.php'); -require(STAFFINC_DIR.$page); -include(STAFFINC_DIR.'footer.inc.php'); -?> diff --git a/scp/js/scp.js b/scp/js/scp.js index 041502735383018b6e848b24a78c181e32ab18a5..cbba7c8e21ff7777f96f5ac5877eb7a4bfce14b1 100644 --- a/scp/js/scp.js +++ b/scp/js/scp.js @@ -516,6 +516,11 @@ var scp_prep = function() { }); }); + $('div.tab_content[id] div.error:not(:empty)').each(function() { + var div = $(this).closest('.tab_content'); + $('a[href^=#'+div.attr('id')+']').parent().addClass('error'); + }); + $('[data-toggle="tooltip"]').tooltip() }; @@ -827,7 +832,9 @@ $(document).on('click.tab', 'ul.tabs li a', function(e) { } else { $tab.addClass('tab_content'); - $.changeHash($(this).attr('href'), true); + // Don't change the URL hash for nested tabs or in dialogs + if ($(this).closest('.tab_content, .dialog').length == 0) + $.changeHash($(this).attr('href'), true); } if ($tab.length) { diff --git a/scp/staff.inc.php b/scp/staff.inc.php index e17314959df935b19883410b89a1a64353e44d65..edbc813006964649e43d1ed6e40cc03282b9fda0 100644 --- a/scp/staff.inc.php +++ b/scp/staff.inc.php @@ -35,7 +35,6 @@ define('KB_PREMADE_TABLE',TABLE_PREFIX.'kb_premade'); /* include what is needed on staff control panel */ require_once(INCLUDE_DIR.'class.staff.php'); -require_once(INCLUDE_DIR.'class.group.php'); require_once(INCLUDE_DIR.'class.csrf.php'); /* First order of the day is see if the user is logged in and with a valid session. diff --git a/scp/users.php b/scp/users.php index 4506941a08a777cbd8e6961045159197e0db99ec..8e88d72a1f00e3debded552b1bb3b98918bffd7b 100644 --- a/scp/users.php +++ b/scp/users.php @@ -14,7 +14,7 @@ **********************************************************************/ require('staff.inc.php'); -if (!$thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) +if (!$thisstaff->hasPerm(User::PERM_DIRECTORY)) Http::redirect('index.php'); require_once INCLUDE_DIR.'class.note.php'; @@ -28,7 +28,7 @@ if ($_POST) { case 'update': if (!$user) { $errors['err']=sprintf(__('%s: Unknown or invalid'), _N('end user', 'end users', 1)); - } elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { + } elseif (!$thisstaff->hasPerm(User::PERM_EDIT)) { $errors['err'] = __('Action denied. Contact admin for access'); } elseif(($acct = $user->getAccount()) && !$acct->update($_POST, $errors)) { diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql index 368b1bf1cf5af4c948d43ac56e67b497299d9a35..720cb2557760c13c459deda590849b8494ec91c1 100644 --- a/setup/inc/streams/core/install-mysql.sql +++ b/setup/inc/streams/core/install-mysql.sql @@ -418,16 +418,6 @@ CREATE TABLE `%TABLE_PREFIX%role` ( UNIQUE KEY `name` (`name`) ) DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `%TABLE_PREFIX%group_dept_access`; -CREATE TABLE `%TABLE_PREFIX%group_dept_access` ( - `group_id` int(10) unsigned NOT NULL default '0', - `dept_id` int(10) unsigned NOT NULL default '0', - `role_id` int(10) unsigned NOT NULL default '0', - UNIQUE KEY `group_dept` (`group_id`,`dept_id`), - KEY `dept_id` (`dept_id`), - KEY `role_id` (`role_id`) -) DEFAULT CHARSET=utf8; - DROP TABLE IF EXISTS `%TABLE_PREFIX%help_topic`; CREATE TABLE `%TABLE_PREFIX%help_topic` ( `topic_id` int(11) unsigned NOT NULL auto_increment, @@ -533,7 +523,6 @@ CREATE TABLE `%TABLE_PREFIX%session` ( DROP TABLE IF EXISTS `%TABLE_PREFIX%staff`; CREATE TABLE `%TABLE_PREFIX%staff` ( `staff_id` int(11) unsigned NOT NULL auto_increment, - `group_id` int(10) unsigned NOT NULL default '0', `dept_id` int(10) unsigned NOT NULL default '0', `role_id` int(10) unsigned NOT NULL default '0', `username` varchar(32) NOT NULL default '', @@ -562,6 +551,7 @@ CREATE TABLE `%TABLE_PREFIX%staff` ( `default_signature_type` ENUM( 'none', 'mine', 'dept' ) NOT NULL DEFAULT 'none', `default_paper_size` ENUM( 'Letter', 'Legal', 'Ledger', 'A4', 'A3' ) NOT NULL DEFAULT 'Letter', `extra` text, + `permissions` text, `created` datetime NOT NULL, `lastlogin` datetime default NULL, `passwdreset` datetime default NULL, @@ -573,6 +563,16 @@ CREATE TABLE `%TABLE_PREFIX%staff` ( KEY `group_id` (`group_id`,`staff_id`) ) DEFAULT CHARSET=utf8; +DROP TABLE IF EXISTS `%TABLE_PREFIX%staff_dept_access`; +CREATE TABLE `%TABLE_PREFIX%staff_dept_access` ( + `staff_id` int(10) unsigned NOT NULL DEFAULT '0', + `dept_id` int(10) unsigned NOT NULL DEFAULT '0', + `role_id` int(10) unsigned NOT NULL DEFAULT '0', + `flags` int(10) unsigned NOT NULL DEFAULT '1', + PRIMARY KEY `staff_dept` (`staff_id`,`dept_id`), + KEY `dept_id` (`dept_id`) +) DEFAULT CHARSET=utf8; + DROP TABLE IF EXISTS `%TABLE_PREFIX%syslog`; CREATE TABLE `%TABLE_PREFIX%syslog` ( `log_id` int(11) unsigned NOT NULL auto_increment, @@ -605,7 +605,7 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%team_member`; CREATE TABLE `%TABLE_PREFIX%team_member` ( `team_id` int(10) unsigned NOT NULL default '0', `staff_id` int(10) unsigned NOT NULL, - `updated` datetime NOT NULL, + `flags` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`team_id`,`staff_id`) ) DEFAULT CHARSET=utf8;