diff --git a/include/ajax.orgs.php b/include/ajax.orgs.php index def54cf3c549d98188a801a78199e52fd6b9e1ab..eeaa23c7eb4a9a1405c624d731dac599ad49a946 100644 --- a/include/ajax.orgs.php +++ b/include/ajax.orgs.php @@ -101,6 +101,64 @@ class OrgsAjaxAPI extends AjaxController { include(STAFFINC_DIR . 'templates/org-delete.tmpl.php'); } + function addUser($id, $userId=0, $remote=false) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, 'Login Required'); + elseif (!($org = Organization::lookup($id))) + Http::response(404, 'Unknown organization'); + + $info = array(); + $info['title'] = 'Add User'; + $info['action'] = '#orgs/'.$org->getId().'/add-user'; + $info['onselect'] = 'ajax.php/orgs/'.$org->getId().'/add-user/'; + + $info['lookup'] = false; + if (AuthenticationBackend::getSearchDirectories()) + $info['lookup'] = 'remote'; + + if ($_POST) { + if ($_POST['id']) { //Existing useer + if (!($user = User::lookup($_POST['id']))) + $info['error'] = 'Unknown user selected'; + elseif ($user->getOrgId() == $org->getId()) + $info['error'] = sprintf('%s already belongs to the organization', + Format::htmlchars($user->getName())); + } else { //Creating new user + $form = UserForm::getUserForm()->getForm($_POST); + if (!($user = User::fromForm($form))) + $info['error'] = 'Error adding user - try again!'; + } + + if (!$info['error'] && $user && $user->setOrganization($org)) + Http::response(201, $user->to_json()); + elseif (!$info['error']) + $info['error'] = 'Unable to add user to the organization - try again'; + + } elseif ($remote && $userId) { + list($bk, $userId) = explode(':', $userId, 2); + if (!($backend = AuthenticationBackend::getSearchDirectoryBackend($bk)) + || !($user_info = $backend->lookup($userId))) + Http::response(404, 'User not found'); + + $form = UserForm::getUserForm()->getForm($user_info); + } elseif ($userId) //Selected local user + $user = User::lookup($userId); + + if ($user && $user->getOrgId()) { + if ($user->getOrgId() == $org->getId()) + $info['warn'] = 'User already belongs to this organization!'; + else + $info['warn'] = "Are you sure you want to change the user's organization?"; + } + + ob_start(); + include(STAFFINC_DIR . 'templates/user-lookup.tmpl.php'); + $resp = ob_get_contents(); + ob_end_clean(); + return $resp; + } function addOrg() { diff --git a/include/ajax.users.php b/include/ajax.users.php index 8c19ec0e7d5a8a255b75e34ab5307bc680aa7d57..5da92b78cbd305675ddf095d6ff84c01a0106db7 100644 --- a/include/ajax.users.php +++ b/include/ajax.users.php @@ -33,7 +33,7 @@ class UsersAjaxAPI extends AjaxController { $emails=array(); if (!$type || !strcasecmp($type, 'remote')) { - foreach (StaffAuthenticationBackend::searchUsers($_REQUEST['q']) as $u) { + foreach (AuthenticationBackend::searchUsers($_REQUEST['q']) as $u) { $name = "{$u['first']} {$u['last']}"; $users[] = array('email' => $u['email'], 'name'=>$name, 'info' => "{$u['email']} - $name (remote)", @@ -213,16 +213,17 @@ class UsersAjaxAPI extends AjaxController { $info = array(); - if ($_POST) { + $info['title'] = 'Add New User'; + + if (!AuthenticationBackend::getSearchDirectories()) + $info['lookup'] = 'local'; + if ($_POST) { $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'; + $info['error'] = 'Error adding user - try again!'; } return self::_lookupform($form, $info); @@ -235,10 +236,10 @@ class UsersAjaxAPI extends AjaxController { Http::response(403, 'Login Required'); elseif (!$bk || !$id) Http::response(422, 'Backend and user id required'); - elseif (!($backend = StaffAuthenticationBackend::getBackend($bk))) + elseif (!($backend = AuthenticationBackend::getSearchDirectoryBackend($bk)) + || !($user_info = $backend->lookup($id))) Http::response(404, 'User not found'); - $user_info = $backend->lookup($id); $form = UserForm::getUserForm()->getForm($user_info); $info = array('title' => 'Import Remote User'); if (!$user_info) @@ -290,13 +291,11 @@ class UsersAjaxAPI extends AjaxController { Http::response(400, 'Query argument is required'); $users = array(); - foreach (StaffAuthenticationBackend::allRegistered() as $ab) { - if (!$ab instanceof AuthDirectorySearch) - continue; - + foreach (AuthenticationBackend::searchDirectories() as $ab) { foreach ($ab->search($_REQUEST['q']) as $u) $users[] = $u; } + return $this->json_encode($users); } @@ -305,9 +304,8 @@ class UsersAjaxAPI extends AjaxController { if (!$thisstaff) Http::response(403, 'Login Required'); - elseif (!($user = User::lookup($id)) - || !($account=$user->getAccount())) - Http::response(404, 'Unknown user account'); + elseif (!($user = User::lookup($id))) + Http::response(404, 'Unknown user'); $info = array(); $info['title'] = 'Organization for '.$user->getName(); @@ -324,20 +322,20 @@ class UsersAjaxAPI extends AjaxController { $info['error'] = 'Unable to create organization - try again!'; } - if ($org && $account->setOrganization($org)) + if ($org && $user->setOrganization($org)) Http::response(201, $org->to_json()); - - $info['error'] = 'Unable to user account - try again!'; + elseif (! $info['error']) + $info['error'] = 'Unable to add organization - try again!'; } elseif ($orgId) $org = Organization::lookup($orgId); - elseif ($org = $account->getOrganization()) { + elseif ($org = $user->getOrganization()) { $info['title'] = $org->getName(); $info['action'] = $info['onselect'] = ''; $tmpl = 'org.tmpl.php'; } - if ($org && $account->getOrgId() && $org->getId() != $account->getOrgId()) + if ($org && $user->getOrgId() && $org->getId() != $user->getOrgId()) $info['warning'] = 'Are you sure you want to change user\'s organization?'; $tmpl = $tmpl ?: 'org-lookup.tmpl.php'; diff --git a/include/class.auth.php b/include/class.auth.php index 74e7b9c787635fbf5cf3a30b6100164f794a8886..487dbe3c6b984530ba750e59f91c60f9efb43540 100644 --- a/include/class.auth.php +++ b/include/class.auth.php @@ -138,6 +138,14 @@ abstract class AuthenticationBackend { return $backends[$id]; } + static function getSearchDirectoryBackend($id) { + + if ($id + && ($backends = static::getSearchDirectories()) + && isset($backends[$id])) + return $backends[$id]; + } + /* * Allow the backend to do login audit depending on the result * This is mainly used to track failed login attempts @@ -229,13 +237,24 @@ abstract class AuthenticationBackend { self::authAudit($result); } + static function getSearchDirectories() { + $backends = array(); + foreach (StaffAuthenticationBackend::allRegistered() as $bk) + if ($bk instanceof AuthDirectorySearch) + $backends[$bk::$id] = $bk; + + foreach (UserAuthenticationBackend::allRegistered() as $bk) + if ($bk instanceof AuthDirectorySearch) + $backends[$bk::$id] = $bk; + + return array_unique($backends); + } + static function searchUsers($query) { $users = array(); - foreach (static::allRegistered() as $bk) { - if ($bk instanceof AuthDirectorySearch) { - $users += $bk->search($query); - } - } + foreach (static::getSearchDirectories() as $bk) + $users += $bk->search($query); + return $users; } diff --git a/include/class.organization.php b/include/class.organization.php index c12ae9a047e467a0ba916622c46fbc8c25c70312..a837505fa4b61c1f40311e2d562f8a9081caa827 100644 --- a/include/class.organization.php +++ b/include/class.organization.php @@ -23,7 +23,7 @@ class OrganizationModel extends VerySimpleModel { 'pk' => array('id'), 'joins' => array( 'users' => array( - 'reverse' => 'UserAccount.org', + 'reverse' => 'User.org', ), ) ); diff --git a/include/class.user.php b/include/class.user.php index a845455e6b9df52da4bb44b5bfcd9ed42b7ebf32..9401429b185fa5b6ba77271222bf96f383ae2c3e 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -67,6 +67,9 @@ class UserModel extends VerySimpleModel { 'list' => false, 'reverse' => 'UserAccount.user', ), + 'org' => array( + 'constraint' => array('org_id' => 'Organization.id') + ), 'default_email' => array( 'null' => true, 'constraint' => array('default_email_id' => 'UserEmailModel.id') @@ -85,6 +88,28 @@ class UserModel extends VerySimpleModel { function getDefaultEmail() { return $this->default_email; } + + function getAccount() { + return $this->account; + } + + function getOrgId() { + return $this->get('org_id'); + } + + function getOrganization() { + return $this->org; + } + + function setOrganization($org) { + if (!$org instanceof Organization) + return false; + + $this->set('org', $org); + $this->save(); + + return true; + } } class User extends UserModel { @@ -234,22 +259,12 @@ class User extends UserModel { return $this->_forms; } - function getAccount() { - 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'; + return (string) $account->getStatus(); } function register($vars, &$errors) { @@ -540,19 +555,17 @@ class UserAccountModel extends VerySimpleModel { 'null' => false, 'constraint' => array('user_id' => 'User.id') ), - 'org' => array( - 'constraint' => array('org_id' => 'Organization.id') - ), ), ); - const CONFIRMED = 0x0001; - const LOCKED = 0x0002; - const REQUIRE_PASSWD_RESET = 0x0004; - const FORBID_PASSWD_RESET = 0x0008; + var $_status; + + function __onload() { + $this->_status = new UserAccountStatus($this->get('status')); + } protected function hasStatus($flag) { - return 0 !== ($this->get('status') & $flag); + return $this->_status->check($flag); } protected function clearStatus($flag) { @@ -564,38 +577,38 @@ class UserAccountModel extends VerySimpleModel { } function confirm() { - $this->setStatus(self::CONFIRMED); + $this->setStatus(UserAccountStatus::CONFIRMED); return $this->save(); } function isConfirmed() { - return $this->hasStatus(self::CONFIRMED); + return $this->_status->isConfirmed(); } function lock() { - $this->setStatus(self::LOCKED); + $this->setStatus(UserAccountStatus::LOCKED); $this->save(); } function isLocked() { - return $this->hasStatus(self::LOCKED); + return $this->_status->isLocked(); } function forcePasswdReset() { - $this->setStatus(self::REQUIRE_PASSWD_RESET); + $this->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET); return $this->save(); } function isPasswdResetForced() { - return $this->hasStatus(self::REQUIRE_PASSWD_RESET); + return $this->hasStatus(UserAccountStatus::REQUIRE_PASSWD_RESET); } function isPasswdResetEnabled() { - return !$this->hasStatus(self::FORBID_PASSWD_RESET); + return !$this->hasStatus(UserAccountStatus::FORBID_PASSWD_RESET); } function getStatus() { - return $this->get('status'); + return $this->_status; } function getInfo() { @@ -614,25 +627,6 @@ class UserAccountModel extends VerySimpleModel { $this->user->set('account', $this); return $this->user; } - - function getOrgId() { - return $this->get('org_id'); - } - - function getOrganization() { - return $this->org; - } - - function setOrganization($org) { - if (!$org instanceof Organization) - return false; - - $this->set('org', $org); - $this->save(); - - return true; - } - } class UserAccount extends UserAccountModel { @@ -733,14 +727,14 @@ class UserAccount extends UserAccountModel { if ($vars['passwd1']) { $this->set('passwd', Passwd::hash($vars['passwd'])); - $this->setStatus(self::CONFIRMED); + $this->setStatus(UserAccountStatus::CONFIRMED); } // Set flags foreach (array( - 'pwreset-flag'=> self::REQUIRE_PASSWD_RESET, - 'locked-flag'=> self::LOCKED, - 'forbid-pwchange-flag'=> self::FORBID_PASSWD_RESET + 'pwreset-flag' => UserAccountStatus::REQUIRE_PASSWD_RESET, + 'locked-flag' => UserAccountStatus::LOCKED, + 'forbid-pwchange-flag' => UserAccountStatus::FORBID_PASSWD_RESET ) as $ck=>$flag) { if ($vars[$ck]) $this->setStatus($flag); @@ -795,11 +789,11 @@ class UserAccount extends UserAccountModel { if ($vars['passwd1'] && !$vars['sendemail']) { $account->set('passwd', Passwd::hash($vars['passwd1'])); - $account->setStatus(self::CONFIRMED); + $account->setStatus(UserAccountStatus::CONFIRMED); if ($vars['pwreset-flag']) - $account->setStatus(self::REQUIRE_PASSWD_RESET); + $account->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET); if ($vars['forbid-pwreset-flag']) - $account->setStatus(self::FORBID_PASSWD_RESET); + $account->setStatus(UserAccountStatus::FORBID_PASSWD_RESET); } $account->save(true); @@ -812,6 +806,46 @@ class UserAccount extends UserAccountModel { } +class UserAccountStatus { + + var $flag; + + const CONFIRMED = 0x0001; + const LOCKED = 0x0002; + const REQUIRE_PASSWD_RESET = 0x0004; + const FORBID_PASSWD_RESET = 0x0008; + + function __construct($flag) { + $this->flag = $flag; + } + + function check($flag) { + return 0 !== ($this->flag & $flag); + } + + function isLocked() { + return $this->check(self::LOCKED); + } + + function isConfirmed() { + return $this->check(self::CONFIRMED); + } + + function __toString() { + + if (!$this->flag) + return 'Guest'; + + if ($this->isLocked()) + return 'Locked (Administrative)'; + + if (!$this->isConfirmed()) + return 'Locked (Pending Activation)'; + + return 'Active (Registered)'; + } +} + /* * Generic user list. diff --git a/include/staff/orgs.inc.php b/include/staff/orgs.inc.php index ded6efeb259f66a21580d9e7d8a7454c37b20f7c..4c11d1d369f283ff5bb949f6f17001bf6fd1d815 100644 --- a/include/staff/orgs.inc.php +++ b/include/staff/orgs.inc.php @@ -56,7 +56,7 @@ $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) '; +$from .= ' LEFT JOIN '.USER_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(); diff --git a/include/staff/templates/tickets.tmpl.php b/include/staff/templates/tickets.tmpl.php index bdd5625786e86815aca2540e6955e5bae92517df..abf3314ef753f97742d97d7a2398a8f9ef73d919 100644 --- a/include/staff/templates/tickets.tmpl.php +++ b/include/staff/templates/tickets.tmpl.php @@ -23,7 +23,7 @@ $from =' FROM '.TICKET_TABLE.' ticket ' if ($user) $where = 'WHERE ticket.user_id = '.db_input($user->getId()); elseif ($org) - $where = 'WHERE account.org_id = '.db_input($org->getId()); + $where = 'WHERE user.org_id = '.db_input($org->getId()); TicketForm::ensureDynamicDataView(); diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php index 39a617e01d4672c661cd65a2699d559c202dcb68..d21d457d2d1c6fe1bb7d6236bfdad276998111a8 100644 --- a/include/staff/templates/user-lookup.tmpl.php +++ b/include/staff/templates/user-lookup.tmpl.php @@ -2,6 +2,8 @@ <h3><?php echo $info['title']; ?></h3> <b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> <hr/> +<?php +if (!isset($info['lookup']) || $info['lookup'] !== false) { ?> <div><p id="msg_info"><i class="icon-info-sign"></i> Search existing users or add a new user.</p></div> <div style="margin-bottom:10px;"> <input type="text" class="search-input" style="width:100%;" @@ -9,8 +11,12 @@ autocorrect="off" autocomplete="off"/> </div> <?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']); } ?> @@ -20,9 +26,14 @@ if ($info['error']) { <i class="icon-user icon-4x pull-left icon-border"></i> <a class="action-button pull-right" style="overflow:inherit" id="unselect-user" href="#"><i class="icon-remove"></i> Add New User</a> - <div><strong id="user-name"><?php echo $user ? Format::htmlchars($user->getName()->getOriginal()) : ''; ?></strong></div> - <div><<span id="user-email"><?php echo $user ? $user->getEmail() : ''; ?></span>></div> <?php if ($user) { ?> + <div><strong id="user-name"><?php echo Format::htmlchars($user->getName()->getOriginal()); ?></strong></div> + <div><<span id="user-email"><?php echo $user->getEmail(); ?></span>></div> + <?php + if ($org=$user->getOrganization()) { ?> + <div><span id="user-org"><?php echo $org->getName(); ?></span></div> + <?php + } ?> <table style="margin-top: 1em;"> <?php foreach ($user->getDynamicData() as $entry) { ?> <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php @@ -78,7 +89,7 @@ $(function() { if (last_req) last_req.abort(); last_req = $.ajax({ url: "ajax.php/users<?php - echo $info['lookuptype'] ? "/{$info['lookuptype']}" : '' ?>?q="+query, + echo $info['lookup'] ? "/{$info['lookup']}" : '' ?>?q="+query, dataType: 'json', success: function (data) { typeahead.process(data); @@ -95,6 +106,7 @@ $(function() { $('a#unselect-user').click( function(e) { e.preventDefault(); + $("#msg_error, #msg_notice, #msg_warning").fadeOut(); $('div#selected-user-info').hide(); $('div#new-user-form').fadeIn({start: function(){ $('#user-search').focus(); }}); return false; diff --git a/include/staff/templates/user.tmpl.php b/include/staff/templates/user.tmpl.php index 6c91f3b26416d0b0684a2fc9b1d7efa0ca4cc001..cacd574b395c60c4e196fcd8c474fb88a98b302f 100644 --- a/include/staff/templates/user.tmpl.php +++ b/include/staff/templates/user.tmpl.php @@ -22,6 +22,11 @@ if ($info['error']) { <div><b><a href="#" id="edituser"><i class="icon-edit"></i> <?php echo Format::htmlchars($user->getName()->getOriginal()); ?></a></b></div> <div><<?php echo $user->getEmail(); ?>></div> + <?php + if (($org=$user->getOrganization())) { ?> + <div><?php echo $org->getName(); ?></div> + <?php + } ?> <table style="margin-top: 1em;"> <?php foreach ($user->getDynamicData() as $entry) { ?> diff --git a/include/staff/templates/users.tmpl.php b/include/staff/templates/users.tmpl.php index 1b7ab4e1e5d25cf4e69fcf38ff9b76134d682a42..f0be96907b6a7d52333c989a274ed86073cf573e 100644 --- a/include/staff/templates/users.tmpl.php +++ b/include/staff/templates/users.tmpl.php @@ -1,14 +1,11 @@ <?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()); - +$where = ' WHERE user.org_id='.db_input($org->getId()); $sortOptions = array('name' => 'user.name', 'email' => 'email.address', @@ -53,7 +50,7 @@ $res = db_query($query); if($res && ($num=db_num_rows($res))) $showing .= $pageNav->showing(); else - $showing .= 'No users found!'; + $showing .= "This organization doesn't have any users yet"; ?> <div style="width:700px; float:left;"><b><?php echo $showing; ?></b></div> @@ -61,6 +58,8 @@ else <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/> +<?php +if ($num) { ?> <form action="users.php" method="POST" name="staff" > <?php csrf_token(); ?> <input type="hidden" name="do" value="mass_process" > @@ -111,13 +110,15 @@ if($res && $num): //Show options.. endif; ?> </form> +<?php +} ?> <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; + $.userLookup('ajax.php/orgs/<?php echo $org->getId(); ?>/add-user', function (user) { + window.location.href = 'orgs.php?id=<?php echo $org->getId(); ?>' }); return false; diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php index de27ddc2fc5f2bf1bfdc11cfe6e2114d946d9e9a..0e297150cbfce08f75add4395e6393f50ceeda50 100644 --- a/include/staff/user-view.inc.php +++ b/include/staff/user-view.inc.php @@ -2,7 +2,8 @@ if(!defined('OSTSCPINC') || !$thisstaff || !is_object($user)) die('Invalid path'); $account = $user->getAccount(); -$org = $account ? $account->getOrganization() : null; +$org = $user->getOrganization(); + ?> <table width="940" cellpadding="2" cellspacing="0" border="0"> @@ -84,12 +85,10 @@ $org = $account ? $account->getOrganization() : null; echo sprintf('<a href="#users/%d/org" class="user-action">%s</a>', $user->getId(), $org->getName()); - elseif ($account) + else echo sprintf('<a href="#users/%d/org" class="user-action">Add Organization</a>', $user->getId()); - else - echo ' '; ?> </span> </td> diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php index 62361f198e57510487e798d47bde5cb077a9b85d..4bc597c15c4d2c8369d377d7ea343e9f1e2d4875 100644 --- a/include/staff/users.inc.php +++ b/include/staff/users.inc.php @@ -3,10 +3,11 @@ if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied'); $qstr=''; -$select = 'SELECT user.*, email.address as email '; +$select = 'SELECT user.*, email.address as email, account.status '; $from = 'FROM '.USER_TABLE.' user ' - . 'JOIN '.USER_EMAIL_TABLE.' email ON (user.id = email.user_id) '; + . 'LEFT JOIN '.USER_EMAIL_TABLE.' email ON (user.id = email.user_id) ' + . 'LEFT JOIN '.USER_ACCOUNT_TABLE.' account ON (account.user_id = user.id) '; $where='WHERE 1 '; @@ -100,9 +101,8 @@ else <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="350"><a <?php echo $name_sort; ?> href="users.php?<?php echo $qstr; ?>&sort=name">Name</a></th> + <th width="250"><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> @@ -112,9 +112,13 @@ else 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'; + // Account status + if ($row['status']) + $status = new UserAccountStatus($row['status']); + else + $status = 'Guest'; + $sel=false; if($ids && in_array($row['id'], $ids)) $sel=true; @@ -129,7 +133,6 @@ else <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']); ?> </td> diff --git a/include/upgrader/streams/core.sig b/include/upgrader/streams/core.sig index 267cb8e334b83f11d55b2e6341254bc297b0f766..324095cf42b6af08769dcb485913dacba7cc301d 100644 --- a/include/upgrader/streams/core.sig +++ b/include/upgrader/streams/core.sig @@ -1 +1 @@ -9ef33a062ca3a20190dfad594d594a69 +8f99b8bf9bee63c8e4dc274ffbdda383 diff --git a/include/upgrader/streams/core/4323a6a8-9ef33a06.patch.sql b/include/upgrader/streams/core/4323a6a8-9ef33a06.patch.sql index 9867ef23cb3e7a72b141aa6d56276b3a8d2d8c2d..d49df2d43befcdfc32e538caddd71d6470552e0c 100644 --- a/include/upgrader/streams/core/4323a6a8-9ef33a06.patch.sql +++ b/include/upgrader/streams/core/4323a6a8-9ef33a06.patch.sql @@ -13,7 +13,7 @@ ALTER TABLE `%TABLE_PREFIX%list_items` ADD `properties` text AFTER `sort`; ALTER TABLE `%TABLE_PREFIX%organization` - ADD `status` int(11) NOT NULL DEFAULT 0 AFTER `staff_id`, + ADD `status` int(11) unsigned NOT NULL DEFAULT 0 AFTER `staff_id`, ADD `domain` varchar(128) NOT NULL DEFAULT '' AFTER `status`, ADD `extra` text AFTER `domain`; diff --git a/include/upgrader/streams/core/9ef33a06-8f99b8bf.patch.sql b/include/upgrader/streams/core/9ef33a06-8f99b8bf.patch.sql new file mode 100644 index 0000000000000000000000000000000000000000..da9dbcd29171ca968205fc584b1c3eb1badea83b --- /dev/null +++ b/include/upgrader/streams/core/9ef33a06-8f99b8bf.patch.sql @@ -0,0 +1,29 @@ +/** + * @version v1.8.2 + * @signature 8f99b8bf9bee63c8e4dc274ffbdda383 + * @title Move organization support from UserAccount to User model. + * + */ + +ALTER TABLE `%TABLE_PREFIX%user` + ADD `org_id` int(11) unsigned NOT NULL AFTER `id`, + ADD `status` int(11) unsigned NOT NULL DEFAULT 0 AFTER `default_email_id`, + ADD INDEX (`org_id`); + +ALTER TABLE `%TABLE_PREFIX%user_account` + DROP `org_id`, + ADD INDEX (`user_id`); + +ALTER TABLE `%TABLE_PREFIX%ticket` + ADD INDEX (`user_id`); + +ALTER TABLE `%TABLE_PREFIX%draft` + ADD `extra` text AFTER `body`; + +ALTER TABLE `%TABLE_PREFIX%organization` + CHANGE `staff_id` `manager` varchar(16) NOT NULL DEFAULT '', + CHANGE `domain` `domain` varchar(256) NOT NULL DEFAULT ''; + +UPDATE `%TABLE_PREFIX%config` + SET `value` = '8f99b8bf9bee63c8e4dc274ffbdda383' + WHERE `key` = 'schema_signature' AND `namespace` = 'core'; diff --git a/scp/ajax.php b/scp/ajax.php index 5a340bbce92122a5eb79af30a2269e43ac857989..27fb8022a9d143a2856bc3ad95b686dfef8ffb06 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -103,6 +103,9 @@ $dispatcher = patterns('', url_post('^/add$', 'addOrg'), url_get('^/select$', 'selectOrg'), url_get('^/select/(?P<id>\d+)$', 'selectOrg'), + url_get('^/(?P<id>\d+)/add-user(?:/(?P<userid>\d+))?$', 'addUser'), + url_get('^/(?P<id>\d+)/add-user(?:/auth:(?P<userid>.+))?$', 'addUser', array(true)), + url_post('^/(?P<id>\d+)/add-user$', 'addUser'), url_get('^/(?P<id>\d+)/delete$', 'delete'), url_delete('^/(?P<id>\d+)/delete$', 'delete') )), diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql index acd48f9bb4cc395860fb93293a6b6e470d2ed2e8..20c3dc3460c7cb3f323d1f6425e0844d9b6ffa3d 100644 --- a/setup/inc/streams/core/install-mysql.sql +++ b/setup/inc/streams/core/install-mysql.sql @@ -203,6 +203,7 @@ CREATE TABLE `%TABLE_PREFIX%draft` ( `staff_id` int(11) unsigned NOT NULL, `namespace` varchar(32) NOT NULL DEFAULT '', `body` text NOT NULL, + `extra` text, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) @@ -429,9 +430,9 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%organization`; CREATE TABLE `%TABLE_PREFIX%organization` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(128) NOT NULL DEFAULT '', - `staff_id` int(10) unsigned NOT NULL DEFAULT '0', + `manager` varchar(16) NOT NULL DEFAULT '', `status` int(11) unsigned NOT NULL DEFAULT '0', - `domain` varchar(128) NOT NULL DEFAULT '', + `domain` varchar(256) NOT NULL DEFAULT '', `extra` text, `created` timestamp NULL DEFAULT NULL, `updated` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, @@ -586,6 +587,7 @@ CREATE TABLE `%TABLE_PREFIX%ticket` ( `created` datetime NOT NULL, `updated` datetime NOT NULL, PRIMARY KEY (`ticket_id`), + KEY `user_id` (`user_id`), KEY `dept_id` (`dept_id`), KEY `staff_id` (`staff_id`), KEY `team_id` (`staff_id`), @@ -771,11 +773,14 @@ CREATE TABLE `%TABLE_PREFIX%plugin` ( DROP TABLE IF EXISTS `%TABLE_PREFIX%user`; CREATE TABLE `%TABLE_PREFIX%user` ( `id` int(10) unsigned NOT NULL auto_increment, + `org_id` int(10) unsigned NOT NULL, `default_email_id` int(10) NOT NULL, + `status` int(11) unsigned NOT NULL DEFAULT '0', `name` varchar(128) NOT NULL, `created` datetime NOT NULL, `updated` datetime NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `org_id` (`org_id`) ) DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `%TABLE_PREFIX%user_email`; @@ -792,7 +797,6 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%user_account`; CREATE TABLE `%TABLE_PREFIX%user_account` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL, - `org_id` int(11) unsigned NOT NULL, `status` int(11) unsigned NOT NULL DEFAULT '0', `timezone_id` int(11) NOT NULL DEFAULT '0', `dst` tinyint(1) NOT NULL DEFAULT '1', @@ -802,5 +806,6 @@ CREATE TABLE `%TABLE_PREFIX%user_account` ( `backend` varchar(32) DEFAULT NULL, `registered` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), + KEY `user_id` (`user_id`), UNIQUE KEY `username` (`username`) ) DEFAULT CHARSET=utf8;