diff --git a/bootstrap.php b/bootstrap.php
index 832fe96e50a6b89f9c7d952c5fa355295fcd8ca5..b8d9052f2475e58192b9f0e301dbe446e9c52cd0 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -72,6 +72,8 @@ class Bootstrap {
         define('USER_EMAIL_TABLE',$prefix.'user_email');
         define('USER_ACCOUNT_TABLE',$prefix.'user_account');
 
+        define('ORGANIZATION_TABLE', $prefix.'organization');
+
         define('STAFF_TABLE',$prefix.'staff');
         define('TEAM_TABLE',$prefix.'team');
         define('TEAM_MEMBER_TABLE',$prefix.'team_member');
@@ -174,6 +176,7 @@ class Bootstrap {
     function loadCode() {
         #include required files
         require(INCLUDE_DIR.'class.signal.php');
+        require(INCLUDE_DIR.'class.user.php');
         require(INCLUDE_DIR.'class.auth.php');
         require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
         require(INCLUDE_DIR.'class.log.php');
diff --git a/include/ajax.orgs.php b/include/ajax.orgs.php
new file mode 100644
index 0000000000000000000000000000000000000000..def54cf3c549d98188a801a78199e52fd6b9e1ab
--- /dev/null
+++ b/include/ajax.orgs.php
@@ -0,0 +1,154 @@
+<?php
+/*********************************************************************
+    ajax.orgs.php
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2014 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+
+if(!defined('INCLUDE_DIR')) die('403');
+
+include_once(INCLUDE_DIR.'class.ticket.php');
+
+class OrgsAjaxAPI extends AjaxController {
+
+    function search($type = null) {
+
+        if(!isset($_REQUEST['q'])) {
+            Http::response(400, 'Query argument is required');
+        }
+
+        $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
+        $orgs=array();
+
+        $escaped = db_input(strtolower($_REQUEST['q']), false);
+        $sql='SELECT DISTINCT org.id, org.name '
+            .' FROM '.ORGANIZATION_TABLE.' org '
+            .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON (entry.object_type=\'O\' AND entry.object_id = org.id)
+               LEFT JOIN '.FORM_ANSWER_TABLE.' value ON (value.entry_id=entry.id) '
+            .' WHERE org.name LIKE \'%'.$escaped.'%\' OR value.value LIKE \'%'.$escaped.'%\''
+            .' ORDER BY org.created '
+            .' LIMIT '.$limit;
+
+        if(($res=db_query($sql)) && db_num_rows($res)){
+            while(list($id, $name)=db_fetch_row($res)) {
+                $orgs[] = array('name' => Format::htmlchars($name), 'info' => $name,
+                    'id' => $id, '/bin/true' => $_REQUEST['q']);
+            }
+        }
+
+        return $this->json_encode(array_values($orgs));
+
+    }
+
+    function editOrg($id) {
+        global $thisstaff;
+
+        if(!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif(!($org = Organization::lookup($id)))
+            Http::response(404, 'Unknown organization');
+
+        $info = array(
+            'title' => sprintf('Update %s', $org->getName())
+        );
+
+        $forms = $org->getForms();
+
+        include(STAFFINC_DIR . 'templates/org.tmpl.php');
+    }
+
+    function updateOrg($id) {
+        global $thisstaff;
+
+        if(!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif(!($org = Organization::lookup($id)))
+            Http::response(404, 'Unknown organization');
+
+        $errors = array();
+        if($org->update($_POST, $errors))
+             Http::response(201, $org->to_json());
+
+        $forms = $org->getForms();
+        include(STAFFINC_DIR . 'templates/org.tmpl.php');
+    }
+
+
+    function delete($id) {
+        global $thisstaff;
+
+        if (!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif (!($org = Organization::lookup($id)))
+            Http::response(404, 'Unknown organization');
+
+        $info = array();
+        if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
+            if ($org->delete())
+                 Http::response(204, 'Organization deleted successfully');
+            else
+                $info['error'] = 'Unable to delete organization - try again!';
+        }
+
+        include(STAFFINC_DIR . 'templates/org-delete.tmpl.php');
+    }
+
+
+    function addOrg() {
+
+        $info = array();
+
+        if ($_POST) {
+            $form = OrganizationForm::getDefaultForm()->getForm($_POST);
+            if (($org = Organization::fromForm($form)))
+                Http::response(201, $org->to_json());
+
+            $info = array('error' =>'Error adding organization - try again!');
+        }
+
+        $info['title'] = 'Add New Organization';
+        $info['search'] = false;
+
+        return self::_lookupform($form, $info);
+    }
+
+    function lookup() {
+        return self::_lookupform();
+    }
+
+    function selectOrg($id) {
+
+        if ($id) $org = Organization::lookup($id);
+
+        $info = array('title' => 'Select Organization');
+
+        ob_start();
+        include(STAFFINC_DIR . 'templates/org-lookup.tmpl.php');
+        $resp = ob_get_contents();
+        ob_end_clean();
+        return $resp;
+
+    }
+
+    static function _lookupform($form=null, $info=array()) {
+
+        if (!$info or !$info['title'])
+            $info += array('title' => 'Organization Lookup');
+
+        ob_start();
+        include(STAFFINC_DIR . 'templates/org-lookup.tmpl.php');
+        $resp = ob_get_contents();
+        ob_end_clean();
+
+        return $resp;
+    }
+}
+?>
diff --git a/include/ajax.users.php b/include/ajax.users.php
index 2e5a83e32dfda68542fe3186ef66734a9c40b25b..05b4094e4fd0449bb2c144e686ffa9276799d425 100644
--- a/include/ajax.users.php
+++ b/include/ajax.users.php
@@ -22,7 +22,7 @@ include_once(INCLUDE_DIR.'class.ticket.php');
 class UsersAjaxAPI extends AjaxController {
 
     /* Assumes search by emal for now */
-    function search() {
+    function search($type = null) {
 
         if(!isset($_REQUEST['q'])) {
             Http::response(400, 'Query argument is required');
@@ -31,40 +31,46 @@ class UsersAjaxAPI extends AjaxController {
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $users=array();
         $emails=array();
-        foreach (StaffAuthenticationBackend::searchUsers($_REQUEST['q']) as $u) {
-            $name = "{$u['first']} {$u['last']}";
-            $users[] = array('email' => $u['email'], 'name'=>$name,
-                'info' => "{$u['email']} - $name (remote)",
-                'id' => "auth:".$u['id'], "/bin/true" => $_REQUEST['q']);
-            $emails[] = $u['email'];
+
+        if (!$type || !strcasecmp($type, 'remote')) {
+            foreach (StaffAuthenticationBackend::searchUsers($_REQUEST['q']) as $u) {
+                $name = "{$u['first']} {$u['last']}";
+                $users[] = array('email' => $u['email'], 'name'=>$name,
+                    'info' => "{$u['email']} - $name (remote)",
+                    'id' => "auth:".$u['id'], "/bin/true" => $_REQUEST['q']);
+                $emails[] = $u['email'];
+            }
         }
-        $remote_emails = ($emails = array_filter($emails))
-            ? ' OR email.address IN ('.implode(',',db_input($emails)).') '
-            : '';
-
-        $escaped = db_input(strtolower($_REQUEST['q']), false);
-        $sql='SELECT DISTINCT user.id, email.address, name '
-            .' FROM '.USER_TABLE.' user '
-            .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id '
-            .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON (entry.object_type=\'U\' AND entry.object_id = user.id)
-               LEFT JOIN '.FORM_ANSWER_TABLE.' value ON (value.entry_id=entry.id) '
-            .' WHERE email.address LIKE \'%'.$escaped.'%\'
-               OR user.name LIKE \'%'.$escaped.'%\'
-               OR value.value LIKE \'%'.$escaped.'%\''.$remote_emails
-            .' ORDER BY user.created '
-            .' LIMIT '.$limit;
-
-        if(($res=db_query($sql)) && db_num_rows($res)){
-            while(list($id,$email,$name)=db_fetch_row($res)) {
-                foreach ($users as $i=>$u) {
-                    if ($u['email'] == $email) {
-                        unset($users[$i]);
-                        break;
+
+        if (!$type || !strcasecmp($type, 'local')) {
+            $remote_emails = ($emails = array_filter($emails))
+                ? ' OR email.address IN ('.implode(',',db_input($emails)).') '
+                : '';
+
+            $escaped = db_input(strtolower($_REQUEST['q']), false);
+            $sql='SELECT DISTINCT user.id, email.address, name '
+                .' FROM '.USER_TABLE.' user '
+                .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id '
+                .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON (entry.object_type=\'U\' AND entry.object_id = user.id)
+                   LEFT JOIN '.FORM_ANSWER_TABLE.' value ON (value.entry_id=entry.id) '
+                .' WHERE email.address LIKE \'%'.$escaped.'%\'
+                   OR user.name LIKE \'%'.$escaped.'%\'
+                   OR value.value LIKE \'%'.$escaped.'%\''.$remote_emails
+                .' ORDER BY user.created '
+                .' LIMIT '.$limit;
+
+            if(($res=db_query($sql)) && db_num_rows($res)){
+                while(list($id,$email,$name)=db_fetch_row($res)) {
+                    foreach ($users as $i=>$u) {
+                        if ($u['email'] == $email) {
+                            unset($users[$i]);
+                            break;
+                        }
                     }
+                    $name = Format::htmlchars($name);
+                    $users[] = array('email'=>$email, 'name'=>$name, 'info'=>"$email - $name",
+                        "id" => $id, "/bin/true" => $_REQUEST['q']);
                 }
-                $name = Format::htmlchars($name);
-                $users[] = array('email'=>$email, 'name'=>$name, 'info'=>"$email - $name",
-                    "id" => $id, "/bin/true" => $_REQUEST['q']);
             }
         }
 
@@ -104,6 +110,91 @@ class UsersAjaxAPI extends AjaxController {
         include(STAFFINC_DIR . 'templates/user.tmpl.php');
     }
 
+    function register($id) {
+        global $thisstaff;
+
+        if (!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif (!($user = User::lookup($id)))
+            Http::response(404, 'Unknown user');
+
+        $errors = $info = array();
+        if ($_POST) {
+            // Register user on post
+            if ($user->getAccount())
+                $info['error'] = 'User already registered';
+            elseif ($user->register($_POST, $errors))
+                Http::response(201, 'Account created successfully');
+
+            // Unable to create user.
+            $info = Format::htmlchars($_POST);
+            if ($errors['err'])
+                $info['error'] = $errors['err'];
+            else
+                $info['error'] = 'Unable to register user - try again!';
+        }
+
+        include(STAFFINC_DIR . 'templates/user-register.tmpl.php');
+    }
+
+    function manage($id, $target=null) {
+        global $thisstaff;
+
+        if (!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif (!($user = User::lookup($id)))
+            Http::response(404, 'Unknown user');
+
+        if (!($account = $user->getAccount()))
+            return self::register($id);
+
+        $errors = array();
+        $info = $account->getInfo();
+
+        if ($_POST) {
+            if ($account->update($_POST, $errors))
+                Http::response(201, 'Account updated successfully');
+
+            // Unable to update account
+            $info = Format::htmlchars($_POST);
+
+            if ($errors['err'])
+                $info['error'] = $errors['err'];
+            else
+                $info['error'] = 'Unable to update account - try again!';
+        }
+
+        $info['_target'] = $target;
+
+        include(STAFFINC_DIR . 'templates/user-account.tmpl.php');
+    }
+
+    function delete($id) {
+        global $thisstaff;
+
+        if (!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif (!($user = User::lookup($id)))
+            Http::response(404, 'Unknown user');
+
+        //Switch to end user so we can get ticket stats
+        // fixme: use orm to get ticket count at the user model level.
+        $user = new EndUser($user);
+
+        $info = array();
+        if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
+
+            if ($user->getNumTickets())
+                $info['error'] = 'You cannot delete a user with tickets!';
+            elseif ($user->delete())
+                 Http::response(204, 'User deleted successfully');
+            else
+                $info['error'] = 'Unable to delete user - try again!';
+        }
+
+        include(STAFFINC_DIR . 'templates/user-delete.tmpl.php');
+    }
+
     function getUser($id=false) {
 
         if(($user=User::lookup(($id) ? $id : $_REQUEST['id'])))
@@ -116,11 +207,19 @@ class UsersAjaxAPI extends AjaxController {
 
     function addUser() {
 
-        $form = UserForm::getUserForm()->getForm($_POST);
-        if (($user = User::fromForm($form)))
-            Http::response(201, $user->to_json());
+        $info = array();
+
+        if ($_POST) {
 
-        $info = array('error' =>'Error adding user - try again!');
+            $form = UserForm::getUserForm()->getForm($_POST);
+            if (($user = User::fromForm($form)))
+                Http::response(201, $user->to_json());
+
+            $info = array('error' =>'Error adding user - try again!');
+        } else {
+            $info['lookuptype'] = remote;
+            $info['title'] = 'Add New User';
+        }
 
         return self::_lookupform($form, $info);
     }
@@ -196,5 +295,55 @@ class UsersAjaxAPI extends AjaxController {
         }
         return $this->json_encode($users);
     }
+
+    function updateOrg($id, $orgId = 0) {
+        global $thisstaff;
+
+        if (!$thisstaff)
+            Http::response(403, 'Login Required');
+        elseif (!($user = User::lookup($id))
+                || !($account=$user->getAccount()))
+            Http::response(404, 'Unknown user account');
+
+        $info['title'] = 'Organization for '.$user->getName();
+        $info['action'] = '#users/'.$user->getId().'/org';
+        $info['onselect'] = 'ajax.php/users/'.$user->getId().'/org';
+
+        if ($_POST) {
+            if ($_POST['orgid']) { //Existing org.
+                if (!($org = Organization::lookup($_POST['orgid'])))
+                    $info['error'] = 'Unknown organization selected';
+            } else { //Creating new org.
+                $form = OrganizationForm::getDefaultForm()->getForm($_POST);
+                if (!($org = Organization::fromForm($form)))
+                    $info['error'] = 'Unable to create organization - try again!';
+            }
+
+            if ($org && $account->setOrganization($org))
+                Http::response(201, $org->to_json());
+
+            $info['error'] = 'Unable to user account - try again!';
+
+        } elseif ($orgId)
+            $org = Organization::lookup($orgId);
+        elseif ($org = $account->getOrganization()) {
+            $info['title'] =  $org->getName();
+            $info['action'] = $info['onselect'] = '';
+            $tmpl = 'org.tmpl.php';
+        }
+
+        if ($org && $account->getOrgId() && $org->getId() != $account->getOrgId())
+            $info['warning'] = 'Are you sure you want to change user\'s organization?';
+
+        $tmpl = $tmpl ?: 'org-lookup.tmpl.php';
+
+        ob_start();
+        include(STAFFINC_DIR . "templates/$tmpl");
+        $resp = ob_get_contents();
+        ob_end_clean();
+
+        return $resp;
+    }
+
 }
 ?>
diff --git a/include/class.auth.php b/include/class.auth.php
index dcde257c8ed86d3a83983fbfb4e7ff5f8bc71164..213730e67b06748a6057afb10e34393b18124a18 100644
--- a/include/class.auth.php
+++ b/include/class.auth.php
@@ -497,6 +497,11 @@ abstract class UserAuthenticationBackend  extends AuthenticationBackend {
 
         $user->refreshSession(true); //set the hash.
 
+        if (($acct = $user->getAccount()) && ($tid = $acct->get('timezone_id'))) {
+            $_SESSION['TZ_OFFSET'] = Timezone::getOffsetById($tid);
+            $_SESSION['TZ_DST'] = $acct->get('dst');
+        }
+
         //Log login info...
         $msg=sprintf('%s (%s) logged in [%s]',
                 $user->getUserName(), $user->getId(), $_SERVER['REMOTE_ADDR']);
diff --git a/include/class.client.php b/include/class.client.php
index 7d1dfbcb7c93e6852070098c10774cee7f891dab..707418456e3e15b1ebefc53d2f10d0ba360b258d 100644
--- a/include/class.client.php
+++ b/include/class.client.php
@@ -269,43 +269,7 @@ class  EndUser extends AuthenticatedUser {
     }
 }
 
-require_once INCLUDE_DIR.'class.orm.php';
-class ClientAccountModel extends VerySimpleModel {
-    static $meta = array(
-        'table' => USER_ACCOUNT_TABLE,
-        'pk' => array('id'),
-        'joins' => array(
-            'user' => array(
-                'null' => false,
-                'constraint' => array('user_id' => 'UserModel.id')
-            ),
-        ),
-    );
-}
-
-class ClientAccount extends ClientAccountModel {
-    var $_options = null;
-    var $timezone;
-
-    const CONFIRMED             = 0x0001;
-    const LOCKED                = 0x0002;
-    const PASSWD_RESET_REQUIRED = 0x0004;
-
-    function __onload() {
-        if ($this->get('timezone_id')) {
-            $this->timezone = Timezone::getOffsetById($this->ht['timezone_id']);
-            $_SESSION['TZ_OFFSET'] = $this->timezone;
-            $_SESSION['TZ_DST'] = $this->get('dst');
-        }
-    }
-
-    function getId() {
-        return $this->get('id');
-    }
-
-    function getUserId() {
-        return $this->get('user_id');
-    }
+class ClientAccount extends UserAccount {
 
     function checkPassword($password, $autoupdate=true) {
 
@@ -331,87 +295,6 @@ class ClientAccount extends ClientAccountModel {
         return $this->checkPassword($password, false);
     }
 
-    function hasPassword() {
-        return (bool) $this->get('passwd');
-    }
-
-    function sendResetEmail($template='pwreset-client') {
-        global $ost, $cfg;
-
-        $token = Misc::randCode(48); // 290-bits
-
-        $email = $cfg->getDefaultEmail();
-        $content = Page::lookup(Page::getIdByType($template));
-
-        if (!$email ||  !$content)
-            return new Error('Unable to retrieve password reset email template');
-
-        $vars = array(
-            'url' => $ost->getConfig()->getBaseUrl(),
-            'token' => $token,
-            'user' => $this->getUser(),
-            'recipient' => $this->getUser(),
-            'link' => sprintf(
-                "%s/pwreset.php?token=%s",
-                $ost->getConfig()->getBaseUrl(),
-                $token),
-        );
-        $vars['reset_link'] = &$vars['link'];
-
-        $info = array('email' => $email, 'vars' => &$vars, 'log'=>true);
-        Signal::send('auth.pwreset.email', $this, $info);
-
-        $msg = $ost->replaceTemplateVariables(array(
-            'subj' => $content->getName(),
-            'body' => $content->getBody(),
-        ), $vars);
-
-        $_config = new Config('pwreset');
-        $_config->set($vars['token'], $this->user->getId());
-
-        $email->send($this->user->default_email->get('address'),
-            Format::striptags($msg['subj']), $msg['body']);
-    }
-
-    function confirm() {
-        $this->_setStatus(self::CONFIRMED);
-        return $this->save();
-    }
-
-    function isConfirmed() {
-        return $this->_getStatus(self::CONFIRMED);
-    }
-
-    function lock() {
-        $this->_setStatus(self::LOCKED);
-        $this->save();
-    }
-
-    function isLocked() {
-        return $this->_getStatus(self::LOCKED);
-    }
-
-    function forcePasswdReset() {
-        $this->_setStatus(self::PASSWD_RESET_REQUIRED);
-        return $this->save();
-    }
-
-    function isPasswdResetForced() {
-        return $this->_getStatus(self::PASSWD_RESET_REQUIRED);
-    }
-
-    function _getStatus($flag) {
-        return 0 !== ($this->get('status') & $flag);
-    }
-
-    function _clearStatus($flag) {
-        return $this->set('status', $this->get('status') & ~$flag);
-    }
-
-    function _setStatus($flag) {
-        return $this->set('status', $this->get('status') | $flag);
-    }
-
     function cancelResetTokens() {
         // TODO: Drop password-reset tokens from the config table for
         //       this user id
@@ -424,17 +307,11 @@ class ClientAccount extends ClientAccountModel {
     }
 
     function getInfo() {
-        $base = $this->ht;
+        $base = parent::getInfo();
         $base['tz_offset'] = $this->timezone;
         return $base;
     }
 
-    function getUser() {
-        $user = User::lookup($this->get('user_id'));
-        $user->set('account', $this);
-        return $user;
-    }
-
     function update($vars, &$errors) {
         $rtoken = $_SESSION['_client']['reset-token'];
         if ($vars['passwd1'] || $vars['passwd2'] || $vars['cpasswd'] || $rtoken) {
@@ -490,20 +367,6 @@ class ClientAccount extends ClientAccountModel {
 
         return $this->save();
     }
-
-    static function createForUser($user) {
-        return static::create(array('user_id'=>$user->getId()));
-    }
-
-    static function lookupByUsername($username) {
-        if (strpos($username, '@') !== false)
-            $user = self::lookup(array('user__emails__address'=>$username));
-        else
-            $user = self::lookup(array('username'=>$username));
-
-        return $user;
-    }
 }
-ClientAccount::_inspect();
 
 ?>
diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index 01682d00cf20c9f71976f7821a73076a98881f60..c58a22f4644e3d768caf172579fe5b2c2310ff4a 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -18,6 +18,7 @@
 **********************************************************************/
 require_once(INCLUDE_DIR . 'class.orm.php');
 require_once(INCLUDE_DIR . 'class.forms.php');
+require_once(INCLUDE_DIR . 'class.filter.php');
 require_once(INCLUDE_DIR . 'class.signal.php');
 
 /**
@@ -36,6 +37,7 @@ class DynamicForm extends VerySimpleModel {
     static $types = array(
         'T' => 'Ticket Information',
         'U' => 'User Information',
+        'O' => 'Organization Information',
     );
 
     var $_form;
@@ -562,11 +564,21 @@ class DynamicFormEntry extends VerySimpleModel {
         return DynamicFormEntry::objects()
             ->filter(array('object_id'=>$user_id, 'object_type'=>'U'));
     }
+
     function setClientId($user_id) {
         $this->object_type = 'U';
         $this->object_id = $user_id;
     }
 
+    function setObjectId($object_id) {
+        $this->object_id = $object_id;
+    }
+
+    function forOrganization($org_id) {
+        return DynamicFormEntry::objects()
+            ->filter(array('object_id'=>$org_id, 'object_type'=>'O'));
+    }
+
     function render($staff=true, $title=false) {
         return $this->getForm()->render($staff, $title);
     }
@@ -596,14 +608,23 @@ class DynamicFormEntry extends VerySimpleModel {
                 // Add to list of answers
                 $this->_values[] = $a;
                 $this->_fields[] = $field;
+                $this->_form = null;
+
                 // Omit fields without data
                 // For user entries, the name and email fields should not be
                 // saved with the rest of the data
-                if (!($this->object_type == 'U'
+                if ($this->object_type == 'U'
                         && in_array($field->get('name'), array('name','email')))
-                        && $field->hasData())
-                    $a->save();
-                $this->_form = null;
+                    continue;
+
+                if ($this->object_type == 'O'
+                        && in_array($field->get('name'), array('name')))
+                    continue;
+
+                if (!$field->hasData())
+                    continue;
+
+                $a->save();
             }
             // Sort the form the way it is declared to be sorted
             if ($this->_fields)
@@ -623,6 +644,11 @@ class DynamicFormEntry extends VerySimpleModel {
             if ($this->object_type == 'U'
                     && in_array($field->get('name'), array('name','email')))
                 continue;
+
+            if ($this->object_type == 'O'
+                    && in_array($field->get('name'), array('name')))
+                continue;
+
             $val = $field->to_database($field->getClean());
             if (is_array($val)) {
                 $a->set('value', $val[0]);
diff --git a/include/class.nav.php b/include/class.nav.php
index 6e0179890938e6f7a933f7b089b2368dd8e0afa2..992daf107f8f8c212d4fc5528a9912e0f5e21e1b 100644
--- a/include/class.nav.php
+++ b/include/class.nav.php
@@ -96,9 +96,10 @@ class StaffNav {
 
         if(!$this->tabs) {
             $this->tabs=array();
-            $this->tabs['dashboard']=array('desc'=>'Dashboard','href'=>'dashboard.php','title'=>'Staff Dashboard');
-            $this->tabs['tickets']=array('desc'=>'Tickets','href'=>'tickets.php','title'=>'Ticket Queue');
-            $this->tabs['kbase']=array('desc'=>'Knowledgebase','href'=>'kb.php','title'=>'Knowledgebase');
+            $this->tabs['dashboard'] = array('desc'=>'Dashboard','href'=>'dashboard.php','title'=>'Staff Dashboard');
+            $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');
         }
 
         return $this->tabs;
@@ -134,6 +135,10 @@ class StaffNav {
                     $subnav[]=array('desc'=>'Staff&nbsp;Directory','href'=>'directory.php','iconclass'=>'teams');
                     $subnav[]=array('desc'=>'My&nbsp;Profile','href'=>'profile.php','iconclass'=>'users');
                     break;
+                case 'users':
+                    $subnav[] = array('desc' => 'User&nbsp;Directory', 'href' => 'users.php', 'iconclass' => 'teams');
+                    $subnav[] = array('desc' => 'Organizations', 'href' => 'orgs.php', 'iconclass' => 'departments');
+                    break;
                 case 'kbase':
                     $subnav[]=array('desc'=>'FAQs','href'=>'kb.php', 'urls'=>array('faq.php'), 'iconclass'=>'kb');
                     if($staff) {
diff --git a/include/class.organization.php b/include/class.organization.php
new file mode 100644
index 0000000000000000000000000000000000000000..18b9f537d92735ad613b1fbc57af0f0e73f38284
--- /dev/null
+++ b/include/class.organization.php
@@ -0,0 +1,256 @@
+<?php
+/*********************************************************************
+    class.organization.php
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2014 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+require_once(INCLUDE_DIR . 'class.orm.php');
+require_once(INCLUDE_DIR . 'class.forms.php');
+require_once(INCLUDE_DIR . 'class.dynamic_forms.php');
+
+class OrganizationModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => ORGANIZATION_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'users' => array(
+                'reverse' => 'UserAccountModel.org',
+            ),
+        )
+    );
+
+    var $users;
+
+    static function objects() {
+        $qs = parent::objects();
+
+        return $qs;
+    }
+
+    function getId() {
+        return $this->id;
+    }
+}
+
+class Organization extends OrganizationModel {
+    var $_entries;
+    var $_forms;
+
+    function __construct($ht) {
+        parent::__construct($ht);
+    }
+
+    //XXX: Shouldn't getName use magic get method to figure this out?
+    function getName() {
+        return $this->name;
+    }
+
+    function getUpdateDate() {
+        return $this->updated;
+    }
+
+    function getCreateDate() {
+        return $this->created;
+    }
+
+    function addDynamicData($data) {
+
+        $of = OrganizationForm::getInstance($this->id);
+        foreach ($of->getFields() as $f)
+            if (isset($data[$f->get('name')]))
+                $of->setAnswer($f->get('name'), $data[$f->get('name')]);
+
+        $of->save();
+
+        return $of;
+    }
+
+    function getDynamicData() {
+        if (!isset($this->_entries)) {
+            $this->_entries = DynamicFormEntry::forOrganization($this->id)->all();
+            if (!$this->_entries) {
+                $g = OrganizationForm::getInstance($this->id);
+                $g->save();
+                $this->_entries[] = $g;
+            }
+        }
+
+        return $this->_entries;
+    }
+
+    function getForms($data=null) {
+
+        if (!isset($this->_forms)) {
+            $this->_forms = array();
+            foreach ($this->getDynamicData() as $cd) {
+                $cd->addMissingFields();
+                if(!$data
+                        && ($form = $cd->getForm())
+                        && $form->get('type') == 'O' ) {
+                    foreach ($cd->getFields() as $f) {
+                        if ($f->get('name') == 'name')
+                            $f->value = $this->getName();
+                    }
+                }
+
+                $this->_forms[] = $cd->getForm();
+            }
+        }
+
+        return $this->_forms;
+    }
+
+    function to_json() {
+
+        $info = array(
+                'id'  => $this->getId(),
+                'name' => (string) $this->getName()
+                );
+
+        return JsonDataEncoder::encode($info);
+    }
+
+
+    function __toString() {
+        return (string) $this->getName();
+    }
+
+    function delete() {
+        //TODO: delete  or reset intrumented list.
+        return parent::delete();
+    }
+
+    function update($vars, &$errors) {
+
+        $valid = true;
+        $forms = $this->getForms($vars);
+        foreach ($forms as $cd) {
+            if (!$cd->isValid())
+                $valid = false;
+            if ($cd->get('type') == 'O'
+                        && ($form= $cd->getForm($vars))
+                        && ($f=$form->getField('name'))
+                        && $f->getClean()
+                        && ($o=Organization::lookup(array('name'=>$f->getClean())))
+                        && $o->id != $this->getId()) {
+                $valid = false;
+                $f->addError('Organization with the same name already exists');
+            }
+        }
+
+        if (!$valid)
+            return false;
+
+        foreach ($this->getDynamicData() as $cd) {
+            if (($f=$cd->getForm())
+                    && ($f->get('type') == 'O')
+                    && ($name = $f->getField('name'))) {
+                    $this->name = $name->getClean();
+                    $this->save();
+                }
+            $cd->save();
+        }
+
+        return true;
+    }
+
+    static function fromVars($vars) {
+
+        if (!($org = Organization::lookup(array('name' => $vars['name'])))) {
+            $org = Organization::create(array(
+                'name' => $vars['name'],
+                'created' => new SqlFunction('NOW'),
+                'updated' => new SqlFunction('NOW'),
+            ));
+            $org->save(true);
+            $org->addDynamicData($vars);
+        }
+
+        return $org;
+    }
+
+    static function fromForm($form) {
+
+        if(!$form) return null;
+
+        //Validate the form
+        $valid = true;
+        if (!$form->isValid())
+            $valid  = false;
+
+        //Make sure the email is not in-use
+        if (($field=$form->getField('name'))
+                && $field->getClean()
+                && Organization::lookup(array('name' => $field->getClean()))) {
+            $field->addError('Organization with the same name already exists');
+            $valid = false;
+        }
+
+        return $valid ? self::fromVars($form->getClean()) : null;
+    }
+
+}
+
+class OrganizationForm extends DynamicForm {
+    static $instance;
+    static $form;
+
+    static function objects() {
+        $os = parent::objects();
+        return $os->filter(array('type'=>'O'));
+    }
+
+    static function getDefaultForm() {
+        if (!isset(static::$form)) {
+            if (($o = static::objects()) && $o[0])
+                static::$form = $o[0];
+            else //TODO: Remove the code below and move it to task??
+                static::$form = self::__loadDefaultForm();
+        }
+
+        return static::$form;
+    }
+
+    static function getInstance($object_id=0) {
+        if (!isset(static::$instance))
+            static::$instance = static::getDefaultForm()->instanciate();
+
+        static::$instance->object_type = 'O';
+
+        if ($object_id)
+            static::$instance->object_id = $object_id;
+
+        return static::$instance;
+    }
+
+    static function __loadDefaultForm() {
+        require_once(INCLUDE_DIR.'class.i18n.php');
+
+        $i18n = new Internationalization();
+        $tpl = $i18n->getTemplate('form.yaml');
+        foreach ($tpl->getData() as $f) {
+            if ($f['type'] == 'O') {
+                $form = DynamicForm::create($f);
+                $form->save();
+                break;
+            }
+        }
+
+        $o =static::objects();
+
+        return $o[0];
+    }
+
+}
+
+//Organization::_inspect();
+
+?>
diff --git a/include/class.user.php b/include/class.user.php
index d23d1e9f1b857bd343f74c42bc7348580703df56..77131657e62e097fe36c980e254b08cef0bd54c9 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -15,6 +15,7 @@
     vim: expandtab sw=4 ts=4 sts=4:
 **********************************************************************/
 require_once(INCLUDE_DIR . 'class.orm.php');
+require_once(INCLUDE_DIR . 'class.organization.php');
 
 class UserEmailModel extends VerySimpleModel {
     static $meta = array(
@@ -38,7 +39,7 @@ class UserModel extends VerySimpleModel {
             ),
             'account' => array(
                 'list' => false,
-                'reverse' => 'ClientAccount.user',
+                'reverse' => 'UserAccount.user',
             ),
             'default_email' => array(
                 'null' => true,
@@ -73,6 +74,8 @@ class User extends UserModel {
     var $_entries;
     var $_forms;
 
+    var $_account;
+
     function __construct($ht) {
         parent::__construct($ht);
         // TODO: Make this automatic with select_related()
@@ -147,10 +150,6 @@ class User extends UserModel {
         return $this->created;
     }
 
-    function getAccount() {
-        return $this->account;
-    }
-
     function to_json() {
 
         $info = array(
@@ -194,9 +193,11 @@ class User extends UserModel {
             if (!$this->_entries) {
                 $g = UserForm::getInstance();
                 $g->setClientId($this->id);
+                $g->save();
                 $this->_entries[] = $g;
             }
         }
+
         return $this->_entries;
     }
 
@@ -224,6 +225,44 @@ class User extends UserModel {
         return $this->_forms;
     }
 
+    function getAccount() {
+        // XXX: return $this->account;
+
+        if (!isset($this->_account))
+            $this->_account = UserAccount::lookup(array('user_id'=>$this->getId()));
+
+        return $this->_account;
+    }
+
+    function getAccountStatus() {
+
+        if (!($account=$this->getAccount()))
+            return 'Guest';
+
+        if ($account->isLocked())
+            return 'Locked (Administrative)';
+
+        if (!$account->isConfirmed())
+            return 'Locked (Pending Activation)';
+
+        return 'Active';
+    }
+
+    function register($vars, &$errors) {
+
+        // user already registered?
+        if ($this->getAccount())
+            return true;
+
+        return UserAccount::register($this, $vars, $errors);
+    }
+
+    //TODO: Add organization support
+    function getOrg() {
+        return '';
+    }
+
+
     function updateInfo($vars, &$errors) {
 
         $valid = true;
@@ -288,16 +327,22 @@ class User extends UserModel {
             $this->name = mb_convert_case($this->name, MB_CASE_TITLE);
         }
 
-        if (count($this->dirty))
+        if (count($this->dirty)) //XXX: doesn't work??
             $this->set('updated', new SqlFunction('NOW'));
         return parent::save($refetch);
     }
 
     function delete() {
-        return parent::delete() && $this->default_email->delete();
+        //TODO:  See about deleting other associated models.
+
+        // Delete email
+        if ($this->default_email)
+            $this->default_email->delete();
+
+        // Delete user
+        return parent::delete();
     }
 }
-User::_inspect();
 
 class PersonsName {
     var $parts;
@@ -482,6 +527,287 @@ class UserEmail extends UserEmailModel {
 }
 
 
+class UserAccountModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => USER_ACCOUNT_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'user' => array(
+                'null' => false,
+                'constraint' => array('user_id' => 'UserModel.id')
+            ),
+        ),
+    );
+}
+
+class UserAccount extends UserAccountModel {
+    var $_options = null;
+    var $_user;
+    var $_org;
+
+    const CONFIRMED             = 0x0001;
+    const LOCKED                = 0x0002;
+    const PASSWD_RESET_REQUIRED = 0x0004;
+
+    protected function hasStatus($flag) {
+        return 0 !== ($this->get('status') & $flag);
+    }
+
+    protected function clearStatus($flag) {
+        return $this->set('status', $this->get('status') & ~$flag);
+    }
+
+    protected function setStatus($flag) {
+        return $this->set('status', $this->get('status') | $flag);
+    }
+
+    function confirm() {
+        $this->setStatus(self::CONFIRMED);
+        return $this->save();
+    }
+
+    function isConfirmed() {
+        return $this->hasStatus(self::CONFIRMED);
+    }
+
+    function lock() {
+        $this->setStatus(self::LOCKED);
+        $this->save();
+    }
+
+    function isLocked() {
+        return $this->hasStatus(self::LOCKED);
+    }
+
+    function forcePasswdReset() {
+        $this->setStatus(self::PASSWD_RESET_REQUIRED);
+        return $this->save();
+    }
+
+    function isPasswdResetForced() {
+        return $this->hasStatus(self::PASSWD_RESET_REQUIRED);
+    }
+
+    function hasPassword() {
+        return (bool) $this->get('passwd');
+    }
+
+    function getStatus() {
+        return $this->get('status');
+    }
+
+    function getInfo() {
+        return $this->ht;
+    }
+
+    function getId() {
+        return $this->get('id');
+    }
+
+    function getUserId() {
+        return $this->get('user_id');
+    }
+
+    function getUser() {
+
+        if (!isset($this->_user)) {
+            if ($this->_user = User::lookup($this->getUserId()))
+                $this->_user->set('account', $this);
+        }
+        return $this->_user;
+    }
+
+    function getOrgId() {
+         return $this->get('org_id');
+    }
+
+    function getOrganization() {
+
+        if (!isset($this->_org))
+            $this->_org = Organization::lookup($this->getOrgId());
+
+        return $this->_org;
+    }
+
+    function setOrganization($org) {
+        if (!$org instanceof Organization)
+            return false;
+
+        $this->set('org_id', $org->getId());
+        $this->_org = null;
+        $this->save();
+
+        return true;
+   }
+
+
+    function sendResetEmail() {
+        return static::sendUnlockEmail('pwreset-client') === true;
+    }
+
+    function sendConfirmEmail() {
+        return static::sendUnlockEmail('registration-client') === true;
+    }
+
+    protected function sendUnlockEmail($template) {
+        global $ost, $cfg;
+
+        $token = Misc::randCode(48); // 290-bits
+
+        $email = $cfg->getDefaultEmail();
+        $content = Page::lookup(Page::getIdByType($template));
+
+        if (!$email ||  !$content)
+            return new Error($template.': Unable to retrieve template');
+
+        $vars = array(
+            'url' => $ost->getConfig()->getBaseUrl(),
+            'token' => $token,
+            'user' => $this->getUser(),
+            'recipient' => $this->getUser(),
+            'link' => sprintf(
+                "%s/pwreset.php?token=%s",
+                $ost->getConfig()->getBaseUrl(),
+                $token),
+        );
+        $vars['reset_link'] = &$vars['link'];
+
+        $info = array('email' => $email, 'vars' => &$vars, 'log'=>true);
+        Signal::send('auth.pwreset.email', $this, $info);
+
+        $msg = $ost->replaceTemplateVariables(array(
+            'subj' => $content->getName(),
+            'body' => $content->getBody(),
+        ), $vars);
+
+        $_config = new Config('pwreset');
+        $_config->set($vars['token'], $this->getUser()->getId());
+
+        $email->send($this->getUser()->getEmail(),
+            Format::striptags($msg['subj']), $msg['body']);
+
+        return true;
+    }
+
+    function __toString() {
+        return (string) $this->getStatus();
+    }
+
+    /*
+     * This assumes the staff is doing the update
+     */
+    function update($vars, &$errors) {
+        global $thisstaff;
+
+
+        if (!$thisstaff) {
+            $errors['err'] = 'Access Denied';
+            return false;
+        }
+
+        // TODO: Make sure the username is unique
+
+        if (!$vars['timezone_id'])
+            $errors['timezone_id'] = 'Time zone required';
+
+        // Changing password?
+        if ($vars['passwd1'] || $vars['passwd2']) {
+            if (!$vars['passwd1'])
+                $errors['passwd1'] = 'New password required';
+            elseif ($vars['passwd1'] && strlen($vars['passwd1'])<6)
+                $errors['passwd1'] = 'Must be at least 6 characters';
+            elseif ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2']))
+                $errors['passwd2'] = 'Password(s) do not match';
+        }
+
+        if ($errors) return false;
+
+        $this->set('timezone_id', $vars['timezone_id']);
+        $this->set('dst', isset($vars['dst']) ? 1 : 0);
+
+        // Make sure the username is not an email.
+        if ($vars['username'] && Validator::is_email($vars['username']))
+             $vars['username'] = '';
+
+        $this->set('username', $vars['username']);
+
+        if ($vars['passwd1']) {
+            $this->set('passwd', Passwd::hash($vars['passwd']));
+            $this->setStatus(self::CONFIRMED);
+        }
+
+        // Set flags
+        if ($vars['pwreset-flag'])
+            $this->setStatus(self::PASSWD_RESET_REQUIRED);
+        else
+            $this->clearStatus(self::PASSWD_RESET_REQUIRED);
+
+        if ($vars['locked-flag'])
+            $this->setStatus(self::LOCKED);
+        else
+            $this->clearStatus(self::LOCKED);
+
+        return $this->save(true);
+    }
+
+    static function createForUser($user) {
+        return static::create(array('user_id'=>$user->getId()));
+    }
+
+    static function lookupByUsername($username) {
+        if (strpos($username, '@') !== false)
+            $user = static::lookup(array('user__emails__address'=>$username));
+        else
+            $user = static::lookup(array('username'=>$username));
+
+        return $user;
+    }
+
+    static function  register($user, $vars, &$errors) {
+
+        if (!$user || !$vars)
+            return false;
+
+        //Require temp password.
+        if (!isset($vars['sendemail'])) {
+            if (!$vars['passwd1'])
+                $errors['passwd1'] = 'Temp. password required';
+            elseif ($vars['passwd1'] && strlen($vars['passwd1'])<6)
+                $errors['passwd1'] = 'Must be at least 6 characters';
+            elseif ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2']))
+                $errors['passwd2'] = 'Password(s) do not match';
+        }
+
+        if ($errors) return false;
+
+        $account = UserAccount::create(array('user_id' => $user->getId()));
+        if (!$account)
+            return false;
+
+        $account->set('dst', isset($vars['dst'])?1:0);
+        $account->set('timezone_id', $vars['timezone_id']);
+
+        if ($vars['username'] && strcasecmp($vars['username'], $user->getEmail()))
+            $account->set('username', $vars['username']);
+
+        if ($vars['passwd1'] && !$vars['sendemail']) {
+            $account->set('passwd', Password::hash($vars['passwd1']));
+            $account->setStatus(self::CONFIRMED);
+            if ($vars['pwreset-flag'])
+                $account->setStatus(self::PASSWD_RESET_REQUIRED);
+        }
+
+        $account->save(true);
+
+        if ($vars['sendemail'])
+            $account->sendConfirmEmail();
+
+        return $account;
+    }
+
+}
+
+
 /*
  *  Generic user list.
  */
@@ -531,5 +857,6 @@ class UserList implements  IteratorAggregate, ArrayAccess {
         return $list ? implode(', ', $list) : '';
     }
 }
+User::_inspect();
 
 ?>
diff --git a/include/i18n/en_US/form.yaml b/include/i18n/en_US/form.yaml
index 244374279f619144b466304f2d2641810f454564..a5030c0333383fc972837aabe8c48add5550b775 100644
--- a/include/i18n/en_US/form.yaml
+++ b/include/i18n/en_US/form.yaml
@@ -146,3 +146,26 @@
         html: false
         maxlength: 100
 
+- type: O # notrans
+  title: Organization Information
+  instructions: Details on user organization
+  deletable: false
+  fields:
+    - type: text # notrans
+      name: name # notrans
+      label: Name
+      required: true
+      sort: 1
+      edit_mask: 15
+      configuration:
+        size: 40
+        length: 64
+
+    - type: memo # notrans
+      name: notes
+      label: Internal Notes
+      required: false
+      sort: 2
+      configuration:
+        rows: 4
+        cols: 40
diff --git a/include/staff/org-view.inc.php b/include/staff/org-view.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..89a8ee39df6d587cc7db14297e25c49ff9d18581
--- /dev/null
+++ b/include/staff/org-view.inc.php
@@ -0,0 +1,85 @@
+<?php
+if(!defined('OSTSCPINC') || !$thisstaff || !is_object($org)) die('Invalid path');
+
+?>
+<table width="940" cellpadding="2" cellspacing="0" border="0">
+    <tr>
+        <td width="50%" class="has_bottom_border">
+             <h2><a href="orgs.php?id=<?php echo $org->getId(); ?>"
+             title="Reload"><i class="icon-refresh"></i> <?php echo $org->getName(); ?></a></h2>
+        </td>
+        <td width="50%" class="right_align has_bottom_border">
+            <a id="org-delete" class="action-button org-action"
+            href="#orgs/<?php echo $org->getId(); ?>/delete"><i class="icon-trash"></i> Delete Organization</a>
+        </td>
+    </tr>
+</table>
+<table class="ticket_info" cellspacing="0" cellpadding="0" width="940" border="0">
+    <tr>
+        <td width="50">
+            <table border="0" cellspacing="" cellpadding="4" width="100%">
+                <tr>
+                    <th width="100">Name:</th>
+                    <td><b><a href="#orgs/<?php echo $org->getId();
+                    ?>/edit" class="org-action"><i
+                    class="icon-edit"></i>&nbsp;<?php echo
+                    $org->getName();
+                    ?></a></td>
+                </tr>
+                <tr>
+                    <th>Users:</th>
+                    <td> {num-here}
+                    </td>
+                </tr>
+            </table>
+        </td>
+        <td width="50%" style="vertical-align:top">
+            <table border="0" cellspacing="" cellpadding="4" width="100%">
+                <tr>
+                    <th>Created:</th>
+                    <td><?php echo Format::db_datetime($org->getCreateDate()); ?></td>
+                </tr>
+                <tr>
+                    <th>Updated:</th>
+                    <td><?php echo Format::db_datetime($org->getUpdateDate()); ?></td>
+                </tr>
+            </table>
+        </td>
+    </tr>
+</table>
+<br>
+<div class="clear"></div>
+<ul class="tabs">
+    <li><a class="active" id="users_tab" href="#users"><i
+    class="icon-user"></i>&nbsp;Users</a></li>
+    <li><a id="tickets_tab" href="#tickets"><i
+    class="icon-list-alt"></i>&nbsp;Tickets</a></li>
+</ul>
+<div class="tab_content" id="users">
+<?php
+include STAFFINC_DIR . 'templates/users.tmpl.php';
+?>
+</div>
+<div class="tab_content" id="tickets"  style="display:none;">
+<?php
+include STAFFINC_DIR . 'templates/tickets.tmpl.php';
+?>
+</div>
+
+<script type="text/javascript">
+$(function() {
+    $(document).on('click', 'a.org-action', function(e) {
+        e.preventDefault();
+        var url = 'ajax.php/'+$(this).attr('href').substr(1);
+        $.dialog(url, [201, 204], function (xhr) {
+            if (xhr.status == 204)
+                window.location.href = 'orgs.php';
+            else
+                window.location.href = window.location.href;
+         }, {
+            onshow: function() { $('#org-search').focus(); }
+         });
+        return false;
+    });
+});
+</script>
diff --git a/include/staff/orgs.inc.php b/include/staff/orgs.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..0df382c6d9aa02f431f2bb952ca7683cb03c56e0
--- /dev/null
+++ b/include/staff/orgs.inc.php
@@ -0,0 +1,164 @@
+<?php
+if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
+
+$qstr='';
+
+$select = 'SELECT org.* ';
+
+$from = 'FROM '.ORGANIZATION_TABLE.' org ';
+
+$where = ' WHERE 1 ';
+
+if ($_REQUEST['query']) {
+
+    $from .=' LEFT JOIN '.FORM_ENTRY_TABLE.' entry
+                ON (entry.object_type=\'O\' AND entry.object_id = org.id)
+              LEFT JOIN '.FORM_ANSWER_TABLE.' value
+                ON (value.entry_id=entry.id) ';
+
+    $search = db_input(strtolower($_REQUEST['query']), false);
+    $where .= ' AND (
+                    org.name LIKE \'%'.$search.'%\' OR value.value LIKE \'%'.$search.'%\'
+                )';
+
+    $qstr.='&query='.urlencode($_REQUEST['query']);
+}
+
+$sortOptions = array('name' => 'org.name',
+                     'users' => 'users',
+                     'create' => 'org.created',
+                     'update' => 'org.updated');
+$orderWays = array('DESC'=>'DESC','ASC'=>'ASC');
+$sort= ($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])]) ? strtolower($_REQUEST['sort']) : 'name';
+//Sorting options...
+if ($sort && $sortOptions[$sort])
+    $order_column =$sortOptions[$sort];
+
+$order_column = $order_column ?: 'org.name';
+
+if ($_REQUEST['order'] && $orderWays[strtoupper($_REQUEST['order'])])
+    $order = $orderWays[strtoupper($_REQUEST['order'])];
+
+$order=$order ?: 'ASC';
+if ($order_column && strpos($order_column,','))
+    $order_column = str_replace(','," $order,",$order_column);
+
+$x=$sort.'_sort';
+$$x=' class="'.strtolower($order).'" ';
+$order_by="$order_column $order ";
+
+$total=db_count('SELECT count(DISTINCT org.id) '.$from.' '.$where);
+$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
+$pageNav=new Pagenate($total,$page,PAGE_LIMIT);
+$pageNav->setURL('orgs.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
+//Ok..lets roll...create the actual query
+$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
+
+$select .= ', count(DISTINCT user.id) as users ';
+
+$from .= ' LEFT JOIN '.USER_ACCOUNT_TABLE.' user ON (user.org_id = org.id) ';
+
+
+$query="$select $from $where GROUP BY org.id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
+//echo $query;
+?>
+<h2>Organizations</h2>
+<div style="width:700px; float:left;">
+    <form action="orgs.php" method="get">
+        <?php csrf_token(); ?>
+        <input type="hidden" name="a" value="search">
+        <table>
+            <tr>
+                <td><input type="text" id="basic-org-search" name="query" size=30 value="<?php echo Format::htmlchars($_REQUEST['query']); ?>"
+                autocomplete="off" autocorrect="off" autocapitalize="off"></td>
+                <td><input type="submit" name="basic_search" class="button" value="Search"></td>
+                <!-- <td>&nbsp;&nbsp;<a href="" id="advanced-user-search">[advanced]</a></td> -->
+            </tr>
+        </table>
+    </form>
+ </div>
+ <div style="float:right;text-align:right;padding-right:5px;">
+    <b><a href="#orgs/add" class="Icon newDepartment add-org">Add New Organization</a></b></div>
+<div class="clear"></div>
+<?php
+$showing = $search ? 'Search Results: ' : '';
+$res = db_query($query);
+if($res && ($num=db_num_rows($res)))
+    $showing .= $pageNav->showing();
+else
+    $showing .= 'No organizations found!';
+?>
+<form action="orgs.php" method="POST" name="staff" >
+ <?php csrf_token(); ?>
+ <input type="hidden" name="do" value="mass_process" >
+ <input type="hidden" id="action" name="a" value="" >
+ <table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
+    <caption><?php echo $showing; ?></caption>
+    <thead>
+        <tr>
+            <th width="400"><a <?php echo $name_sort; ?> href="orgs.php?<?php echo $qstr; ?>&sort=name">Name</a></th>
+            <th width="100"><a <?php echo $users_sort; ?> href="orgs.php?<?php echo $qstr; ?>&sort=users">Users</a></th>
+            <th width="150"><a <?php echo $create_sort; ?> href="orgs.php?<?php echo $qstr; ?>&sort=create">Created</a></th>
+            <th width="145"><a <?php echo $update_sort; ?> href="orgs.php?<?php echo $qstr; ?>&sort=update">Updated</a></th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php
+        if($res && db_num_rows($res)):
+            $ids=($errors && is_array($_POST['ids']))?$_POST['ids']:null;
+            while ($row = db_fetch_array($res)) {
+
+                $sel=false;
+                if($ids && in_array($row['id'], $ids))
+                    $sel=true;
+                ?>
+               <tr id="<?php echo $row['id']; ?>">
+                <td>&nbsp; <a href="orgs.php?id=<?php echo $row['id']; ?>"><?php echo $row['name']; ?></a> </td>
+                <td>&nbsp;<?php echo $row['users']; ?></td>
+                <td><?php echo Format::db_date($row['created']); ?></td>
+                <td><?php echo Format::db_datetime($row['updated']); ?>&nbsp;</td>
+               </tr>
+            <?php
+            } //end of while.
+        endif; ?>
+    <tfoot>
+     <tr>
+        <td colspan="5"> &nbsp; </td>
+     </tr>
+    </tfoot>
+</table>
+<?php
+if($res && $num): //Show options..
+    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
+endif;
+?>
+</form>
+
+<script type="text/javascript">
+$(function() {
+    $('input#basic-org-search').typeahead({
+        source: function (typeahead, query) {
+            $.ajax({
+                url: "ajax.php/orgs/search?q="+query,
+                dataType: 'json',
+                success: function (data) {
+                    typeahead.process(data);
+                }
+            });
+        },
+        onselect: function (obj) {
+            window.location.href = 'orgs.php?id='+obj.id;
+        },
+        property: "/bin/true"
+    });
+
+    $(document).on('click', 'a.add-org', function(e) {
+        e.preventDefault();
+        $.orgLookup('ajax.php/orgs/add', function (org) {
+            window.location.href = 'orgs.php?id='+org.id;
+         });
+
+        return false;
+     });
+});
+</script>
diff --git a/include/staff/templates/org-delete.tmpl.php b/include/staff/templates/org-delete.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..17ab2bc6a94577e0967059c64050124ff2d910fa
--- /dev/null
+++ b/include/staff/templates/org-delete.tmpl.php
@@ -0,0 +1,56 @@
+<?php
+
+if (!$info['title'])
+    $info['title'] = 'Delete '.Format::htmlchars($org->getName());
+
+$info['warn'] = 'Deleted organization CANNOT be recovered';
+
+?>
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<hr/>
+<?php
+
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['warn']) {
+    echo sprintf('<p id="msg_warning">%s</p>', $info['warn']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+
+<div id="org-profile" style="margin:5px;">
+    <i class="icon-group icon-4x pull-left icon-border"></i>
+    <div><b> <?php echo Format::htmlchars($org->getName()); ?></b></div>
+    <table style="margin-top: 1em;">
+<?php foreach ($org->getDynamicData() as $entry) {
+?>
+    <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php
+         echo $entry->getForm()->get('title'); ?></strong></td></tr>
+<?php foreach ($entry->getAnswers() as $a) { ?>
+    <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label'));
+         ?>:</td>
+    <td style="border-bottom: 1px dotted #ccc"><?php echo $a->display(); ?></td>
+    </tr>
+<?php }
+}
+?>
+    </table>
+    <div class="clear"></div>
+    <hr>
+    <form method="delete" class="org"
+        action="#orgs/<?php echo $org->getId(); ?>/delete">
+        <input type="hidden" name="id" value="<?php echo $org->getId(); ?>" />
+        <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="reset" value="Reset">
+            <input type="button" name="cancel" class="close"
+                value="No, Cancel">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="submit" value="Yes, Delete">
+        </span>
+        </p>
+    </form>
+</div>
+<div class="clear"></div>
diff --git a/include/staff/templates/org-lookup.tmpl.php b/include/staff/templates/org-lookup.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7c82f5daa4f40149b2bd802df2eb3cb8b7374ee
--- /dev/null
+++ b/include/staff/templates/org-lookup.tmpl.php
@@ -0,0 +1,123 @@
+<?php
+
+if (!$info['title'])
+    $info['title'] = 'Organization Lookup';
+
+$msg_info = 'Search existing organizations or add a new one';
+if ($info['search'] === false)
+    $msg_info = 'Complete the form below to add a new organization';
+
+?>
+<div id="the-lookup-form">
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<hr/>
+<div><p id="msg_info"><i class="icon-info-sign"></i>&nbsp; <?php echo $msg_info; ?></p></div>
+<?php
+if ($info['search'] !== false) { ?>
+<div style="margin-bottom:10px;">
+    <input type="text" class="search-input" style="width:100%;"
+    placeholder="Search by name" id="org-search" autocorrect="off" autocomplete="off"/>
+</div>
+<?php
+}
+
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['warning']) {
+    echo sprintf('<p id="msg_warning">%s</p>', $info['warning']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+<div id="selected-org-info" style="display:<?php echo $org ? 'block' :'none'; ?>;margin:5px;">
+<form method="post" class="org" action="<?php echo $info['action'] ?: '#orgs/lookup'; ?>">
+    <input type="hidden" id="org-id" name="orgid" value="<?php echo $org ? $org->getId() : 0; ?>"/>
+    <i class="icon-group icon-4x pull-left icon-border"></i>
+    <a class="action-button pull-right" style="overflow:inherit"
+        id="unselect-org"  href="#"><i class="icon-remove"></i> Add New Organization</a>
+    <div><strong id="org-name"><?php echo $org ?  Format::htmlchars($org->getName()) : ''; ?></strong></div>
+<?php if ($org) { ?>
+    <table style="margin-top: 1em;">
+<?php foreach ($org->getDynamicData() as $entry) { ?>
+    <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php
+         echo $entry->getForm()->get('title'); ?></strong></td></tr>
+<?php foreach ($entry->getAnswers() as $a) { ?>
+    <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label'));
+         ?>:</td>
+    <td style="border-bottom: 1px dotted #ccc"><?php echo $a->display(); ?></td>
+    </tr>
+<?php }
+    } ?>
+   </table>
+ <?php
+  } ?>
+<div class="clear"></div>
+<hr>
+<p class="full-width">
+    <span class="buttons" style="float:left">
+        <input type="button" name="cancel" class="close"  value="Cancel">
+    </span>
+    <span class="buttons" style="float:right">
+        <input type="submit" value="Continue">
+    </span>
+ </p>
+</form>
+</div>
+<div id="new-org-form" style="display:<?php echo $org ? 'none' :'block'; ?>;">
+<form method="post" class="org" action="<?php echo $info['action'] ?: '#orgs/add'; ?>">
+    <table width="100%" class="fixed">
+    <?php
+        if (!$form) $form = OrganizationForm::getInstance();
+        $form->render(true, 'Create New Organization'); ?>
+    </table>
+    <hr>
+    <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="reset" value="Reset">
+            <input type="button" name="cancel" class="<?php echo $org ? 'cancel' : 'close' ?>"  value="Cancel">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="submit" value="Add Organization">
+        </span>
+     </p>
+</form>
+</div>
+<div class="clear"></div>
+</div>
+<script type="text/javascript">
+$(function() {
+    var last_req;
+    $('#org-search').typeahead({
+        source: function (typeahead, query) {
+            if (last_req) last_req.abort();
+            last_req = $.ajax({
+                url: "ajax.php/orgs/search?q="+query,
+                dataType: 'json',
+                success: function (data) {
+                    typeahead.process(data);
+                }
+            });
+        },
+        onselect: function (obj) {
+            $('#the-lookup-form').load(
+                '<?php echo $info['onselect'] ?: 'ajax.php/orgs/select'; ?>/'+encodeURIComponent(obj.id)
+            );
+        },
+        property: "/bin/true"
+    });
+
+    $('a#unselect-org').click( function(e) {
+        e.preventDefault();
+        $('div#selected-org-info').hide();
+        $('div#new-org-form').fadeIn({start: function(){ $('#org-search').focus(); }});
+        return false;
+     });
+
+    $(document).on('click', 'form.org input.cancel', function (e) {
+        e.preventDefault();
+        $('div#new-org-form').hide();
+        $('div#selected-org-info').fadeIn({start: function(){ $('#org-search').focus(); }});
+        return false;
+     });
+});
+</script>
diff --git a/include/staff/templates/org.tmpl.php b/include/staff/templates/org.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..b1d58427a0b46c7245c5263bc319839c608cd5eb
--- /dev/null
+++ b/include/staff/templates/org.tmpl.php
@@ -0,0 +1,88 @@
+<?php
+if (!$info['title'])
+    $info['title'] = Format::htmlchars($org->getName());
+?>
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<hr/>
+<?php
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+<div id="org-profile" style="display:<?php echo $forms ? 'none' : 'block'; ?>;margin:5px;">
+    <i class="icon-group icon-4x pull-left icon-border"></i>
+    <?php
+    if ($account) { ?>
+    <a class="action-button pull-right user-action" style="overflow:inherit"
+        href="#users/<?php echo $account->getUserId(); ?>/org/<?php echo $org->getId(); ?>" ><i class="icon-user"></i> Change Organization</a>
+    <?php
+    } ?>
+    <div><b><a href="#" id="editorg"><i class="icon-edit"></i>&nbsp;<?php
+    echo Format::htmlchars($org->getName()); ?></a></b></div>
+    <table style="margin-top: 1em;">
+<?php foreach ($org->getDynamicData() as $entry) {
+?>
+    <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php
+         echo $entry->getForm()->get('title'); ?></strong></td></tr>
+<?php foreach ($entry->getAnswers() as $a) { ?>
+    <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label'));
+         ?>:</td>
+    <td style="border-bottom: 1px dotted #ccc"><?php echo $a->display(); ?></td>
+    </tr>
+<?php }
+}
+?>
+    </table>
+    <div class="clear"></div>
+    <hr>
+    <div class="faded">Last updated <b><?php echo Format::db_datetime($org->getUpdateDate()); ?> </b></div>
+</div>
+<div id="org-form" style="display:<?php echo $forms ? 'block' : 'none'; ?>;">
+<div><p id="msg_info"><i class="icon-info-sign"></i>&nbsp; Please note that updates will be reflected system-wide.</p></div>
+<?php
+$action = $info['action'] ? $info['action'] : ('#orgs/'.$org->getId());
+if ($ticket && $ticket->getOwnerId() == $user->getId())
+    $action = '#tickets/'.$ticket->getId().'/user';
+?>
+<form method="post" class="org" action="<?php echo $action; ?>">
+    <input type="hidden" name="id" value="<?php echo $org->getId(); ?>" />
+    <table width="100%">
+    <?php
+        if (!$forms) $forms = $org->getForms();
+        foreach ($forms as $form)
+            $form->render();
+    ?>
+    </table>
+    <hr>
+    <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="reset" value="Reset">
+            <input type="button" name="cancel" class="<?php
+    echo $account ? 'cancel' : 'close'; ?>"  value="Cancel">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="submit" value="Update Organization">
+        </span>
+     </p>
+</form>
+</div>
+<div class="clear"></div>
+<script type="text/javascript">
+$(function() {
+    $('a#editorg').click( function(e) {
+        e.preventDefault();
+        $('div#org-profile').hide();
+        $('div#org-form').fadeIn();
+        return false;
+     });
+
+    $(document).on('click', 'form.org input.cancel', function (e) {
+        e.preventDefault();
+        $('div#org-form').hide();
+        $('div#org-profile').fadeIn();
+        return false;
+     });
+});
+</script>
diff --git a/include/staff/templates/tickets.tmpl.php b/include/staff/templates/tickets.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdd5625786e86815aca2540e6955e5bae92517df
--- /dev/null
+++ b/include/staff/templates/tickets.tmpl.php
@@ -0,0 +1,174 @@
+<?php
+
+$select ='SELECT ticket.ticket_id,ticket.`number`,ticket.dept_id,ticket.staff_id,ticket.team_id, ticket.user_id '
+        .' ,dept.dept_name,ticket.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_id, cdata.subject, user.name, email.address as email';
+
+$from =' FROM '.TICKET_TABLE.' ticket '
+      .' 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.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_id)';
+
+if ($user)
+    $where = 'WHERE ticket.user_id = '.db_input($user->getId());
+elseif ($org)
+    $where = 'WHERE account.org_id = '.db_input($org->getId());
+
+
+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.attach_id) as attachments,
+        count(DISTINCT thread.id) as thread_count,
+        count(DISTINCT collab.id) as collaborators
+        FROM '.TICKET_TABLE.' ticket
+        LEFT JOIN '.TICKET_ATTACHMENT_TABLE.' attach ON (ticket.ticket_id=attach.ticket_id) '
+     .' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON ( ticket.ticket_id=thread.ticket_id) '
+     .' LEFT JOIN '.TICKET_COLLABORATOR_TABLE.' collab
+            ON ( ticket.ticket_id=collab.ticket_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;
+    }
+}
+?>
+<div style="width:700px; float:left;">
+   <?php
+    if ($results) {
+        echo  sprintf('<strong>Showing 1 - %d of %s</strong>', count($results), count($results));
+    } else {
+        echo sprintf('%s does not have any tickets', $user? 'User' : 'Organization');
+    }
+   ?>
+</div>
+<div style="float:right;text-align:right;padding-right:5px;">
+    <?php
+    if ($user) { ?>
+    <b><a class="Icon newTicket" href="tickets.php?a=open&uid=<?php echo $user->getId(); ?>"> Create New Ticket</a></b>
+    <?php
+    } ?>
+</div>
+<br/>
+<div>
+<?php
+if ($results) { ?>
+<form action="users.php" method="POST" name='tickets' style="padding-top:10px;">
+<?php csrf_token(); ?>
+ <input type="hidden" name="a" value="mass_process" >
+ <input type="hidden" name="do" id="action" value="" >
+ <table class="list" border="0" cellspacing="1" cellpadding="2" width="940">
+    <thead>
+        <tr>
+            <?php
+            if (0) {?>
+            <th width="8px">&nbsp;</th>
+            <?php
+            } ?>
+            <th width="70">Ticket</th>
+            <th width="100">Date</th>
+            <th width="100">Status</th>
+            <th width="300">Subject</th>
+            <?php
+            if ($user) { ?>
+            <th width="200">Department</th>
+            <th width="200">Assignee</th>
+            <?php
+            } else { ?>
+            <th width="400">User</th>
+            <?php
+            } ?>
+        </tr>
+    </thead>
+    <tbody>
+    <?php
+    foreach($results as $row) {
+        $flag=null;
+        if ($row['lock_id'])
+            $flag='locked';
+        elseif ($row['isoverdue'])
+            $flag='overdue';
+
+        $assigned='';
+        if ($row['staff_id'])
+            $assigned=sprintf('<span class="Icon staffAssigned">%s</span>',Format::truncate($row['staff'],40));
+        elseif ($row['team_id'])
+            $assigned=sprintf('<span class="Icon teamAssigned">%s</span>',Format::truncate($row['team'],40));
+        else
+            $assigned=' ';
+
+        $status = ucfirst($row['status']);
+        if(!strcasecmp($row['status'], 'open'))
+            $status = "<b>$status</b>";
+
+        $tid=$row['number'];
+        $subject = Format::htmlchars(Format::truncate($row['subject'],40));
+        $threadcount=$row['thread_count'];
+        ?>
+        <tr id="<?php echo $row['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"':''; ?>>
+            </td>
+            <?php
+            } ?>
+            <td align="center" nowrap>
+              <a class="Icon <?php echo strtolower($row['source']); ?>Ticket ticketPreview" title="Preview Ticket"
+                href="tickets.php?id=<?php echo $row['ticket_id']; ?>"><?php echo $tid; ?></a></td>
+            <td align="center" nowrap><?php echo Format::db_datetime($row['effective_date']); ?></td>
+            <td><?php echo $status; ?></td>
+            <td><a <?php if ($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?>
+                href="tickets.php?id=<?php echo $row['ticket_id']; ?>"><?php echo $subject; ?></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 ($row['attachments'])
+                        echo '<i class="icon-fixed-width icon-paperclip"></i>&nbsp;';
+                ?>
+            </td>
+            <?php
+            if ($user) { ?>
+            <td><?php echo Format::truncate($row['dept_name'], 40); ?></td>
+            <td>&nbsp;<?php echo $assigned; ?></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>
+            <?php
+            } ?>
+        </tr>
+   <?php
+    }
+    ?>
+    </tbody>
+</table>
+</form>
+<?php
+ } ?>
+</div>
diff --git a/include/staff/templates/user-account.tmpl.php b/include/staff/templates/user-account.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..5a08e8e4cf3696c44efbdcd59d3a5530b7850dfd
--- /dev/null
+++ b/include/staff/templates/user-account.tmpl.php
@@ -0,0 +1,173 @@
+<?php
+$account = $user->getAccount();
+$access = (isset($info['_target']) && $info['_target'] == 'access');
+
+if (!$info['title'])
+    $info['title'] = Format::htmlchars($user->getName());
+?>
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<div class="clear"></div>
+<hr/>
+<?php
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+<ul class="tabs">
+    <li><a href="#user-account" <?php echo !$access? 'class="active"' : ''; ?>
+        ><i class="icon-user"></i>&nbsp;User Information</a></li>
+    <li><a href="#user-access" <?php echo $access? 'class="active"' : ''; ?>
+        ><i class="icon-fixed-width icon-lock faded"></i>&nbsp;Manage Access</a></li>
+</ul>
+
+
+<form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" >
+ <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" />
+ <div class="tab_content"  id="user-account" style="display:<?php echo $access? 'none' : 'block'; ?>; margin:5px;">
+    <form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" >
+        <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" />
+        <table width="100%">
+        <tbody>
+            <tr>
+                <th colspan="2">
+                    <em><strong>User Information</strong></em>
+                </th>
+            </tr>
+            <tr>
+                <td width="180">
+                    Name:
+                </td>
+                <td> <?php echo $user->getName(); ?> </td>
+            </tr>
+            <tr>
+                <td width="180">
+                    Email:
+                </td>
+                <td> <?php echo $user->getEmail(); ?> </td>
+            </tr>
+            <tr>
+                <td width="180">
+                    Organization:
+                </td>
+                <td>
+                    <input type="text" size="35" name="org" value="<?php echo $info['org']; ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo $errors['org']; ?></span>
+                </td>
+            </tr>
+        </tbody>
+        <tbody>
+            <tr>
+                <th colspan="2"><em><strong>User Preferences</strong></em></th>
+            </tr>
+                <td>Time Zone:</td>
+                <td>
+                    <select name="timezone_id" id="timezone_id">
+                        <?php
+                        $sql='SELECT id, offset,timezone FROM '.TIMEZONE_TABLE.' ORDER BY id';
+                        if(($res=db_query($sql)) && db_num_rows($res)){
+                            while(list($id,$offset, $tz)=db_fetch_row($res)){
+                                $sel=($info['timezone_id']==$id)?'selected="selected"':'';
+                                echo sprintf('<option value="%d" %s>GMT %s - %s</option>',$id,$sel,$offset,$tz);
+                            }
+                        }
+                        ?>
+                    </select>
+                    &nbsp;<span class="error"><?php echo $errors['timezone_id']; ?></span>
+                </td>
+            </tr>
+            <tr>
+                <td width="180">
+                   Daylight Saving:
+                </td>
+                <td>
+                    <input type="checkbox" name="dst" value="1" <?php echo $info['dst']?'checked="checked"':''; ?>>
+                    Observe daylight saving
+                </td>
+            </tr>
+        </tbody>
+        </table>
+ </div>
+ <div class="tab_content"  id="user-access" style="display:<?php echo $access? 'block' : 'none'; ?>; margin:5px;">
+        <table width="100%">
+        <tbody>
+            <tr>
+                <th colspan="2"><em><strong>Account Access</strong></em></th>
+            </tr>
+            <tr>
+                <td width="180"> Status: </td>
+                <td> <?php echo $user->getAccountStatus(); ?> </td>
+            </tr>
+            <tr>
+                <td width="180">
+                    Username:
+                </td>
+                <td>
+                    <input type="text" size="35" name="username" value="<?php echo $info['username'] ?: $user->getEmail(); ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo $errors['username']; ?></span>
+                </td>
+            </tr>
+            <tr>
+                <td width="180">
+                    New Password:
+                </td>
+                <td>
+                    <input type="password" size="35" name="passwd1" value="<?php echo $info['passwd1']; ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo
+                    $errors['passwd1']; ?></span>
+                </td>
+            </tr>
+            <tr>
+                <td width="180">
+                   Confirm Password:
+                </td>
+                <td>
+                    <input type="password" size="35" name="passwd2" value="<?php echo $info['passwd2']; ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo $errors['passwd2']; ?></span>
+                </td>
+            </tr>
+        </tbody>
+        <tbody>
+            <tr>
+                <th colspan="2"><em><strong>Account Flags</strong></em></th>
+            </tr>
+            <tr>
+                <td colspan="2">
+                <?php
+                  echo sprintf('<div><input type="checkbox" name="locked-flag" %s
+                       value="1"> Administratively Locked</div>',
+                       $account->isLocked() ?  'checked="checked"' : ''
+                       );
+                  ?>
+                   <div><input type="checkbox" name="pwreset-flag" value="1" <?php
+                    echo $account->isPasswdResetForced() ?
+                    'checked="checked"' : ''; ?>> Password Reset Required</div>
+                </td>
+            </tr>
+        </tbody>
+        </table>
+   </div>
+   <hr>
+   <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="reset" value="Reset">
+            <input type="button" name="cancel" class="close" value="Cancel">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="submit"
+                value="Save Changes">
+        </span>
+    </p>
+</form>
+<div class="clear"></div>
+<script type="text/javascript">
+$(function() {
+    $(document).on('click', 'input#sendemail', function(e) {
+        if ($(this).prop('checked'))
+            $('tbody#password').hide();
+        else
+            $('tbody#password').show();
+    });
+});
+</script>
diff --git a/include/staff/templates/user-delete.tmpl.php b/include/staff/templates/user-delete.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..661bfa70ee08148f1291238337edbf686ccdd77c
--- /dev/null
+++ b/include/staff/templates/user-delete.tmpl.php
@@ -0,0 +1,93 @@
+<?php
+
+if (!$info['title'])
+    $info['title'] = 'Delete User: '.Format::htmlchars($user->getName());
+
+$info['warn'] = 'Deleted users and tickets CANNOT be recovered';
+
+?>
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<hr/>
+<?php
+
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['warn']) {
+    echo sprintf('<p id="msg_warning">%s</p>', $info['warn']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+
+<div id="user-profile" style="margin:5px;">
+    <i class="icon-user icon-4x pull-left icon-border"></i>
+    <?php
+    // TODO: Implement change of ownership
+    if (0 && $user->getNumTickets()) { ?>
+    <a class="action-button pull-right change-user" style="overflow:inherit"
+        href="#users/<?php echo $user->getId(); ?>/replace" ><i
+        class="icon-user"></i> Change Tickets Ownership</a>
+    <?php
+    } ?>
+    <div><b> <?php echo Format::htmlchars($user->getName()->getOriginal()); ?></b></div>
+    <div>&lt;<?php echo $user->getEmail(); ?>&gt;</div>
+    <table style="margin-top: 1em;">
+<?php foreach ($user->getDynamicData() as $entry) {
+?>
+    <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php
+         echo $entry->getForm()->get('title'); ?></strong></td></tr>
+<?php foreach ($entry->getAnswers() as $a) { ?>
+    <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label'));
+         ?>:</td>
+    <td style="border-bottom: 1px dotted #ccc"><?php echo $a->display(); ?></td>
+    </tr>
+<?php }
+}
+?>
+    </table>
+    <div class="clear"></div>
+    <hr>
+    <?php
+    if ($user->getNumTickets()) {
+        echo sprintf('<div><input type="checkbox" name="deletetickets" value="1" >
+            <strong>Delete <a href="tickets.php?a=search&uid=%d" target="_blank">%d
+            %s</a> and any associated attachments and data.</strong></div><hr>',
+            $user->getId(),
+            $user->getNumTickets(),
+            ($user->getNumTickets() >1) ? 'tickets' : 'ticket'
+            );
+    }
+    ?>
+    <form method="delete" class="user"
+        action="#users/<?php echo $user->getId(); ?>/delete">
+        <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" />
+        <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="reset" value="Reset">
+            <input type="button" name="cancel" class="close"
+                value="No, Cancel">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="submit" value="Yes, Delete User">
+        </span>
+        </p>
+    </form>
+</div>
+<div class="clear"></div>
+<script type="text/javascript">
+$(function() {
+    $('a#edituser').click( function(e) {
+        e.preventDefault();
+        $('div#user-profile').hide();
+        $('div#user-form').fadeIn();
+        return false;
+     });
+
+    $(document).on('click', 'form.user input.cancel', function (e) {
+        e.preventDefault();
+        $('div#user-form').hide();
+        $('div#user-profile').fadeIn();
+        return false;
+     });
+});
+</script>
diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php
index 3604ed5a29ddff2246343d69a41a32a9cad810fc..39a617e01d4672c661cd65a2699d559c202dcb68 100644
--- a/include/staff/templates/user-lookup.tmpl.php
+++ b/include/staff/templates/user-lookup.tmpl.php
@@ -3,7 +3,11 @@
 <b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
 <hr/>
 <div><p id="msg_info"><i class="icon-info-sign"></i>&nbsp; Search existing users or add a new user.</p></div>
-<div style="margin-bottom:10px;"><input type="text" class="search-input" style="width:100%;" placeholder="Search by email, phone or name" id="user-search" autocorrect="off" autocomplete="off"/></div>
+<div style="margin-bottom:10px;">
+    <input type="text" class="search-input" style="width:100%;"
+    placeholder="Search by email, phone or name" id="user-search"
+    autocorrect="off" autocomplete="off"/>
+</div>
 <?php
 if ($info['error']) {
     echo sprintf('<p id="msg_error">%s</p>', $info['error']);
@@ -73,7 +77,8 @@ $(function() {
         source: function (typeahead, query) {
             if (last_req) last_req.abort();
             last_req = $.ajax({
-                url: "ajax.php/users?q="+query,
+                url: "ajax.php/users<?php
+                    echo $info['lookuptype'] ? "/{$info['lookuptype']}" : '' ?>?q="+query,
                 dataType: 'json',
                 success: function (data) {
                     typeahead.process(data);
diff --git a/include/staff/templates/user-register.tmpl.php b/include/staff/templates/user-register.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f87c41a3453add53001dc3d1bf62f2671a07bf4
--- /dev/null
+++ b/include/staff/templates/user-register.tmpl.php
@@ -0,0 +1,149 @@
+<?php
+global $cfg;
+
+if (!$info['title'])
+    $info['title'] = 'Register: '.Format::htmlchars($user->getName());
+
+if (!$_POST) {
+
+    $info['sendemail'] = true; // send email confirmation.
+
+    if (!isset($info['timezone_id']))
+        $info['timezone_id'] = $cfg->getDefaultTimezoneId();
+
+    if (!isset($info['dst']))
+        $info['dst'] = $cfg->observeDaylightSaving();
+}
+
+?>
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<div class="clear"></div>
+<hr/>
+<?php
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} ?>
+<div><p id="msg_info"><i class="icon-info-sign"></i>&nbsp;Complete the form
+below to create a user account for <b><?php echo
+$user->getName()->getOriginal(); ?></b>.</p></div>
+<div id="user-registration" style="display:block; margin:5px;">
+    <form method="post" class="user"
+        action="#users/<?php echo $user->getId(); ?>/register">
+        <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" />
+        <table width="100%">
+        <tbody>
+            <tr>
+                <th colspan="2">
+                    <em><strong>User Account Login</strong></em>
+                </th>
+            </tr>
+            <tr>
+                <td width="180">
+                    Status:
+                </td>
+                <td>
+                  <input type="checkbox" id="sendemail" name="sendemail" value="1"
+                    <?php echo $info['sendemail'] ? 'checked="checked"' : ''; ?> >
+                    Send account activation email to <?php echo $user->getEmail(); ?>.
+                </td>
+            </tr>
+            <tr>
+                <td width="180">
+                    Username:
+                </td>
+                <td>
+                    <input type="text" size="35" name="username" value="<?php echo $info['username'] ?: $user->getEmail(); ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo $errors['username']; ?></span>
+                </td>
+            </tr>
+        </tbody>
+        <tbody id="password"
+            style="<?php echo $info['sendemail'] ? 'display:none;' : ''; ?>"
+            >
+            <tr>
+                <td width="180">
+                    Temp. Password:
+                </td>
+                <td>
+                    <input type="password" size="35" name="passwd1" value="<?php echo $info['passwd1']; ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo
+                    $errors['passwd1']; ?></span>
+                </td>
+            </tr>
+            <tr>
+                <td width="180">
+                   Confirm Password:
+                </td>
+                <td>
+                    <input type="password" size="35" name="passwd2" value="<?php echo $info['passwd2']; ?>">
+                    &nbsp;<span class="error">&nbsp;<?php echo $errors['passwd2']; ?></span>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    Password Change:
+                </td>
+                <td colspan=2>
+                    <input type="checkbox" name="pwreset-flag" value="1" <?php
+                        echo $info['pwreset-flag'] ?  'checked="checked"' : ''; ?>> Require password change on login
+                </td>
+            </tr>
+        </tbody>
+        <tbody>
+            <tr>
+                <th colspan="2"><em><strong>User Preferences</strong></em></th>
+            </tr>
+                <td>Time Zone:</td>
+                <td>
+                    <select name="timezone_id" id="timezone_id">
+                        <?php
+                        $sql='SELECT id, offset, timezone FROM '.TIMEZONE_TABLE.' ORDER BY id';
+                        if(($res=db_query($sql)) && db_num_rows($res)){
+                            while(list($id, $offset, $tz) = db_fetch_row($res)) {
+                                $sel=($info['timezone_id']==$id) ? 'selected="selected"' : '';
+                                echo sprintf('<option value="%d" %s>GMT %s - %s</option>',
+                                        $id, $sel, $offset, $tz);
+                            }
+                        }
+                        ?>
+                    </select>
+                    &nbsp;<span class="error"><?php echo $errors['timezone_id']; ?></span>
+                </td>
+            </tr>
+            <tr>
+                <td width="180">
+                   Daylight Saving:
+                </td>
+                <td>
+                    <input type="checkbox" name="dst" value="1" <?php echo $info['dst'] ? 'checked="checked"' : ''; ?>>
+                    Observe daylight saving
+                </td>
+            </tr>
+        </tbody>
+        </table>
+        <hr>
+        <p class="full-width">
+            <span class="buttons" style="float:left">
+                <input type="reset" value="Reset">
+                <input type="button" name="cancel" class="close" value="Cancel">
+            </span>
+            <span class="buttons" style="float:right">
+                <input type="submit" value="Create Account">
+            </span>
+         </p>
+    </form>
+</div>
+<div class="clear"></div>
+<script type="text/javascript">
+$(function() {
+    $(document).on('click', 'input#sendemail', function(e) {
+        if ($(this).prop('checked'))
+            $('tbody#password').hide();
+        else
+            $('tbody#password').show();
+    });
+});
+</script>
diff --git a/include/staff/templates/users.tmpl.php b/include/staff/templates/users.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b22d3db9ed111fb2a9ba72b86e3f4558e8e57f1
--- /dev/null
+++ b/include/staff/templates/users.tmpl.php
@@ -0,0 +1,131 @@
+<?php
+
+$qstr='';
+$select = 'SELECT user.*, email.address as email ';
+
+$from = 'FROM '.USER_TABLE.' user '
+      . 'LEFT JOIN '.USER_ACCOUNT_TABLE.' account ON (user.id = account.user_id) '
+      . 'LEFT JOIN '.USER_EMAIL_TABLE.' email ON (user.id = email.user_id) ';
+
+$where='WHERE account.org_id='.db_input($org->getId());
+
+
+$sortOptions = array('name' => 'user.name',
+                     'email' => 'email.address',
+                     'create' => 'user.created',
+                     'update' => 'user.updated');
+$orderWays = array('DESC'=>'DESC','ASC'=>'ASC');
+$sort= ($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])]) ? strtolower($_REQUEST['sort']) : 'name';
+//Sorting options...
+if ($sort && $sortOptions[$sort])
+    $order_column =$sortOptions[$sort];
+
+$order_column = $order_column ?: 'user.name';
+
+if ($_REQUEST['order'] && $orderWays[strtoupper($_REQUEST['order'])])
+    $order = $orderWays[strtoupper($_REQUEST['order'])];
+
+$order=$order ?: 'ASC';
+if ($order_column && strpos($order_column,','))
+    $order_column = str_replace(','," $order,",$order_column);
+
+$x=$sort.'_sort';
+$$x=' class="'.strtolower($order).'" ';
+$order_by="$order_column $order ";
+
+$total=db_count('SELECT count(DISTINCT user.id) '.$from.' '.$where);
+$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
+$pageNav=new Pagenate($total,$page,PAGE_LIMIT);
+$pageNav->setURL('users.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
+//Ok..lets roll...create the actual query
+$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
+
+$select .= ', count(DISTINCT ticket.ticket_id) as tickets ';
+
+$from .= ' LEFT JOIN '.TICKET_TABLE.' ticket ON (ticket.user_id = user.id) ';
+
+
+$query="$select $from $where GROUP BY user.id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
+//echo $query;
+
+$showing = $search ? 'Search Results: ' : '';
+$res = db_query($query);
+if($res && ($num=db_num_rows($res)))
+    $showing .= $pageNav->showing();
+else
+    $showing .= 'No users found!';
+
+?>
+<div style="width:700px; float:left;"><b><?php echo $showing; ?></b></div>
+<div style="float:right;text-align:right;padding-right:5px;">
+    <b><a href="#orgs/<?php echo $org->getId(); ?>/add-user" class="Icon newstaff add-user">Add New User</a></b></div>
+<div class="clear"></div>
+<br/>
+<form action="users.php" method="POST" name="staff" >
+ <?php csrf_token(); ?>
+ <input type="hidden" name="do" value="mass_process" >
+ <input type="hidden" id="action" name="a" value="" >
+ <table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
+    <thead>
+        <tr>
+            <th width="350"> Name</th>
+            <th width="300"> Email</th>
+            <th width="100"> Status</th>
+            <th width="100"> Created</th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php
+        if($res && db_num_rows($res)):
+            $ids=($errors && is_array($_POST['ids']))?$_POST['ids']:null;
+            while ($row = db_fetch_array($res)) {
+
+                $name = new PersonsName($row['name']);
+                $status = 'Active';
+                $sel=false;
+                if($ids && in_array($row['id'], $ids))
+                    $sel=true;
+                ?>
+               <tr id="<?php echo $row['id']; ?>">
+                <td>&nbsp;
+                    <a href="users.php?id=<?php echo $row['id']; ?>"><?php echo $name; ?></a>
+                    &nbsp;
+                    <?php
+                    if ($row['tickets'])
+                         echo sprintf('<i class="icon-fixed-width icon-file-text-alt"></i>
+                             <small>(%d)</small>', $row['tickets']);
+                    ?>
+                </td>
+                <td><?php echo $row['email']; ?></td>
+                <td><?php echo $status; ?></td>
+                <td><?php echo Format::db_date($row['created']); ?></td>
+               </tr>
+            <?php
+            } //end of while.
+        endif; ?>
+    <tfoot>
+     <tr>
+        <td colspan="4"> &nbsp; </td>
+     </tr>
+    </tfoot>
+</table>
+<?php
+if($res && $num): //Show options..
+    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
+endif;
+?>
+</form>
+
+<script type="text/javascript">
+$(function() {
+    $(document).on('click', 'a.add-user', function(e) {
+        e.preventDefault();
+        $.userLookup('ajax.php/users/add', function (user) {
+            window.location.href = 'users.php?id='+user.id;
+         });
+
+        return false;
+     });
+});
+</script>
+
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 9568dbf656c5513a28980f101ee35089368643f3..fc636f515dee5388adaa6ee20d554137238f3b0a 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -54,7 +54,7 @@ if($ticket->isOverdue())
             <?php
             } ?>
             <?php if($thisstaff->canDeleteTickets()) { ?>
-                <a id="ticket-delete" class="action-button" href="#delete"><i class="icon-trash"></i> Delete</a>
+                <a id="ticket-delete" class="action-button confirm-action" href="#delete"><i class="icon-trash"></i> Delete</a>
             <?php } ?>
             <?php
             if($thisstaff->canCloseTickets()) {
@@ -74,7 +74,7 @@ if($ticket->isOverdue())
             } ?>
             <?php
             if($ticket->isOpen() && !$ticket->isAssigned() && $thisstaff->canAssignTickets()) {?>
-                <a id="ticket-claim" class="action-button" href="#claim"><i class="icon-user"></i> Claim</a>
+                <a id="ticket-claim" class="action-button confirm-action" href="#claim"><i class="icon-user"></i> Claim</a>
 
             <?php
             }?>
@@ -91,30 +91,32 @@ if($ticket->isOverdue())
                 if($ticket->isOpen() && ($dept && $dept->isManager($thisstaff))) {
 
                     if($ticket->isAssigned()) { ?>
-                        <li><a id="ticket-release" href="#release"><i class="icon-user"></i> Release (unassign) Ticket</a></li>
+                        <li><a  class="confirm-action" id="ticket-release" href="#release"><i class="icon-user"></i> Release (unassign) Ticket</a></li>
                     <?php
                     }
 
                     if(!$ticket->isOverdue()) { ?>
-                        <li><a id="ticket-overdue" href="#overdue"><i class="icon-bell"></i> Mark as Overdue</a></li>
+                        <li><a class="confirm-action" id="ticket-overdue" href="#overdue"><i class="icon-bell"></i> Mark as Overdue</a></li>
                     <?php
                     }
 
                     if($ticket->isAnswered()) { ?>
-                        <li><a id="ticket-unanswered" href="#unanswered"><i class="icon-circle-arrow-left"></i> Mark as Unanswered</a></li>
+                        <li><a class="confirm-action" id="ticket-unanswered" href="#unanswered"><i class="icon-circle-arrow-left"></i> Mark as Unanswered</a></li>
                     <?php
                     } else { ?>
-                        <li><a id="ticket-answered" href="#answered"><i class="icon-circle-arrow-right"></i> Mark as Answered</a></li>
+                        <li><a class="confirm-action" id="ticket-answered" href="#answered"><i class="icon-circle-arrow-right"></i> Mark as Answered</a></li>
                     <?php
                     }
                 }
 
                 if($thisstaff->canBanEmails()) {
                      if(!$emailBanned) {?>
-                        <li><a id="ticket-banemail" href="#banemail"><i class="icon-ban-circle"></i> Ban Email (<?php echo $ticket->getEmail(); ?>)</a></li>
+                        <li><a class="confirm-action" id="ticket-banemail"
+                            href="#banemail"><i class="icon-ban-circle"></i> Ban Email (<?php echo $ticket->getEmail(); ?>)</a></li>
                 <?php
                      } elseif($unbannable) { ?>
-                        <li><a id="ticket-banemail" href="#unbanemail"><i class="icon-undo"></i> Unban Email (<?php echo $ticket->getEmail(); ?>)</a></li>
+                        <li><a  class="confirm-action" id="ticket-banemail"
+                            href="#unbanemail"><i class="icon-undo"></i> Unban Email (<?php echo $ticket->getEmail(); ?>)</a></li>
                     <?php
                      }
                 }?>
diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..5ad4478c7fea8e9954a304eef9fffc4a1bd130a6
--- /dev/null
+++ b/include/staff/user-view.inc.php
@@ -0,0 +1,180 @@
+<?php
+if(!defined('OSTSCPINC') || !$thisstaff || !is_object($user)) die('Invalid path');
+
+$account = $user->getAccount();
+$org = $account ? $account->getOrganization() : null;
+
+
+?>
+<table width="940" cellpadding="2" cellspacing="0" border="0">
+    <tr>
+        <td width="50%" class="has_bottom_border">
+             <h2><a href="users.php?id=<?php echo $user->getId(); ?>"
+             title="Reload"><i class="icon-refresh"></i> <?php echo $user->getName(); ?></a></h2>
+        </td>
+        <td width="50%" class="right_align has_bottom_border">
+           <?php
+            if ($account) { ?>
+            <span class="action-button" data-dropdown="#action-dropdown-more">
+                <span ><i class="icon-cog"></i> More</span>
+                <i class="icon-caret-down"></i>
+            </span>
+            <?php
+            } ?>
+            <a id="user-delete" class="action-button user-action"
+            href="#users/<?php echo $user->getId(); ?>/delete"><i class="icon-trash"></i> Delete User</a>
+            <?php
+            if ($account) { ?>
+            <a id="user-manage" class="action-button user-action"
+            href="#users/<?php echo $user->getId(); ?>/manage"><i class="icon-edit"></i> Manage Account</a>
+            <?php
+            } else { ?>
+            <a id="user-register" class="action-button user-action"
+            href="#users/<?php echo $user->getId(); ?>/register"><i class="icon-edit"></i> Register</a>
+            <?php
+            } ?>
+            <div id="action-dropdown-more" class="action-dropdown anchor-right">
+              <ul>
+                <?php
+                if ($account) {
+                    if (!$account->isConfirmed()) {
+                        ?>
+                    <li><a class="confirm-action" href="#confirmlink"><i
+                        class="icon-envelope"></i> Send Activation Email</a></li>
+                    <?php
+                    } else { ?>
+                    <li><a class="confirm-action" href="#pwreset"><i
+                        class="icon-envelope"></i> Send Password Reset Email</a></li>
+                    <?php
+                    } ?>
+                    <li><a class="user-action"
+                        href="#users/<?php echo $user->getId(); ?>/manage/access"><i
+                        class="icon-lock"></i> Manage Account Access</a></li>
+                <?php
+
+                } ?>
+              </ul>
+            </div>
+        </td>
+    </tr>
+</table>
+<table class="ticket_info" cellspacing="0" cellpadding="0" width="940" border="0">
+    <tr>
+        <td width="50">
+            <table border="0" cellspacing="" cellpadding="4" width="100%">
+                <tr>
+                    <th width="100">Name:</th>
+                    <td><b><a href="#users/<?php echo $user->getId();
+                    ?>/edit" class="user-action"><i
+                    class="icon-edit"></i>&nbsp;<?php echo
+                    $user->getName()->getOriginal();
+                    ?></a></td>
+                </tr>
+                <tr>
+                    <th>Email:</th>
+                    <td>
+                        <span id="user-<?php echo $user->getId(); ?>-email"><?php echo $user->getEmail(); ?></span>
+                    </td>
+                </tr>
+                <tr>
+                    <th>Organization:</th>
+                    <td>
+                        <span id="user-<?php echo $user->getId(); ?>-org">
+                        <?php
+                            if ($org)
+                                echo sprintf('<a href="#users/%d/org"
+                                        class="user-action">%s</a>',
+                                        $user->getId(), $org->getName());
+                            elseif ($account)
+                                echo sprintf('<a href="#users/%d/org"
+                                        class="user-action">Add Organization</a>',
+                                        $user->getId());
+                            else
+                                echo '&nbsp;';
+                        ?>
+                        </span>
+                    </td>
+                </tr>
+            </table>
+        </td>
+        <td width="50%" style="vertical-align:top">
+            <table border="0" cellspacing="" cellpadding="4" width="100%">
+                <tr>
+                    <th>Status:</th>
+                    <td> <span id="user-<?php echo $user->getId();
+                    ?>-status"><?php echo $user->getAccountStatus(); ?></span></td>
+                </tr>
+                <tr>
+                    <th>Created:</th>
+                    <td><?php echo Format::db_datetime($user->getCreateDate()); ?></td>
+                </tr>
+                <tr>
+                    <th>Updated:</th>
+                    <td><?php echo Format::db_datetime($user->getUpdateDate()); ?></td>
+                </tr>
+            </table>
+        </td>
+    </tr>
+</table>
+<br>
+<div class="clear"></div>
+<ul class="tabs">
+    <li><a class="active" id="tickets_tab" href="#tickets"><i
+    class="icon-list-alt"></i>&nbsp;User Tickets</a></li>
+</ul>
+<div id="tickets">
+<?php
+include STAFFINC_DIR . 'templates/tickets.tmpl.php';
+?>
+</div>
+
+<div style="display:none;" class="dialog" id="confirm-action">
+    <h3>Please Confirm</h3>
+    <a class="close" href=""><i class="icon-remove-circle"></i></a>
+    <hr/>
+    <p class="confirm-action" style="display:none;" id="banemail-confirm">
+        Are you sure want to <b>ban</b> <?php echo $user->getEmail(); ?>? <br><br>
+        New tickets from the email address will be auto-rejected.
+    </p>
+    <p class="confirm-action" style="display:none;" id="confirmlink-confirm">
+        Are you sure want to send <b>Account Activation Link</b> to <em><?php echo $user->getEmail()?></em>?
+    </p>
+    <p class="confirm-action" style="display:none;" id="pwreset-confirm">
+        Are you sure want to send <b>Password Reset Link</b> to <em><?php echo $user->getEmail()?></em>?
+    </p>
+    <div>Please confirm to continue.</div>
+    <form action="users.php?id=<?php echo $user->getId(); ?>" method="post" id="confirm-form" name="confirm-form">
+        <?php csrf_token(); ?>
+        <input type="hidden" name="id" value="<?php echo $user->getId(); ?>">
+        <input type="hidden" name="a" value="process">
+        <input type="hidden" name="do" id="action" value="">
+        <hr style="margin-top:1em"/>
+        <p class="full-width">
+            <span class="buttons" style="float:left">
+                <input type="button" value="Cancel" class="close">
+            </span>
+            <span class="buttons" style="float:right">
+                <input type="submit" value="OK">
+            </span>
+         </p>
+    </form>
+    <div class="clear"></div>
+</div>
+
+<script type="text/javascript">
+$(function() {
+    $(document).on('click', 'a.user-action', function(e) {
+        e.preventDefault();
+        var url = 'ajax.php/'+$(this).attr('href').substr(1);
+        $.dialog(url, [201, 204], function (xhr) {
+            if (xhr.status == 204)
+                window.location.href = 'users.php';
+            else
+                window.location.href = window.location.href;
+         }, {
+            onshow: function() { $('#user-search').focus(); }
+         });
+        return false;
+    });
+});
+</script>
diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..dab7d730527eddcc74afb20865285af5d154a3a9
--- /dev/null
+++ b/include/staff/users.inc.php
@@ -0,0 +1,181 @@
+<?php
+if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
+
+$qstr='';
+
+$select = 'SELECT user.*, email.address as email ';
+
+$from = 'FROM '.USER_TABLE.' user '
+      . 'JOIN '.USER_EMAIL_TABLE.' email ON (user.id = email.user_id) ';
+
+$where='WHERE 1 ';
+
+
+if ($_REQUEST['query']) {
+
+    $from .=' LEFT JOIN '.FORM_ENTRY_TABLE.' entry
+                ON (entry.object_type=\'U\' AND entry.object_id = user.id)
+              LEFT JOIN '.FORM_ANSWER_TABLE.' value
+                ON (value.entry_id=entry.id) ';
+
+    $search = db_input(strtolower($_REQUEST['query']), false);
+    $where .= ' AND (
+                    email.address LIKE \'%'.$search.'%\'
+                    OR user.name LIKE \'%'.$search.'%\'
+                    OR value.value LIKE \'%'.$search.'%\'
+                )';
+
+    $qstr.='&query='.urlencode($_REQUEST['query']);
+}
+
+$sortOptions = array('name' => 'user.name',
+                     'email' => 'email.address',
+                     'create' => 'user.created',
+                     'update' => 'user.updated');
+$orderWays = array('DESC'=>'DESC','ASC'=>'ASC');
+$sort= ($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])]) ? strtolower($_REQUEST['sort']) : 'name';
+//Sorting options...
+if ($sort && $sortOptions[$sort])
+    $order_column =$sortOptions[$sort];
+
+$order_column = $order_column ?: 'user.name';
+
+if ($_REQUEST['order'] && $orderWays[strtoupper($_REQUEST['order'])])
+    $order = $orderWays[strtoupper($_REQUEST['order'])];
+
+$order=$order ?: 'ASC';
+if ($order_column && strpos($order_column,','))
+    $order_column = str_replace(','," $order,",$order_column);
+
+$x=$sort.'_sort';
+$$x=' class="'.strtolower($order).'" ';
+$order_by="$order_column $order ";
+
+$total=db_count('SELECT count(DISTINCT user.id) '.$from.' '.$where);
+$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
+$pageNav=new Pagenate($total,$page,PAGE_LIMIT);
+$pageNav->setURL('users.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
+//Ok..lets roll...create the actual query
+$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
+
+$select .= ', count(DISTINCT ticket.ticket_id) as tickets ';
+
+$from .= ' LEFT JOIN '.TICKET_TABLE.' ticket ON (ticket.user_id = user.id) ';
+
+
+$query="$select $from $where GROUP BY user.id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
+//echo $query;
+?>
+<h2>User Directory</h2>
+<div style="width:700px; float:left;">
+    <form action="users.php" method="get">
+        <?php csrf_token(); ?>
+        <input type="hidden" name="a" value="search">
+        <table>
+            <tr>
+                <td><input type="text" id="basic-user-search" name="query" size=30 value="<?php echo Format::htmlchars($_REQUEST['query']); ?>"
+                autocomplete="off" autocorrect="off" autocapitalize="off"></td>
+                <td><input type="submit" name="basic_search" class="button" value="Search"></td>
+                <!-- <td>&nbsp;&nbsp;<a href="" id="advanced-user-search">[advanced]</a></td> -->
+            </tr>
+        </table>
+    </form>
+ </div>
+ <div style="float:right;text-align:right;padding-right:5px;">
+    <b><a href="#users/add" class="Icon newstaff add-user">Add New User</a></b></div>
+<div class="clear"></div>
+<?php
+$showing = $search ? 'Search Results: ' : '';
+$res = db_query($query);
+if($res && ($num=db_num_rows($res)))
+    $showing .= $pageNav->showing();
+else
+    $showing .= 'No users found!';
+?>
+<form action="users.php" method="POST" name="staff" >
+ <?php csrf_token(); ?>
+ <input type="hidden" name="do" value="mass_process" >
+ <input type="hidden" id="action" name="a" value="" >
+ <table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
+    <caption><?php echo $showing; ?></caption>
+    <thead>
+        <tr>
+            <th width="300"><a <?php echo $name_sort; ?> href="users.php?<?php echo $qstr; ?>&sort=name">Name</a></th>
+            <th width="300"><a <?php echo $email_sort; ?> href="users.php?<?php echo $qstr; ?>&sort=email">Email</a></th>
+            <th width="100"><a  <?php echo $status_sort; ?> href="users.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
+            <th width="100"><a <?php echo $create_sort; ?> href="users.php?<?php echo $qstr; ?>&sort=create">Created</a></th>
+            <th width="145"><a <?php echo $update_sort; ?> href="users.php?<?php echo $qstr; ?>&sort=update">Updated</a></th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php
+        if($res && db_num_rows($res)):
+            $ids=($errors && is_array($_POST['ids']))?$_POST['ids']:null;
+            while ($row = db_fetch_array($res)) {
+
+                $name = new PersonsName($row['name']);
+                $status = 'Active';
+                $sel=false;
+                if($ids && in_array($row['id'], $ids))
+                    $sel=true;
+                ?>
+               <tr id="<?php echo $row['id']; ?>">
+                <td>&nbsp;
+                    <a href="users.php?id=<?php echo $row['id']; ?>"><?php echo $name; ?></a>
+                    &nbsp;
+                    <?php
+                    if ($row['tickets'])
+                         echo sprintf('<i class="icon-fixed-width icon-file-text-alt"></i>
+                             <small>(%d)</small>', $row['tickets']);
+                    ?>
+                </td>
+                <td><?php echo $row['email']; ?></td>
+                <td><?php echo $status; ?></td>
+                <td><?php echo Format::db_date($row['created']); ?></td>
+                <td><?php echo Format::db_datetime($row['updated']); ?>&nbsp;</td>
+               </tr>
+            <?php
+            } //end of while.
+        endif; ?>
+    <tfoot>
+     <tr>
+        <td colspan="5"> &nbsp; </td>
+     </tr>
+    </tfoot>
+</table>
+<?php
+if($res && $num): //Show options..
+    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
+endif;
+?>
+</form>
+
+<script type="text/javascript">
+$(function() {
+    $('input#basic-user-search').typeahead({
+        source: function (typeahead, query) {
+            $.ajax({
+                url: "ajax.php/users/local?q="+query,
+                dataType: 'json',
+                success: function (data) {
+                    typeahead.process(data);
+                }
+            });
+        },
+        onselect: function (obj) {
+            window.location.href = 'users.php?id='+obj.id;
+        },
+        property: "/bin/true"
+    });
+
+    $(document).on('click', 'a.add-user', function(e) {
+        e.preventDefault();
+        $.userLookup('ajax.php/users/add', function (user) {
+            window.location.href = 'users.php?id='+user.id;
+         });
+
+        return false;
+     });
+});
+</script>
+
diff --git a/scp/ajax.php b/scp/ajax.php
index 9ef736ef7999896da99e8c889e97dde6a7b682d2..b13822d17c0ebefd04d02a89d4af76c79d8c9980 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -64,17 +64,43 @@ $dispatcher = patterns('',
     )),
     url('^/users', patterns('ajax.users.php:UsersAjaxAPI',
         url_get('^$', 'search'),
+        url_get('^/local$', 'search', array('local')),
+        url_get('^/remote$', 'search', array('remote')),
         url_get('^/(?P<id>\d+)$', 'getUser'),
         url_post('^/(?P<id>\d+)$', 'updateUser'),
         url_get('^/(?P<id>\d+)/edit$', 'editUser'),
         url('^/lookup$', 'getUser'),
         url_get('^/lookup/form$', 'getLookupForm'),
         url_post('^/lookup/form$', 'addUser'),
+        url_get('^/add$', 'addUser'),
         url_get('^/select$', 'selectUser'),
         url_get('^/select/(?P<id>\d+)$', 'selectUser'),
         url_get('^/select/auth:(?P<bk>\w+):(?P<id>.+)$', 'addRemoteUser'),
+        url_get('^/(?P<id>\d+)/register$', 'register'),
+        url_post('^/(?P<id>\d+)/register$', 'register'),
+        url_get('^/(?P<id>\d+)/delete$', 'delete'),
+        url_delete('^/(?P<id>\d+)/delete$', 'delete'),
+        url_get('^/(?P<id>\d+)/manage(?:/(?P<target>\w+))?$', 'manage'),
+        url_post('^/(?P<id>\d+)/manage(?:/(?P<target>\w+))?$', 'manage'),
+        url_get('^/(?P<id>\d+)/org(?:/(?P<orgid>\d+))?$', 'updateOrg'),
+        url_post('^/(?P<id>\d+)/org$', 'updateOrg'),
         url_get('^/staff$', 'searchStaff')
     )),
+    url('^/orgs', patterns('ajax.orgs.php:OrgsAjaxAPI',
+        url_get('^$', 'search'),
+        url_get('^/search$', 'search'),
+        url_get('^/(?P<id>\d+)$', 'getOrg'),
+        url_post('^/(?P<id>\d+)$', 'updateOrg'),
+        url_get('^/(?P<id>\d+)/edit$', 'editOrg'),
+        url_get('^/lookup/form$', 'lookup'),
+        url_post('^/lookup/form$', 'addOrg'),
+        url_get('^/add$', 'addOrg'),
+        url_post('^/add$', 'addOrg'),
+        url_get('^/select$', 'selectOrg'),
+        url_get('^/select/(?P<id>\d+)$', 'selectOrg'),
+        url_get('^/(?P<id>\d+)/delete$', 'delete'),
+        url_delete('^/(?P<id>\d+)/delete$', 'delete')
+    )),
     url('^/tickets/', patterns('ajax.tickets.php:TicketsAjaxAPI',
         url_get('^(?P<tid>\d+)/change-user$', 'changeUserForm'),
         url_post('^(?P<tid>\d+)/change-user$', 'changeUser'),
diff --git a/scp/css/scp.css b/scp/css/scp.css
index 4500c2dfbeb0a04c7820a08775f148bcef77c5be..50bea7ea4bc26d2cc5634889b0ff35e6c9ec3d34 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -1359,6 +1359,12 @@ time {
     font-size:0.75em;
 }
 
+.dialog ul.tabs, .dialog ul.tabs * {
+    box-sizing: content-box;
+    -moz-box-sizing: content-box;
+    -webkit-box-sizing: content-box;
+}
+
 .dialog.draggable h3:hover {
     cursor: crosshair;
 }
diff --git a/scp/js/scp.js b/scp/js/scp.js
index 33839e80c39174391d9d10e9e2c2029a44af9221..2119131553d6c7f48d4601be8f8a529f2d7f3114 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -103,6 +103,24 @@ $(document).ready(function(){
         return false;
      });
 
+    $('a.confirm-action').click(function(e) {
+        $dialog = $('.dialog#confirm-action');
+        if ($($(this).attr('href')+'-confirm', $dialog).length) {
+            e.preventDefault();
+            var action = $(this).attr('href').substr(1, $(this).attr('href').length);
+
+            $('input#action', $dialog).val(action);
+            $('#overlay').show();
+            $('.confirm-action', $dialog).hide();
+            $('p'+$(this).attr('href')+'-confirm', $dialog)
+            .show()
+            .parent('div').show().trigger('click');
+
+            return false;
+        }
+     });
+
+
     if($.browser.msie) {
         $('.inactive').mouseenter(function() {
             var elem = $(this);
@@ -431,9 +449,12 @@ $(document).ready(function(){
         $('#advanced-search').show();
     });
 
-    $.dialog = function (url, code, cb, options) {
+    $.dialog = function (url, codes, cb, options) {
         options = options||{};
 
+        if (codes && !$.isArray(codes))
+            codes = [codes];
+
         $('.dialog#popup .body').load(url, function () {
             $('#overlay').show();
             $('.dialog#popup').show({
@@ -451,11 +472,12 @@ $(document).ready(function(){
                     data: $form.serialize(),
                     cache: false,
                     success: function(resp, status, xhr) {
-                        if (xhr && xhr.status == code) {
+                        if (xhr && xhr.status && codes
+                            && $.inArray(xhr.status, codes) != -1) {
                             $('div.body', $dialog).empty();
                             $dialog.hide();
                             $('#overlay').hide();
-                            if(cb) cb(xhr.responseText);
+                            if(cb) cb(xhr);
                         } else {
                             $('div.body', $dialog).html(resp);
                             $('#msg_notice, #msg_error', $dialog).delay(5000).slideUp();
@@ -471,14 +493,23 @@ $(document).ready(function(){
      };
 
     $.userLookup = function (url, cb) {
-        $.dialog(url, 201, function (resp) {
-            var user = $.parseJSON(resp);
-            if(cb) cb(user);
+        $.dialog(url, 201, function (xhr) {
+            var user = $.parseJSON(xhr.responseText);
+            if (cb) cb(user);
         }, {
             onshow: function() { $('#user-search').focus(); }
         });
     };
 
+    $.orgLookup = function (url, cb) {
+        $.dialog(url, 201, function (xhr) {
+            var org = $.parseJSON(xhr.responseText);
+            if (cb) cb(org);
+        }, {
+            onshow: function() { $('#org-search').focus(); }
+        });
+    };
+
     $('#advanced-search').delegate('#status', 'change', function() {
         switch($(this).val()) {
             case 'closed':
@@ -558,7 +589,7 @@ $(document).ready(function(){
    $(document).on('click.tab', 'ul.tabs li a', function(e) {
         e.preventDefault();
         if ($('.tab_content'+$(this).attr('href')).length) {
-            $('ul.tabs li a').removeClass('active');
+            $('ul.tabs li a', $(this).closest('ul').parent()).removeClass('active');
             $(this).addClass('active');
             $('.tab_content').hide();
             $('.tab_content'+$(this).attr('href')).show();
@@ -569,9 +600,9 @@ $(document).ready(function(){
     $(document).on('click', 'a.collaborator, a.collaborators', function(e) {
         e.preventDefault();
         var url = 'ajax.php/'+$(this).attr('href').substr(1);
-        $.dialog(url, 201, function (resp) {
+        $.dialog(url, 201, function (xhr) {
            $('input#emailcollab').show();
-           $('#recipients').text(resp);
+           $('#recipients').text(xhr.responseText);
            $('.tip_box').remove();
         }, {
             onshow: function() { $('#user-search').focus(); }
diff --git a/scp/js/ticket.js b/scp/js/ticket.js
index 357031c9e00f4dd506c1d93346f7c0bea3e901df..7199d0829ef136a746413894d3584d3ad66234f1 100644
--- a/scp/js/ticket.js
+++ b/scp/js/ticket.js
@@ -336,7 +336,7 @@ jQuery(function($) {
         return false;
     });
 
-    //ticket status (close & reopen)
+    //ticket status (close & reopen) xxx: move to backend ticket-action
     $('a#ticket-close, a#ticket-reopen').click(function(e) {
         e.preventDefault();
         $('#overlay').show();
@@ -344,25 +344,6 @@ jQuery(function($) {
         return false;
     });
 
-    //ticket actions confirmation - Delete + more
-    $('a#ticket-delete, a#ticket-claim, #action-dropdown-more li a:not(.change-user)').click(function(e) {
-        e.preventDefault();
-        if($('.dialog#confirm-action '+$(this).attr('href')+'-confirm').length) {
-            var action = $(this).attr('href').substr(1, $(this).attr('href').length);
-            $('.dialog#confirm-action #action').val(action);
-            $('#overlay').show();
-            $('.dialog#confirm-action .confirm-action').hide();
-            $('.dialog#confirm-action p'+$(this).attr('href')+'-confirm')
-            .show()
-            .parent('div').show().trigger('click');
-
-        } else {
-            alert('Unknown action '+$(this).attr('href')+'- get technical help.');
-        }
-
-        return false;
-    });
-
     $(document).on('change', 'form#reply select#emailreply', function(e) {
          var $cc = $('form#reply tbody#cc_sec');
         if($(this).val() == 0)
diff --git a/scp/orgs.php b/scp/orgs.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ecb8d1892cbed3f27610139a5a6fb0d4e3a53af
--- /dev/null
+++ b/scp/orgs.php
@@ -0,0 +1,26 @@
+<?php
+/*********************************************************************
+    orgs.php
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2014 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+require('staff.inc.php');
+$org = null;
+if ($_REQUEST['id'])
+    $org = Organization::lookup($_REQUEST['id']);
+
+
+$page = $org? 'org-view.inc.php' : 'orgs.inc.php';
+$nav->setTabActive('users');
+require(STAFFINC_DIR.'header.inc.php');
+require(STAFFINC_DIR.$page);
+include(STAFFINC_DIR.'footer.inc.php');
+?>
diff --git a/scp/users.php b/scp/users.php
new file mode 100644
index 0000000000000000000000000000000000000000..3020a91f19fceb60517d817382d28a1cdfb1e2e2
--- /dev/null
+++ b/scp/users.php
@@ -0,0 +1,81 @@
+<?php
+/*********************************************************************
+    users.php
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2014 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+require('staff.inc.php');
+$user = null;
+if ($_REQUEST['id'] && !($user=User::lookup($_REQUEST['id'])))
+    $errors['err'] = 'Unknown or invalid user ID.';
+
+if ($_POST) {
+    switch(strtolower($_POST['do'])) {
+        case 'update':
+            if (!$user) {
+                $errors['err']='Unknown or invalid user.';
+            } elseif(($acct = $user->getAccount())
+                    && !$acct->update($_POST, $errors)) {
+                 $errors['err']='Unable to update user account information';
+            } elseif($user->updateInfo($_POST, $errors)) {
+                $msg='User updated successfully';
+                $_REQUEST['a'] = null;
+            } elseif(!$errors['err']) {
+                $errors['err']='Unable to update user profile. Correct any error(s) below and try again!';
+            }
+            break;
+        case 'create':
+            $form = UserForm::getUserForm()->getForm($_POST);
+            if (($user = User::fromForm($form))) {
+                $msg = Format::htmlchars($user->getName()).' added successfully';
+                $_REQUEST['a'] = null;
+            } elseif (!$errors['err']) {
+                $errors['err'] = 'Unable to add user. Correct any error(s) below and try again.';
+            }
+            break;
+        case 'confirmlink':
+            if (!$user || !$user->getAccount())
+                $errors['err'] = 'Unknown or invalid user account';
+            elseif ($user->getAccount()->isConfirmed())
+                $errors['err'] = 'Account is already confirmed';
+            elseif ($user->getAccount()->sendConfirmEmail())
+                $msg = 'Account activation email sent to '.$user->getEmail();
+            else
+                $errors['err'] = 'Unable to send account activation email - try again!';
+            break;
+        case 'pwreset':
+            if (!$user || !$user->getAccount())
+                $errors['err'] = 'Unknown or invalid user account';
+            elseif ($user->getAccount()->sendResetEmail())
+                $msg = 'Account password reset email sent to '.$user->getEmail();
+            else
+                $errors['err'] = 'Unable to send account password reset email - try again!';
+            break;
+        case 'mass_process':
+            if (!$_POST['ids'] || !is_array($_POST['ids']) || !count($_POST['ids'])) {
+                $errors['err'] = 'You must select at least one user member.';
+            } else {
+                $errors['err'] = "Coming soon!";
+            }
+            break;
+        default:
+            $errors['err'] = 'Unknown action/command';
+            break;
+    }
+}
+
+$page = $user? 'user-view.inc.php' : 'users.inc.php';
+
+$nav->setTabActive('users');
+require(STAFFINC_DIR.'header.inc.php');
+require(STAFFINC_DIR.$page);
+include(STAFFINC_DIR.'footer.inc.php');
+?>
diff --git a/setup/cli/modules/org.php b/setup/cli/modules/org.php
new file mode 100644
index 0000000000000000000000000000000000000000..c47e5cd7d628d1638d922e1f28a09ac9cc7599a9
--- /dev/null
+++ b/setup/cli/modules/org.php
@@ -0,0 +1,72 @@
+<?php
+require_once dirname(__file__) . "/class.module.php";
+require_once dirname(__file__) . "/../cli.inc.php";
+
+class OrganizationManager extends Module {
+    var $prologue = 'CLI organization manager';
+
+    var $arguments = array(
+        'action' => array(
+            'help' => 'Action to be performed',
+            'options' => array(
+                'import' => 'Import organizations to the system',
+                'export' => 'Export organizations from the system',
+            ),
+        ),
+    );
+
+
+    var $options = array(
+        'file' => array('-f', '--file', 'metavar'=>'path',
+            'help' => 'File or stream to process'),
+        );
+
+    var $stream;
+
+    function run($args, $options) {
+
+        Bootstrap::connect();
+
+        switch ($args['action']) {
+            case 'import':
+                if (!$options['file'])
+                    $this->fail('Import CSV file required!');
+                elseif (!($this->stream = fopen($options['file'], 'rb')))
+                    $this->fail("Unable to open input file [{$options['file']}]");
+
+                //Read the header (if any)
+                if (($data = fgetcsv($this->stream, 1000, ","))) {
+                    if (strcasecmp($data[0], 'name'))
+                        fseek($this->stream, 0); // We don't have an header!
+                    else;
+                    // TODO: process the header here to figure out the columns
+                    // for now we're assuming one column of Name
+                }
+
+                while (($data = fgetcsv($this->stream, 1000, ",")) !== FALSE) {
+                    if (!$data[0])
+                        $this->stderr->write('Invalid data format: Name
+                                required');
+                    elseif (!Organization::fromVars(array('name' => $data[0], 'email')))
+                        $this->stderr->write('Unable to import record: '.print_r($data, true));
+                }
+
+                break;
+            case 'export':
+                $stream = $options['file'] ?: 'php://stdout';
+                if (!($this->stream = fopen($stream, 'c')))
+                    $this->fail("Unable to open output file [{$options['file']}]");
+
+                fputcsv($this->stream, array('Name'));
+                foreach (Organization::objects() as $org)
+                    fputcsv($this->stream,
+                            array((string) $org->getName()));
+                break;
+            default:
+                $this->stderr->write('Unknown action!');
+        }
+        @fclose($this->stream);
+    }
+}
+Module::register('org', 'OrganizationManager');
+?>