Odyssey
admAudit.prg
1 <?php
2 /**
3  * @package admAudit.prg
4  * Shows all admin audits.
5  */
6 
7 // For GetAuditTime().
8 require_once("$admLibrary/aAudit.i");
9 
10 $parameters = array("a" => array("operation" => ""));
11 $string = array("filter" => HCUFILTER_INPUT_STRING);
12 HCU_ImportVars($parameters, "a", array("operation" => $string));
13 extract($parameters["a"]);
14 
15 $operation = isset($operation) ? trim($operation) : "";
16 if ($operation != "") {
17  switch($operation) {
18  case "readAudits":
19  $parameters = array("a" => array("duration" => "", "auditUser" => "", "loggedInUser" => "", "actionType" => "", "startOn" => ""));
20  $string = array("filter" => HCUFILTER_INPUT_STRING);
21  HCU_ImportVars($parameters, "a", array("duration" => $string, "auditUser" => $string, "loggedInUser" => $string, "actionType" => $string, "startOn" => $string));
22  $returnArray = getAuditRecords($dbh, $Cu, $parameters["a"], $SYSENV["logger"]);
23  break;
24  default: // Won't get here
25  $returnArray = array("error" => array("Operation not specified: '$operation'"), "record" => array(), "sql" => array());
26  }
27 
28  header('Content-type: application/json');
29  print HCU_JsonEncode($returnArray);
30 } else {
31  PrintPage("$menu_link?ft=$ft", GetAuditTypes($dbh, $Cu), GetAuditRecords($dbh, $Cu, array("duration" => 30), $SYSENV["logger"]));
32 }
33 
34 /**
35  * function GetAuditTypes($dbh, $Cu)
36  * This will get the audit types from what is currently in the database.
37  *
38  * @param $dbh -- the database connection
39  * @param $Cu -- the credit union
40  *
41  * @return $status -- "000" if successful, nonzero otherwise.
42  * @return $error -- "" if successful, nonempty otherwise.
43  * @return $ddl -- the distinct types of audits for the query.
44  */
45 function GetAuditTypes($dbh, $Cu) {
46  try {
47  $sql = "select distinct auditfulldesc as text, auditaction as value from cuauditadmin";
48  $sth = db_query($sql, $dbh);
49  if (!$sth) {
50  throw new exception("Select query failed.", 1);
51  }
52  $ddl = array(array("text" => "All Types", "value" => ""));
53  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
54  $ddl[] = $row;
55  }
56 
57  $returnArray = array("status" => "000", "error" => "", "ddl" => $ddl);
58  } catch(exception $e) {
59  $returnArray = array("status" => $e->getCode(), "error" => $e->getMessage(), "ddl" => array());
60  }
61  return $returnArray;
62 }
63 
64 /**
65  * function GetAuditRecords($dbh, $Cu, $parameters)
66  * Gets the audit records
67  *
68  * @param $dbh -- the database connection
69  * @param string $Cu -- the credit union
70  * @param array $parameters -- the parameters for the audit record.
71  * @param object $logger -- logs to kibana
72  * @return [date:"", actioncode:"", user:"", script:"", action:"", rown:0, details: [{table:"", label:"", type:"",
73  * rows: [{type: "", values: [{col: "", before: "", after: "", label: "", same: false}, ...]}, ...]}, ... ]]
74  * Type can be "mixed", "add", "delete", or "update" at the table level. It cannot be "mixed" at the column level.
75  */
76 function GetAuditRecords($dbh, $Cu, $parameters, $logger) {
77  try {
78  extract($parameters);
79 
80  $duration = strtolower(isset($duration) ? trim($duration) : "");
81  $auditUser = strtolower(isset($auditUser) ? trim($auditUser) : "");
82  $loggedInUser = strtolower(isset($loggedInUser) ? trim($loggedInUser) : "");
83  $actionType = strtolower(isset($actionType) ? trim($actionType) : "");
84  $startOn = isset($startOn) ? trim($startOn) : "";
85 
86  $where = array("cu = '$Cu'");
87 
88  if ($duration == "") {
89  throw new exception("Duration is required.", 20);
90  }
91  switch($duration) {
92  case "all":
93  break;
94  case "30":
95  case "60":
96  case "90":
97  $date = new DateTime();
98  $date = DateTime::createFromFormat("Y-m-d", $date->format("Y-m-d")); // Remove time but keep the date.
99  $date->modify("-$duration days");
100  $date = $date->format("Y-m-d");
101  $where[] = "auditdate >= '$date'";
102  break;
103  case "on":
104  if ($startOn == "") {
105  throw new exception("Start On is required.", 21);
106  }
107  if (!DateTime::createFromFormat("Y-m-d", $startOn)) {
108  throw new exception("Start On is invalid.", 22);
109  }
110  $where[] = "auditdate >= '$startOn'";
111  break;
112  default:
113  throw new exception("Duration is invalid.", 23);
114  break;
115  }
116 
117  if ($auditUser != "") {
118  $where[] = "lower(user_name) = '" . prep_save($auditUser, 50) . "'";
119  }
120  if ($loggedInUser != "") {
121  $where[] = "lower(auditsrcuser_name) = '" . prep_save($loggedInUser, 50) . "'";
122  }
123  if ($actionType != "") {
124  $where[] = "lower(auditaction) = '" . prep_save($actionType, 10) . "'";
125  }
126 
127  $sql = "select auditdate as date, auditaction as actioncode, auditsrcuser_name as srcuser, user_name as user, auditrecbefore as before, auditrecafter as after,
128  auditsrccode_context as script, auditfulldesc as action, row_number() over (order by auditdate desc) as rown from cuauditadmin where " . implode(" and ", $where);
129  $sth = db_query($sql, $dbh);
130  if (!$sth) {
131  throw new exception("Audit query failed.", 12);
132  }
133  $auditRecords = array();
134  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
135  $results = ParseAuditRow($row, $Cu, $dbh);
136  if ($results["status"] !== "000") { // Audit row is invalid in the database. DO NOT KILL THE PAGE. Instead DO NOT DISPLAY and log error in Kibana.
137  $logger->error("Admin audit is invalid in the database. CU: $Cu, Audit Date: " . $row["date"]);
138  continue;
139  } else {
140  $row = $results["row"];
141  }
142  // #820 added and commented out reference. This is more a stage 3 new feature.
143  //addDetailedDescription($row);
144 
145  // Do date stuff
146  $tz = GetCreditUnionTimezone($dbh, $Cu);
147  $dateTime = new DateTime($row["date"]);
148  $dateTime->setTimezone(new DateTimeZone($tz));
149  $row["date"] = $dateTime->format("Y-m-d H:i:s.u") . "Z";
150 
151  $auditRecords[] = $row;
152  }
153 
154  $returnArray = array("code" => 0, "error" => array(), "auditRecords" => $auditRecords);
155  } catch(exception $e) {
156  $returnArray = array("code" => $e->getCode(), "error" => array($e->getMessage()), "auditRecords" => array());
157  }
158  return $returnArray;
159 }
160 
161 /**
162  * function PrintPage($self, $readData, $auditRecords)
163  * This function will print out the popup for the audit.
164  *
165  * @param $self -- the URL of this page.
166  * @param $readData -- the data needed for this page's load.
167  * @param $auditRecords -- the audit records for this page.
168  */
169 function PrintPage($self, $readData, $auditRecords) { ?>
170  <script type="text/javascript">
171  <?php // Library javascript functions
172  getShowWaitFunctions(); ?>
173 
174  function AddDays(date, numberofDays) {
175  var d = new Date(date);
176  return new Date(d.getFullYear(), d.getMonth(), (d.getDate() + numberofDays));
177  }
178 
179  <?php
180  /**
181  * function Init()
182  * Initializes everything. It is a super magical function.
183  */
184  ?>
185  function Init() {
186  $.homecuValidator.setup({formValidate: "searchForm", formStatusField: "formValidateDiv"});
187  var record = <?php echo HCU_JsonEncode($auditRecords); ?>;
188  var ddlError = <?php echo HCU_JsonEncode($readData["error"]); ?>;
189  if (record.error.length > 0) {
190  $.homecuValidator.displayMessage(record.error, $.homecuValidator.settings.statusError);
191  } else if (ddlError.length > 0) {
192  $.homecuValidator.displayMessage(ddlError, $.homecuValidator.settings.statusError);
193  } else {
194  var auditData = record.auditRecords;
195  <?php printAuditInit("all admin"); ?>
196  }
197 
198  var actionDDL = $("#actionDDL").kendoDropDownList({
199  dataSource: {
200  data: <?php echo HCU_JsonEncode($readData["ddl"]); ?>
201  },
202  dataTextField: "text",
203  dataValueField: "value"
204  }).data("kendoDropDownList");
205 
206  $("#okayBtn").click(function() {
207  if ($.homecuValidator.validate()) {
208  var duration = $("#durationDDL").data("kendoDropDownList").value();
209  var startOn = $("#startingDatePicker").data("kendoDatePicker").value();
210  startOn = startOn == null || duration != "on" ? "" : kendo.toString(startOn, "yyyy-MM-dd");
211  var parameters = {duration: duration, startOn: startOn, auditUser: $("[name='auditUser']").val().trim(), loggedInUser: $("[name='loggedInUser']").val().trim(),
212  actionType: actionDDL.value()};
213 
214  showWaitWindow();
215  $.post("<?php echo $self; ?>&operation=readAudits", parameters, function(data) {
216  hideWaitWindow();
217  auditData = data.auditRecords;
218 
219  if (data.error.length > 0) {
220  $.homecuValidator.displayMessage(data.error, $.homecuValidator.settings.statusError);
221  } else {
222  $("#auditGrid").data("kendoGrid").dataSource.read();
223  }
224  });
225  }
226  return false;
227  });
228 
229  $("[name='durationCheck']").click(function() {
230  var thisElement = this;
231  startingDatePicker.enable(($(thisElement).data("val") + "").trim() == "on");
232  });
233 
234  var now = new Date();
235  now.setHours(0, 0, 0, 0);
236  var all = new Date();
237  all.setHours(0, 0, 0, 0);
238  all.setDate(1);
239  all.setMonth((all.getMonth() - 1) % 12);
240  all.setFullYear(all.getFullYear() - 1);
241 
242  var minx = new Date();
243  minx.setHours(0, 0, 0, 0);
244  var min30 = AddDays(minx, -30);
245  var min60 = AddDays(minx, -60);
246  var min90 = AddDays(minx, -90);
247 
248  var startingDatePicker = $("#startingDatePicker").kendoDatePicker({
249  max: now,
250  min: all,
251  format: "MM/dd/yyyy", <?php // Add zeroes so that MTB looks okay. ?>
252  change: function() {
253  $("#durationDDL").data("kendoDropDownList").value("on"); <?php // Now doesn't align with the duration options. ?>
254  }
255  }).data("kendoDatePicker");
256 
257  $("#startingDatePicker").focus(function() { <?php // Clear out when selecting the date. ?>
258  $(this).val(null);
259  startingDatePicker.value(null);
260  });
261 
262  $("#startingDatePicker").blur(function() {
263  if ($(this).hasClass("k-invalid")) {
264  $(startingDatePicker.wrapper).css("border", "1px solid #d80000");
265  } else {
266  $(startingDatePicker.wrapper).css("border", "inherit");
267  }
268  });
269 
270  var durationDDL = $("#durationDDL").kendoDropDownList({
271  dataSource: {
272  data: [
273  {text: "Last 30 days", value: "30"},
274  {text: "Last 60 days", value: "60"},
275  {text: "Last 90 days", value: "90"},
276  {text: "All Available", value: "all"},
277  {text: "Custom", value: "on"}
278  ]
279  },
280  dataTextField: "text",
281  dataValueField: "value",
282  change: function() {
283  switch(this.value())
284  {
285  case "custom": break; <?php // Nothing to do. The date is whatever they want. ?>
286  case "all": startingDatePicker.value(all); break;
287  case "30": startingDatePicker.value(min30); break;
288  case "60": startingDatePicker.value(min60); break;
289  case "90": startingDatePicker.value(min90); break;
290  }
291  }
292  }).data("kendoDropDownList");
293 
294  startingDatePicker.value(min30); <?php // Starting value: previous 30 days. ?>
295  }
296 
297  var activeWindows = [];
298  $(document).ready(function() {
299  Init();
300  <?php printClickOverlayEvent(); ?>
301  });
302 
303  <?php PrintPrintAudits("all admin");
304  printAuditOpenPopup(); ?>
305  </script>
306  <style>
307  .auditFilterDiv > div {
308  max-width: 950px;
309  }
310  </style>
311  <?php PrintAuditTemplates(true); ?>
312  <div id="formValidateDiv" class="k-block k-error-colored formValidateDiv" style="display:none"></div>
313  <div class="container-fluid">
314  <form id="searchForm"><div class="well well-sm container-fluid auditFilterDiv" style="display:none;"><div>
315  <div class="col-xs-12 hcuSpacer hcu-no-padding">
316  <div class="container-fluid">
317  <div class="row hcuSpacer"><label class="col-xs-12 col-sm-5">Date Search Range</label>
318  <div class="col-xs-12 col-sm-7"><div id="durationDDL" class="hcu-all-100"></div></div>
319  </div>
320  <div class="row hcuSpacer"><label class="col-xs-12 col-sm-5">&nbsp;</label>
321  <div class="col-xs-12 col-sm-7"><input type="text" id="startingDatePicker" class="hcu-all-100" homecu-match="date" data-homecuCustomMatch-msg="Date is invalid."></div>
322  </div>
323  </div>
324  </div>
325 
326  <div class="col-xs-12 hcuSpacer hcu-no-padding">
327  <div class="container hcu-all-100">
328  <div class="row hcuSpacer">
329  <label class="col-xs-12 col-sm-5">Changes for Admin User</label>
330  <div class="col-xs-12 col-sm-7"><input type="text" class="k-input k-textbox hcu-all-100" name="auditUser"></div>
331  </div>
332  <div class="row hcuSpacer">
333  <label class="col-xs-12 col-sm-5">Changed by Admin User</label>
334  <div class="col-xs-12 col-sm-7"><input type="text" class="k-input k-textbox hcu-all-100" name="loggedInUser"></div>
335  </div>
336  <div class="row hcuSpacer">
337  <label class="col-sm-5 col-xs-12">Action Type</label>
338  <div class="col-sm-7 col-xs-12"><div id="actionDDL" class="hcu-all-100"></div></div>
339  </div>
340  </div>
341  </div>
342 
343  <div class="col-xs-12 hcuSpacer hcu-no-padding"><div class="container hcu-all-100"><div class="row"><div class="col-xs-12">
344  <a href="#" class="k-button k-primary floatRight" id="okayBtn">Show</a>
345  </div></div></div></div>
346  </div></div></form>
347  <div id="auditGrid" class="hcu-all-100 pointerGrid"></div>
348  <form id="auditPrintForm" method="post" action="shell.prg" target="auditPrint">
349  <input type="hidden" name="shell" value="">
350  <input type="hidden" name="title" value="">
351  </form>
352  </div>
353  <div id="previewWindow"></div>
354 <?php }
Definition: User.php:7