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">&mdash; <?php
-                        echo __('Group Default'); ?> &mdash;</option>
+                    echo __('Group Default'); ?><?php
+                    if (isset($group)) echo ' ('.$group->role->getName().')';
+                    ?> &mdash;</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>
-                &nbsp;<span class="error">*&nbsp;<?php echo $errors['dept_id']; ?></span>&nbsp;<i class="help-tip icon-question-sign" href="#primary_department"></i>
+                &nbsp;
+                <select name="role_id">
+                    <option value="0">&mdash; <?php echo __('Select Role');?> &mdash;</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>
+                &nbsp;<span class="error">*</span>
+                &nbsp;<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,