Skip to content
Permalink
Browse files

Audits Feature

This commit adds the functionality for the Audits view to be available within Tickets, User Directory, Admin Dashboard, and Agents section
  • Loading branch information...
aydreeihn committed Jan 18, 2019
1 parent 8e3fd4d commit bb3d092e5f844445bec739eafd63a54e0366f318
@@ -34,7 +34,7 @@
$user_form = $f;
$user_form->getField('email')->configure('disabled', true);
}
}
}
}
// Existing client (with an account) updating profile
else {
@@ -125,4 +125,3 @@
include(CLIENTINC_DIR.'header.inc.php');
include(CLIENTINC_DIR.$inc);
include(CLIENTINC_DIR.'footer.inc.php');
@@ -488,6 +488,9 @@ function login($staff, $bk) {
sprintf(_S("%s logged in [%s], via %s"), $staff->getUserName(),
$_SERVER['REMOTE_ADDR'], get_class($bk))); //Debug.
$type = array('type' => 'Login', 'data' => array('id' => $staff->getId(), 'name' => $staff->getName()->name));
Signal::send('staff.login', $staff, $type);
// Tag the authkey.
$authkey = $bk::$id.':'.$authkey;
@@ -528,6 +531,8 @@ static function signOut($staff) {
$staff->getUserName(),
$_SERVER['REMOTE_ADDR'])); //Debug.
$type = array('type' => 'Logout', 'data' => array('id' => $staff->getId(), 'name' => $staff->getName()->name));
Signal::send('staff.logout', $staff, $type);
Signal::send('auth.logout', $staff);
}
@@ -677,7 +682,6 @@ function login($user, $bk) {
$user->getUserName(), $user->getId(), $_SERVER['REMOTE_ADDR']);
$ost->logDebug(_S('User login'), $msg);
// Allow audit and other external interaction
$type = array('type' => 'Login', 'data' => array('id' => $user->getId(), 'name' => $user->getName()->name));
Signal::send('user.login', $user, $type);
@@ -717,7 +721,6 @@ static function signOut($user) {
sprintf(_S("%s logged out [%s]" /* Tokens are <username> and <ip> */),
$user->getUserName(), $_SERVER['REMOTE_ADDR']));
// Allow audit and other external interaction
$type = array('type' => 'Logout', 'data' => array('id' => $user->getId(), 'name' => $user->getName()->name));
Signal::send('user.logout', $user, $type);
}
@@ -898,6 +901,19 @@ function authstrike($credentials) {
$admin_alert = ($cfg->alertONLoginError() == 1) ? TRUE : FALSE;
$ost->logWarning(sprintf(_S('Excessive login attempts (%s)'),$username),
$alert, $admin_alert);
if ($username) {
$staffId = Staff::objects()->filter(array('username'=>$username))->values_flat('staff_id')->first();
if ($staffId)
$staff = Staff::lookup($staffId[0]);
if ($staff) {
$type = array('type' => 'Login',
'data' => array('id' => $staff->getId(), 'name' => $staff->getName()->name,
'msg' => 'Excessive login attempts (' . $authsession['strikes'] . ')'));
Signal::send('staff.login', $staff, $type);
}
}
return new AccessDenied(__('Forgot your login info? Contact Admin.'));
//Log every other third failed login attempt as a warning.
} elseif($authsession['strikes']%3==0) {
@@ -959,7 +975,6 @@ function authstrike($credentials) {
$admin_alert = ($cfg->alertONLoginError() == 1 ? TRUE : FALSE);
$ost->logError(_S('Excessive login attempts (user)'), $alert, $admin_alert);
// Allow audit and other external interaction
if ($username) {
$account = UserAccount::lookupByUsername($username);
$id = UserEmailModel::getIdByEmail($username);
@@ -322,32 +322,46 @@ static function departmentMembers($dept, $agents, $filename='', $how='csv') {
exit;
}
static function audits($tableInfo, $user, $filename='', $how='csv') {
$sql = AuditEntry::objects()->filter(array('user_id'=>$user->getId()))->order_by('timestamp');
// Filename or stream to export to
$filename = $filename ?: sprintf('%s-%s.csv', $user->getName()->name,
strftime('%Y%m%d'));
static function audits($type, $filename='', $tableInfo='', $object='', $how='csv') {
$headings = array('Description', 'Timestamp', 'IP');
switch ($type) {
case 'audit':
$state = $_REQUEST['state'];
$sql = AuditEntry::objects()->filter(array('object_type'=>$_REQUEST['type']));
if ($state && $state != 'All')
$sql = $sql->filter(array('state'=>$state));
if ($_REQUEST['starttime'] && $_REQUEST['endtime'])
$sql = $sql->filter(array('timestamp__range' =>
array('"'.$_REQUEST['starttime'].'"', '"'.$_REQUEST['endtime'].'"', true)));
$sql = $sql->order_by('timestamp');
$tableInfo = $sql;
break;
case 'user':
$sql = AuditEntry::objects()->filter(array('user_id'=>$object->getId()))->order_by('timestamp');
break;
case 'staff':
// code...
break;
}
//Download the file
Http::download($filename, "text/$how");
echo self::dumpQuery($sql, array(
0 => 'ID',
1 => 'User Class',
2 => 'User Name',
3 => 'Object',
4 => 'Description',
5 => 'Timestamp',
6 => 'IP',
),
echo self::dumpQuery($sql, $headings,
$how,
array('modify' => function(&$record, $keys, $obj) use ($tableInfo) {
foreach ($tableInfo as $k => $v) {
if (is_numeric($k) && ($i = in_array($obj->id, $v)) !== false) {
$record[0] = $v['id'];
$record[1] = $v['class'];
$record[2] = $v['name'];
$record[3] = $v['object'];
$record[4] = $v['description'];
$record[5] = $v['timestamp'];
$record[6] = $v['ip'];
if (is_object($v)) {
$description = AuditEntry::getDescription($v, true);
$v = $v->ht;
}
if (is_numeric($k) && ($i = in_array(
is_array($obj->ht) ? $obj->ht['id'] : $obj->id,
$v)) !== false) {
$record[0] = $description ?: $v['description'];
$record[1] = $v['timestamp'];
$record[2] = $v['ip'];
}
}
return $record;
@@ -31,18 +31,18 @@ private function objects() {
static $objects = false;
if ($objects == false) {
$objects = array(
self::OBJECT_TYPE_TICKET => 'Ticket',
self::OBJECT_TYPE_THREAD => 'ThreadEntry',
self::OBJECT_TYPE_USER => 'User',
self::OBJECT_TYPE_ORG => 'Organization',
self::OBJECT_TYPE_FAQ => 'FAQ',
self::OBJECT_TYPE_FILE => 'AttachmentFile',
self::OBJECT_TYPE_TASK => 'Task',
self::OBJECT_TYPE_TEAM => 'Team',
self::OBJECT_TYPE_DEPT => 'Dept',
self::OBJECT_TYPE_STAFF => 'Staff',
self::OBJECT_TYPE_CHILD_TICKET => 'Ticket',
);
self::OBJECT_TYPE_TICKET => 'Ticket',
self::OBJECT_TYPE_THREAD => 'ThreadEntry',
self::OBJECT_TYPE_USER => 'User',
self::OBJECT_TYPE_ORG => 'Organization',
self::OBJECT_TYPE_FAQ => 'FAQ',
self::OBJECT_TYPE_FILE => 'AttachmentFile',
self::OBJECT_TYPE_TASK => 'Task',
self::OBJECT_TYPE_TEAM => 'Team',
self::OBJECT_TYPE_DEPT => 'Dept',
self::OBJECT_TYPE_STAFF => 'Staff',
self::OBJECT_TYPE_CHILD_TICKET => 'Ticket',
);
}
return $objects;
@@ -234,6 +234,7 @@ function getSubMenus(){
switch(strtolower($k)){
case 'dashboard':
$subnav[]=array('desc'=>__('System Logs'),'href'=>'logs.php','iconclass'=>'logs');
$subnav[]=array('desc'=>__('Audit Logs'),'href'=>'audits.php','iconclass'=>'open');
$subnav[]=array('desc'=>__('Information'),'href'=>'system.php','iconclass'=>'preferences');
break;
case 'settings':
@@ -521,6 +521,8 @@ static function fromVars($vars) {
}
Signal::send('organization.created', $org);
$type = array('type' => 'Created');
Signal::send('object.created', $org, $type);
return $org;
}
@@ -555,6 +555,10 @@ function setStatus($status, $comments='', &$errors=array()) {
$ecb = function ($t) use($thisstaff) {
$t->logEvent('reopened', false, null, 'closed');
$type = array('type' => 'Reopened', 'data' => array('name' => $this->getNumber()));
Signal::send('object.edited', $this, $type);
if ($t->ticket) {
$t->ticket->reopen();
$vars = array(
@@ -582,6 +586,9 @@ function setStatus($status, $comments='', &$errors=array()) {
$this->closed = SqlFunction::NOW();
$ecb = function($t) use($thisstaff) {
$t->logEvent('closed');
$type = array('type' => 'Closed', 'data' => array('name' => $t->getNumber()));
Signal::send('object.edited', $t, $type);
if ($t->ticket) {
$vars = array(
'title' => sprintf('Task %s Closed',
@@ -698,6 +705,9 @@ function assignToStaff($staff, $note, $alert=true) {
$this->logEvent('assigned', $data);
$type = array('type' => 'Assigned', 'data' => array('name' => $this->getNumber(), 'staff' => $staff->getName()->name));
Signal::send('object.edited', $this, $type);
return true;
}
@@ -706,6 +716,7 @@ function assign(AssignmentForm $form, &$errors, $alert=true) {
global $thisstaff;
$evd = array();
$audit = array();
$assignee = $form->getAssignee();
if ($assignee instanceof Staff) {
$dept = $this->getDept();
@@ -725,6 +736,7 @@ function assign(AssignmentForm $form, &$errors, $alert=true) {
$evd['claim'] = true;
else
$evd['staff'] = array($assignee->getId(), $assignee->getName());
$audit = array('name' => $this->getNumber(), 'staff' => $assignee->getName()->name);
}
} elseif ($assignee instanceof Team) {
if ($this->getTeamId() == $assignee->getId()) {
@@ -735,6 +747,7 @@ function assign(AssignmentForm $form, &$errors, $alert=true) {
} else {
$this->team_id = $assignee->getId();
$evd = array('team' => $assignee->getId());
$audit = array('name' => $this->getNumber(), 'team' => $assignee->getName());
}
} else {
$errors['assignee'] = __('Unknown assignee');
@@ -745,6 +758,9 @@ function assign(AssignmentForm $form, &$errors, $alert=true) {
$this->logEvent('assigned', $evd);
$type = array('type' => 'Assigned', 'data' => $audit);
Signal::send('object.edited', $this, $type);
$this->onAssignment($assignee,
$form->getField('comments')->getClean(),
$alert);
@@ -847,6 +863,9 @@ function transfer(TransferForm $form, &$errors, $alert=true) {
// Log transfer event
$this->logEvent('transferred');
$type = array('type' => 'Transferred', 'data' => array('name' => $this->getNumber(), 'dept' => $dept->getName()));
Signal::send('object.edited', $this, $type);
// Post internal note if any
$note = $form->getField('comments')->getClean();
if ($note) {
@@ -1298,6 +1317,8 @@ function update($forms, $vars, &$errors) {
if ($changes)
$this->logEvent('edited', array('fields' => $changes));
$type = array('type' => 'Edited', 'data' => array('name' => $this->getNumber(), 'fields' => $changes));
Signal::send('object.edited', $this, $type);
Signal::send('model.updated', $this);
return $this->save();
}
@@ -1349,6 +1370,9 @@ static function create($vars=false) {
$task->logEvent('created', null, $thisstaff);
$type = array('type' => 'Created');
Signal::send('object.created', $task, $type);
// Get role for the dept
$role = $thisstaff->getRole($task->getDept());
// Assignment
@@ -1382,6 +1406,9 @@ function delete($comments='') {
$thread->delete();
$this->logEvent('deleted');
$type = array('type' => 'Deleted', 'data' => array('name' => $this->getNumber()));
Signal::send('object.deleted', $this, $type);
Draft::deleteForNamespace('task.%.' . $this->getId());
foreach (DynamicFormEntry::forObject($this->getId(), ObjectModel::OBJECT_TYPE_TASK) as $form)
@@ -183,15 +183,23 @@ function addCollaborator($user, $vars, &$errors, $event=true) {

$this->_collaborators = null;

if ($event)
$this->getEvents()->log($this->getObject(),
'collab',
array('add' => array($user->getId() => array(
'name' => $user->getName()->getOriginal(),
'src' => @$vars['source'],
))
)
);
if ($event) {
$this->getEvents()->log($this->getObject(),
'collab',
array('add' => array($user->getId() => array(
'name' => $user->getName()->getOriginal(),
'src' => @$vars['source'],
))
)
);

$type = array('type' => 'Collaborator', 'data' => array('name' => $this->getObject()->getNumber(), 'add' => array($user->getId() => array(
'name' => $user->getName()->name,
'src' => @$vars['source'],
))));
Signal::send('object.created', $this->getObject(), $type);
}


return $c;
}
@@ -213,6 +221,9 @@ function updateCollaborators($vars, &$errors) {
$this->getEvents()->log($this->getObject(), 'collab', array(
'del' => array($c->user_id => array('name' => $c->getName()->getOriginal()))
));

$type = array('type' => 'Collaborator', 'data' => array('name' => $this->getObject()->getNumber(), 'del' => array($c->user_id => array('name' => $c->getName()->name))));
Signal::send('object.deleted', $this->getObject(), $type);
}
}

@@ -398,6 +398,9 @@ function resend($response) {
// Log an event that the item was resent
$object->logEvent('resent', array('entry' => $response->id));
$type = array('type' => 'Resent', 'data' => array('name' => $object->getNumber()));
Signal::send('object.edited', $object, $type);
// Flag the entry as resent
$response->flags |= ThreadEntry::FLAG_RESENT;
$response->save();

0 comments on commit bb3d092

Please sign in to comment.
You can’t perform that action at this time.