diff --git a/bootstrap.php b/bootstrap.php
index ef78830715a162dd91118d3edb8e600159adc8fd..4e2259cc3c86660bca8b49c888af6f73c6264a01 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -198,7 +198,6 @@ class Bootstrap {
         require(INCLUDE_DIR.'class.crypto.php');
         require(INCLUDE_DIR.'class.timezone.php');
         require_once(INCLUDE_DIR.'class.signal.php');
-        require(INCLUDE_DIR.'class.nav.php');
         require(INCLUDE_DIR.'class.page.php');
         require_once(INCLUDE_DIR.'class.format.php'); //format helpers
         require_once(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
diff --git a/client.inc.php b/client.inc.php
index 0a572ed1cfb82278c620945c00d32fb60e712427..2ad4d4702139d68e589dd917acfcedd4ca28f30d 100644
--- a/client.inc.php
+++ b/client.inc.php
@@ -76,6 +76,7 @@ $ost->addExtraHeader('<meta name="csrf_token" content="'.$ost->getCSRFToken().'"
 /* Client specific defaults */
 define('PAGE_LIMIT', DEFAULT_PAGE_LIMIT);
 
+require(INCLUDE_DIR.'class.nav.php');
 $nav = new UserNav($thisclient, 'home');
 
 $exempt = in_array(basename($_SERVER['SCRIPT_NAME']), array('logout.php', 'ajax.php', 'logs.php', 'upgrade.php'));
diff --git a/include/ajax.orgs.php b/include/ajax.orgs.php
index 7c849e6db88bd31267ebd2ab67a9aabb0e1d6e09..c582b578060b8ba09151db6739cc49c6431809ad 100644
--- a/include/ajax.orgs.php
+++ b/include/ajax.orgs.php
@@ -54,6 +54,8 @@ class OrgsAjaxAPI extends AjaxController {
 
         if(!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif(!($org = Organization::lookup($id)))
             Http::response(404, 'Unknown organization');
 
@@ -72,6 +74,8 @@ class OrgsAjaxAPI extends AjaxController {
 
         if(!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif(!($org = Organization::lookup($id)))
             Http::response(404, 'Unknown organization');
 
@@ -97,6 +101,8 @@ class OrgsAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_DELETE))
+            Http::response(403, 'Permission Denied');
         elseif (!($org = Organization::lookup($id)))
             Http::response(404, 'Unknown organization');
 
@@ -116,6 +122,8 @@ class OrgsAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif (!($org = Organization::lookup($id)))
             Http::response(404, 'Unknown organization');
 
@@ -137,7 +145,8 @@ class OrgsAjaxAPI extends AjaxController {
                             Format::htmlchars($user->getName()));
             } else { //Creating new  user
                 $form = UserForm::getUserForm()->getForm($_POST);
-                if (!($user = User::fromForm($form)))
+                $can_create = $thisstaff->getRole()->hasPerm(User::PERM_CREATE);
+                if (!($user = User::fromForm($form, $can_create)))
                     $info['error'] = __('Error adding user - try again!');
             }
 
@@ -175,6 +184,8 @@ class OrgsAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_CREATE))
+            Http::response(403, 'Permission Denied');
         elseif (!($org = Organization::lookup($org_id)))
             Http::response(404, 'No such organization');
 
@@ -198,6 +209,10 @@ class OrgsAjaxAPI extends AjaxController {
     }
 
     function addOrg() {
+        global $thisstaff;
+
+        if (!$thisstaff->getRole()->hasPerm(Organization::PERM_CREATE))
+            Http::response(403, 'Permission Denied');
 
         $info = array();
 
@@ -266,6 +281,8 @@ class OrgsAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, "Login required");
+        elseif (!$thisstaff->getRole()->hasPerm(Organization::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif (!($org = Organization::lookup($org_id)))
             Http::response(404, "No such ticket");
         elseif (!isset($_POST['forms']))
diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 721da44032dd29c96893016f5733564157732528..990ae735677c635ffbc7f1b78454e33df5282b82 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -181,7 +181,6 @@ class TicketsAjaxAPI extends AjaxController {
     }
 
     function previewTicket ($tid) {
-
         global $thisstaff;
 
         if(!$thisstaff || !($ticket=Ticket::lookup($tid))
@@ -448,6 +447,7 @@ class TicketsAjaxAPI extends AjaxController {
     }
 
     function _userlookup($user, $form, $info) {
+        global $thisstaff;
 
         ob_start();
         include(STAFFINC_DIR . 'templates/user-lookup.tmpl.php');
diff --git a/include/ajax.users.php b/include/ajax.users.php
index cca1b11631263981e16c4f61b4ae6f5065878e45..f3b6c247a00fd57dc8379c077c6e07c1c0e084da 100644
--- a/include/ajax.users.php
+++ b/include/ajax.users.php
@@ -109,6 +109,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if(!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif(!($user = User::lookup($id)))
             Http::response(404, 'Unknown user');
 
@@ -125,6 +127,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if(!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif(!($user = User::lookup($id)))
             Http::response(404, 'Unknown user');
 
@@ -141,6 +145,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_MANAGE))
+            Http::response(403, 'Permission Denied');
         elseif (!($user = User::lookup($id)))
             Http::response(404, 'Unknown user');
 
@@ -168,6 +174,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_MANAGE))
+            Http::response(403, 'Permission Denied');
         elseif (!($user = User::lookup($id)))
             Http::response(404, 'Unknown user');
 
@@ -200,6 +208,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_DELETE))
+            Http::response(403, 'Permission Denied');
         elseif (!($user = User::lookup($id)))
             Http::response(404, 'Unknown user');
 
@@ -240,6 +250,7 @@ class UsersAjaxAPI extends AjaxController {
     }
 
     function addUser() {
+        global $thisstaff;
 
         $info = array();
 
@@ -247,6 +258,9 @@ class UsersAjaxAPI extends AjaxController {
             $info['lookup'] = 'local';
 
         if ($_POST) {
+            if (!$thisstaff->getRole()->hasPerm(User::PERM_CREATE))
+                Http::response(403, 'Permission Denied');
+
             $info['title'] = __('Add New User');
             $form = UserForm::getUserForm()->getForm($_POST);
             if (($user = User::fromForm($form)))
@@ -263,6 +277,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_CREATE))
+            Http::response(403, 'Permission Denied');
         elseif (!$bk || !$id)
             Http::response(422, 'Backend and user id required');
         elseif (!($backend = AuthenticationBackend::getSearchDirectoryBackend($bk))
@@ -284,6 +300,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, 'Login Required');
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_CREATE))
+            Http::response(403, 'Permission Denied');
 
         $info = array(
             'title' => __('Import Users'),
@@ -304,6 +322,7 @@ class UsersAjaxAPI extends AjaxController {
     }
 
     function selectUser($id) {
+        global $thisstaff;
 
         if ($id)
             $user = User::lookup($id);
@@ -319,9 +338,14 @@ class UsersAjaxAPI extends AjaxController {
     }
 
     static function _lookupform($form=null, $info=array()) {
+        global $thisstaff;
 
-        if (!$info or !$info['title'])
-            $info += array('title' => __('Lookup or create a user'));
+        if (!$info or !$info['title']) {
+            if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE))
+                $info += array('title' => __('Lookup or create a user'));
+            else
+                $info += array('title' => __('Lookup a user'));
+        }
 
         ob_start();
         include(STAFFINC_DIR . 'templates/user-lookup.tmpl.php');
@@ -422,6 +446,8 @@ class UsersAjaxAPI extends AjaxController {
 
         if (!$thisstaff)
             Http::response(403, "Login required");
+        elseif (!$thisstaff->getRole()->hasPerm(User::PERM_EDIT))
+            Http::response(403, 'Permission Denied');
         elseif (!($user = User::lookup($user_id)))
             Http::response(404, "No such user");
         elseif (!isset($_POST['forms']))
diff --git a/include/class.email.php b/include/class.email.php
index 31c3dda775dd5f0b8aef0c6300e3a03f6f088add..2943192ef5c6734698829e874275c7574e590ed7 100644
--- a/include/class.email.php
+++ b/include/class.email.php
@@ -42,8 +42,9 @@ class EmailModel extends VerySimpleModel {
                 'title' =>
                 /* @trans */ 'Banlist',
                 'desc'  =>
-                /* @trans */ 'Ability to add/remove emails from banlist via ticket interface'),
-            );
+                /* @trans */ 'Ability to add/remove emails from banlist via ticket interface',
+                'primary' => true,
+            ));
 
     function getId() {
         return $this->email_id;
diff --git a/include/class.faq.php b/include/class.faq.php
index 9b95776031909bb948bacd74127e45182cca2135..a20060729ac804fe4284778fbe2424ba2002bffd 100644
--- a/include/class.faq.php
+++ b/include/class.faq.php
@@ -53,9 +53,9 @@ class FAQ extends VerySimpleModel {
                 'title' =>
                 /* @trans */ 'FAQ',
                 'desc'  =>
-                /* @trans */ 'Ability to add/update/disable/delete knowledgebase categories and FAQs'),
-            );
-
+                /* @trans */ 'Ability to add/update/disable/delete knowledgebase categories and FAQs',
+                'primary' => true,
+            ));
 
     var $attachments;
     var $topics;
