Odyssey
userSupportAudit.prg
1 <?php
2 /**
3  * @package UserSupport (Subpackage audit)
4  * @author SPB
5  *
6  * This script is run when the user opens up the audit card in the user hub. It cannot be run independently of that.
7  */
8 require_once("$admLibrary/aAudit.i");
9 
10 $string = array("filter" => HCUFILTER_INPUT_STRING);
11 HCU_ImportVars($parameters, "a", array("operation" => $string, "payload" => $string, "ft" => $string, "userId" => $string));
12 extract($parameters["a"]);
13 
14 $operation = is_null($operation) ? "" : trim($operation);
15 
16 try {
17  $userId = HCU_PayloadDecode($Cu, $payload);
18 } catch(exception $e) { ?>
19  <div class='noUserFound'><div>No User Found</div></div>
20 <?php exit;
21 }
22 PrintPage("$menu_link?ft=$ft", $userId["user_id"], GetAuditRecords($dbh, $Cu, $userId["user_id"], $SYSENV["logger"]));
23 
24 /**
25  * function GetAuditRecords($dbh, $Cu, $userId, $logger)
26  * Gets the audit records
27  *
28  * @param $dbh -- the database connection
29  * @param string $Cu -- the credit union
30  * @param integer $userId -- the userId
31  * @param object $logger -- for logging an error that shouldn't go to the admin user.
32  * @return [date:"", actioncode:"", user:"", script:"", action:"", rown:0, details: [{table:"", label:"", type:"",
33  * rows: [{type: "", values: [{col: "", before: "", after: "", label: "", same: false}, ...]}, ...]}, ... ]]
34  * Type can be "mixed", "add", "delete", or "update" at the table level. It cannot be "mixed" at the column level.
35  */
36 function GetAuditRecords($dbh, $Cu, $userId, $logger) {
37 
38  try {
39  $sql = "select auditdate as date, auditaction as actioncode, auditsrcuser_name as srcuser, auditrecbefore as before, auditrecafter as after, auditsrccode_context as script,
40  auditfulldesc as action, row_number() over (order by auditdate desc) as rown from ${Cu}audituser where user_id = " . intval($userId);
41  $sth = db_query($sql, $dbh);
42  if (!$sth) {
43  throw new exception("Audit query failed.", 12);
44  }
45  $auditRecords = array();
46  $tz = null;
47  for($i = 0; $row = db_fetch_assoc($sth, $i); $i++) {
48 
49  $results = ParseUserAuditRow($row, $Cu, $dbh);
50  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.
51  $logger->error("Banking audit is invalid in the database. CU: $Cu, Audit Date: " . $row["date"]);
52  continue;
53  }
54 
55  unset($row["before"]);
56  unset($row["after"]);
57  $row["details"] = $results["details"];
58 
59  // Do date stuff
60  $tz = GetCreditUnionTimezone($dbh, $Cu);
61  $dateTime = new DateTime($row["date"]);
62  $dateTime->setTimezone(new DateTimeZone($tz));
63  $row["date"] = $dateTime->format("Y-m-d H:i:s.u") . "Z";
64 
65  $auditRecords[] = $row;
66  }
67  $returnArray = array("status" => "000", "error" => array(), "auditRecords" => $auditRecords);
68  } catch(exception $e) {
69  $returnArray = array("status" => $e->getCode(), "error" => array($e->getMessage()));
70  }
71  return $returnArray;
72 }
73 
74 /**
75  * function PrintPage($self, $userId, $readData)
76  * This function will print out the popup for the audit.
77  *
78  * @param $self -- the URL of this page
79  * @param $userId -- the user id to get audits for.
80  * @param $readData -- Audit data.
81  */
82 function PrintPage($self, $userId, $readData) { ?>
83  <script type="text/javascript">
84  //# sourceURL=audit.js
85 
86  <?php
87  /**
88  * function Init()
89  * Initializes kendo widgets for the page.
90  */
91  ?>
92  function Init() {
93  $.homecuValidator.setup({formValidate: "auditPrintForm", formStatusField: "formValidateDiv"});
94  $("#externalTabWindow").data("preferredHeight", "auto");
95  var record = <?php echo HCU_JsonEncode($readData); ?>;
96  if (record.error.length > 0) {
97  $.homecuValidator.displayMessage(record.error, $.homecuValidator.settings.statusError );
98  } else {
99  var auditData = record.auditRecords;
100  $.homecuValidator.setup({formValidate:'auditPrintForm', formStatusField: 'formValidateStatusDiv'});
101 
102  var grid = $("#auditGrid").kendoGrid({
103  dataSource: {
104  transport: {
105  read: function(options) {
106  options.success(auditData);
107  }
108  },
109  schema: {
110  model: {
111  id: "rown",
112  fields: {
113  rown: {type: "number"},
114  date: {type: "date"},
115  action: {type: "string"},
116  actioncode: {type: "string"},
117  details: {type: "odata"},
118  script: {type: "string"},
119  checked: {type: "boolean"},
120  srcuser: {type: "string"}
121  }
122  }
123  }
124  },
125  columns: [
126  {template: "<input type='checkbox' class='rowCheckbox'>", attributes: {"class": "checkboxTD"},
127  headerTemplate: "<input type='checkbox' class='allCheckbox'>", width: "45px", sortable: false, filterable: false},
128  {field: "date", title: "Date", format: "{0:G}"},
129  {field: "srcuser", title: "Changed By"},
130  {field: "action", title: "Action Type"},
131 
132  ],
133  noRecords: {
134  template: "<tr class='noRecordsDiv'><td colspan='4'>No Records Found</td></tr>"
135  },
136  scrollable: false,
137  sortable: true,
138  toolbar: [{name: "print", text: "Print"}],
139  detailTemplate: ReturnAuditDetailTemplate,
140  }).data("kendoGrid");
141 
142  $("#auditGrid").on("click", ".auditDetailContainer .auditShowAllBtn", function() {
143  if ($(this).text().trim() == "Show All") {
144  $(this).closest(".auditDetailContainer").removeClass("hideAA");
145  $(this).text("Show Changed");
146  } else {
147  $(this).closest(".auditDetailContainer").addClass("hideAA");
148  $(this).text("Show All");
149  }
150 
151  return false;
152  });
153 
154  <?php printCheckboxEvents("#auditGrid", ".k-grid-print"); ?>
155 
156  $(".k-grid-print").addClass("k-state-disabled");
157 
158  $(".k-grid-print").click(function() {
159  if (!$(this).hasClass("k-state-disabled")) {
160  PrintAudits();
161  }
162  return false;
163  });
164 
165  $(".k-grid-show").click(function() {
166  if ($(this).text().trim() == "Show Filter") {
167  $(".auditFilterDiv").show();
168  $(this).text("Hide Filter");
169  } else {
170  $(".auditFilterDiv").hide();
171  $(this).text("Show Filter");
172  }
173  });
174  }
175  }
176 
177  <?php
178  /**
179  * function AuditOpenPopup(auditData)
180  * Opens up the popup for the audit.
181  *
182  * @param auditData -- the data for the audit.
183  */
184  ?>
185  function AuditOpenPopup(auditData) {
186  var dialog = $("#auditDetailWindow").data("kendoDialog");
187  var template = kendo.template($("#auditDetailTemplate").html());
188 
189  if (dialog == null) {
190  dialog = $("#previewWindow").kendoDialog({
191  title: "Preview",
192  actions: [{text: "Okay", primary: true}],
193  visible: false,
194  maxWidth: "99%",
195  minWidth: 333,
196  open: function() {
197  if (window.activeWindows != null) {
198  window.activeWindows.push(this);
199  }
200  },
201  close: function() {
202  if (window.activeWindows != null) {
203  window.activeWindows.pop();
204  }
205  }
206  }).data("kendoDialog");
207  }
208 
209  dialog.content(template(auditData)).open();
210 
211  var maxHeight1 = 600;
212  var maxHeight2 = $(window).height() - 150;
213  var maxHeight = maxHeight2 >= maxHeight1 ? maxHeight1 : maxHeight2;
214  $(dialog.wrapper).css({top: 5});
215  $("#previewWindow .auditMaxHeight").css({maxHeight: maxHeight, overflowY: "auto", overflowX: "hidden"});
216  }
217 
218  <?php
219  /**
220  * function PrintAudits()
221  * This function prints the audits.
222  */
223  ?>
224  function PrintAudits() {
225  $("<div id='tempAudit' style='display:none;'><div class='container'><div class='row form-group mockKendoTable auditInsertion'></div></div></div>").appendTo("body");
226 
227  var gridData = $("#auditGrid").data("kendoGrid").dataSource.view();
228 
229  for(var i = 0; i != gridData.length; i++) {
230  var record = gridData[i];
231  if (record.checked) {
232  var rowTemplate = "<div class='tr nobottom'><span class='col-xs-4'>" + record.action + "</span><span class='col-xs-4'>" + record.srcuser + "</span>"
233  + "<span class='col-xs-4'>" + kendo.toString(record.date, 'd') + "</span></div><div class='tr notop'><span class='col-xs-12'><div class='container-fluid'><div class=' col-xs-12'>"
234  + ReturnAuditDetailTemplate(record, true) + "</div></div></span></div>";
235  $(".auditInsertion").append(rowTemplate);
236  }
237  }
238  var newWindow = window.open("", "auditPrint");
239  $("#auditPrintForm [name='shell']").val($("#tempAudit").html());
240  $("#auditPrintForm [name='title']").val("User Audit of " + $(".kWindowCard .k-window-title").text().split("/")[2].trim());
241  $("#auditPrintForm").submit();
242  $("#tempAudit").remove();
243  }
244 
245  <?php
246  /**
247  * function ReturnAuditDetailTemplate(row, isPrinting)
248  * This function returns the detail template and is used in the grid.
249  *
250  * @param $row -- the row to display
251  * @param isPrinting -- if true, display/hide some things
252  * @return string of the whole HTML to paste
253  */
254  ?>
255  function ReturnAuditDetailTemplate(row, isPrinting) {
256  var returnString = '<div class="auditMaxHeight"><div class="container-fluid auditDetailContainer hideAA">';
257 
258  for (var i = 0, iLength = row.details.length; i != iLength; i++) {
259  var tableRow = row.details[i];
260  if (iLength > 1) {
261  var message = tableRow.label + (tableRow.type != "mixed" ? "(" + tableRow.type + " records)" : "");
262  returnString += '<div class="row form-group"><div class="col-xs-12"><h4 class="h4 hcuSpacerx">' + message + '</h4></div></div>';
263  }
264 
265  if (tableRow.altDesc != null && tableRow.altDesc != "") {
266  returnString += tableRow.altDesc;
267  continue;
268  }
269 
270  for (var j = 0, jLength = tableRow.rows.length; j != jLength; j++) {
271  var rowRow = tableRow.rows[j];
272 
273  if (rowRow.altDesc != null && rowRow.altDesc != "") {
274  returnString += '<div class="row"><div class="col-xs-12">' + rowRow.altDesc + '</div></div>';
275  continue;
276  }
277 
278  var showBefore = true;
279  var showAfter = true;
280  switch (rowRow.type) {
281  case "add": showBefore = false; break;
282  case "remove": showAfter = false; break;
283  }
284  var theseClasses = showBefore && showAfter ? "col-xs-4 col-md-4" : "col-xs-8 col-md-8";
285  if (tableRow.type == "mixed") {
286  var message = rowRow.type + " record:";
287  returnString += '<div class="row form-group"><div class="col-xs-12"><h4 class="h4 hcuSpacerx">' + message + '</h4></div></div>';
288  }
289  returnString += '<div class="row form-group mockKendoTable">';
290  if (!isPrinting && i == 0 && j == 0) {
291  returnString += '<a href="#" class="auditShowAllBtn">Show All</a><br>';
292  }
293  returnString += '<div class="th">';
294  returnString += '<span class="col-xs-3 col-md-4">Column</span>';
295 
296  if (showBefore) {
297  returnString += '<span class="' + theseClasses + '">Before</span>';
298  }
299  if (showAfter) {
300  returnString += '<span class="' + theseClasses + '">After</span>';
301  }
302 
303  returnString += '<div class="clearfix hidden-xs-block"></div>';
304  returnString += '</div>'; <?php // Ends TH. ?>
305 
306  for (var k = 0, kLength = rowRow.values.length; k != kLength; k++) {
307  var colRow = rowRow.values[k];
308  var same = !isPrinting && colRow.same ? "aa" : "";
309 
310  returnString += '<div class="tr ' + same + '">';
311  returnString += '<span class="col-xs-3 col-md-4">' + colRow.label + '</span>';
312 
313  if (showBefore) {
314  returnString += '<span class="' + theseClasses + '">';
315  if (colRow.before == "") {
316  returnString += "&nbsp;";
317  } else {
318  returnString += colRow.before;
319  }
320  returnString += "</span>";
321  }
322 
323  if (showAfter) {
324  returnString += '<span class="' + theseClasses + '">';
325  if (colRow.after == "") {
326  returnString += "&nbsp;";
327  } else {
328  returnString += colRow.after;
329  }
330  returnString += "</span>";
331  }
332 
333  returnString += '<div class="clearfix hidden-xs-block"></div>';
334  returnString += '</div>'; <?php // Ends TR. ?>
335  }
336 
337  returnString += "</div>"; <?php // Ends mockKendoTable. ?>
338  }
339  }
340 
341  returnString += "</div></div>"; <?php // Ends auditMaxHeight, container-fluid. ?>
342  return returnString;
343  }
344 
345  Init();
346  </script>
347 
348  <div id="formValidateDiv" class="k-block k-error-colored" style="display:none"></div>
349  <div id="auditGrid" class="hcu-all-100 pointerGrid"></div>
350  <form id="auditPrintForm" method="post" action="shell.prg" target="auditPrint">
351  <input type="hidden" name="shell" value="">
352  <input type="hidden" name="title" value="">
353  </form>
354  <div id="previewWindow"></div>
355 <?php }
Definition: User.php:7