summaryrefslogtreecommitdiffstats
path: root/interface/js/app/history.js
diff options
context:
space:
mode:
Diffstat (limited to 'interface/js/app/history.js')
-rw-r--r--interface/js/app/history.js306
1 files changed, 306 insertions, 0 deletions
diff --git a/interface/js/app/history.js b/interface/js/app/history.js
new file mode 100644
index 0000000..0d953ec
--- /dev/null
+++ b/interface/js/app/history.js
@@ -0,0 +1,306 @@
+/*
+ The MIT License (MIT)
+
+ Copyright (C) 2017 Vsevolod Stakhov <vsevolod@highsecure.ru>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+/* global FooTable */
+
+define(["jquery", "app/common", "app/libft", "footable"],
+ ($, common, libft) => {
+ "use strict";
+ const ui = {};
+ let prevVersion = null;
+
+ function process_history_legacy(data) {
+ const items = [];
+
+ function compare(e1, e2) { return e1.name.localeCompare(e2.name); }
+
+ $("#selSymOrder_history, label[for='selSymOrder_history']").hide();
+
+ $.each(data, (i, item) => {
+ item.time = libft.unix_time_format(item.unix_time);
+ libft.preprocess_item(item);
+ item.symbols = Object.keys(item.symbols)
+ .map((key) => item.symbols[key])
+ .sort(compare)
+ .map((e) => e.name)
+ .join(", ");
+ item.time = {
+ value: libft.unix_time_format(item.unix_time),
+ options: {
+ sortValue: item.unix_time
+ }
+ };
+
+ items.push(item);
+ });
+
+ return {items: items};
+ }
+
+ function columns_legacy() {
+ return [{
+ name: "id",
+ title: "ID",
+ style: {
+ width: 300,
+ maxWidth: 300,
+ overflow: "hidden",
+ textOverflow: "ellipsis",
+ wordBreak: "keep-all",
+ whiteSpace: "nowrap"
+ }
+ }, {
+ name: "ip",
+ title: "IP address",
+ breakpoints: "xs sm",
+ style: {width: 150, maxWidth: 150}
+ }, {
+ name: "action",
+ title: "Action",
+ style: {width: 110, maxWidth: 110}
+ }, {
+ name: "score",
+ title: "Score",
+ style: {maxWidth: 110},
+ sortValue: function (val) { return Number(val.options.sortValue); }
+ }, {
+ name: "symbols",
+ title: "Symbols",
+ breakpoints: "all",
+ style: {width: 550, maxWidth: 550}
+ }, {
+ name: "size",
+ title: "Message size",
+ breakpoints: "xs sm",
+ style: {width: 120, maxWidth: 120},
+ formatter: libft.formatBytesIEC
+ }, {
+ name: "scan_time",
+ title: "Scan time",
+ breakpoints: "xs sm",
+ style: {maxWidth: 80},
+ sortValue: function (val) { return Number(val); }
+ }, {
+ sorted: true,
+ direction: "DESC",
+ name: "time",
+ title: "Time",
+ sortValue: function (val) { return Number(val.options.sortValue); }
+ }, {
+ name: "user",
+ title: "Authenticated user",
+ breakpoints: "xs sm",
+ style: {width: 200, maxWidth: 200}
+ }];
+ }
+
+ const columns = {
+ 2: libft.columns_v2("history"),
+ legacy: columns_legacy()
+ };
+
+ function process_history_data(data) {
+ const process_functions = {
+ 2: libft.process_history_v2,
+ legacy: process_history_legacy
+ };
+ let pf = process_functions.legacy;
+
+ if (data.version) {
+ const strkey = data.version.toString();
+ if (process_functions[strkey]) {
+ pf = process_functions[strkey];
+ }
+ }
+
+ return pf(data, "history");
+ }
+
+ function get_history_columns(data) {
+ let func = columns.legacy;
+
+ if (data.version) {
+ const strkey = data.version.toString();
+ if (columns[strkey]) {
+ func = columns[strkey];
+ }
+ }
+
+ return func;
+ }
+
+ ui.getHistory = function () {
+ common.query("history", {
+ success: function (req_data) {
+ function differentVersions(neighbours_data) {
+ const dv = neighbours_data.some((e) => e.version !== neighbours_data[0].version);
+ if (dv) {
+ common.alertMessage("alert-error",
+ "Neighbours history backend versions do not match. Cannot display history.");
+ return true;
+ }
+ return false;
+ }
+
+ const neighbours_data = req_data
+ .filter((d) => d.status) // filter out unavailable neighbours
+ .map((d) => d.data);
+ if (neighbours_data.length && !differentVersions(neighbours_data)) {
+ let data = {};
+ const [{version}] = neighbours_data;
+ if (version) {
+ data.rows = [].concat.apply([], neighbours_data
+ .map((e) => e.rows));
+ data.version = version;
+ $("#legacy-history-badge").hide();
+ } else {
+ // Legacy version
+ data = [].concat.apply([], neighbours_data);
+ $("#legacy-history-badge").show();
+ }
+ const o = process_history_data(data);
+ const {items} = o;
+ common.symbols.history = o.symbols;
+
+ if (Object.prototype.hasOwnProperty.call(common.tables, "history") &&
+ version === prevVersion) {
+ common.tables.history.rows.load(items);
+ } else {
+ libft.destroyTable("history");
+ // Is there a way to get an event when the table is destroyed?
+ setTimeout(() => {
+ libft.initHistoryTable(data, items, "history", get_history_columns(data), false);
+ }, 200);
+ }
+ prevVersion = version;
+ } else {
+ libft.destroyTable("history");
+ }
+ },
+ complete: function () { $("#refresh").removeAttr("disabled").removeClass("disabled"); },
+ errorMessage: "Cannot receive history",
+ });
+ };
+
+ function initErrorsTable(rows) {
+ common.tables.errors = FooTable.init("#errorsLog", {
+ columns: [
+ {sorted: true,
+ direction: "DESC",
+ name: "ts",
+ title: "Time",
+ style: {width: 300, maxWidth: 300},
+ sortValue: function (val) { return Number(val.options.sortValue); }},
+ {name: "type",
+ title: "Worker type",
+ breakpoints: "xs sm",
+ style: {width: 150, maxWidth: 150}},
+ {name: "pid",
+ title: "PID",
+ breakpoints: "xs sm",
+ style: {width: 110, maxWidth: 110}},
+ {name: "module", title: "Module"},
+ {name: "id", title: "Internal ID"},
+ {name: "message", title: "Message", breakpoints: "xs sm"},
+ ],
+ rows: rows,
+ paging: {
+ enabled: true,
+ limit: 5,
+ size: common.page_size.errors
+ },
+ filtering: {
+ enabled: true,
+ position: "left",
+ connectors: false
+ },
+ sorting: {
+ enabled: true
+ }
+ });
+ }
+
+ ui.getErrors = function () {
+ if (common.read_only) return;
+
+ common.query("errors", {
+ success: function (data) {
+ const neighbours_data = data
+ .filter((d) => d.status) // filter out unavailable neighbours
+ .map((d) => d.data);
+ const rows = [].concat.apply([], neighbours_data);
+ $.each(rows, (i, item) => {
+ item.ts = {
+ value: libft.unix_time_format(item.ts),
+ options: {
+ sortValue: item.ts
+ }
+ };
+ });
+ if (Object.prototype.hasOwnProperty.call(common.tables, "errors")) {
+ common.tables.errors.rows.load(rows);
+ } else {
+ initErrorsTable(rows);
+ }
+ }
+ });
+
+ $("#updateErrors").off("click");
+ $("#updateErrors").on("click", (e) => {
+ e.preventDefault();
+ ui.getErrors();
+ });
+ };
+
+
+ libft.set_page_size("history", $("#history_page_size").val());
+ libft.bindHistoryTableEventHandlers("history", 8);
+
+ $("#updateHistory").off("click");
+ $("#updateHistory").on("click", (e) => {
+ e.preventDefault();
+ ui.getHistory();
+ });
+
+ // @reset history log
+ $("#resetHistory").off("click");
+ $("#resetHistory").on("click", (e) => {
+ e.preventDefault();
+ if (!confirm("Are you sure you want to reset history log?")) { // eslint-disable-line no-alert
+ return;
+ }
+ libft.destroyTable("history");
+ libft.destroyTable("errors");
+
+ common.query("historyreset", {
+ success: function () {
+ ui.getHistory();
+ ui.getErrors();
+ },
+ errorMessage: "Cannot reset history log"
+ });
+ });
+
+ return ui;
+ });