diff --git a/include/class.role.php b/include/class.role.php index 1a9aec2e54d8acf09d506bf331671e97ff0d5103..ef424a917d5cd45a95e0186977cd6e578893005c 100644 --- a/include/class.role.php +++ b/include/class.role.php @@ -24,6 +24,9 @@ class RoleModel extends VerySimpleModel { 'list' => true, 'reverse' => 'Group.role', ), + 'agents' => array( + 'reverse' => 'Staff.role', + ), ), ); @@ -67,7 +70,7 @@ class RoleModel extends VerySimpleModel { } function isDeleteable() { - return ($this->groups->count() == 0); + return $this->groups->count() + $this->agents->count() == 0; } } @@ -79,9 +82,11 @@ class Role extends RoleModel { var $_perm; function getPermission() { - if (!$this->_perm) - $this->_perm = new RolePermission('role.'.$this->getId()); - + if (!$this->_perm) { + $this->_perm = new RolePermission( + isset($this->permissions) ? $this->permissions : array() + ); + } return $this->_perm; } @@ -125,13 +130,13 @@ class Role extends RoleModel { private function updatePerms($vars, &$errors=array()) { $config = array(); + $permissions = $this->getPermission(); foreach (RolePermission::allPermissions() as $g => $perms) { - foreach($perms as $k => $v) - $config[$k] = in_array($k, $vars) ? 1 : 0; + foreach($perms as $k => $v) { + $permissions->set($k, in_array($k, $vars) ? 1 : 0); + } } - - $this->getPermission()->updateAll($config); - $this->getPermission()->load(); + $this->permissions = $permissions->toJson(); } function update($vars, &$errors) { @@ -149,11 +154,12 @@ class Role extends RoleModel { $this->name = $vars['name']; $this->notes = $vars['notes']; - if (!$this->save(true)) - return false; $this->updatePerms($vars['perms'], $errors); + if (!$this->save(true)) + return false; + return true; } @@ -179,9 +185,6 @@ class Role extends RoleModel { ->filter(array('role_id'=>$this->getId())) ->update(array('role_id' => 0)); - // Delete permission settings - $this->getPermission()->destroy(); - return true; } @@ -193,10 +196,10 @@ class Role extends RoleModel { static function __create($vars, &$errors) { $role = self::create($vars); - $role->save(); if ($vars['permissions']) $role->updatePerms($vars['permissions']); + $role->save(); return $role; } @@ -252,7 +255,7 @@ class Role extends RoleModel { } -class RolePermission extends Config { +class RolePermission { static $_permissions = array( /* @trans */ 'Tickets' => array( @@ -296,46 +299,75 @@ class RolePermission extends Config { ), ); + var $perms; + static function allPermissions() { return static::$_permissions; } - function get($var) { - return (bool) parent::get($var); + function __construct($perms) { + $this->perms = $perms; + if (is_string($this->perms)) + $this->perms = JsonDataParser::parse($this->perms); + elseif (!$this->perms) + $this->perms = array(); + } + + function has($perm) { + return (bool) $this->get($perm); + } + + function get($perm) { + return @$this->perms[$perm]; + } + + function set($perm, $value) { + if (!$value) + unset($this->perms[$perm]); + else + $this->perms[$perm] = $value; + } + + function toJson() { + return JsonDataEncoder::encode($this->perms); + } + + function getInfo() { + return $this->perms; } /* tickets */ function canCreateTickets() { - return ($this->get('ticket.create')); + return ($this->has('ticket.create')); } function canEditTickets() { - return ($this->get('ticket.edit')); + return ($this->has('ticket.edit')); } function canAssignTickets() { - return ($this->get('ticket.assign')); + return ($this->has('ticket.assign')); } function canTransferTickets() { - return ($this->get('ticket.transfer')); + return ($this->has('ticket.transfer')); } function canPostReply() { - return ($this->get('ticket.reply')); + return ($this->has('ticket.reply')); } function canCloseTickets() { - return ($this->get('ticket.close')); + return ($this->has('ticket.close')); } function canDeleteTickets() { - return ($this->get('ticket.delete')); + return ($this->has('ticket.delete')); } /* Knowledge base */ function canManagePremade() { - return ($this->get('kb.premade')); + return ($this->has('kb.premade')); } function canManageCannedResponses() { @@ -343,7 +375,7 @@ class RolePermission extends Config { } function canManageFAQ() { - return ($this->get('kb.faq')); + return ($this->has('kb.faq')); } function canManageFAQs() { @@ -352,12 +384,12 @@ class RolePermission extends Config { /* stats */ function canViewStaffStats() { - return ($this->get('stats.agents')); + return ($this->has('stats.agents')); } /* email */ function canBanEmails() { - return ($this->get('emails.banlist')); + return ($this->has('emails.banlist')); } } ?> diff --git a/include/class.staff.php b/include/class.staff.php index e72fac6f05796f51135e89c6c6735b4a15fc6bd4..4fa79eb6a9a62e83065c1c7b80d92cd9b6b1832a 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -34,6 +34,9 @@ implements AuthenticatedUser { 'dept' => array( 'constraint' => array('dept_id' => 'Dept.id'), ), + 'role' => array( + 'constraint' => array('role_id' => 'Role.id'), + ), 'group' => array( 'constraint' => array('group_id' => 'Group.id'), ), @@ -53,6 +56,7 @@ implements AuthenticatedUser { var $passwd_change; var $_roles = null; var $_teams = null; + var $_perms = null; function __onload() { // WE have to patch info here to support upgrading from old versions. @@ -271,32 +275,29 @@ implements AuthenticatedUser { } function getRole($dept=null) { - - if ($dept) { - $deptId = is_object($dept) ? $dept->getId() : $dept; + $deptId = is_object($dept) ? $dept->getId() : $dept; + if ($deptId && $deptId != $this->dept_id) { if (isset($this->_roles[$deptId])) return $this->_roles[$deptId]; if (($role=$this->group->getRole($deptId))) return $this->_roles[$deptId] = $role; } - - return $this->group->getRole(); + // For the primary department, use the primary role + return $this->role; } function hasPermission($perm) { - static $perms = null; - if (!isset($perms[$perm])) { - $perms[$perm] = false; - foreach($this->getDepartments() as $deptId) { - if (($role=$this->getRole($deptId)) - && $role->getPermission() - && $role->getPermission()->get($perm)) - $perms[$perm] = true; + if (!isset($this->_perms)) { + foreach ($this->getDepartments() as $deptId) { + if (($role = $this->getRole($deptId))) { + foreach ($role->getPermission()->getInfo() as $perm=>$v) { + $this->_perms[$perm] |= $v; + } + } } } - - return $perms[$perm]; + return @$this->_perms[$perm]; } function canCreateTickets() { @@ -756,6 +757,8 @@ implements AuthenticatedUser { if(!$vars['dept_id']) $errors['dept_id']=__('Department is required'); + if(!$vars['role_id']) + $errors['role_id']=__('Role for primary department is required'); if(!$vars['group_id']) $errors['group_id']=__('Group is required'); @@ -769,6 +772,7 @@ implements AuthenticatedUser { $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']; diff --git a/include/staff/group.inc.php b/include/staff/group.inc.php index d471b791d8da636d5897153fd8e886bcf6332af4..2a3a63807fc54c6c3e56edad8bc031af9fc9e0d5 100644 --- a/include/staff/group.inc.php +++ b/include/staff/group.inc.php @@ -75,7 +75,7 @@ $roles = Role::getActiveRoles(); </td> <td> <select name="role_id"> - <option value="0">Select One</option> + <option value="0"><?php echo __('Select One'); ?></option> <?php foreach ($roles as $id => $role) { $sel = ($info['role_id'] == $id) ? 'selected="selected"' : ''; @@ -140,7 +140,9 @@ $roles = Role::getActiveRoles(); ?> <select name="<?php echo $_name; ?>"> <option value="0">— <?php - echo __('Group Default'); ?> —</option> + echo __('Group Default'); ?><?php + if (isset($group)) echo ' ('.$group->role->getName().')'; + ?> —</option> <?php foreach ($roles as $rid => $role) { $sel = ''; diff --git a/include/staff/staff.inc.php b/include/staff/staff.inc.php index 1bc7ca1d675f14a7be2c5346d14f173c9a1e3949..7a9c01eeedacff6d082453c7aeaf44fbe74c7fb7 100644 --- a/include/staff/staff.inc.php +++ b/include/staff/staff.inc.php @@ -258,7 +258,20 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); } ?> </select> - <span class="error">* <?php echo $errors['dept_id']; ?></span> <i class="help-tip icon-question-sign" href="#primary_department"></i> + + <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_department"></i> + <div class="error"><?php echo $errors['dept_id']; ?></div> + <div class="error"><?php echo $errors['role_id']; ?></div> </td> </tr> <tr> diff --git a/include/upgrader/streams/core.sig b/include/upgrader/streams/core.sig index ffd1538e853ca6f5780cc554c6aaf40d9b013416..ca8a3dae54ce2f95a30f3729ff58cffbde89ef0b 100644 --- a/include/upgrader/streams/core.sig +++ b/include/upgrader/streams/core.sig @@ -1 +1 @@ -c7c828356c88b462ba2e3e1437dca0df +36f6b32893c2b97c5104ab5302d2dd2e diff --git a/include/upgrader/streams/core/1ee831c8-c7c82835.cleanup.sql b/include/upgrader/streams/core/1ee831c8-36f6b328.cleanup.sql similarity index 100% rename from include/upgrader/streams/core/1ee831c8-c7c82835.cleanup.sql rename to include/upgrader/streams/core/1ee831c8-36f6b328.cleanup.sql diff --git a/include/upgrader/streams/core/1ee831c8-c7c82835.patch.sql b/include/upgrader/streams/core/1ee831c8-36f6b328.patch.sql similarity index 86% rename from include/upgrader/streams/core/1ee831c8-c7c82835.patch.sql rename to include/upgrader/streams/core/1ee831c8-36f6b328.patch.sql index 0f29e473c460b400e58b8e23e6f9793d2d2891ab..7ec72fbfdac2a66cbc7607e5b7c186f089cb1dc6 100644 --- a/include/upgrader/streams/core/1ee831c8-c7c82835.patch.sql +++ b/include/upgrader/streams/core/1ee831c8-36f6b328.patch.sql @@ -1,5 +1,5 @@ /** - * @signature c7c828356c88b462ba2e3e1437dca0df + * @signature 36f6b32893c2b97c5104ab5302d2dd2e * @version v1.9.6 * @title Add role-based access * @@ -11,6 +11,7 @@ CREATE TABLE `%TABLE_PREFIX%role` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `flags` int(10) unsigned NOT NULL DEFAULT '1', `name` varchar(64) DEFAULT NULL, + `permissions` text, `notes` text, `created` datetime NOT NULL, `updated` datetime NOT NULL, @@ -21,6 +22,9 @@ CREATE TABLE `%TABLE_PREFIX%role` ( ALTER TABLE `%TABLE_PREFIX%group_dept_access` ADD `role_id` INT UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `%TABLE_PREFIX%staff` + ADD `role_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `dept_id`; + ALTER TABLE `%TABLE_PREFIX%groups` CHANGE `group_id` `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, CHANGE `group_name` `name` VARCHAR(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', @@ -38,5 +42,5 @@ ALTER TABLE `%TABLE_PREFIX%department` -- Finished with patch UPDATE `%TABLE_PREFIX%config` - SET `value`='c7c828356c88b462ba2e3e1437dca0df' + SET `value`='36f6b32893c2b97c5104ab5302d2dd2e' WHERE `key` = 'schema_signature' AND `namespace` = 'core'; diff --git a/include/upgrader/streams/core/1ee831c8-c7c82835.task.php b/include/upgrader/streams/core/1ee831c8-36f6b328.task.php similarity index 86% rename from include/upgrader/streams/core/1ee831c8-c7c82835.task.php rename to include/upgrader/streams/core/1ee831c8-36f6b328.task.php index 3785980847f16fdf290ed2c8f5f805ef89478bca..3b8ff65b41343cff6852899844942b3ed63b04ce 100644 --- a/include/upgrader/streams/core/1ee831c8-c7c82835.task.php +++ b/include/upgrader/streams/core/1ee831c8-36f6b328.task.php @@ -41,6 +41,13 @@ class GroupRoles extends MigrationTask { $group->role_id = $role->getId(); $group->save(); } + + // Copy group default role to the agent for the respective primary + // department role + foreach (Staff::objects()->select_related('group') as $staff) { + $staff->role_id = $staff->group->role_id; + $staff->save(); + } } } diff --git a/scp/roles.php b/scp/roles.php index 43c097f5c09c96400feae5b41d02ac8c240053fd..02bb0fec0c8d663c2e5e014e03a24c72cbffcbb0 100644 --- a/scp/roles.php +++ b/scp/roles.php @@ -42,6 +42,7 @@ if ($_POST) { case 'add': $_role = Role::create(); if ($_role->update($_POST, $errors)) { + unset($_REQUEST['a']); $msg = sprintf(__('Successfully added %s'), __('role')); } elseif ($errors) { diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql index e35b6a364b6e6de4ee4af0ff4ed01eda630f50ee..94492a21ade51447ee70c52fec850b15e253383d 100644 --- a/setup/inc/streams/core/install-mysql.sql +++ b/setup/inc/streams/core/install-mysql.sql @@ -406,6 +406,7 @@ CREATE TABLE `%TABLE_PREFIX%role` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `flags` int(10) unsigned NOT NULL DEFAULT '1', `name` varchar(64) DEFAULT NULL, + `permissions` text, `notes` text, `created` datetime NOT NULL, `updated` datetime NOT NULL, @@ -520,6 +521,7 @@ 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 '', `firstname` varchar(32) default NULL, `lastname` varchar(32) default NULL,