diff --git a/include/class.auth.php b/include/class.auth.php index 4cbbea0359ea071be9791ad9b8dba85eeb82ee5e..fb055a5c379a706682a48d38b0e5a54e5622ab6d 100644 --- a/include/class.auth.php +++ b/include/class.auth.php @@ -1,9 +1,29 @@ <?php -require(INCLUDE_DIR.'class.ostsession.php'); -require(INCLUDE_DIR.'class.usersession.php'); +interface AuthenticatedUser { + // Get basic information + function getId(); + function getUsername(); + function getRole(); + + //Backend used to authenticate the user + function getAuthBackend(); -abstract class AuthenticatedUser { + //Authentication key + function setAuthKey($key); + + function getAuthKey(); + + // logOut the user + function logOut(); + + // Signal method to allow performing extra things when a user is logged + // into the sysem + function onLogin($bk); +} + +abstract class BaseAuthenticatedUser +implements AuthenticatedUser { //Authorization key returned by the backend used to authorize the user private $authkey; @@ -38,6 +58,9 @@ abstract class AuthenticatedUser { function onLogin($bk) {} } +require_once(INCLUDE_DIR.'class.ostsession.php'); +require_once(INCLUDE_DIR.'class.usersession.php'); + interface AuthDirectorySearch { /** * Indicates if the backend can be used to search for user information. @@ -509,7 +532,7 @@ abstract class StaffAuthenticationBackend extends AuthenticationBackend { protected function validate($authkey) { - if (($staff = new StaffSession($authkey)) && $staff->getId()) + if (($staff = StaffSession::lookup($authkey)) && $staff->getId()) return $staff; } } @@ -909,7 +932,7 @@ class osTicketAuthentication extends StaffAuthenticationBackend { static $id = "local"; function authenticate($username, $password) { - if (($user = new StaffSession($username)) && $user->getId() && + if (($user = StaffSession::lookup($username)) && $user->getId() && $user->check_passwd($password)) { //update last login && password reset stuff. @@ -940,7 +963,7 @@ class PasswordResetTokenBackend extends StaffAuthenticationBackend { return false; elseif (!($_config = new Config('pwreset'))) return false; - elseif (($staff = new StaffSession($_POST['userid'])) && + elseif (($staff = StaffSession::lookup($_POST['userid'])) && !$staff->getId()) $errors['msg'] = __('Invalid user-id given'); elseif (!($id = $_config->get($_POST['token'])) diff --git a/include/class.client.php b/include/class.client.php index e29f570b77e2c94b5ec8b6fb270165d9eef206a7..a8b39d1e5135bc69e01fccf9ef711bfbf32b613b 100644 --- a/include/class.client.php +++ b/include/class.client.php @@ -182,7 +182,7 @@ class TicketOwner extends TicketUser { * */ -class EndUser extends AuthenticatedUser { +class EndUser extends BaseAuthenticatedUser { protected $user; protected $_account = false; diff --git a/include/class.dept.php b/include/class.dept.php index c40effd262d2da8ef26420ee612fb35fbb70affb..9f07577d3add50087aaf8da7e1dc0b10bc5cdff5 100644 --- a/include/class.dept.php +++ b/include/class.dept.php @@ -25,7 +25,7 @@ class Dept extends VerySimpleModel { 'null' => true, ), 'manager' => array( - 'constraint' => array('manager_id' => 'StaffModel.staff_id'), + 'constraint' => array('manager_id' => 'Staff.staff_id'), ), 'groups' => array( 'reverse' => 'GroupDeptAccess.dept' @@ -89,7 +89,7 @@ class Dept extends VerySimpleModel { function getMembers($criteria=null) { if (!$this->members || $criteria) { - $members = StaffModel::objects() + $members = Staff::objects() ->filter(Q::any(array( 'dept_id' => $this->getId(), new Q(array( @@ -273,7 +273,7 @@ class Dept extends VerySimpleModel { // Default department cannot be deleted || $this->getId()==$cfg->getDefaultDeptId() // Department with users cannot be deleted - || StaffModel::objects() + || Staff::objects() ->filter(array('dept_id'=>$this->getId())) ->count() ) { diff --git a/include/class.group.php b/include/class.group.php index 0d9fd872a4f59d27ec8108a11789223ba535ae34..0a9dc94e138004ebfcdd8ef800d9ffebc026a8d8 100644 --- a/include/class.group.php +++ b/include/class.group.php @@ -44,7 +44,7 @@ class Group extends VerySimpleModel { } function getNumUsers(){ - return StaffModel::objects()->filter(array('group_id'=>$this->getId()))->count(); + return Staff::objects()->filter(array('group_id'=>$this->getId()))->count(); } function isEnabled(){ @@ -73,7 +73,7 @@ class Group extends VerySimpleModel { function getMembers() { if (!$this->members) { - $this->members = StaffModel::objects() + $this->members = Staff::objects() ->filter(array('group_id'=>$this->getId())) ->order_by('lastname', 'firstname') ->all(); diff --git a/include/class.staff.php b/include/class.staff.php index e157682c0fe0fc6c6cdec1e6c37b8eb711e5e3d8..77d5384befe7bc3f17dac41b6075f9b78766a2e7 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -22,10 +22,13 @@ include_once(INCLUDE_DIR.'class.passwd.php'); include_once(INCLUDE_DIR.'class.user.php'); include_once(INCLUDE_DIR.'class.auth.php'); -class StaffModel extends VerySimpleModel { +class Staff extends VerySimpleModel +implements AuthenticatedUser { + static $meta = array( 'table' => STAFF_TABLE, 'pk' => array('staff_id'), + 'select_related' => array('group'), 'joins' => array( 'dept' => array( 'constraint' => array('dept_id' => 'Dept.dept_id'), @@ -36,66 +39,17 @@ class StaffModel extends VerySimpleModel { ), ); - function getName() { - return $this->firstname . ' ' . $this->lastname; - } -} - -class Staff extends AuthenticatedUser { - - var $ht; - var $id; - - var $dept; + var $authkey; var $departments; - var $group; var $teams; var $timezone; - var $stats; - - function Staff($var) { - $this->id =0; - return ($this->load($var)); - } - - function load($var='') { - - if(!$var && !($var=$this->getId())) - return false; - - $sql='SELECT staff.created as added, grp.*, staff.* ' - .' FROM '.STAFF_TABLE.' staff ' - .' LEFT JOIN '.GROUP_TABLE.' grp ON(grp.group_id=staff.group_id) - WHERE '; + var $stats = array(); + var $_extra; - if (is_numeric($var)) - $sql .= 'staff_id='.db_input($var); - elseif (Validator::is_email($var)) - $sql .= 'email='.db_input($var); - elseif (is_string($var)) - $sql .= 'username='.db_input($var); - else - return null; - - if(!($res=db_query($sql)) || !db_num_rows($res)) - return NULL; - - - $this->ht=db_fetch_array($res); - $this->id = $this->ht['staff_id']; - $this->teams = $this->ht['teams'] = array(); - $this->group = $this->dept = null; - $this->departments = $this->stats = array(); - - //WE have to patch info here to support upgrading from old versions. - if(($time=strtotime($this->ht['passwdreset']?$this->ht['passwdreset']:$this->ht['added']))) - $this->ht['passwd_change'] = time()-$time; //XXX: check timezone issues. - - return ($this->id); - } - - function reload() { - return $this->load(); + function __onload() { + // WE have to patch info here to support upgrading from old versions. + if ($time=strtotime($this->passwdreset ?: (isset($this->added) ? $this->added : ''))) + $this->passwd_change = time()-$time; //XXX: check timezone issues. } function __toString() { @@ -125,6 +79,23 @@ class Staff extends AuthenticatedUser { return StaffAuthenticationBackend::getBackend($authkey); } + function setAuthKey($key) { + $this->authkey = $key; + } + + function getAuthKey() { + return $this->authkey; + } + + // logOut the user + function logOut() { + + if ($bk = $this->getAuthBackend()) + return $bk->signOut($this); + + return false; + } + /*compares user password*/ function check_passwd($password, $autoupdate=true) { @@ -137,10 +108,9 @@ class Staff extends AuthenticatedUser { return false; //Password is a MD5 hash: rehash it (if enabled) otherwise force passwd change. - $sql='UPDATE '.STAFF_TABLE.' SET passwd='.db_input(Passwd::hash($password)) - .' WHERE staff_id='.db_input($this->getId()); + $this->passwd = Passwd::hash($password); - if(!$autoupdate || !db_query($sql)) + if(!$autoupdate || !$this->save()) $this->forcePasswdRest(); return true; @@ -151,18 +121,19 @@ class Staff extends AuthenticatedUser { } function hasPassword() { - return (bool) $this->ht['passwd']; + return (bool) $this->passwd; } function forcePasswdRest() { - return db_query('UPDATE '.STAFF_TABLE.' SET change_passwd=1 WHERE staff_id='.db_input($this->getId())); + $this->change_passwd = 1; + return $this->update(); } /* check if passwd reset is due. */ function isPasswdResetDue() { global $cfg; return ($cfg && $cfg->getPasswdResetPeriod() - && $this->ht['passwd_change']>($cfg->getPasswdResetPeriod()*30*24*60*60)); + && $this->passwd_change>($cfg->getPasswdResetPeriod()*30*24*60*60)); } function isPasswdChangeDue() { @@ -170,81 +141,81 @@ class Staff extends AuthenticatedUser { } function getRefreshRate() { - return $this->ht['auto_refresh_rate']; + return $this->auto_refresh_rate; } function getPageLimit() { - return $this->ht['max_page_size']; + return $this->max_page_size; } function getId() { - return $this->id; + return $this->staff_id; } function getEmail() { - return $this->ht['email']; + return $this->email; } function getUserName() { - return $this->ht['username']; + return $this->username; } function getPasswd() { - return $this->ht['passwd']; + return $this->passwd; } function getName() { - return new PersonsName($this->ht['firstname'].' '.$this->ht['lastname']); + return new PersonsName($this->firstname.' '.$this->lastname); } function getFirstName() { - return $this->ht['firstname']; + return $this->firstname; } function getLastName() { - return $this->ht['lastname']; + return $this->lastname; } function getSignature() { - return $this->ht['signature']; + return $this->signature; } function getDefaultSignatureType() { - return $this->ht['default_signature_type']; + return $this->default_signature_type; } function getDefaultPaperSize() { - return $this->ht['default_paper_size']; + return $this->default_paper_size; } function forcePasswdChange() { - return ($this->ht['change_passwd']); + return $this->change_passwd; } function getDepartments() { - if($this->departments) + if (isset($this->departments)) return $this->departments; - //Departments the staff is "allowed" to access... + // Departments the staff is "allowed" to access... // based on the group they belong to + user's primary dept + user's managed depts. - $sql='SELECT DISTINCT d.dept_id FROM '.STAFF_TABLE.' s ' - .' LEFT JOIN '.GROUP_DEPT_TABLE.' g ON(s.group_id=g.group_id) ' - .' INNER JOIN '.DEPT_TABLE.' d ON(d.dept_id=s.dept_id OR d.manager_id=s.staff_id OR d.dept_id=g.dept_id) ' - .' WHERE s.staff_id='.db_input($this->getId()); - - $depts = array(); - if(($res=db_query($sql)) && db_num_rows($res)) { - while(list($id)=db_fetch_row($res)) - $depts[] = $id; - } else { //Neptune help us! (fallback) - $depts = array_merge($this->getGroup()->getDepartments(), array($this->getDeptId())); + $dept_ids = array(); + $depts = Dept::objects() + ->filter(Q::any(array( + 'dept_id' => $this->dept_id, + 'groups__group_id' => $this->group_id, + 'manager_id' => $this->getId(), + ))) + ->values_flat('dept_id'); + + foreach ($depts as $row) { + list($id) = $row; + $dept_ids[] = $id; } - - $this->departments = array_filter(array_unique($depts)); - - - return $this->departments; + if (!$dept_ids) { //Neptune help us! (fallback) + $dept_ids = array_merge($this->getGroup()->getDepartments(), array($this->getDeptId())); + } + return $this->departments = array_filter(array_unique($dept_ids)); } function getDepts() { @@ -259,39 +230,31 @@ class Staff extends AuthenticatedUser { } function getGroupId() { - return $this->ht['group_id']; + return $this->group_id; } function getGroup() { - - if(!$this->group && $this->getGroupId()) - $this->group = Group::lookup($this->getGroupId()); - return $this->group; } function getDeptId() { - return $this->ht['dept_id']; + return $this->dept_id; } function getDept() { - - if(!$this->dept && $this->getDeptId()) - $this->dept= Dept::lookup($this->getDeptId()); - return $this->dept; } function getLanguage() { - return $this->ht['lang']; + return $this->lang; } function getTimezone() { - return $this->ht['timezone']; + return $this->timezone; } function getLocale() { - return $this->ht['locale']; + return $this->locale; } function isManager() { @@ -303,19 +266,19 @@ class Staff extends AuthenticatedUser { } function isGroupActive() { - return ($this->ht['group_enabled']); + return $this->group->group_enabled; } function isactive() { - return ($this->ht['isactive']); + return $this->isactive; } function isVisible() { - return ($this->ht['isvisible']); + return $this->isvisible; } function onVacation() { - return ($this->ht['onvacation']); + return $this->onvacation; } function isAvailable() { @@ -323,7 +286,7 @@ class Staff extends AuthenticatedUser { } function showAssignedOnly() { - return ($this->ht['assigned_only']); + return $this->assigned_only; } function isAccessLimited() { @@ -331,7 +294,7 @@ class Staff extends AuthenticatedUser { } function isAdmin() { - return ($this->ht['isadmin']); + return $this->isadmin; } function isTeamMember($teamId) { @@ -343,39 +306,39 @@ class Staff extends AuthenticatedUser { } function canCreateTickets() { - return ($this->ht['can_create_tickets']); + return $this->group->can_create_tickets; } function canEditTickets() { - return ($this->ht['can_edit_tickets']); + return $this->group->can_edit_tickets; } function canDeleteTickets() { - return ($this->ht['can_delete_tickets']); + return $this->group->can_delete_tickets; } function canCloseTickets() { - return ($this->ht['can_close_tickets']); + return $this->group->can_close_tickets; } function canPostReply() { - return ($this->ht['can_post_ticket_reply']); + return $this->group->can_post_ticket_reply; } function canViewStaffStats() { - return ($this->ht['can_view_staff_stats']); + return $this->group->can_view_staff_stats; } function canAssignTickets() { - return ($this->ht['can_assign_tickets']); + return $this->group->can_assign_tickets; } function canTransferTickets() { - return ($this->ht['can_transfer_tickets']); + return $this->group->can_transfer_tickets; } function canBanEmails() { - return ($this->ht['can_ban_emails']); + return $this->group->can_ban_emails; } function canManageTickets() { @@ -385,7 +348,7 @@ class Staff extends AuthenticatedUser { } function canManagePremade() { - return ($this->ht['can_manage_premade']); + return $this->group->can_manage_premade; } function canManageCannedResponses() { @@ -393,7 +356,7 @@ class Staff extends AuthenticatedUser { } function canManageFAQ() { - return ($this->ht['can_manage_faq']); + return $this->group->can_manage_faq; } function canManageFAQs() { @@ -401,12 +364,13 @@ class Staff extends AuthenticatedUser { } function showAssignedTickets() { - return ($this->ht['show_assigned_tickets']); + return $this->group->show_assigned_tickets; } function getTeams() { - if(!$this->teams) { + if (!isset($this->teams)) { + $this->teams = array(); $sql='SELECT team_id FROM '.TEAM_MEMBER_TABLE .' WHERE staff_id='.db_input($this->getId()); if(($res=db_query($sql)) && db_num_rows($res)) @@ -441,20 +405,18 @@ class Staff extends AuthenticatedUser { function getExtraAttr($attr=false, $default=null) { if (!isset($this->_extra)) - $this->_extra = JsonDataParser::decode($this->ht['extra']); + $this->_extra = JsonDataParser::decode($this->extra); return $attr ? (@$this->_extra[$attr] ?: $default) : $this->_extra; } function setExtraAttr($attr, $value, $commit=true) { $this->getExtraAttr(); - $this->extra[$attr] = $value; + $this->_extra[$attr] = $value; if ($commit) { - $sql='UPDATE '.STAFF_TABLE.' SET ' - .'`extra`='.db_input(JsonDataEncoder::encode($this->extra)) - .' WHERE staff_id='.db_input($this->getId()); - db_query($sql); + $this->extra = JsonDataEncoder::encode($this->_extra); + $this->save(); } } @@ -464,12 +426,8 @@ class Staff extends AuthenticatedUser { Internationalization::getCurrentLanguage(), false); - $sql='UPDATE '.STAFF_TABLE.' SET ' - // Update time of last login - .' `lastlogin`=NOW() ' - .', `extra`='.db_input(JsonDataEncoder::encode($this->extra)) - .' WHERE staff_id='.db_input($this->getId()); - db_query($sql); + $this->lastlogin = SqlFunction::NOW(); + $this->save(); } //Staff profile update...unfortunately we have to separate it from admin update to avoid potential issues @@ -479,7 +437,7 @@ class Staff extends AuthenticatedUser { $vars['firstname']=Format::striptags($vars['firstname']); $vars['lastname']=Format::striptags($vars['lastname']); - if($this->getId()!=$vars['id']) + if (isset($this->staff_id) && $this->getId() != $vars['id']) $errors['err']=__('Internal error occurred'); if(!$vars['firstname']) @@ -492,7 +450,8 @@ class Staff extends AuthenticatedUser { $errors['email']=__('Valid email is required'); elseif(Email::getIdByEmail($vars['email'])) $errors['email']=__('Already in-use as system email'); - elseif(($uid=Staff::getIdByEmail($vars['email'])) && $uid!=$this->getId()) + elseif (($uid=static::getIdByEmail($vars['email'])) + && (!isset($this->staff_id) || $uid!=$this->getId())) $errors['email']=__('Email already in-use by another agent'); if($vars['phone'] && !Validator::is_phone($vars['phone'])) @@ -536,113 +495,114 @@ class Staff extends AuthenticatedUser { $_SESSION['staff:lang'] = null; TextDomain::configureForUser($this); - $sql='UPDATE '.STAFF_TABLE.' SET updated=NOW() ' - .' ,firstname='.db_input($vars['firstname']) - .' ,lastname='.db_input($vars['lastname']) - .' ,email='.db_input($vars['email']) - .' ,phone="'.db_input(Format::phone($vars['phone']),false).'"' - .' ,phone_ext='.db_input($vars['phone_ext']) - .' ,mobile="'.db_input(Format::phone($vars['mobile']),false).'"' - .' ,signature='.db_input(Format::sanitize($vars['signature'])) - .' ,timezone='.db_input($vars['timezone']) - .' ,locale='.db_input($vars['locale']) - .' ,show_assigned_tickets='.db_input(isset($vars['show_assigned_tickets'])?1:0) - .' ,max_page_size='.db_input($vars['max_page_size']) - .' ,auto_refresh_rate='.db_input($vars['auto_refresh_rate']) - .' ,default_signature_type='.db_input($vars['default_signature_type']) - .' ,default_paper_size='.db_input($vars['default_paper_size']) - .' ,lang='.db_input($vars['lang']); - - if($vars['passwd1']) { - $sql.=' ,change_passwd=0, passwdreset=NOW(), passwd='.db_input(Passwd::hash($vars['passwd1'])); + $this->firstname = $vars['firstname']; + $this->lastname = $vars['lastname']; + $this->email = $vars['email']; + $this->phone = Format::phone($vars['phone']); + $this->phone_ext = $vars['phone_ext']; + $this->mobile = Format::phone($vars['mobile']); + $this->signature = Format::sanitize($vars['signature']); + $this->timezone = $vars['timezone']; + $this->locale = $vars['locale']; + $this->show_assigned_tickets = isset($vars['show_assigned_tickets'])?1:0; + $this->max_page_size = $vars['max_page_size']; + $this->auto_refresh_rate = $vars['auto_refresh_rate']; + $this->default_signature_type = $vars['default_signature_type']; + $this->default_paper_size = $vars['default_paper_size']; + $this->lang = $vars['lang']; + + if ($vars['passwd1']) { + $this->change_passwd = 0; + $this->passwdreset = SqlFunction::NOW(); + $this->passwd = Passwd::hash($vars['passwd1']); $info = array('password' => $vars['passwd1']); Signal::send('auth.pwchange', $this, $info); $this->cancelResetTokens(); } - $sql.=' WHERE staff_id='.db_input($this->getId()); - - //echo $sql; - - return (db_query($sql)); - } - - - function updateTeams($teams) { - - if($teams) { - foreach($teams as $k=>$id) { - $sql='INSERT IGNORE INTO '.TEAM_MEMBER_TABLE.' SET updated=NOW() ' - .' ,staff_id='.db_input($this->getId()).', team_id='.db_input($id); - db_query($sql); + return $this->save(); + } + + function updateTeams($team_ids) { + if ($team_ids && is_array($team_ids)) { + $teams = TeamMember::object() + ->filter(array('staff_id' => $this->getId())); + foreach ($team_ids as $member) { + if ($idx = array_search($member->team_id, $team_ids)) { + // XXX: Do we really need to track the time of update? + $member->updated = SqlFunction::NOW(); + $member->save(); + unset($team_ids[$idx]); + } + else { + $member->delete(); + } + } + foreach ($team_ids as $id) { + TeamMember::create(array( + 'updated'=>SqlFunction::NOW(), + 'staff_id'=>$this->getId(), 'team_id'=>$id + ))->save(); } } - - $sql='DELETE FROM '.TEAM_MEMBER_TABLE.' WHERE staff_id='.db_input($this->getId()); - if($teams) - $sql.=' AND team_id NOT IN('.implode(',', db_input($teams)).')'; - - db_query($sql); - return true; } - function update($vars, &$errors) { + function delete() { + global $thisstaff; - if(!$this->save($this->getId(), $vars, $errors)) + if (!$thisstaff || $this->getId() == $thisstaff->getId()) return false; - $this->updateTeams($vars['teams']); - $this->reload(); + if (!parent::delete()) + return false; - Signal::send('model.modified', $this); + // DO SOME HOUSE CLEANING + //Move remove any ticket assignments...TODO: send alert to Dept. manager? + db_query('UPDATE '.TICKET_TABLE.' SET staff_id=0 WHERE staff_id='.db_input($this->getId())); - return true; - } - - function delete() { - global $thisstaff; + //Update the poster and clear staff_id on ticket thread table. + db_query('UPDATE '.TICKET_THREAD_TABLE + .' SET staff_id=0, poster= '.db_input($this->getName()->getOriginal()) + .' WHERE staff_id='.db_input($this->getId())); - if (!$thisstaff || $this->getId() == $thisstaff->getId()) - return 0; - - $sql='DELETE FROM '.STAFF_TABLE - .' WHERE staff_id = '.db_input($this->getId()).' LIMIT 1'; - if(db_query($sql) && ($num=db_affected_rows())) { - // DO SOME HOUSE CLEANING - //Move remove any ticket assignments...TODO: send alert to Dept. manager? - db_query('UPDATE '.TICKET_TABLE.' SET staff_id=0 WHERE staff_id='.db_input($this->getId())); - - //Update the poster and clear staff_id on ticket thread table. - db_query('UPDATE '.TICKET_THREAD_TABLE - .' SET staff_id=0, poster= '.db_input($this->getName()->getOriginal()) - .' WHERE staff_id='.db_input($this->getId())); - - //Cleanup Team membership table. - db_query('DELETE FROM '.TEAM_MEMBER_TABLE.' WHERE staff_id='.db_input($this->getId())); - } + // Cleanup Team membership table. + TeamMember::objects() + ->filter(array('staff_id'=>$this->getId())) + ->delete(); - Signal::send('model.deleted', $this); - - return $num; + return true; } /**** Static functions ********/ - function getStaffMembers($availableonly=false) { + static function lookup($var) { + if (is_array($var)) + return parent::lookup($var); + elseif (is_numeric($var)) + return parent::lookup(array('staff_id'=>$var)); + elseif (Validator::is_email($var)) + return parent::lookup(array('email'=>$var)); + elseif (is_string($var)) + return parent::lookup(array('username'=>$var)); + else + return null; + } + + static function getStaffMembers($availableonly=false) { - $sql='SELECT s.staff_id, CONCAT_WS(" ", s.firstname, s.lastname) as name ' - .' FROM '.STAFF_TABLE.' s '; + $members = static::objects()->order_by('lastname', 'firstname'); - if($availableonly) { - $sql.=' INNER JOIN '.GROUP_TABLE.' g ON(g.group_id=s.group_id AND g.group_enabled=1) ' - .' WHERE s.isactive=1 AND s.onvacation=0'; + if ($availableonly) { + $members = $members->filter(array( + 'group__group_enabled' => 1, + 'onvacation' => 0, + 'isactive' => 1, + )); } - $sql.=' ORDER BY s.lastname, s.firstname'; $users=array(); - if(($res=db_query($sql)) && db_num_rows($res)) { - while(list($id, $name) = db_fetch_row($res)) - $users[$id] = $name; + foreach ($members as $M) { + $users[$S->id] = $M->getName(); } return $users; @@ -652,38 +612,23 @@ class Staff extends AuthenticatedUser { return self::getStaffMembers(true); } - function getIdByUsername($username) { - - $sql='SELECT staff_id FROM '.STAFF_TABLE.' WHERE username='.db_input($username); - if(($res=db_query($sql)) && db_num_rows($res)) - list($id) = db_fetch_row($res); - - return $id; - } - function getIdByEmail($email) { - - $sql='SELECT staff_id FROM '.STAFF_TABLE.' WHERE email='.db_input($email); - if(($res=db_query($sql)) && db_num_rows($res)) - list($id) = db_fetch_row($res); - - return $id; + static function getIdByUsername($username) { + $row = static::objects()->filter(array('username' => $username)) + ->values_flat('staff_id')->first(); + return $row ? $row[0] : 0; } - function lookup($id) { - return ($id && ($staff= new Staff($id)) && $staff->getId()) ? $staff : null; + function getIdByEmail($email) { + $row = static::objects()->filter(array('email' => $email)) + ->values_flat('staff_id')->first(); + return $row ? $row[0] : 0; } - function create($vars, &$errors) { - if(($id=self::save(0, $vars, $errors)) && ($staff=Staff::lookup($id))) { - if ($vars['teams']) - $staff->updateTeams($vars['teams']); - if ($vars['welcome_email']) - $staff->sendResetEmail('registration-staff'); - Signal::send('model.created', $staff); - } - - return $id; + static function create($vars=false) { + $staff = parent::create($vars); + $staff->created = SqlFunction::NOW(); + return $staff; } function cancelResetTokens() { @@ -736,7 +681,7 @@ class Staff extends AuthenticatedUser { $email->getEmail() ), false); - $lang = $this->ht['lang'] ?: $this->getExtraAttr('browser_lang'); + $lang = $this->lang ?: $this->getExtraAttr('browser_lang'); $msg = $ost->replaceTemplateVariables(array( 'subj' => $content->getLocalName($lang), 'body' => $content->getLocalBody($lang), @@ -749,13 +694,19 @@ class Staff extends AuthenticatedUser { $msg['body']); } - function save($id, $vars, &$errors) { + function save($refetch=false) { + if ($this->dirty) + $this->updated = SqlFunction::NOW(); + return parent::save($refetch || $this->dirty); + } + + function update($vars, &$errors) { $vars['username']=Format::striptags($vars['username']); $vars['firstname']=Format::striptags($vars['firstname']); $vars['lastname']=Format::striptags($vars['lastname']); - if($id && $id!=$vars['id']) + if (isset($this->staff_id) && $this->getId() != $vars['id']) $errors['err']=__('Internal Error'); if(!$vars['firstname']) @@ -766,14 +717,16 @@ class Staff extends AuthenticatedUser { $error = ''; if(!$vars['username'] || !Validator::is_username($vars['username'], $error)) $errors['username']=($error) ? $error : __('Username is required'); - elseif(($uid=Staff::getIdByUsername($vars['username'])) && $uid!=$id) + elseif (($uid=static::getIdByUsername($vars['username'])) + && (!isset($this->staff_id) || $uid!=$this->getId())) $errors['username']=__('Username already in use'); if(!$vars['email'] || !Validator::is_email($vars['email'])) $errors['email']=__('Valid email is required'); elseif(Email::getIdByEmail($vars['email'])) $errors['email']=__('Already in use system email'); - elseif(($uid=Staff::getIdByEmail($vars['email'])) && $uid!=$id) + elseif (($uid=static::getIdByEmail($vars['email'])) + && (!isset($this->staff_id) || $uid!=$this->getId())) $errors['email']=__('Email already in use by another agent'); if($vars['phone'] && !Validator::is_phone($vars['phone'])) @@ -803,55 +756,63 @@ class Staff extends AuthenticatedUser { if(!$vars['group_id']) $errors['group_id']=__('Group is required'); - if($errors) return false; - + if ($errors) + return false; - $sql='SET updated=NOW() ' - .' ,isadmin='.db_input($vars['isadmin']) - .' ,isactive='.db_input($vars['isactive']) - .' ,isvisible='.db_input(isset($vars['isvisible'])?1:0) - .' ,onvacation='.db_input(isset($vars['onvacation'])?1:0) - .' ,assigned_only='.db_input(isset($vars['assigned_only'])?1:0) - .' ,dept_id='.db_input($vars['dept_id']) - .' ,group_id='.db_input($vars['group_id']) - .' ,timezone='.db_input($vars['timezone']) - .' ,username='.db_input($vars['username']) - .' ,firstname='.db_input($vars['firstname']) - .' ,lastname='.db_input($vars['lastname']) - .' ,email='.db_input($vars['email']) - .' ,backend='.db_input($vars['backend']) - .' ,phone="'.db_input(Format::phone($vars['phone']),false).'"' - .' ,phone_ext='.db_input($vars['phone_ext']) - .' ,mobile="'.db_input(Format::phone($vars['mobile']),false).'"' - .' ,signature='.db_input(Format::sanitize($vars['signature'])) - .' ,notes='.db_input(Format::sanitize($vars['notes'])); - - if($vars['passwd1']) { - $sql.=' ,passwd='.db_input(Passwd::hash($vars['passwd1'])); - - if(isset($vars['change_passwd'])) - $sql.=' ,change_passwd=1'; + $this->isadmin = $vars['isadmin']; + $this->isactive = $vars['isactive']; + $this->isvisible = isset($vars['isvisible'])?1:0; + $this->onvacation = isset($vars['onvacation'])?1:0; + $this->assigned_only = isset($vars['assigned_only'])?1:0; + $this->dept_id = $vars['dept_id']; + $this->group_id = $vars['group_id']; + $this->timezone = $vars['timezone']; + $this->username = $vars['username']; + $this->firstname = $vars['firstname']; + $this->lastname = $vars['lastname']; + $this->email = $vars['email']; + $this->backend = $vars['backend']; + $this->phone = Format::phone($vars['phone']); + $this->phone_ext = $vars['phone_ext']; + $this->mobile = Format::phone($vars['mobile']); + $this->signature = Format::sanitize($vars['signature']); + $this->notes = Format::sanitize($vars['notes']); + + if ($vars['passwd1']) { + $this->passwd = Passwd::hash($vars['passwd1']); + if (isset($vars['change_passwd'])) + $this->change_passwd = 1; + } + elseif (!isset($vars['change_passwd'])) { + $this->change_passwd = 0; } - elseif (!isset($vars['change_passwd'])) - $sql .= ' ,change_passwd=0'; - if($id) { - $sql='UPDATE '.STAFF_TABLE.' '.$sql.' WHERE staff_id='.db_input($id); - if(db_query($sql) && db_affected_rows()) - return true; + if ($this->save() && $this->updateTeams($vars['teams'])) { + if ($vars['welcome_email']) + $this->sendResetEmail('registration-staff'); + return true; + } + if (isset($this->staff_id)) { $errors['err']=sprintf(__('Unable to update %s.'), __('this agent')) .' '.__('Internal error occurred'); } else { - $sql='INSERT INTO '.STAFF_TABLE.' '.$sql.', created=NOW()'; - if(db_query($sql) && ($uid=db_insert_id())) - return $uid; - $errors['err']=sprintf(__('Unable to create %s.'), __('this agent')) .' '.__('Internal error occurred'); } - return false; } } + +class StaffTeamMember extends VerySimpleModel { + static $meta = array( + 'table' => TEAM_MEMBER_TABLE, + 'pk' => array('staff_id', 'team_id'), + 'joins' => array( + 'staff' => array( + 'constraint' => array('staff_id' => 'Staff.staff_id'), + ), + ), + ); +} ?> diff --git a/include/class.ticket.php b/include/class.ticket.php index 4ca2477a3b8d39652ca5ec086f9180aea85f2935..3183caf8242f7f59520ee1431023c58ca04d0a29 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -54,7 +54,7 @@ class TicketModel extends VerySimpleModel { 'constraint' => array('dept_id' => 'Dept.dept_id'), ), 'staff' => array( - 'constraint' => array('staff_id' => 'StaffModel.staff_id'), + 'constraint' => array('staff_id' => 'Staff.staff_id'), 'null' => true, ), 'team' => array( diff --git a/include/class.topic.php b/include/class.topic.php index e4afba9c0cfee7a28352d3075d8489804ca7c7dc..ba9e1a82788c2d83c345f28f4b5f52b52de8ffe5 100644 --- a/include/class.topic.php +++ b/include/class.topic.php @@ -15,6 +15,7 @@ **********************************************************************/ require_once INCLUDE_DIR . 'class.sequence.php'; +require_once INCLUDE_DIR . 'class.filter.php'; class Topic extends VerySimpleModel { diff --git a/include/class.usersession.php b/include/class.usersession.php index 9e7fd277baf58d59b39ade1255bd29a1308493a4..999d3adb4f550554f25a71fcb8d654723a5cd81e 100644 --- a/include/class.usersession.php +++ b/include/class.usersession.php @@ -161,10 +161,11 @@ class StaffSession extends Staff { var $session; var $token; - function __construct($var) { - parent::__construct($var); - $this->token = &$_SESSION[':token']['staff']; - $this->session= new UserSession($this->getId()); + static function lookup($var) { + $staff = parent::lookup($var); + $staff->token = &$_SESSION[':token']['staff']; + $staff->session= new UserSession($staff->getId()); + return $staff; } function isValid(){ diff --git a/scp/staff.php b/scp/staff.php index 0ad72c2a1cc518be449f69902044dc860e712711..384af7df0771efdeafd05a8684aa03114950b899 100644 --- a/scp/staff.php +++ b/scp/staff.php @@ -33,7 +33,8 @@ if($_POST){ } break; case 'create': - if(($id=Staff::create($_POST,$errors))){ + $staff = Staff::create(); + if ($staff->update($_POST,$errors)) { $msg=sprintf(__('Successfully added %s'),Format::htmlchars($_POST['firstname'])); $_REQUEST['a']=null; }elseif(!$errors['err']){