diff --git a/include/class.nav.php b/include/class.nav.php
index d3cbb943dfe2cd0e219060dea7802482f8d23585..92d08996a2bcd6d2076955021b36fc570c2e7dda 100644
--- a/include/class.nav.php
+++ b/include/class.nav.php
@@ -111,10 +111,18 @@ class StaffNav {
 
 
     function getTabs(){
+        global $thisstaff;
+
         if(!$this->tabs) {
-            $this->tabs=array();
-            $this->tabs['dashboard'] = array('desc'=>__('Dashboard'),'href'=>'dashboard.php','title'=>__('Agent Dashboard'));
-            $this->tabs['users'] = array('desc' => __('Users'), 'href' => 'users.php', 'title' => __('User Directory'));
+            $this->tabs = array();
+            $this->tabs['dashboard'] = array(
+                'desc'=>__('Dashboard'),'href'=>'dashboard.php','title'=>__('Agent Dashboard')
+            );
+            if ($thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY)) {
+                $this->tabs['users'] = array(
+                    'desc' => __('Users'), 'href' => 'users.php', 'title' => __('User Directory')
+                );
+            }
             $this->tabs['tickets'] = array('desc'=>__('Tickets'),'href'=>'tickets.php','title'=>__('Ticket Queue'));
             $this->tabs['kbase'] = array('desc'=>__('Knowledgebase'),'href'=>'kb.php','title'=>__('Knowledgebase'));
             if (count($this->getRegisteredApps()))
diff --git a/include/class.organization.php b/include/class.organization.php
index e13329507aba063361ad6cd834554f89b37f18cd..b5fed6c32115a366971834803f7f4f231771cdfc 100644
--- a/include/class.organization.php
+++ b/include/class.organization.php
@@ -35,6 +35,28 @@ class OrganizationModel extends VerySimpleModel {
     const COLLAB_PRIMARY_CONTACT =  0x0002;
     const ASSIGN_AGENT_MANAGER =    0x0004;
 
+    const PERM_CREATE =     'org.create';
+    const PERM_EDIT =       'org.edit';
+    const PERM_DELETE =     'org.delete';
+
+    static protected $perms = array(
+        self::PERM_CREATE => array(
+            'title' => /* @trans */ 'Create',
+            'desc' => /* @trans */ 'Ability to create new organizations',
+            'primary' => true,
+        ),
+        self::PERM_EDIT => array(
+            'title' => /* @trans */ 'Edit',
+            'desc' => /* @trans */ 'Ability to manage organizations',
+            'primary' => true,
+        ),
+        self::PERM_DELETE => array(
+            'title' => /* @trans */ 'Delete',
+            'desc' => /* @trans */ 'Ability to delete organizations',
+            'primary' => true,
+        ),
+    );
+
     var $_manager;
 
     function getId() {
@@ -101,7 +123,14 @@ class OrganizationModel extends VerySimpleModel {
     function allMembers() {
         return $this->users;
     }
+
+    static function getPermissions() {
+        return self::$perms;
+    }
 }
+include_once INCLUDE_DIR.'class.role.php';
+RolePermission::register(/* @trans */ 'Organizations',
+    OrganizationModel::getPermissions());
 
 class OrganizationCdata extends VerySimpleModel {
     static $meta = array(
diff --git a/include/class.report.php b/include/class.report.php
index 0e8bae980f7af555cd743551655df3fbdb89e7e5..059325b3f44a69c1905582ba1826a8594ad93dc1 100644
--- a/include/class.report.php
+++ b/include/class.report.php
@@ -9,8 +9,9 @@ class ReportModel {
                 'title' =>
                 /* @trans */ 'Stats',
                 'desc'  =>
-                /* @trans */ 'Ability to view stats of other agents in allowed departments'),
-            );
+                /* @trans */ 'Ability to view stats of other agents in allowed departments',
+                'primary' => true,
+            ));
 
     static function getPermissions() {
         return self::$perms;
diff --git a/include/class.role.php b/include/class.role.php
index 476bd9a72b89721f1235a9f3b1dfdf65a2d89587..b2bcd2c97d0813d7cff5fd03d854bbf607cadeb1 100644
--- a/include/class.role.php
+++ b/include/class.role.php
@@ -266,6 +266,8 @@ class RolePermission {
     static protected $_permissions = array(
             /* @trans */ 'Tickets' => array(),
             /* @trans */ 'Tasks' => array(),
+            /* @trans */ 'Users' => array(),
+            /* @trans */ 'Organizations' => array(),
             /* @trans */ 'Knowledgebase' => array(),
             /* @trans */ 'Miscellaneous' => array(),
             );
diff --git a/include/class.search.php b/include/class.search.php
index 5436ff519333b7ff3e578703fc13672cd194ed34..84d3bbbcdc7d4478be5d1af5e733eadda3e7a323 100644
--- a/include/class.search.php
+++ b/include/class.search.php
@@ -30,6 +30,16 @@ abstract class SearchBackend {
     const SORT_RECENT = 2;
     const SORT_OLDEST = 3;
 
+    const PERM_EVERYTHING = 'search.all';
+
+    static protected $perms = array(
+        self::PERM_EVERYTHING => array(
+            'title' => /* @trans */ 'Search',
+            'desc'  => /* @trans */ 'See all tickets in search results, regardless of access',
+            'primary' => true,
+        ),
+    );
+
     abstract function update($model, $id, $content, $new=false, $attrs=array());
     abstract function find($query, QuerySet $criteria);
 
@@ -48,7 +58,12 @@ abstract class SearchBackend {
 
         return new self::$registry[$id]();
     }
+
+    static function getPermissions() {
+        return self::$perms;
+    }
 }
+RolePermission::register(/* @trans */ 'Miscellaneous', SearchBackend::getPermissions());
 
 // Register signals to intercept saving of various content throughout the
 // system
diff --git a/include/class.staff.php b/include/class.staff.php
index 44f7d6302e70558bbfe604b74050d825218836a7..6a7c06a260ddf63e0cdfda442c65cd74f7daa548 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -320,7 +320,7 @@ implements AuthenticatedUser, EmailContact {
             if (isset($this->_roles[$deptId]))
                 return $this->_roles[$deptId];
 
-            if (($role=$this->group->getRole($deptId)))
+            if (($role = $this->group->getRole($deptId)))
                 return $this->_roles[$deptId] = $role;
         }
         // For the primary department, use the primary role
@@ -329,6 +329,7 @@ implements AuthenticatedUser, EmailContact {
 
     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) {
@@ -337,7 +338,7 @@ implements AuthenticatedUser, EmailContact {
                 }
             }
         }
-        return @$this->_perms[$perm];
+        return @$this->_perms[$perm] ?: false;
     }
 
     function canManageTickets() {
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 0505d9832bceb4ceda56ce80d52c462fd3b95e54..c5f364de9b756bbbb9e9db142ae1a4bbc3b3514e 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -2790,7 +2790,7 @@ implements RestrictedAccess, Threadable {
      */
     static function create($vars, &$errors, $origin, $autorespond=true,
             $alertstaff=true) {
-        global $ost, $cfg, $thisclient, $_FILES;
+        global $ost, $cfg, $thisclient, $thisstaff;
 
         // Don't enforce form validation for email
         $field_filter = function($type) use ($origin) {
@@ -2958,9 +2958,14 @@ implements RestrictedAccess, Threadable {
                 }
 
                 $user_form = UserForm::getUserForm()->getForm($vars);
+                $can_create = $thisstaff->getRole()->hasPerm(User::PERM_CREATE);
                 if (!$user_form->isValid($field_filter('user'))
-                        || !($user=User::fromVars($user_form->getClean())))
-                    $errors['user'] = __('Incomplete client information');
+                    || !($user=User::fromVars($user_form->getClean(), $can_create))
+                ) {
+                    $errors['user'] = $can_create
+                        ? __('Incomplete client information')
+                        : __('You do not have permission to create users.');
+                }
             }
         }
 
diff --git a/include/class.user.php b/include/class.user.php
index 1bef5404b7eb68cec647d2e4864e296f85680b00..0ad21e055023ae751ebe044f54cb78068c1d9ad3 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -69,6 +69,40 @@ class UserModel extends VerySimpleModel {
 
     const PRIMARY_ORG_CONTACT   = 0x0001;
 
+    const PERM_CREATE =     'user.create';
+    const PERM_EDIT =       'user.edit';
+    const PERM_DELETE =     'user.delete';
+    const PERM_MANAGE =     'user.manage';
+    const PERM_DIRECTORY =  'user.dir';
+
+    static protected $perms = array(
+        self::PERM_CREATE => array(
+            'title' => /* @trans */ 'Create',
+            'desc' => /* @trans */ 'Ability to add new users',
+            'primary' => true,
+        ),
+        self::PERM_EDIT => array(
+            'title' => /* @trans */ 'Edit',
+            'desc' => /* @trans */ 'Ability to manage user information',
+            'primary' => true,
+        ),
+        self::PERM_DELETE => array(
+            'title' => /* @trans */ 'Delete',
+            'desc' => /* @trans */ 'Ability to delete users',
+            'primary' => true,
+        ),
+        self::PERM_MANAGE => array(
+            'title' => /* @trans */ 'Manage Account',
+            'desc' => /* @trans */ 'Ability to manage active user accounts',
+            'primary' => true,
+        ),
+        self::PERM_DIRECTORY => array(
+            'title' => /* @trans */ 'User Directory',
+            'desc' => /* @trans */ 'Ability to access the user directory',
+            'primary' => true,
+        ),
+    );
+
     function getId() {
         return $this->id;
     }
@@ -125,7 +159,13 @@ class UserModel extends VerySimpleModel {
         else
             $this->clearStatus(User::PRIMARY_ORG_CONTACT);
     }
+
+    static function getPermissions() {
+        return self::$perms;
+    }
 }
+include_once INCLUDE_DIR.'class.role.php';
+RolePermission::register(/* @trans */ 'Users', UserModel::getPermissions());
 
 class UserCdata extends VerySimpleModel {
     static $meta = array(
@@ -146,10 +186,10 @@ class User extends UserModel {
     var $_entries;
     var $_forms;
 
-    static function fromVars($vars) {
+    static function fromVars($vars, $create=true) {
         // Try and lookup by email address
         $user = static::lookupByEmail($vars['email']);
-        if (!$user) {
+        if (!$user && $create) {
             $name = $vars['name'];
             if (!$name)
                 list($name) = explode('@', $vars['email'], 2);
@@ -184,7 +224,7 @@ class User extends UserModel {
         return $user;
     }
 
-    static function fromForm($form) {
+    static function fromForm($form, $create=true) {
         global $thisstaff;
 
         if(!$form) return null;
@@ -205,7 +245,7 @@ class User extends UserModel {
             $valid = false;
         }
 
-        return $valid ? self::fromVars($form->getClean()) : null;
+        return $valid ? self::fromVars($form->getClean(), $create) : null;
     }
 
     function getEmail() {
@@ -623,8 +663,14 @@ class PersonsName {
         elseif($cfg)
             $this->format = $cfg->getDefaultNameFormat();
 
-        $this->parts = static::splitName($name);
-        $this->name = $name;
+        if (!is_array($name)) {
+            $this->parts = static::splitName($name);
+            $this->name = $name;
+        }
+        else {
+            $this->parts = $name;
+            $this->name = implode(' ', $name);
+        }
     }
 
     function getFirst() {
diff --git a/include/i18n/en_US/role.yaml b/include/i18n/en_US/role.yaml
index d83a60c2914848730123c02c623b52e7b210cd71..4e3a15e839dc06621146f12a3ca46e1f24ed2e3f 100644
--- a/include/i18n/en_US/role.yaml
+++ b/include/i18n/en_US/role.yaml
@@ -34,7 +34,15 @@
     kb.premade,
     kb.faq,
     stats.agents,
-    emails.banlist]
+    emails.banlist,
+    user.edit,
+    user.delete,
+    user.manage,
+    user.dir,
+    org.create,
+    org.edit,
+    org.delete,
+    search.all]
 
 - id: 2
   flags: 1
@@ -58,7 +66,14 @@
     kb.premade,
     kb.faq,
     stats.agents,
-    emails.banlist]
+    emails.banlist,
+    user.edit,
+    user.delete,
+    user.manage,
+    user.dir,
+    org.create,
+    org.edit,
+    org.delete]
 
 - id: 3
   flags: 1
@@ -74,4 +89,9 @@
     task.create,
     task.assign,
     task.transfer,
-    task.reply]
+    task.reply,
+    user.edit,
+    user.manage,
+    user.dir,
+    org.create,
+    org.edit]
diff --git a/include/staff/org-view.inc.php b/include/staff/org-view.inc.php
index 112570e2e8c0f7679281b1d0a2cb88dbbfb31f06..492a5b86c51a9725f0a4a34de459afe66aa8cd7f 100644
--- a/include/staff/org-view.inc.php
+++ b/include/staff/org-view.inc.php
@@ -9,21 +9,27 @@ 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)) { ?>
             <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)) { ?>
             <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)) { ?>
                 <li><a href="#ajax.php/orgs/<?php echo $org->getId();
                     ?>/forms/manage" onclick="javascript:
                     $.dialog($(this).attr('href').substr(1), 201);
                     return false"
                     ><i class="icon-paste"></i>
                     <?php echo __('Manage Forms'); ?></a></li>
+<?php } ?>
               </ul>
             </div>
         </td>
@@ -35,11 +41,17 @@ if(!defined('OSTSCPINC') || !$thisstaff || !is_object($org)) die('Invalid path')
             <table border="0" cellspacing="" cellpadding="4" width="100%">
                 <tr>
                     <th width="150"><?php echo __('Name'); ?>:</th>
-                    <td><b><a href="#orgs/<?php echo $org->getId();
+                    <td>
+<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) { ?>
+                    <b><a href="#orgs/<?php echo $org->getId();
                     ?>/edit" class="org-action"><i
-                    class="icon-edit"></i>&nbsp;<?php echo
-                    $org->getName();
-                    ?></a></td>
+                        class="icon-edit"></i>
+<?php }
+                    echo $org->getName();
+    if ($thisstaff->getRole()->hasPerm(Organization::PERM_EDIT)) { ?>
+                    </a></b>
+<?php } ?>
+                    </td>
                 </tr>
                 <tr>
                     <th><?php echo __('Account Manager'); ?>:</th>
diff --git a/include/staff/orgs.inc.php b/include/staff/orgs.inc.php
index f75f67f556d9e6fbf715ed374a1771e5b06c44d0..4973b0b6252933fc87a8106b3ad3f0fcbe79f6bf 100644
--- a/include/staff/orgs.inc.php
+++ b/include/staff/orgs.inc.php
@@ -86,9 +86,11 @@ $_SESSION['orgs_qs_'.$qhash] = $query;
         </table>
     </form>
  </div>
+<?php if ($thisstaff->getRole()->hasPerm(Organization::PERM_CREATE)) { ?>
  <div class="pull-right flush-right">
     <b><a href="#orgs/add" class="Icon newDepartment add-org"><?php
     echo __('Add New Organization'); ?></a></b></div>
+<?php } ?>
 <div class="clear"></div>
 <?php
 $showing = $search ? __('Search Results').': ' : '';
diff --git a/include/staff/role.inc.php b/include/staff/role.inc.php
index 25384cd39977d15950297605ec05bc11b3308db8..309d26d7bd86dfb74c6deb1fc8ffd020a0a3a92b 100644
--- a/include/staff/role.inc.php
+++ b/include/staff/role.inc.php
@@ -96,11 +96,15 @@ $info = Format::htmlchars(($errors && $_POST) ? array_merge($info, $_POST) : $in
                     (isset($setting[$k]) && $setting[$k]) ?  'checked="checked"' : '');
               ?>
               &nbsp;&nbsp;
+              <?php echo Format::htmlchars(__($v['title'])); ?>
+              —
               <?php
-                echo sprintf('%s - <em>%s</em>',
-                      Format::htmlchars(__($v['title'])),
-                    Format::htmlchars(__($v['desc'])));
-              ?>
+              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>
             </td>
           </tr>
diff --git a/include/staff/templates/tickets.tmpl.php b/include/staff/templates/tickets.tmpl.php
index e70d3e29cd537338d5feb20b6f5f070acdf60de9..7fc45a41afd9328dc2b3300b16b935385e57fa76 100644
--- a/include/staff/templates/tickets.tmpl.php
+++ b/include/staff/templates/tickets.tmpl.php
@@ -1,63 +1,42 @@
 <?php
 
-$select ='SELECT ticket.ticket_id,ticket.`number`,ticket.dept_id,ticket.staff_id,ticket.team_id, ticket.user_id '
-        .' ,dept.name as department, status.name as status,ticket.source,ticket.isoverdue,ticket.isanswered,ticket.created '
-        .' ,CAST(GREATEST(IFNULL(ticket.lastmessage, 0), IFNULL(ticket.reopened, 0), ticket.created) as datetime) as effective_date '
-        .' ,CONCAT_WS(" ", staff.firstname, staff.lastname) as staff, team.name as team '
-        .' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned '
-        .' ,IF(ptopic.topic_pid IS NULL, topic.topic, CONCAT_WS(" / ", ptopic.topic, topic.topic)) as helptopic '
-        .' ,cdata.priority as priority_id, cdata.subject, user.name, email.address as email';
+$tickets = TicketModel::objects();
 
-$from =' FROM '.TICKET_TABLE.' ticket '
-      .' LEFT JOIN '.TICKET_STATUS_TABLE.' status
-        ON status.id = ticket.status_id '
-      .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id '
-      .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id '
-      .' LEFT JOIN '.USER_ACCOUNT_TABLE.' account ON (ticket.user_id=account.user_id) '
-      .' LEFT JOIN '.DEPT_TABLE.' dept ON ticket.dept_id=dept.id '
-      .' LEFT JOIN '.STAFF_TABLE.' staff ON (ticket.staff_id=staff.staff_id) '
-      .' LEFT JOIN '.TEAM_TABLE.' team ON (ticket.team_id=team.team_id) '
-      .' LEFT JOIN '.TOPIC_TABLE.' topic ON (ticket.topic_id=topic.topic_id) '
-      .' LEFT JOIN '.TOPIC_TABLE.' ptopic ON (ptopic.topic_id=topic.topic_pid) '
-      .' LEFT JOIN '.TABLE_PREFIX.'ticket__cdata cdata ON (cdata.ticket_id = ticket.ticket_id) '
-      .' LEFT JOIN '.PRIORITY_TABLE.' pri ON (pri.priority_id = cdata.priority)';
+if ($user) {
+    $tickets->filter(array('user_id' => $user->getId()));
+}
+elseif ($org) {
+    $tickets->filter(array('user__org' => $org));
+}
+
+if (!$thisstaff->getRole()->hasPerm(SearchBackend::PERM_EVERYTHING)) {
+    // -- Open and assigned to me
+    $visibility = array(
+        new Q(array('status__state'=>'open', 'staff_id' => $thisstaff->getId()))
+    );
+    // -- Routed to a department of mine
+    if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
+        $visibility[] = new Q(array('dept_id__in' => $depts));
+    // -- Open and assigned to a team of mine
+    if (($teams = $thisstaff->getTeams()) && count(array_filter($teams)))
+        $visibility[] = new Q(array(
+            'team_id__in' => array_filter($teams), 'status__state'=>'open'
+        ));
+    $tickets->filter(Q::any($visibility));
+}
 
-if ($user)
-    $where = 'WHERE ticket.user_id = '.db_input($user->getId());
-elseif ($org)
-    $where = 'WHERE user.org_id = '.db_input($org->getId());
+$tickets->annotate(array(
+    'collab_count' => SqlAggregate::COUNT('thread__collaborators'),
+    'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'),
+    'thread_count' => SqlAggregate::COUNT('thread__entries'),
+));
 
+$tickets->values('staff_id', 'staff__firstname', 'staff__lastname', 'team__name', 'team_id', 'lock__lock_id', 'lock__staff_id', 'isoverdue', 'status_id', 'status__name', 'status__state', 'number', 'cdata__subject', 'ticket_id', 'source', 'dept_id', 'dept__name', 'user_id', 'user__default_email__address', 'user__name');
 
 TicketForm::ensureDynamicDataView();
 
-$query ="$select $from $where ORDER BY ticket.created DESC";
-
 // Fetch the results
-$results = array();
-$res = db_query($query);
-while ($row = db_fetch_array($res))
-    $results[$row['ticket_id']] = $row;
-
-if ($results) {
-    $counts_sql = 'SELECT ticket.ticket_id,
-        count(DISTINCT attach.id) as attachments,
-        count(DISTINCT entry.id) as thread_count,
-        count(DISTINCT collab.id) as collaborators
-        FROM '.TICKET_TABLE.' ticket '
-     .' LEFT JOIN '.THREAD_TABLE.' thread
-            ON (thread.object_id=ticket.ticket_id AND thread.object_type="T") '
-     .' LEFT JOIN '.THREAD_ENTRY_TABLE.' entry ON (entry.thread_id=thread.id) '
-     .' LEFT JOIN '.ATTACHMENT_TABLE.' attach
-            ON (attach.object_id=entry.id AND attach.`type` = "H") '
-     .' LEFT JOIN '.THREAD_COLLABORATOR_TABLE.' collab
-            ON ( thread.id=collab.thread_id) '
-     .' WHERE ticket.ticket_id IN ('.implode(',', db_input(array_keys($results))).')
-        GROUP BY ticket.ticket_id';
-    $ids_res = db_query($counts_sql);
-    while ($row = db_fetch_array($ids_res)) {
-        $results[$row['ticket_id']] += $row;
-    }
-}
+$results = count($tickets);
 ?>
 <div style="width:700px;" class="pull-left">
    <?php
@@ -94,80 +73,91 @@ if ($results) { ?>
             <?php
             } ?>
             <th width="70"><?php echo __('Ticket'); ?></th>
-            <th width="100"><?php echo __('Date'); ?></th>
-            <th width="100"><?php echo __('Status'); ?></th>
-            <th width="300"><?php echo __('Subject'); ?></th>
+            <th width="120"><?php echo __('Date'); ?></th>
+            <th width="70"><?php echo __('Status'); ?></th>
+            <th width="380"><?php echo __('Subject'); ?></th>
             <?php
             if ($user) { ?>
-            <th width="100"><?php echo __('Department'); ?></th>
-            <th width="100"><?php echo __('Assignee'); ?></th>
+            <th width="150"><?php echo __('Department'); ?></th>
+            <th width="150"><?php echo __('Assignee'); ?></th>
             <?php
             } else { ?>
-            <th width="200"><?php echo __('User'); ?></th>
+            <th width="300"><?php echo __('User'); ?></th>
             <?php
             } ?>
         </tr>
     </thead>
     <tbody>
     <?php
-    foreach($results as $row) {
+    $subject_field = TicketForm::objects()->one()->getField('subject');
+    foreach($tickets as $T) {
         $flag=null;
-        if ($row['lock_id'])
+        if ($T['lock__lock_id'] && $T['lock__staff_id'] != $thisstaff->getId())
             $flag='locked';
-        elseif ($row['isoverdue'])
+        elseif ($T['isoverdue'])
             $flag='overdue';
 
         $assigned='';
-        if ($row['staff_id'])
-            $assigned=sprintf('<span class="truncate Icon staffAssigned">%s</span>',$row['staff']);
-        elseif ($row['team_id'])
-            $assigned=sprintf('<span class="truncate Icon teamAssigned">%s</span>',$row['team']);
+        if ($T['staff_id'])
+            $assigned = new PersonsName(array(
+                'first' => $row['staff__firstname'],
+                'last' => $row['staff__lastname']
+            ));
+        elseif ($T['team_id'])
+            $assigned = Team::getLocalById($T['team_id'], 'name', $T['team__name']);
         else
             $assigned=' ';
 
-        $status = ucfirst($row['status']);
-        $tid=$row['number'];
-        $subject = Format::htmlchars($row['subject']);
-        $threadcount=$row['thread_count'];
+        $status = TicketStatus::getLocalById($T['status_id'], 'value', $T['status__name']);
+        $tid = $T['number'];
+        $subject = $subject_field->display($subject_field->to_php($T['cdata__subject']));
+        $threadcount = $T['thread_count'];
         ?>
-        <tr id="<?php echo $row['ticket_id']; ?>">
+        <tr id="<?php echo $T['ticket_id']; ?>">
             <?php
             //Implement mass  action....if need be.
             if (0) { ?>
             <td align="center" class="nohover">
-                <input class="ckb" type="checkbox" name="tids[]" value="<?php echo $row['ticket_id']; ?>" <?php echo $sel?'checked="checked"':''; ?>>
+                <input class="ckb" type="checkbox" name="tids[]" value="<?php echo $T['ticket_id']; ?>" <?php echo $sel?'checked="checked"':''; ?>>
             </td>
             <?php
             } ?>
             <td align="center" nowrap>
               <a class="Icon <?php
-                echo strtolower($row['source']); ?>Ticket preview"
+                echo strtolower($T['source']); ?>Ticket preview"
                 title="<?php echo __('Preview Ticket'); ?>"
-                href="tickets.php?id=<?php echo $row['ticket_id']; ?>"
-                data-preview="#tickets/<?php echo $row['ticket_id']; ?>/preview"><?php echo $tid; ?></a></td>
+                href="tickets.php?id=<?php echo $T['ticket_id']; ?>"
+                data-preview="#tickets/<?php echo $T['ticket_id']; ?>/preview"><?php echo $tid; ?></a></td>
             <td align="center" nowrap><?php echo Format::datetime($row['effective_date']); ?></td>
             <td><?php echo $status; ?></td>
-            <td><a class="truncate <?php if ($flag) { ?> Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket<?php } ?>"
-                style="max-width: 80%; max-width: calc(100% - 86px);"
-                href="tickets.php?id=<?php echo $row['ticket_id']; ?>"><?php echo $subject; ?></a>
+            <td><a <?php if ($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?>
+                href="tickets.php?id=<?php echo $T['ticket_id']; ?>"><span class="truncate"
+                style="max-width: 290px"><?php echo $subject; ?></span></a>
                  <?php
-                    if ($threadcount>1)
-                        echo "<small>($threadcount)</small>&nbsp;".'<i
-                            class="icon-fixed-width icon-comments-alt"></i>&nbsp;';
-                    if ($row['collaborators'])
-                        echo '<i class="icon-fixed-width icon-group faded"></i>&nbsp;';
+                    if ($threadcount > 1) { ?>
+                        <span class="pull-right faded-more"><i class="icon-comments-alt"></i>
+                        <small><?php echo $threadcount; ?></small>
+<?php               }
                     if ($row['attachments'])
-                        echo '<i class="icon-fixed-width icon-paperclip"></i>&nbsp;';
+                        echo '<i class="small icon-paperclip icon-flip-horizontal"></i>';
+                    if ($row['collaborators'])
+                        echo '<i class="icon-group faded-more"></i>';
                 ?>
             </td>
             <?php
-            if ($user) { ?>
-            <td><span class="truncate"><?php echo $row['department']; ?></td>
-            <td>&nbsp;<?php echo $assigned; ?></td>
+            if ($user) {
+                $dept = Dept::getLocalById($T['dept_id'], 'name', $T['dept__name']); ?>
+            <td><span class="truncate" style="max-wdith:150px"><?php
+                echo Format::htmlchars($dept); ?></span></td>
+            <td><span class="truncate" style="max-width:150px"><?php
+                echo Format::htmlchars($assigned); ?></span></td>
             <?php
             } else { ?>
-            <td>&nbsp;<?php echo sprintf('<a href="users.php?id=%d">%s <em> &lt;%s&gt;</em></a>',
-                    $row['user_id'], $row['name'], $row['email']); ?></td>
+            <td><a class="truncate" style="max-width:250px" href="users.php?id="<?php
+                echo $T['user_id']; ?>><?php echo Format::htmlchars($T['user__name']);
+                    ?> <em>&lt;<?php echo Format::htmlchars($T['user__default_email__address']);
+                    ?>&gt;</em</a>
+            </td>
             <?php
             } ?>
         </tr>
diff --git a/include/staff/templates/user-import.tmpl.php b/include/staff/templates/user-import.tmpl.php
index b9ca02007d39bb21c5806edd74c79acbdd8216b8..413ed54e4bcbaeed35f4a2a234e4d78722b4a96d 100644
--- a/include/staff/templates/user-import.tmpl.php
+++ b/include/staff/templates/user-import.tmpl.php
@@ -22,12 +22,6 @@ if ($info['error']) {
         $(this).attr('action', '<?php echo $info['upload_url']; ?>');
         $(document).unbind('submit.dialog');
     }">
-<ul class="tabs">
-    <li class="active"><a href="#copy-paste"
-        ><i class="icon-edit"></i>&nbsp;<?php echo __('Copy Paste'); ?></a></li>
-    <li><a href="#upload"
-        ><i class="icon-fixed-width icon-cloud-upload"></i>&nbsp;<?php echo __('Upload'); ?></a></li>
-</ul>
 <?php echo csrf_token();
 if ($org_id) { ?>
     <input type="hidden" name="id" value="<?php echo $org_id; ?>"/>
diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php
index fa18f885888041d997c5e75e192d5644e7fd35b2..568df91f8d84ed4c4cb18fcf2745722e2e613a13 100644
--- a/include/staff/templates/user-lookup.tmpl.php
+++ b/include/staff/templates/user-lookup.tmpl.php
@@ -4,9 +4,11 @@
 <hr/>
 <?php
 if (!isset($info['lookup']) || $info['lookup'] !== false) { ?>
-<div><p id="msg_info"><i class="icon-info-sign"></i>&nbsp; <?php echo __(
-'Search existing users or add a new user.'
-); ?></p></div>
+<div><p id="msg_info"><i class="icon-info-sign"></i>&nbsp; <?php echo
+    $thisstaff->getRole()->hasPerm(User::PERM_CREATE)
+    ? __('Search existing users or add a new user.')
+    : __('Search existing users.');
+?></p></div>
 <div style="margin-bottom:10px;">
     <input type="text" class="search-input" style="width:100%;"
     placeholder="<?php echo __('Search by email, phone or name'); ?>" id="user-search"
@@ -26,10 +28,12 @@ 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)) { ?>
     <a class="action-button pull-right" style="overflow:inherit"
         id="unselect-user"  href="#"><i class="icon-remove"></i>
         <?php echo __('Add New User'); ?></a>
-<?php if ($user) { ?>
+<?php }
+if ($user) { ?>
     <div><strong id="user-name"><?php echo Format::htmlchars($user->getName()->getOriginal()); ?></strong></div>
     <div>&lt;<span id="user-email"><?php echo $user->getEmail(); ?></span>&gt;</div>
     <?php
@@ -65,6 +69,7 @@ if ($info['error']) {
 </form>
 </div>
 <div id="new-user-form" style="display:<?php echo $user ? 'none' :'block'; ?>;">
+<?php if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE)) { ?>
 <form method="post" class="user" action="<?php echo $info['action'] ?: '#users/lookup/form'; ?>">
     <table width="100%" class="fixed">
     <?php
@@ -82,6 +87,15 @@ if ($info['error']) {
         </span>
      </p>
 </form>
+<?php }
+else { ?>
+    <hr/>
+    <p class="full-width">
+        <span class="buttons pull-left">
+            <input type="button" name="cancel" class="<?php echo $user ?  'cancel' : 'close' ?>"  value="<?php echo __('Cancel'); ?>">
+        </span>
+     </p>
+<?php } ?>
 </div>
 <div class="clear"></div>
 </div>
diff --git a/include/staff/templates/user.tmpl.php b/include/staff/templates/user.tmpl.php
index 4737aaea25e1d0c5b923912c7d9dc1a67c197622..55538502017858db5a38abd5bf04f69e395cc620 100644
--- a/include/staff/templates/user.tmpl.php
+++ b/include/staff/templates/user.tmpl.php
@@ -50,9 +50,13 @@ 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)) { ?>
     <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)) { ?>
     <a href="users.php?id=<?php echo $user->getId(); ?>" title="<?php
         echo __('Manage User'); ?>" class="action"><i class="icon-share"></i></a>
+<?php } ?>
 </div>
     <table class="custom-info" width="100%">
 <?php foreach ($user->getDynamicData() as $entry) {
@@ -72,10 +76,12 @@ if ($info['error']) {
 
 <?php if ($org) { ?>
 <div class="hidden tab_content" id="org-tab">
+<?php if ($thisstaff->getRole()->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>
 </div>
+<?php } ?>
     <table class="custom-info" width="100%">
 <?php foreach ($org->getDynamicData() as $entry) {
 ?>
diff --git a/include/staff/templates/users.tmpl.php b/include/staff/templates/users.tmpl.php
index b95974d214cf17d57ef2062b1d26de4bd7106307..c8a262022a0d036d6127720354c77902ca59861d 100644
--- a/include/staff/templates/users.tmpl.php
+++ b/include/staff/templates/users.tmpl.php
@@ -57,6 +57,7 @@ else
 
 ?>
 <div style="width:700px;" class="pull-left"><b><?php echo $showing; ?></b></div>
+<?php if ($thisstaff->getRole()->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>
@@ -65,6 +66,7 @@ else
     <i class="icon-cloud-upload icon-large"></i>
     <?php echo __('Import'); ?></a></b>
 </div>
+<?php } ?>
 <div class="clear"></div>
 <br/>
 <?php
diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php
index 9591f1794afe9ba08f62db40f9fafb073fb88954..a6fe4c26cce9173c1c1d30eaaa954e79de4a99e4 100644
--- a/include/staff/ticket-open.inc.php
+++ b/include/staff/ticket-open.inc.php
@@ -45,6 +45,7 @@ if ($_POST)
         <tr>
             <th colspan="2">
                 <em><strong><?php echo __('User Information'); ?></strong>: </em>
+                <div class="error"><?php echo $errors['user']; ?></div>
             </th>
         </tr>
         <?php
@@ -84,7 +85,8 @@ if ($_POST)
                 <span style="display:inline-block;">
                     <input type="text" size=45 name="email" id="user-email"
                         autocomplete="off" autocorrect="off" value="<?php echo $info['email']; ?>" /> </span>
-                <font class="error">* <?php echo $errors['email']; ?></font>
+                <span class="error">*</span>
+                <div class="error"><?php echo $errors['email']; ?></div>
             </td>
         </tr>
         <tr>
@@ -92,7 +94,8 @@ if ($_POST)
             <td>
                 <span style="display:inline-block;">
                     <input type="text" size=45 name="name" id="user-name" value="<?php echo $info['name']; ?>" /> </span>
-                <font class="error">* <?php echo $errors['name']; ?></font>
+                <span class="error">*</span>
+                <div class="error"><?php echo $errors['name']; ?></div>
             </td>
         </tr>
         <?php
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 4b1a1ccef3d645dab29d9c93f1a5e41da187bbbe..a30454b50449800d35b9ddde351faa9ec0722dd1 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -224,14 +224,16 @@ 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)) { ?>
                                     <li><a href="users.php?id=<?php echo
                                     $user->getId(); ?>"><i class="icon-user
                                     icon-fixed-width"></i> <?php echo __('Manage User'); ?></a></li>
-<?php if ($user->getOrgId()) { ?>
+<?php       if ($user->getOrgId()) { ?>
                                     <li><a href="orgs.php?id=<?php echo $user->getOrgId(); ?>"><i
                                         class="icon-building icon-fixed-width"></i> <?php
                                         echo __('Manage Organization'); ?></a></li>
-<?php } ?>
+<?php       }
+        } ?>
                                 </ul>
                             </div>
                     <?php
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index 293acca9a4ee685d2608e3af19d0b7b34813a63f..ca01e03ddb0383ba6451abeeffcf2a85dba5f0b5 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -2,7 +2,7 @@
 $search = SavedSearch::create();
 $tickets = TicketModel::objects();
 $clear_button = false;
-$date_header = $date_col = false;
+$view_all_tickets = $date_header = $date_col = false;
 
 // Figure out REFRESH url — which might not be accurate after posting a
 // response
@@ -64,6 +64,7 @@ case 'search':
         $form = $search->getFormFromSession('advsearch');
         $form->loadState($_SESSION['advsearch']);
         $tickets = $search->mangleQuerySet($tickets, $form);
+        $view_all_tickets = $thisstaff->getRole()->hasPerm(SearchBackend::PERM_EVERYTHING);
         $results_type=__('Advanced Search')
             . '<a class="action-button" href="?clear_filter"><i class="icon-ban-circle"></i> <em>' . __('clear') . '</em></a>';
         break;
@@ -94,19 +95,21 @@ if ($status)
 
 // Impose visibility constraints
 // ------------------------------------------------------------
-// -- Open and assigned to me
-$visibility = array(
-    new Q(array('status__state'=>'open', 'staff_id' => $thisstaff->getId()))
-);
-// -- Routed to a department of mine
-if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
-    $visibility[] = new Q(array('dept_id__in' => $depts));
-// -- Open and assigned to a team of mine
-if (($teams = $thisstaff->getTeams()) && count(array_filter($teams)))
-    $visibility[] = new Q(array(
-        'team_id__in' => array_filter($teams), 'status__state'=>'open'
-    ));
-$tickets->filter(Q::any($visibility));
+if (!$view_all_tickets) {
+    // -- Open and assigned to me
+    $visibility = array(
+        new Q(array('status__state'=>'open', 'staff_id' => $thisstaff->getId()))
+    );
+    // -- Routed to a department of mine
+    if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
+        $visibility[] = new Q(array('dept_id__in' => $depts));
+    // -- Open and assigned to a team of mine
+    if (($teams = $thisstaff->getTeams()) && count(array_filter($teams)))
+        $visibility[] = new Q(array(
+            'team_id__in' => array_filter($teams), 'status__state'=>'open'
+        ));
+    $tickets->filter(Q::any($visibility));
+}
 
 // Add in annotations
 $tickets->annotate(array(
diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php
index 6d29d8b2492287165369760ba3ca7320eaaa9526..9e6fb90faf2f1aeac16daa97a53c5ca0d4325104 100644
--- a/include/staff/user-view.inc.php
+++ b/include/staff/user-view.inc.php
@@ -13,13 +13,19 @@ $org = $user->getOrganization();
              title="Reload"><i class="icon-refresh"></i> <?php echo Format::htmlchars($user->getName()); ?></a></h2>
         </td>
         <td width="50%" class="right_align has_bottom_border">
+<?php if (($account && $account->isConfirmed())
+    || $thisstaff->getRole()->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><i class="icon-cog"></i> <?php echo __('More'); ?></span>
             </span>
+<?php }
+    if ($thisstaff->getRole()->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 ($account) { ?>
             <a id="user-manage" class="action-button pull-right user-action"
@@ -32,6 +38,7 @@ $org = $user->getOrganization();
             <?php echo __('Register'); ?></a>
             <?php
             } ?>
+<?php } ?>
             <div id="action-dropdown-more" class="action-dropdown anchor-right">
               <ul>
                 <?php
@@ -48,19 +55,22 @@ $org = $user->getOrganization();
                         <?php echo __('Send Password Reset Email'); ?></a></li>
                     <?php
                     } ?>
+<?php if ($thisstaff->getRole()->hasPerm(User::PERM_MANAGE)) { ?>
                     <li><a class="user-action"
                         href="#users/<?php echo $user->getId(); ?>/manage/access"><i
                         class="icon-lock"></i>
                         <?php echo __('Manage Account Access'); ?></a></li>
                 <?php
-
+}
                 } ?>
+<?php if ($thisstaff->getRole()->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);
                     return false"
                     ><i class="icon-paste"></i>
                     <?php echo __('Manage Forms'); ?></a></li>
+<?php } ?>
 
               </ul>
             </div>
@@ -73,11 +83,18 @@ $org = $user->getOrganization();
             <table border="0" cellspacing="" cellpadding="4" width="100%">
                 <tr>
                     <th width="150"><?php echo __('Name'); ?>:</th>
-                    <td><b><a href="#users/<?php echo $user->getId();
+                    <td>
+<?php
+if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?>
+                    <b><a href="#users/<?php echo $user->getId();
                     ?>/edit" class="user-action"><i
-                    class="icon-edit"></i>&nbsp;<?php echo
-                    Format::htmlchars($user->getName()->getOriginal());
-                    ?></a></td>
+                        class="icon-edit"></i>
+<?php }
+                    echo Format::htmlchars($user->getName()->getOriginal());
+if ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?>
+                    </a>
+<?php } ?>
+</td>
                 </tr>
                 <tr>
                     <th><?php echo __('Email'); ?>:</th>
@@ -93,10 +110,10 @@ $org = $user->getOrganization();
                             if ($org)
                                 echo sprintf('<a href="#users/%d/org" class="user-action">%s</a>',
                                         $user->getId(), $org->getName());
-                            else
-                                echo sprintf('<a href="#users/%d/org"
-                                        class="user-action">Add Organization</a>',
-                                        $user->getId());
+                            elseif ($thisstaff->getRole()->hasPerm(User::PERM_EDIT)) { ?>
+                                <a href="#users/<?php echo $user->getId(); ?>/org"
+                                class="user-action"><?php echo __('Add Organization'); ?></a>
+<?php                       }
                         ?>
                         </span>
                     </td>
diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php
index 763e121d4fec94ac4e6f1f4ee3b7c5b2c52940ac..7e9be8950c5cd1d9c5895018743c2ad79ecc51f7 100644
--- a/include/staff/users.inc.php
+++ b/include/staff/users.inc.php
@@ -71,12 +71,14 @@ $users->order_by($order . $order_column);
         </table>
     </form>
  </div>
+<?php if ($thisstaff->getRole()->hasPerm(User::PERM_CREATE)) { ?>
  <div class="pull-right flush-right" style="padding-right:5px;">
     <b><a href="#users/add" class="Icon newstaff popup-dialog"><?php echo __('Add User'); ?></a></b>
     |
     <b><a href="#users/import" class="popup-dialog"><i class="icon-cloud-upload icon-large"></i>
     <?php echo __('Import'); ?></a></b>
 </div>
+<?php } ?>
 <div class="clear"></div>
 <?php
 $showing = $search ? __('Search Results').': ' : '';
diff --git a/scp/roles.php b/scp/roles.php
index 2c9476e29b8cb7499b01f7d5e7d171fe980af980..824d13b14e285a4ae22d22283a9e988f36eaf0bf 100644
--- a/scp/roles.php
+++ b/scp/roles.php
@@ -15,6 +15,8 @@
 **********************************************************************/
 
 require 'admin.inc.php';
+include_once INCLUDE_DIR . 'class.user.php';
+include_once INCLUDE_DIR . 'class.organization.php';
 include_once INCLUDE_DIR . 'class.canned.php';
 include_once INCLUDE_DIR . 'class.faq.php';
 include_once INCLUDE_DIR . 'class.email.php';
diff --git a/scp/staff.inc.php b/scp/staff.inc.php
index 2ec1221e7f984044a7612302bcc1ed2c604c2378..e17314959df935b19883410b89a1a64353e44d65 100644
--- a/scp/staff.inc.php
+++ b/scp/staff.inc.php
@@ -36,7 +36,6 @@ define('KB_PREMADE_TABLE',TABLE_PREFIX.'kb_premade');
 
 require_once(INCLUDE_DIR.'class.staff.php');
 require_once(INCLUDE_DIR.'class.group.php');
-require_once(INCLUDE_DIR.'class.nav.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.
@@ -103,6 +102,9 @@ if ($_POST  && !$ost->checkCSRFToken()) {
 //Add token to the header - used on ajax calls [DO NOT CHANGE THE NAME]
 $ost->addExtraHeader('<meta name="csrf_token" content="'.$ost->getCSRFToken().'" />');
 
+// Load the navigation after the user in case some things are hidden
+require_once(INCLUDE_DIR.'class.nav.php');
+
 /******* SET STAFF DEFAULTS **********/
 define('PAGE_LIMIT', $thisstaff->getPageLimit()?$thisstaff->getPageLimit():DEFAULT_PAGE_LIMIT);
 
diff --git a/scp/users.php b/scp/users.php
index ade2474137ff87dd793e9ebc01d9aad9dcd2a98c..a606ddca6adadd5aa34b520348d3ad9f760cd045 100644
--- a/scp/users.php
+++ b/scp/users.php
@@ -14,6 +14,9 @@
 **********************************************************************/
 require('staff.inc.php');
 
+if (!$thisstaff->getRole()->hasPerm(User::PERM_DIRECTORY))
+    Http::redirect('index.php');
+
 require_once INCLUDE_DIR.'class.note.php';
 
 $user = null;
@@ -25,6 +28,8 @@ 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)) {
+                $errors['err'] = __('Action denied. Contact admin for access');
             } elseif(($acct = $user->getAccount())
                     && !$acct->update($_POST, $errors)) {
                  $errors['err']=__('Unable to update user account information');