diff --git a/include/class.role.php b/include/class.role.php
index 1a9aec2e54d8acf09d506bf331671e97ff0d5103..f934cadd93ea69190bfbb262c5f944be31b9ba98 100644
--- a/include/class.role.php
+++ b/include/class.role.php
@@ -79,9 +79,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 +127,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 +151,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 +182,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 +193,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 +252,7 @@ class Role extends RoleModel {
 }
 
 
-class RolePermission extends Config {
+class RolePermission {
 
     static $_permissions = array(
             /* @trans */ 'Tickets' => array(
@@ -296,46 +296,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 +372,7 @@ class RolePermission extends Config {
     }
 
     function canManageFAQ() {
-        return ($this->get('kb.faq'));
+        return ($this->has('kb.faq'));
     }
 
     function canManageFAQs() {
@@ -352,12 +381,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..9fecd59ef4306fb2eb5cb467a544d167f3e287a9 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -53,6 +53,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.
@@ -285,18 +286,16 @@ implements AuthenticatedUser {
     }
 
     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() {
diff --git a/include/upgrader/streams/core.sig b/include/upgrader/streams/core.sig
index ffd1538e853ca6f5780cc554c6aaf40d9b013416..1327f8f5c3b956d8e1080af97b4158cd73874482 100644
--- a/include/upgrader/streams/core.sig
+++ b/include/upgrader/streams/core.sig
@@ -1 +1 @@
-c7c828356c88b462ba2e3e1437dca0df
+e9b05c1970a94c63220bdc6a3bee1c7d
diff --git a/include/upgrader/streams/core/1ee831c8-c7c82835.cleanup.sql b/include/upgrader/streams/core/1ee831c8-e9b05c19.cleanup.sql
similarity index 100%
rename from include/upgrader/streams/core/1ee831c8-c7c82835.cleanup.sql
rename to include/upgrader/streams/core/1ee831c8-e9b05c19.cleanup.sql
diff --git a/include/upgrader/streams/core/1ee831c8-c7c82835.patch.sql b/include/upgrader/streams/core/1ee831c8-e9b05c19.patch.sql
similarity index 92%
rename from include/upgrader/streams/core/1ee831c8-c7c82835.patch.sql
rename to include/upgrader/streams/core/1ee831c8-e9b05c19.patch.sql
index 0f29e473c460b400e58b8e23e6f9793d2d2891ab..b949f52b25196c7b8d17829200b670fe6ffb842d 100644
--- a/include/upgrader/streams/core/1ee831c8-c7c82835.patch.sql
+++ b/include/upgrader/streams/core/1ee831c8-e9b05c19.patch.sql
@@ -1,5 +1,5 @@
 /**
- * @signature c7c828356c88b462ba2e3e1437dca0df
+ * @signature e9b05c1970a94c63220bdc6a3bee1c7d
  * @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,
@@ -38,5 +39,5 @@ ALTER TABLE  `%TABLE_PREFIX%department`
 
 -- Finished with patch
 UPDATE `%TABLE_PREFIX%config`
-    SET `value`='c7c828356c88b462ba2e3e1437dca0df'
+    SET `value`='e9b05c1970a94c63220bdc6a3bee1c7d'
     WHERE `key` = 'schema_signature' AND `namespace` = 'core';
diff --git a/include/upgrader/streams/core/1ee831c8-c7c82835.task.php b/include/upgrader/streams/core/1ee831c8-e9b05c19.task.php
similarity index 100%
rename from include/upgrader/streams/core/1ee831c8-c7c82835.task.php
rename to include/upgrader/streams/core/1ee831c8-e9b05c19.task.php
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..086b648fb4f4c9b6a85ec79edf610c1877469cc5 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,