diff options
-rw-r--r-- | .circleci/config.yml | 18 | ||||
-rw-r--r-- | .eslintrc.json | 8 | ||||
-rw-r--r-- | conf/dmarc_whitelist.inc | 1 | ||||
-rw-r--r-- | interface/js/app/config.js | 470 | ||||
-rw-r--r-- | interface/js/app/graph.js | 470 | ||||
-rw-r--r-- | interface/js/app/history.js | 952 | ||||
-rw-r--r-- | interface/js/app/rspamd.js | 952 | ||||
-rw-r--r-- | interface/js/app/stats.js | 340 | ||||
-rw-r--r-- | interface/js/app/symbols.js | 488 | ||||
-rw-r--r-- | interface/js/app/upload.js | 342 | ||||
-rw-r--r-- | interface/js/main.js | 52 | ||||
-rw-r--r-- | package.json | 6 | ||||
-rw-r--r-- | src/libserver/milter.c | 3 | ||||
-rw-r--r-- | src/plugins/fuzzy_check.c | 34 |
14 files changed, 2086 insertions, 2050 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 51525aae0..400029d69 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -119,11 +119,29 @@ jobs: - run: (exit $RETURN_CODE) + eslint: + docker: + - image: circleci/node:latest + steps: + - checkout + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + - run: npm install + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + - run: ./node_modules/.bin/eslint ./ + workflows: version: 2 build-and-test: jobs: - build + - eslint - rspamd-test: requires: - build diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..64c25a22c --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,8 @@ +{ + "env": { + "browser": true + }, + "rules": { + "newline-per-chained-call": "off" + } +} diff --git a/conf/dmarc_whitelist.inc b/conf/dmarc_whitelist.inc index 80cf2649e..8aa9519ee 100644 --- a/conf/dmarc_whitelist.inc +++ b/conf/dmarc_whitelist.inc @@ -32,6 +32,7 @@ hh.ru instagram.com linkedin.com livejournal.com +lufthansa-group.com mackeeper.com megafon.ru mercadolibre.com.ar diff --git a/interface/js/app/config.js b/interface/js/app/config.js index d10fd6a60..8c15b983e 100644 --- a/interface/js/app/config.js +++ b/interface/js/app/config.js @@ -22,263 +22,263 @@ THE SOFTWARE. */ -define(['jquery'], -function($) { - var interface = {} +define(["jquery"], + function($) { + var interface = {}; - function save_map_success(rspamd) { - rspamd.alertMessage('alert-modal alert-success', 'Map data successfully saved'); - $('#modalDialog').modal('hide'); - } - function save_map_error(rspamd, serv, jqXHR, textStatus, errorThrown) { - rspamd.alertMessage('alert-modal alert-error', 'Save map error on ' + - serv.name + ': ' + errorThrown); - } - // @upload map from modal - function saveMap(rspamd, action, id) { - var data = $('#' + id).find('textarea').val(); - $.ajax({ - data: data, - dataType: 'text', - type: 'POST', - jsonp: false, - url: action, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - xhr.setRequestHeader('Map', id); - xhr.setRequestHeader('Debug', true); - }, - error: function (data) { - save_map_error(rspamd, 'local', null, null, data.statusText); - }, - success: function() {save_map_success(rspamd)}, - }); - } + function save_map_success(rspamd) { + rspamd.alertMessage("alert-modal alert-success", "Map data successfully saved"); + $("#modalDialog").modal("hide"); + } + function save_map_error(rspamd, serv, jqXHR, textStatus, errorThrown) { + rspamd.alertMessage("alert-modal alert-error", "Save map error on " + + serv.name + ": " + errorThrown); + } + // @upload map from modal + function saveMap(rspamd, action, id) { + var data = $("#" + id).find("textarea").val(); + $.ajax({ + data: data, + dataType: "text", + type: "POST", + jsonp: false, + url: action, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + xhr.setRequestHeader("Map", id); + xhr.setRequestHeader("Debug", true); + }, + error: function (data) { + save_map_error(rspamd, "local", null, null, data.statusText); + }, + success: function() { save_map_success(rspamd); }, + }); + } - // @get maps id - function getMaps(rspamd) { - var items = []; - var $listmaps = $('#listMaps') - $listmaps.closest('.widget-box').hide(); - $.ajax({ - dataType: 'json', - url: 'maps', - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - error: function (data) { - rspamd.alertMessage('alert-modal alert-error', data.statusText); - }, - success: function (data) { - $listmaps.empty(); - $('#modalBody').empty(); - $tbody = $('<tbody>'); + // @get maps id + function getMaps(rspamd) { + var items = []; + var $listmaps = $("#listMaps"); + $listmaps.closest(".widget-box").hide(); + $.ajax({ + dataType: "json", + url: "maps", + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + error: function (data) { + rspamd.alertMessage("alert-modal alert-error", data.statusText); + }, + success: function (data) { + $listmaps.empty(); + $("#modalBody").empty(); + $tbody = $("<tbody>"); - $.each(data, function (i, item) { + $.each(data, function (i, item) { + if ((item.editable === false || rspamd.read_only)) { + var label = "<span class=\"label label-default\">Read</span>"; + } else { + var label = "<span class=\"label label-default\">Read</span> <span class=\"label label-success\">Write</span>"; + } + var $tr = $("<tr>"); + $("<td class=\"col-md-2 maps-cell\">" + label + "</td>").appendTo($tr); + $span = $("<span class=\"map-link\" data-toggle=\"modal\" data-target=\"#modalDialog\">" + item.uri + "</span>").data("item", item); + $span.wrap("<td>").parent().appendTo($tr); + $("<td>" + item.description + "</td>").appendTo($tr); + $tr.appendTo($tbody); + }); + $tbody.appendTo($listmaps); + $listmaps.closest(".widget-box").show(); + } + }); + } + // @get map by id + function getMapById(rspamd, item) { + return $.ajax({ + dataType: "text", + url: "getmap", + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + xhr.setRequestHeader("Map", item.map); + }, + error: function () { + rspamd.alertMessage("alert-error", "Cannot receive maps data"); + }, + success: function (text) { + var disabled = ""; if ((item.editable === false || rspamd.read_only)) { - var label = '<span class="label label-default">Read</span>'; - } else { - var label = '<span class="label label-default">Read</span> <span class="label label-success">Write</span>'; + disabled = "disabled=\"disabled\""; } - var $tr = $("<tr>"); - $('<td class="col-md-2 maps-cell">' + label + '</td>').appendTo($tr); - $span = $('<span class="map-link" data-toggle="modal" data-target="#modalDialog">' + item.uri + '</span>').data("item",item); - $span.wrap("<td>").parent().appendTo($tr); - $('<td>' + item.description + '</td>').appendTo($tr); - $tr.appendTo($tbody); - }); - $tbody.appendTo($listmaps); - $listmaps.closest('.widget-box').show(); - } - }); - } - // @get map by id - function getMapById(rspamd, item) { - return $.ajax({ - dataType: 'text', - url: 'getmap', - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - xhr.setRequestHeader('Map', item.map); - }, - error: function () { - rspamd.alertMessage('alert-error', 'Cannot receive maps data'); - }, - success: function (text) { - var disabled = ''; - if ((item.editable === false || rspamd.read_only)) { - disabled = 'disabled="disabled"'; + + $("#"+item.map).remove(); + $("<form class=\"form-horizontal form-map\" method=\"post\" action=\"savemap\" data-type=\"map\" id=\"" + + item.map + "\" style=\"display:none\">" + + "<textarea class=\"list-textarea\"" + disabled + ">" + text + + "</textarea>" + + "</form").appendTo("#modalBody"); } - - $("#"+item.map).remove(); - $('<form class="form-horizontal form-map" method="post" action="savemap" data-type="map" id="' + - item.map + '" style="display:none">' + - '<textarea class="list-textarea"' + disabled + '>' + text + - '</textarea>' + - '</form').appendTo('#modalBody'); - } - }); - } + }); + } - function loadActionsFromForm() { - var values = []; - var inputs = $('#actionsForm :input[data-id="action"]'); - // Rspamd order: [spam, rewrite_subject, probable_spam, greylist] - values[0] = parseFloat(inputs[3].value); - values[1] = parseFloat(inputs[2].value); - values[2] = parseFloat(inputs[1].value); - values[3] = parseFloat(inputs[0].value); + function loadActionsFromForm() { + var values = []; + var inputs = $("#actionsForm :input[data-id=\"action\"]"); + // Rspamd order: [spam, rewrite_subject, probable_spam, greylist] + values[0] = parseFloat(inputs[3].value); + values[1] = parseFloat(inputs[2].value); + values[2] = parseFloat(inputs[1].value); + values[3] = parseFloat(inputs[0].value); - return JSON.stringify(values); - } + return JSON.stringify(values); + } - function getActions(rspamd) { - $.ajax({ - dataType: 'json', - type: 'GET', - url: 'actions', - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - success: function (data) { + function getActions(rspamd) { + $.ajax({ + dataType: "json", + type: "GET", + url: "actions", + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + success: function (data) { // Order of sliders greylist -> probable spam -> rewrite subject -> spam - $('#actionsBody').empty(); - $('#actionsForm').empty(); - var items = []; - $.each(data, function (i, item) { - var idx = -1; - var label; - if (item.action === 'add header') { - label = 'Probably Spam'; - idx = 1; - } else if (item.action === 'greylist') { - label = 'Greylist'; - idx = 0; - } else if (item.action === 'rewrite subject') { - label = 'Rewrite subject'; - idx = 2; - } else if (item.action === 'reject') { - label = 'Spam'; - idx = 3; - } - if (idx >= 0) { - items.push({ - idx: idx, - html: '<div class="form-group">' + - '<label class="control-label col-sm-2">' + label + '</label>' + - '<div class="controls slider-controls col-sm-10">' + - '<input class="action-scores form-control" data-id="action" type="number" value="' + item.value + '">' + - '</div>' + - '</div>' - }); - } - }); + $("#actionsBody").empty(); + $("#actionsForm").empty(); + var items = []; + $.each(data, function (i, item) { + var idx = -1; + var label; + if (item.action === "add header") { + label = "Probably Spam"; + idx = 1; + } else if (item.action === "greylist") { + label = "Greylist"; + idx = 0; + } else if (item.action === "rewrite subject") { + label = "Rewrite subject"; + idx = 2; + } else if (item.action === "reject") { + label = "Spam"; + idx = 3; + } + if (idx >= 0) { + items.push({ + idx: idx, + html: "<div class=\"form-group\">" + + "<label class=\"control-label col-sm-2\">" + label + "</label>" + + "<div class=\"controls slider-controls col-sm-10\">" + + "<input class=\"action-scores form-control\" data-id=\"action\" type=\"number\" value=\"" + item.value + "\">" + + "</div>" + + "</div>" + }); + } + }); - items.sort(function (a, b) { - return a.idx - b.idx; - }); + items.sort(function (a, b) { + return a.idx - b.idx; + }); - $('#actionsBody').html('<form id="actionsForm"><fieldset id="actionsFormField">' + + $("#actionsBody").html("<form id=\"actionsForm\"><fieldset id=\"actionsFormField\">" + items.map(function (e) { return e.html; - }).join('') + - '<br><div class="form-group">' + - '<div class="btn-group">' + - '<button class="btn btn-primary" type="button" id="saveActionsBtn">Save actions</button>' + - '<button class="btn btn-primary" type="button" id="saveActionsClusterBtn">Save cluster</button>' + - '</div></div></fieldset></form>'); - if (rspamd.read_only) { - $('#saveActionsClusterBtn').attr('disabled', true); - $('#saveActionsBtn').attr('disabled', true); - $('#actionsFormField').attr('disabled', true); - } + }).join("") + + "<br><div class=\"form-group\">" + + "<div class=\"btn-group\">" + + "<button class=\"btn btn-primary\" type=\"button\" id=\"saveActionsBtn\">Save actions</button>" + + "<button class=\"btn btn-primary\" type=\"button\" id=\"saveActionsClusterBtn\">Save cluster</button>" + + "</div></div></fieldset></form>"); + if (rspamd.read_only) { + $("#saveActionsClusterBtn").attr("disabled", true); + $("#saveActionsBtn").attr("disabled", true); + $("#actionsFormField").attr("disabled", true); + } - function saveActions(callback) { - var elts = loadActionsFromForm(); - // String to array for comparison - var eltsArray = JSON.parse(loadActionsFromForm()); - if (eltsArray[0] < 0) { - rspamd.alertMessage("alert-modal alert-error", "Spam can not be negative"); - } else if (eltsArray[1] < 0) { - rspamd.alertMessage("alert-modal alert-error", "Rewrite subject can not be negative"); - } else if (eltsArray[2] < 0) { - rspamd.alertMessage("alert-modal alert-error", "Probable spam can not be negative"); - } else if (eltsArray[3] < 0) { - rspamd.alertMessage("alert-modal alert-error", "Greylist can not be negative"); - } else if ( - (eltsArray[2] === null || eltsArray[3] < eltsArray[2]) && + function saveActions(callback) { + var elts = loadActionsFromForm(); + // String to array for comparison + var eltsArray = JSON.parse(loadActionsFromForm()); + if (eltsArray[0] < 0) { + rspamd.alertMessage("alert-modal alert-error", "Spam can not be negative"); + } else if (eltsArray[1] < 0) { + rspamd.alertMessage("alert-modal alert-error", "Rewrite subject can not be negative"); + } else if (eltsArray[2] < 0) { + rspamd.alertMessage("alert-modal alert-error", "Probable spam can not be negative"); + } else if (eltsArray[3] < 0) { + rspamd.alertMessage("alert-modal alert-error", "Greylist can not be negative"); + } else if ( + (eltsArray[2] === null || eltsArray[3] < eltsArray[2]) && (eltsArray[1] === null || eltsArray[2] < eltsArray[1]) && (eltsArray[0] === null || eltsArray[1] < eltsArray[0]) - ) { - callback("saveactions", null, null, "POST", {}, { - data: elts, - dataType: "json" - }); - } else { - rspamd.alertMessage("alert-modal alert-error", "Incorrect order of metric actions threshold"); + ) { + callback("saveactions", null, null, "POST", {}, { + data: elts, + dataType: "json" + }); + } else { + rspamd.alertMessage("alert-modal alert-error", "Incorrect order of metric actions threshold"); + } } - } - $('#saveActionsBtn').on('click', function() { - saveActions(rspamd.queryLocal); - }); - $('#saveActionsClusterBtn').on('click', function() { - saveActions(rspamd.queryNeighbours); - }); - }, - }); - } + $("#saveActionsBtn").on("click", function() { + saveActions(rspamd.queryLocal); + }); + $("#saveActionsClusterBtn").on("click", function() { + saveActions(rspamd.queryNeighbours); + }); + }, + }); + } - // @upload edited actions - interface.setup = function(rspamd) { + // @upload edited actions + interface.setup = function(rspamd) { // Modal form for maps - $(document).on('click', '[data-toggle="modal"]', function () { - var item = $(this).data('item'); - getMapById(rspamd, item).done(function() { - $('#modalTitle').html(item.uri); - $('#' + item.map).first().show(); - $('#modalDialog .progress').hide(); - $('#modalDialog').modal(show = true, backdrop = true, keyboard = show); - if (item.editable === false) { - $('#modalSave').hide(); - $('#modalSaveAll').hide(); - } else { - $('#modalSave').show(); - $('#modalSaveAll').show(); - } + $(document).on("click", "[data-toggle=\"modal\"]", function () { + var item = $(this).data("item"); + getMapById(rspamd, item).done(function() { + $("#modalTitle").html(item.uri); + $("#" + item.map).first().show(); + $("#modalDialog .progress").hide(); + $("#modalDialog").modal(show = true, backdrop = true, keyboard = show); + if (item.editable === false) { + $("#modalSave").hide(); + $("#modalSaveAll").hide(); + } else { + $("#modalSave").show(); + $("#modalSaveAll").show(); + } + }); + return false; }); - return false; - }); - // close modal without saving - $('[data-dismiss="modal"]').on('click', function () { - $('#modalBody form').hide(); - }); - // @save forms from modal - $('#modalSave').on('click', function () { - var form = $('#modalBody').children().filter(':visible'); - var action = $(form).attr('action'); - var id = $(form).attr('id'); - saveMap(rspamd, action, id); - }); - $('#modalSaveAll').on('click', function () { - var form = $('#modalBody').children().filter(':visible'); - var action = $(form).attr('action'); - var id = $(form).attr('id'); - var data = $('#' + id).find('textarea').val(); - rspamd.queryNeighbours(action, save_map_success, save_map_error, "POST", { - "Map": id, - }, { - data: data, - dataType: "text", + // close modal without saving + $("[data-dismiss=\"modal\"]").on("click", function () { + $("#modalBody form").hide(); + }); + // @save forms from modal + $("#modalSave").on("click", function () { + var form = $("#modalBody").children().filter(":visible"); + var action = $(form).attr("action"); + var id = $(form).attr("id"); + saveMap(rspamd, action, id); + }); + $("#modalSaveAll").on("click", function () { + var form = $("#modalBody").children().filter(":visible"); + var action = $(form).attr("action"); + var id = $(form).attr("id"); + var data = $("#" + id).find("textarea").val(); + rspamd.queryNeighbours(action, save_map_success, save_map_error, "POST", { + "Map": id, + }, { + data: data, + dataType: "text", + }); }); - }); - } + }; - interface.getActions = getActions; - interface.getMaps = getMaps; + interface.getActions = getActions; + interface.getMaps = getMaps; - return interface; -}); + return interface; + }); diff --git a/interface/js/app/graph.js b/interface/js/app/graph.js index 20fa36f53..85a11fc46 100644 --- a/interface/js/app/graph.js +++ b/interface/js/app/graph.js @@ -23,274 +23,274 @@ THE SOFTWARE. */ -define(['jquery', 'd3evolution', 'footable'], -function($, D3Evolution, unused) { - var rrd_pie_config = { - header: {}, - size: { - canvasWidth: 400, - canvasHeight: 180, - pieInnerRadius: "20%", - pieOuterRadius: "80%" - }, - labels: { - outer: { - format: "none" +define(["jquery", "d3evolution", "footable"], + function($, D3Evolution, unused) { + var rrd_pie_config = { + header: {}, + size: { + canvasWidth: 400, + canvasHeight: 180, + pieInnerRadius: "20%", + pieOuterRadius: "80%" }, - inner: { - hideWhenLessThanPercentage: 8 - }, - }, - misc: { - pieCenterOffset: { - x: -120, - y: 10, + labels: { + outer: { + format: "none" + }, + inner: { + hideWhenLessThanPercentage: 8 + }, }, - gradient: { - enabled: true, + misc: { + pieCenterOffset: { + x: -120, + y: 10, + }, + gradient: { + enabled: true, + }, }, - }, - }; + }; - var graph_options = { - title: "Rspamd throughput", - width: 1060, - height: 370, - yAxisLabel: "Message rate, msg/s", + var graph_options = { + title: "Rspamd throughput", + width: 1060, + height: 370, + yAxisLabel: "Message rate, msg/s", - legend: { - space: 140, - entries: [{ - label: "Rejected", - color: "#FF0000" - }, { - label: "Temporarily rejected", - color: "#BF8040" - }, { - label: "Subject rewritten", - color: "#FF6600" - }, { - label: "Probable spam", - color: "#FFAD00" - }, { - label: "Greylisted", - color: "#436EEE" - }, { - label: "Clean", - color: "#66CC00" - }] - } - }; + legend: { + space: 140, + entries: [{ + label: "Rejected", + color: "#FF0000" + }, { + label: "Temporarily rejected", + color: "#BF8040" + }, { + label: "Subject rewritten", + color: "#FF6600" + }, { + label: "Probable spam", + color: "#FFAD00" + }, { + label: "Greylisted", + color: "#436EEE" + }, { + label: "Clean", + color: "#66CC00" + }] + } + }; - // Get selectors' current state - function getSelector(id) { - var e = document.getElementById(id); - return e.options[e.selectedIndex].value; - } + // Get selectors' current state + function getSelector(id) { + var e = document.getElementById(id); + return e.options[e.selectedIndex].value; + } - function initGraph() { - var graph = new D3Evolution("graph", $.extend({}, graph_options, { - yScale: getSelector("selYScale"), - type: getSelector("selType"), - interpolate: getSelector("selInterpolate"), - convert: getSelector("selConvert"), - })); - $("#selYScale").change(function() { - graph.yScale(this.value); - }); - $("#selConvert").change(function () { - graph.convert(this.value); - }); - $("#selType").change(function () { - graph.type(this.value); - }); - $("#selInterpolate").change(function () { - graph.interpolate(this.value); - }); + function initGraph() { + var graph = new D3Evolution("graph", $.extend({}, graph_options, { + yScale: getSelector("selYScale"), + type: getSelector("selType"), + interpolate: getSelector("selInterpolate"), + convert: getSelector("selConvert"), + })); + $("#selYScale").change(function() { + graph.yScale(this.value); + }); + $("#selConvert").change(function () { + graph.convert(this.value); + }); + $("#selType").change(function () { + graph.type(this.value); + }); + $("#selInterpolate").change(function () { + graph.interpolate(this.value); + }); - return graph; - } + return graph; + } - function getRrdSummary(json, scaleFactor) { - var xExtents = d3.extent(d3.merge(json), function (d) { return d.x; }); - var timeInterval = xExtents[1] - xExtents[0]; + function getRrdSummary(json, scaleFactor) { + var xExtents = d3.extent(d3.merge(json), function (d) { return d.x; }); + var timeInterval = xExtents[1] - xExtents[0]; - return json.map(function (curr, i) { + return json.map(function (curr, i) { // Time intervals that don't have data are excluded from average calculation as d3.mean()ignores nulls - var avg = d3.mean(curr, function (d) { return d.y; }); - // To find an integral on the whole time interval we need to convert nulls to zeroes - var value = d3.mean(curr, function (d) { return +d.y; }) * timeInterval / scaleFactor; - var yExtents = d3.extent(curr, function (d) { return d.y; }); + var avg = d3.mean(curr, function (d) { return d.y; }); + // To find an integral on the whole time interval we need to convert nulls to zeroes + var value = d3.mean(curr, function (d) { return +d.y; }) * timeInterval / scaleFactor; + var yExtents = d3.extent(curr, function (d) { return d.y; }); - return { - label: graph_options.legend.entries[i].label, - value: value ^ 0, - min: +yExtents[0].toFixed(6), - avg: +avg.toFixed(6), - max: +yExtents[1].toFixed(6), - last: +curr[curr.length - 1].y.toFixed(6), - color: graph_options.legend.entries[i].color, - }; - }, []); - } + return { + label: graph_options.legend.entries[i].label, + value: value ^ 0, + min: +yExtents[0].toFixed(6), + avg: +avg.toFixed(6), + max: +yExtents[1].toFixed(6), + last: +curr[curr.length - 1].y.toFixed(6), + color: graph_options.legend.entries[i].color, + }; + }, []); + } - function drawRrdTable(data, unit) { - var total_messages = 0; - var rows = data.map(function (curr, i) { - total_messages += curr.value; - return { - options: { - style: { - color: graph_options.legend.entries[i].color - } - }, - value: curr - }; - }, []); + function drawRrdTable(data, unit) { + var total_messages = 0; + var rows = data.map(function (curr, i) { + total_messages += curr.value; + return { + options: { + style: { + color: graph_options.legend.entries[i].color + } + }, + value: curr + }; + }, []); - document.getElementById('rrd-total-value').innerHTML = total_messages; + document.getElementById("rrd-total-value").innerHTML = total_messages; - $('#rrd-table').footable({ - sorting: { - enabled: true - }, - columns: [ - { name: "label", title: "Action" }, - { name: "value", title: "Messages", defaultContent: "" }, - { name: "min", title: "Minimum, " + unit, defaultContent: "" }, - { name: "avg", title: "Average, " + unit, defaultContent: "" }, - { name: "max", title: "Maximum, " + unit, defaultContent: "" }, - { name: "last", title: "Last, " + unit }, - ], - rows: rows - }); - } + $("#rrd-table").footable({ + sorting: { + enabled: true + }, + columns: [ + {name: "label", title: "Action"}, + {name: "value", title: "Messages", defaultContent: ""}, + {name: "min", title: "Minimum, " + unit, defaultContent: ""}, + {name: "avg", title: "Average, " + unit, defaultContent: ""}, + {name: "max", title: "Maximum, " + unit, defaultContent: ""}, + {name: "last", title: "Last, " + unit}, + ], + rows: rows + }); + } - var interface = {}; - var prevUnit = "msg/s"; + var interface = {}; + var prevUnit = "msg/s"; - interface.draw = function(rspamd, graphs, neighbours, checked_server, type) { + interface.draw = function(rspamd, graphs, neighbours, checked_server, type) { - function updateWidgets(data) { + function updateWidgets(data) { // Autoranging - var scaleFactor = 1; - var unit = "msg/s"; - var yMax = d3.max(d3.merge(data), function (d) { return d.y; }); - if (yMax < 1) { - scaleFactor = 60; - unit = "msg/min"; - data.forEach(function (s) { - s.forEach(function (d) { - if (d.y !== null) { d.y *= scaleFactor; } + var scaleFactor = 1; + var unit = "msg/s"; + var yMax = d3.max(d3.merge(data), function (d) { return d.y; }); + if (yMax < 1) { + scaleFactor = 60; + unit = "msg/min"; + data.forEach(function (s) { + s.forEach(function (d) { + if (d.y !== null) { d.y *= scaleFactor; } + }); }); - }); - } + } - graphs.graph.data(data); - if (unit != prevUnit) { - graphs.graph.yAxisLabel("Message rate, " + unit); - prevUnit = unit; - } + graphs.graph.data(data); + if (unit != prevUnit) { + graphs.graph.yAxisLabel("Message rate, " + unit); + prevUnit = unit; + } - if (!data) { - graphs.rrd_pie.destroy(); - drawRrdTable([]); - return; + if (!data) { + graphs.rrd_pie.destroy(); + drawRrdTable([]); + return; + } + var rrd_summary = getRrdSummary(data, scaleFactor); + graphs.rrd_pie = rspamd.drawPie(graphs.rrd_pie, + "rrd-pie", + rrd_summary, + rrd_pie_config); + drawRrdTable(rrd_summary, unit); } - var rrd_summary = getRrdSummary(data, scaleFactor); - graphs.rrd_pie = rspamd.drawPie(graphs.rrd_pie, - "rrd-pie", - rrd_summary, - rrd_pie_config); - drawRrdTable(rrd_summary, unit); - } - if (graphs.graph === undefined) { - graphs.graph = initGraph(); - } + if (graphs.graph === undefined) { + graphs.graph = initGraph(); + } - if (checked_server === "All SERVERS") { - rspamd.queryNeighbours("graph", function (req_data) { - var neighbours_data = req_data - .filter(function (d) { return d.status }) // filter out unavailable neighbours - .map(function (d){ return d.data; }); + if (checked_server === "All SERVERS") { + rspamd.queryNeighbours("graph", function (req_data) { + var neighbours_data = req_data + .filter(function (d) { return d.status; }) // filter out unavailable neighbours + .map(function (d) { return d.data; }); - if (neighbours_data.length > 1) { - neighbours_data.reduce(function (res, curr) { - if ((curr[0][0].x !== res[0][0].x) || + if (neighbours_data.length > 1) { + neighbours_data.reduce(function (res, curr) { + if ((curr[0][0].x !== res[0][0].x) || (curr[0][curr[0].length - 1].x !== res[0][res[0].length - 1].x)) { - rspamd.alertMessage('alert-error', - 'Neighbours time extents do not match. Check if time is synchronized on all servers.'); - updateWidgets(); - return; - } + rspamd.alertMessage("alert-error", + "Neighbours time extents do not match. Check if time is synchronized on all servers."); + updateWidgets(); + return; + } - var data = []; - curr.forEach(function (action, j) { - data.push( - action.map(function (d, i) { - return { - x: d.x, - y: ((res[j][i].y === null) ? d.y : res[j][i].y + d.y) - }; - }) - ); + var data = []; + curr.forEach(function (action, j) { + data.push( + action.map(function (d, i) { + return { + x: d.x, + y: ((res[j][i].y === null) ? d.y : res[j][i].y + d.y) + }; + }) + ); + }); + updateWidgets(data); }); - updateWidgets(data); - }); - } - else { - updateWidgets(neighbours_data[0]); - } - }, - function (serv, jqXHR, textStatus, errorThrown) { - var alert_status = serv.name + '_alerted'; + } + else { + updateWidgets(neighbours_data[0]); + } + }, + function (serv, jqXHR, textStatus, errorThrown) { + var alert_status = serv.name + "_alerted"; + + if (!(alert_status in sessionStorage)) { + sessionStorage.setItem(alert_status, true); + rspamd.alertMessage("alert-error", "Cannot receive RRD data from: " + + serv.name + ", error: " + errorThrown); + } + }, "GET", {}, {}, { + type: type + }); + return; + } - if (!(alert_status in sessionStorage)) { - sessionStorage.setItem(alert_status, true); - rspamd.alertMessage('alert-error', 'Cannot receive RRD data from: ' + - serv.name + ', error: ' + errorThrown); + $.ajax({ + dataType: "json", + type: "GET", + url: neighbours[checked_server].url + "graph", + jsonp: false, + data: { + "type": type + }, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + success: function (data) { + updateWidgets(data); + }, + error: function (jqXHR, textStatus, errorThrown) { + rspamd.alertMessage("alert-error", "Cannot receive throughput data: " + + textStatus + " " + jqXHR.status + " " + errorThrown); } - }, "GET", {}, {}, { - type: type }); - return; - } + }; - $.ajax({ - dataType: 'json', - type: 'GET', - url: neighbours[checked_server].url + 'graph', - jsonp: false, - data: { - "type": type - }, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - success: function (data) { - updateWidgets(data); - }, - error: function (jqXHR, textStatus, errorThrown) { - rspamd.alertMessage('alert-error', 'Cannot receive throughput data: ' + - textStatus + ' ' + jqXHR.status + ' ' + errorThrown); - } - }); - }; - - interface.setup = function() { + interface.setup = function() { // Handling mouse events on overlapping elements - $("#rrd-pie").mouseover(function () { - $("#rrd-pie").css("z-index", "200"); - $("#rrd-table_toggle").css("z-index", "300"); - }); - $("#rrd-table_toggle").mouseover(function () { - $("#rrd-pie").css("z-index", "0"); - $("#rrd-table_toggle").css("z-index", "0"); - }); + $("#rrd-pie").mouseover(function () { + $("#rrd-pie").css("z-index", "200"); + $("#rrd-table_toggle").css("z-index", "300"); + }); + $("#rrd-table_toggle").mouseover(function () { + $("#rrd-pie").css("z-index", "0"); + $("#rrd-table_toggle").css("z-index", "0"); + }); - return getSelector("selData"); - }; + return getSelector("selData"); + }; - return interface; -}); + return interface; + }); diff --git a/interface/js/app/history.js b/interface/js/app/history.js index fbae27959..ce9d8e90c 100644 --- a/interface/js/app/history.js +++ b/interface/js/app/history.js @@ -22,41 +22,41 @@ THE SOFTWARE. */ -define(['jquery', 'footable', 'humanize'], -function($, _, Humanize) { - var interface = {}; - var ft = {}; - var htmlEscapes = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '/': '/', - '`': '`', - '=': '=' - }; - var htmlEscaper = /[&<>"'\/`=]/g; - var symbolDescriptions = {}; - - EscapeHTML = function(string) { - return ('' + string).replace(htmlEscaper, function(match) { - return htmlEscapes[match]; - }); - }; - - escape_HTML_array = function (arr) { - arr.forEach(function (d, i) { arr[i] = EscapeHTML(d) }); - }; - - function unix_time_format(tm) { - var date = new Date(tm ? tm * 1000 : 0); - return date.toLocaleString(); - } - - function preprocess_item(item) { - for (var prop in item) { - switch (prop) { +define(["jquery", "footable", "humanize"], + function($, _, Humanize) { + var interface = {}; + var ft = {}; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "'": "'", + "/": "/", + "`": "`", + "=": "=" + }; + var htmlEscaper = /[&<>"'\/`=]/g; + var symbolDescriptions = {}; + + EscapeHTML = function(string) { + return ("" + string).replace(htmlEscaper, function(match) { + return htmlEscapes[match]; + }); + }; + + escape_HTML_array = function (arr) { + arr.forEach(function (d, i) { arr[i] = EscapeHTML(d); }); + }; + + function unix_time_format(tm) { + var date = new Date(tm ? tm * 1000 : 0); + return date.toLocaleString(); + } + + function preprocess_item(item) { + for (var prop in item) { + switch (prop) { case "rcpt_mime": case "rcpt_smtp": escape_HTML_array(item[prop]); @@ -69,7 +69,7 @@ function($, _, Humanize) { } sym.name = EscapeHTML(key); if (sym.description) { - sym.description = EscapeHTML(sym.description); + sym.description = EscapeHTML(sym.description); } if (sym.options) { @@ -81,166 +81,166 @@ function($, _, Humanize) { if (typeof (item[prop]) == "string") { item[prop] = EscapeHTML(item[prop]); } + } } - } - if (item.action === 'clean' || item.action === 'no action') { - item.action = "<div style='font-size:11px' class='label label-success'>" + item.action + "</div>"; - } else if (item.action === 'rewrite subject' || item.action === 'add header' || item.action === 'probable spam') { - item.action = "<div style='font-size:11px' class='label label-warning'>" + item.action + "</div>"; - } else if (item.action === 'spam' || item.action === 'reject') { - item.action = "<div style='font-size:11px' class='label label-danger'>" + item.action + "</div>"; - } else { - item.action = "<div style='font-size:11px' class='label label-info'>" + item.action + "</div>"; - } + if (item.action === "clean" || item.action === "no action") { + item.action = "<div style='font-size:11px' class='label label-success'>" + item.action + "</div>"; + } else if (item.action === "rewrite subject" || item.action === "add header" || item.action === "probable spam") { + item.action = "<div style='font-size:11px' class='label label-warning'>" + item.action + "</div>"; + } else if (item.action === "spam" || item.action === "reject") { + item.action = "<div style='font-size:11px' class='label label-danger'>" + item.action + "</div>"; + } else { + item.action = "<div style='font-size:11px' class='label label-info'>" + item.action + "</div>"; + } - var score_content; - if (item.score < item.required_score) { - score_content = "<span class='text-success'>" + item.score.toFixed(2) + " / " + item.required_score + "</span>"; - } else { - score_content = "<span class='text-danger'>" + item.score.toFixed(2) + " / " + item.required_score + "</span>"; - } + var score_content; + if (item.score < item.required_score) { + score_content = "<span class='text-success'>" + item.score.toFixed(2) + " / " + item.required_score + "</span>"; + } else { + score_content = "<span class='text-danger'>" + item.score.toFixed(2) + " / " + item.required_score + "</span>"; + } - item.score = { - "options": { - "sortValue": item.score - }, - "value": score_content - }; + item.score = { + "options": { + "sortValue": item.score + }, + "value": score_content + }; - if (item.user == null) { - item.user = "none"; + if (item.user == null) { + item.user = "none"; + } } - } - function process_history_v2(data) { + function process_history_v2(data) { // Display no more than rcpt_lim recipients - var rcpt_lim = 3; - var items = []; - - function getSelector(id) { - var e = document.getElementById(id); - return e.options[e.selectedIndex].value; - } - var compare = (getSelector("selSymOrder") === "score") - ? function (e1, e2) { - return Math.abs(e1.score) < Math.abs(e2.score); - } - : function (e1, e2) { - return e1.name.localeCompare(e2.name); - }; + var rcpt_lim = 3; + var items = []; - $.each(data.rows, - function (i, item) { - function more(p) { - var l = item[p].length; - return (l > rcpt_lim) ? " … (" + l + ")" : ""; + function getSelector(id) { + var e = document.getElementById(id); + return e.options[e.selectedIndex].value; } - function format_rcpt(smtp, mime) { - var full = shrt = ""; - if (smtp) { - full = "[" + item.rcpt_smtp.join(", ") + "] "; - shrt = "[" + item.rcpt_smtp.slice(0,rcpt_lim).join(",​") + more("rcpt_smtp") + "]"; - if (mime) { - full += " "; - shrt += " "; - } - } - if (mime) { - full += item.rcpt_mime.join(", "); - shrt += item.rcpt_mime.slice(0,rcpt_lim).join(",​") + more("rcpt_mime"); + var compare = (getSelector("selSymOrder") === "score") + ? function (e1, e2) { + return Math.abs(e1.score) < Math.abs(e2.score); } - return {full: full, shrt: shrt}; - } + : function (e1, e2) { + return e1.name.localeCompare(e2.name); + }; + + $.each(data.rows, + function (i, item) { + function more(p) { + var l = item[p].length; + return (l > rcpt_lim) ? " … (" + l + ")" : ""; + } + function format_rcpt(smtp, mime) { + var full = shrt = ""; + if (smtp) { + full = "[" + item.rcpt_smtp.join(", ") + "] "; + shrt = "[" + item.rcpt_smtp.slice(0, rcpt_lim).join(",​") + more("rcpt_smtp") + "]"; + if (mime) { + full += " "; + shrt += " "; + } + } + if (mime) { + full += item.rcpt_mime.join(", "); + shrt += item.rcpt_mime.slice(0, rcpt_lim).join(",​") + more("rcpt_mime"); + } + return {full: full, shrt: shrt}; + } - preprocess_item(item); - Object.keys(item.symbols).map(function(key) { - var sym = item.symbols[key]; + preprocess_item(item); + Object.keys(item.symbols).map(function(key) { + var sym = item.symbols[key]; - if (sym.description) { - var str = '<strong><abbr data-sym-key="' + key + '">' + sym.name + '</abbr></strong>' + "(" + sym.score + ")"; + if (sym.description) { + var str = "<strong><abbr data-sym-key=\"" + key + "\">" + sym.name + "</abbr></strong>" + "(" + sym.score + ")"; - // Store description for tooltip - symbolDescriptions[key] = sym.description; - } else { - var str = '<strong>' + sym.name + '</strong>' + "(" + sym.score + ")"; - } + // Store description for tooltip + symbolDescriptions[key] = sym.description; + } else { + var str = "<strong>" + sym.name + "</strong>" + "(" + sym.score + ")"; + } - if (sym.options) { - str += '[' + sym.options.join(",") + "]"; - } - item.symbols[key].str = str; - }); - item.symbols = Object.keys(item.symbols). - map(function(key) { - return item.symbols[key]; - }). - sort(compare). - map(function(e) { return e.str; }). - join("<br>\n"); - item.time = { - "value": unix_time_format(item.unix_time), - "options": { - "sortValue": item.unix_time - } - }; - var scan_time = item.time_real.toFixed(3) + ' / ' + + if (sym.options) { + str += "[" + sym.options.join(",") + "]"; + } + item.symbols[key].str = str; + }); + item.symbols = Object.keys(item.symbols). + map(function(key) { + return item.symbols[key]; + }). + sort(compare). + map(function(e) { return e.str; }). + join("<br>\n"); + item.time = { + "value": unix_time_format(item.unix_time), + "options": { + "sortValue": item.unix_time + } + }; + var scan_time = item.time_real.toFixed(3) + " / " + item.time_virtual.toFixed(3); - item.scan_time = { - "options": { - "sortValue": item.time_real - }, - "value": scan_time - }; - item.id = item['message-id']; - - var rcpt = {}; - if (!item.rcpt_mime.length) { - rcpt = format_rcpt(true, false); - } else if ($(item.rcpt_mime).not(item.rcpt_smtp).length !== 0 || $(item.rcpt_smtp).not(item.rcpt_mime).length !== 0) { - rcpt = format_rcpt(true, true); - } else { - rcpt = format_rcpt(false, true); - } - item.rcpt_mime_short = rcpt.shrt; - item.rcpt_mime = rcpt.full; + item.scan_time = { + "options": { + "sortValue": item.time_real + }, + "value": scan_time + }; + item.id = item["message-id"]; + + var rcpt = {}; + if (!item.rcpt_mime.length) { + rcpt = format_rcpt(true, false); + } else if ($(item.rcpt_mime).not(item.rcpt_smtp).length !== 0 || $(item.rcpt_smtp).not(item.rcpt_mime).length !== 0) { + rcpt = format_rcpt(true, true); + } else { + rcpt = format_rcpt(false, true); + } + item.rcpt_mime_short = rcpt.shrt; + item.rcpt_mime = rcpt.full; - if (item.sender_mime !== item.sender_smtp) { - item.sender_mime = "[" + item.sender_smtp + "] " + item.sender_mime; - } - items.push(item); - }); + if (item.sender_mime !== item.sender_smtp) { + item.sender_mime = "[" + item.sender_smtp + "] " + item.sender_mime; + } + items.push(item); + }); - return items; - } + return items; + } - function process_history_legacy(data) { - var items = []; + function process_history_legacy(data) { + var items = []; - $.each(data, function (i, item) { - item.time = unix_time_format(item.unix_time); - preprocess_item(item); - item.scan_time = { - "options": { - "sortValue": item.scan_time - }, - "value": item.scan_time - }; - item.time = { - "value": unix_time_format(item.unix_time), - "options": { - "sortValue": item.unix_time - } - }; + $.each(data, function (i, item) { + item.time = unix_time_format(item.unix_time); + preprocess_item(item); + item.scan_time = { + "options": { + "sortValue": item.scan_time + }, + "value": item.scan_time + }; + item.time = { + "value": unix_time_format(item.unix_time), + "options": { + "sortValue": item.unix_time + } + }; - items.push(item) - }); + items.push(item); + }); - return items; - } + return items; + } - function columns_v2() { - return [{ + function columns_v2() { + return [{ "name": "id", "title": "ID", "style": { @@ -358,10 +358,10 @@ function($, _, Humanize) { "word-wrap": "break-word" } }]; - } + } - function columns_legacy() { - return [{ + function columns_legacy() { + return [{ "name": "id", "title": "ID", "style": { @@ -445,343 +445,343 @@ function($, _, Humanize) { "maxWidth": 200 } }]; - } - - var process_functions = { - "2": process_history_v2, - "legacy": process_history_legacy - }; - - var columns = { - "2": columns_v2, - "legacy": columns_legacy - }; - - function process_history_data(data) { - var pf = process_functions.legacy; - - if (data.version) { - var strkey = data.version.toString(); - if (process_functions[strkey]) { - pf = process_functions[strkey]; - } } - return pf(data); - } + var process_functions = { + "2": process_history_v2, + "legacy": process_history_legacy + }; - function get_history_columns(data) { - var func = columns.legacy; + var columns = { + "2": columns_v2, + "legacy": columns_legacy + }; + + function process_history_data(data) { + var pf = process_functions.legacy; - if (data.version) { - var strkey = data.version.toString(); - if (columns[strkey]) { - func = columns[strkey]; + if (data.version) { + var strkey = data.version.toString(); + if (process_functions[strkey]) { + pf = process_functions[strkey]; + } } + + return pf(data); } - return func(); - } - - interface.getHistory = function (rspamd, tables, neighbours, checked_server) { - FooTable.actionFilter = FooTable.Filtering.extend({ - construct : function(instance) { - this._super(instance); - this.actions = [ 'reject', 'add header', 'greylist', - 'no action', 'soft reject', 'rewrite subject' ]; - this.def = 'Any action'; - this.$action = null; - }, - $create : function() { - this._super(); - var self = this, $form_grp = $('<div/>', { - 'class' : 'form-group' - }).append($('<label/>', { - 'class' : 'sr-only', - text : 'Action' - })).prependTo(self.$form); - - self.$action = $('<select/>', { - 'class' : 'form-control' - }).on('change', { - self : self - }, self._onStatusDropdownChanged).append( - $('<option/>', { - text : self.def - })).appendTo($form_grp); - - $.each(self.actions, function(i, action) { - self.$action.append($('<option/>').text(action)); - }); - }, - _onStatusDropdownChanged : function(e) { - var self = e.data.self, selected = $(this).val(); - if (selected !== self.def) { - if(selected === "reject"){ - self.addFilter('action', 'reject -soft', [ 'action' ]); - } else { - self.addFilter('action', selected, [ 'action' ]); - } - } else { - self.removeFilter('action'); - } - self.filter(); - }, - draw : function() { - this._super(); - var action = this.find('action'); - if (action instanceof FooTable.Filter) { - if(action.query.val() === 'reject -soft'){ - this.$action.val('reject'); - } else { - this.$action.val(action.query.val()); + function get_history_columns(data) { + var func = columns.legacy; + + if (data.version) { + var strkey = data.version.toString(); + if (columns[strkey]) { + func = columns[strkey]; } - } else { - this.$action.val(this.def); } - } - }); - var drawTooltips = function() { - // Update symbol description tooltips - $.each(symbolDescriptions, function (key, description) { - $('abbr[data-sym-key=' + key + ']').tooltip({ - "placement": "bottom", - "html": true, - "title": description - }); - }); + return func(); } - if (checked_server === "All SERVERS") { - rspamd.queryNeighbours("history", function (req_data) { - function differentVersions() { - var dv = neighbours_data.some(function (e) { - return e.version !== neighbours_data[0].version; + interface.getHistory = function (rspamd, tables, neighbours, checked_server) { + FooTable.actionFilter = FooTable.Filtering.extend({ + construct : function(instance) { + this._super(instance); + this.actions = ["reject", "add header", "greylist", + "no action", "soft reject", "rewrite subject"]; + this.def = "Any action"; + this.$action = null; + }, + $create : function() { + this._super(); + var self = this, $form_grp = $("<div/>", { + "class" : "form-group" + }).append($("<label/>", { + "class" : "sr-only", + text : "Action" + })).prependTo(self.$form); + + self.$action = $("<select/>", { + "class" : "form-control" + }).on("change", { + self : self + }, self._onStatusDropdownChanged).append( + $("<option/>", { + text : self.def + })).appendTo($form_grp); + + $.each(self.actions, function(i, action) { + self.$action.append($("<option/>").text(action)); }); - if (dv) { - rspamd.alertMessage('alert-error', - 'Neighbours history backend versions do not match. Cannot display history.'); - return true; + }, + _onStatusDropdownChanged : function(e) { + var self = e.data.self, selected = $(this).val(); + if (selected !== self.def) { + if (selected === "reject") { + self.addFilter("action", "reject -soft", ["action"]); + } else { + self.addFilter("action", selected, ["action"]); + } + } else { + self.removeFilter("action"); + } + self.filter(); + }, + draw : function() { + this._super(); + var action = this.find("action"); + if (action instanceof FooTable.Filter) { + if (action.query.val() === "reject -soft") { + this.$action.val("reject"); + } else { + this.$action.val(action.query.val()); + } + } else { + this.$action.val(this.def); } } + }); + + var drawTooltips = function() { + // Update symbol description tooltips + $.each(symbolDescriptions, function (key, description) { + $("abbr[data-sym-key=" + key + "]").tooltip({ + "placement": "bottom", + "html": true, + "title": description + }); + }); + }; - var neighbours_data = req_data - .filter(function (d) { return d.status }) // filter out unavailable neighbours - .map(function (d){ return d.data; }); - if (neighbours_data.length && !differentVersions()) { - var data = {}; - if (neighbours_data[0].version) { - data.rows = [].concat.apply([], neighbours_data - .map(function (e) { - return e.rows; - })); - data.version = neighbours_data[0].version; + if (checked_server === "All SERVERS") { + rspamd.queryNeighbours("history", function (req_data) { + function differentVersions() { + var dv = neighbours_data.some(function (e) { + return e.version !== neighbours_data[0].version; + }); + if (dv) { + rspamd.alertMessage("alert-error", + "Neighbours history backend versions do not match. Cannot display history."); + return true; + } } - else { + + var neighbours_data = req_data + .filter(function (d) { return d.status; }) // filter out unavailable neighbours + .map(function (d) { return d.data; }); + if (neighbours_data.length && !differentVersions()) { + var data = {}; + if (neighbours_data[0].version) { + data.rows = [].concat.apply([], neighbours_data + .map(function (e) { + return e.rows; + })); + data.version = neighbours_data[0].version; + } + else { // Legacy version - data = [].concat.apply([], neighbours_data); + data = [].concat.apply([], neighbours_data); + } + + var items = process_history_data(data); + ft.history = FooTable.init("#historyTable", { + "columns": get_history_columns(data), + "rows": items, + "paging": { + "enabled": true, + "limit": 5, + "size": 25 + }, + "filtering": { + "enabled": true, + "position": "left", + "connectors": false + }, + "sorting": { + "enabled": true + }, + "components": { + "filtering": FooTable.actionFilter + }, + "on": { + "ready.ft.table": drawTooltips, + "after.ft.sorting": drawTooltips, + "after.ft.paging": drawTooltips, + "after.ft.filtering": drawTooltips + } + }); + } else { + if (ft.history) { + ft.history.destroy(); + ft.history = undefined; + } + } + }); + } + else { + $.ajax({ + dataType: "json", + url: neighbours[checked_server].url + "history", + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + error: function () { + rspamd.alertMessage("alert-error", "Cannot receive history"); + }, + success: function (data) { + var items = process_history_data(data); + ft.history = FooTable.init("#historyTable", { + "columns": get_history_columns(data), + "rows": items, + "paging": { + "enabled": true, + "limit": 5, + "size": 25 + }, + "filtering": { + "enabled": true, + "position": "left", + "connectors": false + }, + "sorting": { + "enabled": true + }, + "components": { + "filtering": FooTable.actionFilter + }, + "on": { + "ready.ft.table": drawTooltips, + "after.ft.sorting": drawTooltips, + "after.ft.paging": drawTooltips, + "after.ft.filtering": drawTooltips + } + }); } + }); + } + $("#updateHistory").off("click"); + $("#updateHistory").on("click", function (e) { + e.preventDefault(); + interface.getHistory(rspamd, tables, neighbours, checked_server); + }); + $("#selSymOrder").unbind().change(function() { + interface.getHistory(rspamd, tables, neighbours, checked_server); + }); - var items = process_history_data(data); - ft.history = FooTable.init("#historyTable", { - "columns": get_history_columns(data), - "rows": items, - "paging": { - "enabled": true, - "limit": 5, - "size": 25 - }, - "filtering": { - "enabled": true, - "position": "left", - "connectors": false - }, - "sorting": { - "enabled": true + // @reset history log + $("#resetHistory").off("click"); + $("#resetHistory").on("click", function (e) { + e.preventDefault(); + if (!confirm("Are you sure you want to reset history log?")) { + return; + } + if (ft.history) { + ft.history.destroy(); + ft.history = undefined; + } + if (ft.errors) { + ft.errors.destroy(); + ft.errors = undefined; + } + if (checked_server === "All SERVERS") { + rspamd.queryNeighbours("errors", function (data) { + interface.getHistory(rspamd, tables, neighbours, checked_server); + interface.getErrors(rspamd, tables, neighbours, checked_server); + }); + } + else { + $.ajax({ + dataType: "json", + type: "GET", + jsonp: false, + url: neighbours[checked_server].url + "historyreset", + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); }, - "components": { - "filtering": FooTable.actionFilter + success: function () { + interface.getHistory(rspamd, tables, neighbours, checked_server); + interface.getErrors(rspamd, tables, neighbours, checked_server); }, - "on": { - "ready.ft.table": drawTooltips, - "after.ft.sorting": drawTooltips, - "after.ft.paging": drawTooltips, - "after.ft.filtering": drawTooltips + error: function (data) { + rspamd.alertMessage("alert-modal alert-error", data.statusText); } }); - } else { - if (ft.history) { - ft.history.destroy(); - ft.history = undefined; - } } }); - } - else { - $.ajax({ - dataType: 'json', - url: neighbours[checked_server].url + 'history', - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); + }; + + function drawErrorsTable(data) { + var items = []; + $.each(data, function (i, item) { + items.push( + item.ts = unix_time_format(item.ts) + ); + }); + ft.errors = FooTable.init("#errorsLog", { + "columns": [ + {"sorted": true, "direction": "DESC", "name":"ts", "title":"Time", "style":{"font-size":"11px", "width":300, "maxWidth":300}}, + {"name":"type", "title":"Worker type", "breakpoints":"xs sm", "style":{"font-size":"11px", "width":150, "maxWidth":150}}, + {"name":"pid", "title":"PID", "breakpoints":"xs sm", "style":{"font-size":"11px", "width":110, "maxWidth":110}}, + {"name":"module", "title":"Module", "style":{"font-size":"11px"}}, + {"name":"id", "title":"Internal ID", "style":{"font-size":"11px"}}, + {"name":"message", "title":"Message", "breakpoints":"xs sm", "style":{"font-size":"11px"}}, + ], + "rows": data, + "paging": { + "enabled": true, + "limit": 5, + "size": 25 }, - error: function () { - rspamd.alertMessage('alert-error', 'Cannot receive history'); + "filtering": { + "enabled": true, + "position": "left", + "connectors": false }, - success: function (data) { - var items = process_history_data(data); - ft.history = FooTable.init("#historyTable", { - "columns": get_history_columns(data), - "rows": items, - "paging": { - "enabled": true, - "limit": 5, - "size": 25 - }, - "filtering": { - "enabled": true, - "position": "left", - "connectors": false - }, - "sorting": { - "enabled": true - }, - "components": { - "filtering": FooTable.actionFilter - }, - "on": { - "ready.ft.table": drawTooltips, - "after.ft.sorting": drawTooltips, - "after.ft.paging": drawTooltips, - "after.ft.filtering": drawTooltips - } - }); + "sorting": { + "enabled": true } }); } - $('#updateHistory').off('click'); - $('#updateHistory').on('click', function (e) { - e.preventDefault(); - interface.getHistory(rspamd, tables, neighbours, checked_server); - }); - $("#selSymOrder").unbind().change(function() { - interface.getHistory(rspamd, tables, neighbours, checked_server); - }); - - // @reset history log - $('#resetHistory').off('click'); - $('#resetHistory').on('click', function (e) { - e.preventDefault(); - if (!confirm("Are you sure you want to reset history log?")) { - return; - } - if (ft.history) { - ft.history.destroy(); - ft.history = undefined; - } - if (ft.errors) { - ft.errors.destroy(); - ft.errors = undefined; - } - if (checked_server === "All SERVERS") { - rspamd.queryNeighbours("errors", function (data) { - interface.getHistory(rspamd, tables, neighbours, checked_server); - interface.getErrors(rspamd, tables, neighbours, checked_server); - }); - } - else { + + interface.getErrors = function(rspamd, tables, neighbours, checked_server) { + if (rspamd.read_only) return; + + if (checked_server !== "All SERVERS") { $.ajax({ - dataType: 'json', - type: 'GET', + dataType: "json", + url: neighbours[checked_server].url + "errors", jsonp: false, - url: neighbours[checked_server].url + 'historyreset', beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); + xhr.setRequestHeader("Password", rspamd.getPassword()); }, - success: function () { - interface.getHistory(rspamd, tables, neighbours, checked_server); - interface.getErrors(rspamd, tables, neighbours, checked_server); + error: function () { + rspamd.alertMessage("alert-error", "Cannot receive errors"); }, - error: function (data) { - rspamd.alertMessage('alert-modal alert-error', data.statusText); + success: function (data) { + drawErrorsTable(data); } }); + } else { + rspamd.queryNeighbours("errors", function (req_data) { + var neighbours_data = req_data + .filter(function (d) { + return d.status; + }) // filter out unavailable neighbours + .map(function (d) { + return d.data; + }); + drawErrorsTable([].concat.apply([], neighbours_data)); + }); } - }); - }; - - function drawErrorsTable(data) { - var items = []; - $.each(data, function (i, item) { - items.push( - item.ts = unix_time_format(item.ts) - ); - }); - ft.errors = FooTable.init("#errorsLog", { - "columns": [ - {"sorted": true,"direction": "DESC","name":"ts","title":"Time","style":{"font-size":"11px","width":300,"maxWidth":300}}, - {"name":"type","title":"Worker type","breakpoints":"xs sm","style":{"font-size":"11px","width":150,"maxWidth":150}}, - {"name":"pid","title":"PID","breakpoints":"xs sm","style":{"font-size":"11px","width":110,"maxWidth":110}}, - {"name":"module","title":"Module","style":{"font-size":"11px"}}, - {"name":"id","title":"Internal ID","style":{"font-size":"11px"}}, - {"name":"message","title":"Message","breakpoints":"xs sm","style":{"font-size":"11px"}}, - ], - "rows": data, - "paging": { - "enabled": true, - "limit": 5, - "size": 25 - }, - "filtering": { - "enabled": true, - "position": "left", - "connectors": false - }, - "sorting": { - "enabled": true - } - }); - } - - interface.getErrors = function(rspamd, tables, neighbours, checked_server) { - if (rspamd.read_only) return; - - if (checked_server !== "All SERVERS") { - $.ajax({ - dataType: 'json', - url: neighbours[checked_server].url + 'errors', - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - error: function () { - rspamd.alertMessage('alert-error', 'Cannot receive errors'); - }, - success: function (data) { - drawErrorsTable(data); - } - }); - } else { - rspamd.queryNeighbours("errors", function (req_data) { - var neighbours_data = req_data - .filter(function (d) { - return d.status - }) // filter out unavailable neighbours - .map(function (d) { - return d.data; - }); - drawErrorsTable([].concat.apply([], neighbours_data)); + $("#updateErrors").off("click"); + $("#updateErrors").on("click", function (e) { + e.preventDefault(); + interface.getErrors(rspamd, tables, neighbours, checked_server); }); - } - $('#updateErrors').off('click'); - $('#updateErrors').on('click', function (e) { - e.preventDefault(); - interface.getErrors(rspamd, tables, neighbours, checked_server); - }); - }; - - interface.setup = function(rspamd, tables) { - }; - return interface; -}); + }; + + interface.setup = function(rspamd, tables) { + }; + return interface; + }); diff --git a/interface/js/app/rspamd.js b/interface/js/app/rspamd.js index 120f746c4..03a0713b1 100644 --- a/interface/js/app/rspamd.js +++ b/interface/js/app/rspamd.js @@ -22,531 +22,531 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -define(['jquery', 'd3pie', 'visibility', 'app/stats', 'app/graph', 'app/config', - 'app/symbols', 'app/history', 'app/upload'], - function ($, d3pie, visibility, tab_stat, tab_graph, tab_config, - tab_symbols, tab_history, tab_upload) { - // begin - var graphs = {}; - var tables = {}; - var neighbours = []; //list of clusters - var checked_server = "All SERVERS"; - var interface = { - read_only: false, - }; - - var timer_id = []; - var selData; // Graph's dataset selector state - - function stopTimers() { - for (var key in timer_id) { - Visibility.stop(timer_id[key]); - } +define(["jquery", "d3pie", "visibility", "app/stats", "app/graph", "app/config", + "app/symbols", "app/history", "app/upload"], +function ($, d3pie, visibility, tab_stat, tab_graph, tab_config, + tab_symbols, tab_history, tab_upload) { + // begin + var graphs = {}; + var tables = {}; + var neighbours = []; // list of clusters + var checked_server = "All SERVERS"; + var interface = { + read_only: false, + }; + + var timer_id = []; + var selData; // Graph's dataset selector state + + function stopTimers() { + for (var key in timer_id) { + Visibility.stop(timer_id[key]); } + } - function disconnect() { - if (graphs.chart) { - graphs.chart.destroy(); - graphs.chart = undefined; - } - if (graphs.rrd_pie) { - graphs.rrd_pie.destroy(); - graphs.rrd_pie = undefined; - } - if (graphs.graph) { - graphs.graph.destroy(); - graphs.graph = undefined; - } - if (tables.history) { - tables.history.destroy(); - tables.history = undefined; - } - if (tables.errors) { - tables.errors.destroy(); - tables.errors = undefined; - } - if (tables.symbols) { - tables.symbols.destroy(); - tables.symbols = undefined; - } - - stopTimers(); - cleanCredentials(); - interface.connect(); + function disconnect() { + if (graphs.chart) { + graphs.chart.destroy(); + graphs.chart = undefined; } - - function tabClick(tab_id) { - if ($(tab_id).attr('disabled')) return; - $(tab_id).attr('disabled', true); - - stopTimers(); - - if (tab_id === "#refresh") { - tab_id = "#" + $('.navbar-nav .active > a' ).attr('id'); - } - - switch (tab_id) { - case "#status_nav": - tab_stat.statWidgets(interface, graphs, checked_server); - timer_id.status = Visibility.every(10000, function () { - tab_stat.statWidgets(interface, graphs, checked_server); - }); - break; - case "#throughput_nav": - tab_graph.draw(interface, graphs, neighbours, checked_server, selData); - - var autoRefresh = { - hourly: 60000, - daily: 300000 - }; - timer_id.throughput = Visibility.every(autoRefresh[selData] || 3600000, function () { - tab_graph.draw(interface, graphs, neighbours, checked_server, selData); - }); - break; - case "#configuration_nav": - tab_config.getActions(interface); - tab_config.getMaps(interface); - break; - case "#symbols_nav": - tab_symbols.getSymbols(interface, tables, checked_server); - break; - case "#history_nav": - tab_history.getHistory(interface, tables, neighbours, checked_server); - tab_history.getErrors(interface, tables, neighbours, checked_server); - break; - case "#disconnect": - disconnect(); - break; - } - - setTimeout(function () { - $(tab_id).removeAttr('disabled'); - $('#refresh').removeAttr('disabled'); - }, 1000); + if (graphs.rrd_pie) { + graphs.rrd_pie.destroy(); + graphs.rrd_pie = undefined; } - - // @return password - function getPassword() { - return sessionStorage.getItem('Password'); + if (graphs.graph) { + graphs.graph.destroy(); + graphs.graph = undefined; } - - // @save credentials - function saveCredentials(password) { - sessionStorage.setItem('Password', password); + if (tables.history) { + tables.history.destroy(); + tables.history = undefined; } - - // @clean credentials - function cleanCredentials() { - sessionStorage.clear(); - $('#statWidgets').empty(); - $('#listMaps').empty(); - $('#modalBody').empty(); - $('#historyLog tbody').remove(); - $('#errorsLog tbody').remove(); - $('#symbolsTable tbody').remove(); - password = ''; + if (tables.errors) { + tables.errors.destroy(); + tables.errors = undefined; } - - function isLogged() { - if (sessionStorage.getItem('Credentials') !== null) { - return true; - } - return false; + if (tables.symbols) { + tables.symbols.destroy(); + tables.symbols = undefined; } - function displayUI() { - // @toggle auth and main - var disconnect = $('#navBar .pull-right'); - $('#mainUI').show(); - $('#progress').show(); - $(disconnect).show(); - tabClick("#refresh"); - $('#progress').hide(); - } + stopTimers(); + cleanCredentials(); + interface.connect(); + } - function alertMessage(alertClass, alertText) { - var a = $('<div class="alert ' + alertClass + ' alert-dismissible fade in show">' + - '<button type="button" class="close" data-dismiss="alert" title="Dismiss">×</button>' + - '<strong>' + alertText + '</strong>'); - $('.notification-area').append(a); + function tabClick(tab_id) { + if ($(tab_id).attr("disabled")) return; + $(tab_id).attr("disabled", true); - setTimeout(function () { - $(a).fadeTo(500, 0).slideUp(500, function () { - $(this).alert('close'); - }); - }, 5000); - } + stopTimers(); - // Public functions - interface.alertMessage = alertMessage; - interface.setup = function() { - $("#selData").change(function () { - selData = this.value; - tabClick("#throughput_nav"); - }); - $.ajaxSetup({ - timeout: 20000, - jsonp: false - }); + if (tab_id === "#refresh") { + tab_id = "#" + $(".navbar-nav .active > a" ).attr("id"); + } - $(document).ajaxStart(function () { - $('#navBar').addClass('loading'); - }); - $(document).ajaxComplete(function () { - setTimeout(function () { - $('#navBar').removeClass('loading'); - }, 1000); + switch (tab_id) { + case "#status_nav": + tab_stat.statWidgets(interface, graphs, checked_server); + timer_id.status = Visibility.every(10000, function () { + tab_stat.statWidgets(interface, graphs, checked_server); }); + break; + case "#throughput_nav": + tab_graph.draw(interface, graphs, neighbours, checked_server, selData); - $.ajax({ - type: 'GET', - url: 'stat', - success: function () { - saveCredentials({}, 'nopassword'); - var dialog = $('#connectDialog'); - var backdrop = $('#backDrop'); - $(dialog).hide(); - $(backdrop).hide(); - displayUI(); - }, + var autoRefresh = { + hourly: 60000, + daily: 300000 + }; + timer_id.throughput = Visibility.every(autoRefresh[selData] || 3600000, function () { + tab_graph.draw(interface, graphs, neighbours, checked_server, selData); }); + break; + case "#configuration_nav": + tab_config.getActions(interface); + tab_config.getMaps(interface); + break; + case "#symbols_nav": + tab_symbols.getSymbols(interface, tables, checked_server); + break; + case "#history_nav": + tab_history.getHistory(interface, tables, neighbours, checked_server); + tab_history.getErrors(interface, tables, neighbours, checked_server); + break; + case "#disconnect": + disconnect(); + break; + } - $('a[data-toggle="tab"]').on('click', function (e) { - var tab_id = "#" + $(e.target).attr("id"); - tabClick(tab_id); + setTimeout(function () { + $(tab_id).removeAttr("disabled"); + $("#refresh").removeAttr("disabled"); + }, 1000); + } + + // @return password + function getPassword() { + return sessionStorage.getItem("Password"); + } + + // @save credentials + function saveCredentials(password) { + sessionStorage.setItem("Password", password); + } + + // @clean credentials + function cleanCredentials() { + sessionStorage.clear(); + $("#statWidgets").empty(); + $("#listMaps").empty(); + $("#modalBody").empty(); + $("#historyLog tbody").remove(); + $("#errorsLog tbody").remove(); + $("#symbolsTable tbody").remove(); + password = ""; + } + + function isLogged() { + if (sessionStorage.getItem("Credentials") !== null) { + return true; + } + return false; + } + + function displayUI() { + // @toggle auth and main + var disconnect = $("#navBar .pull-right"); + $("#mainUI").show(); + $("#progress").show(); + $(disconnect).show(); + tabClick("#refresh"); + $("#progress").hide(); + } + + function alertMessage(alertClass, alertText) { + var a = $("<div class=\"alert " + alertClass + " alert-dismissible fade in show\">" + + "<button type=\"button\" class=\"close\" data-dismiss=\"alert\" title=\"Dismiss\">×</button>" + + "<strong>" + alertText + "</strong>"); + $(".notification-area").append(a); + + setTimeout(function () { + $(a).fadeTo(500, 0).slideUp(500, function () { + $(this).alert("close"); }); - - $("#selSrv").change(function () { + }, 5000); + } + + // Public functions + interface.alertMessage = alertMessage; + interface.setup = function() { + $("#selData").change(function () { + selData = this.value; + tabClick("#throughput_nav"); + }); + $.ajaxSetup({ + timeout: 20000, + jsonp: false + }); + + $(document).ajaxStart(function () { + $("#navBar").addClass("loading"); + }); + $(document).ajaxComplete(function () { + setTimeout(function () { + $("#navBar").removeClass("loading"); + }, 1000); + }); + + $.ajax({ + type: "GET", + url: "stat", + success: function () { + saveCredentials({}, "nopassword"); + var dialog = $("#connectDialog"); + var backdrop = $("#backDrop"); + $(dialog).hide(); + $(backdrop).hide(); + displayUI(); + }, + }); + + $("a[data-toggle=\"tab\"]").on("click", function (e) { + var tab_id = "#" + $(e.target).attr("id"); + tabClick(tab_id); + }); + + $("#selSrv").change(function () { + checked_server = this.value; + $("#selSrv [value=\"" + checked_server + "\"]").prop("checked", true); + tabClick("#" + $("#navBar ul li.active > a").attr("id")); + }); + + // Radio buttons + $(document).on("click", "input:radio[name=\"clusterName\"]", function () { + if (!this.disabled) { checked_server = this.value; - $('#selSrv [value="' + checked_server + '"]').prop("checked", true); - tabClick("#" + $("#navBar ul li.active > a").attr("id")); - }); - - // Radio buttons - $(document).on('click', 'input:radio[name="clusterName"]', function () { - if (!this.disabled) { - checked_server = this.value; - tabClick("#status_nav"); - } - }); - tab_config.setup(interface); - tab_symbols.setup(interface, tables); - tab_history.setup(interface, tables); - tab_upload.setup(interface); - selData = tab_graph.setup(); - }; - - interface.connect = function() { - if (isLogged()) { - var data = JSON.parse(sessionStorage.getItem('Credentials')); + tabClick("#status_nav"); + } + }); + tab_config.setup(interface); + tab_symbols.setup(interface, tables); + tab_history.setup(interface, tables); + tab_upload.setup(interface); + selData = tab_graph.setup(); + }; + + interface.connect = function() { + if (isLogged()) { + var data = JSON.parse(sessionStorage.getItem("Credentials")); + + if (data && data[checked_server].read_only) { + interface.read_only = true; + $("#learning_nav").hide(); + $("#resetHistory").attr("disabled", true); + $("#errors-history").hide(); + } + else { + interface.read_only = false; + $("#learning_nav").show(); + $("#resetHistory").removeAttr("disabled", true); + } + displayUI(); + return; + } - if (data && data[checked_server].read_only) { - interface.read_only = true; - $('#learning_nav').hide(); - $('#resetHistory').attr('disabled', true); - $('#errors-history').hide(); - } - else { - interface.read_only = false; - $('#learning_nav').show(); - $('#resetHistory').removeAttr('disabled', true); - } - displayUI(); + var ui = $("#mainUI"); + var dialog = $("#connectDialog"); + var backdrop = $("#backDrop"); + $(ui).hide(); + $(dialog).show(); + $(backdrop).show(); + $("#connectPassword").focus(); + $("#connectForm").off("submit"); + + $("#connectForm").on("submit", function (e) { + e.preventDefault(); + var password = $("#connectPassword").val(); + if (!/^[\u0000-\u007f]*$/.test(password)) { + alertMessage("alert-modal alert-error", "Invalid characters in the password"); + $("#connectPassword").focus(); return; } - var ui = $('#mainUI'); - var dialog = $('#connectDialog'); - var backdrop = $('#backDrop'); - $(ui).hide(); - $(dialog).show(); - $(backdrop).show(); - $('#connectPassword').focus(); - $('#connectForm').off('submit'); - - $('#connectForm').on('submit', function (e) { - e.preventDefault(); - var password = $('#connectPassword').val(); - if (!/^[\u0000-\u007f]*$/.test(password)) { - alertMessage('alert-modal alert-error', 'Invalid characters in the password'); - $('#connectPassword').focus(); - return; - } - - $.ajax({ - global: false, - jsonp: false, - dataType: 'json', - type: 'GET', - url: 'auth', - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', password); - }, - success: function (data) { - $('#connectPassword').val(''); - if (data.auth === 'failed') { - // Is actually never returned by Rspamd - } else { - if (data.read_only) { - interface.read_only = true; - $('#learning_nav').hide(); - $('#resetHistory').attr('disabled', true); - $('#errors-history').hide(); - } - else { - interface.read_only = false; - $('#learning_nav').show(); - $('#resetHistory').removeAttr('disabled', true); - } - - saveCredentials(password); - $(dialog).hide(); - $(backdrop).hide(); - displayUI(); - } - }, - error: function (data) { - interface.alertMessage('alert-modal alert-error', data.statusText); - $('#connectPassword').val(''); - $('#connectPassword').focus(); - } - }); - }); - }; - - interface.queryLocal = function(req_url, on_success, on_error, method, headers, params) { - var req_params = { - type: method, + $.ajax({ + global: false, jsonp: false, + dataType: "json", + type: "GET", + url: "auth", beforeSend: function (xhr) { - xhr.setRequestHeader("Password", getPassword()); - - if (headers) { - $.each(headers, function(hname, hvalue){ - xhr.setRequestHeader(hname, hvalue); - }); - } + xhr.setRequestHeader("Password", password); }, - url: req_url, success: function (data) { - if (on_success) { - on_success(data); - } - else { - alertMessage('alert-success', 'Data saved'); + $("#connectPassword").val(""); + if (data.auth === "failed") { + // Is actually never returned by Rspamd + } else { + if (data.read_only) { + interface.read_only = true; + $("#learning_nav").hide(); + $("#resetHistory").attr("disabled", true); + $("#errors-history").hide(); + } + else { + interface.read_only = false; + $("#learning_nav").show(); + $("#resetHistory").removeAttr("disabled", true); + } + + saveCredentials(password); + $(dialog).hide(); + $(backdrop).hide(); + displayUI(); } }, - error: function(jqXHR, textStatus, errorThrown) { - if (on_error) { - on_error('local', jqXHR, textStatus, errorThrown); - } - else { - alertMessage('alert-error', 'Cannot receive data: ' + errorThrown); - } + error: function (data) { + interface.alertMessage("alert-modal alert-error", data.statusText); + $("#connectPassword").val(""); + $("#connectPassword").focus(); + } + }); + }); + }; + + interface.queryLocal = function(req_url, on_success, on_error, method, headers, params) { + var req_params = { + type: method, + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", getPassword()); + + if (headers) { + $.each(headers, function(hname, hvalue) { + xhr.setRequestHeader(hname, hvalue); + }); + } + }, + url: req_url, + success: function (data) { + if (on_success) { + on_success(data); + } + else { + alertMessage("alert-success", "Data saved"); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + if (on_error) { + on_error("local", jqXHR, textStatus, errorThrown); + } + else { + alertMessage("alert-error", "Cannot receive data: " + errorThrown); } - }; - if (params) { - $.each(params, function(k, v) { - req_params[k] = v; - }); } - $.ajax(req_params); + }; + if (params) { + $.each(params, function(k, v) { + req_params[k] = v; + }); } - - interface.queryNeighbours = function(req_url, on_success, on_error, method, headers, params, req_data) { - $.ajax({ - dataType: "json", - type: "GET", - url: "neighbours", - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader("Password", getPassword()); - }, - success: function (data) { - if (jQuery.isEmptyObject(data)) { - neighbours = { - local: { - host: window.location.host, - url: window.location.href - } - }; - } else { - neighbours = data; - } - var neighbours_status = []; - $.each(neighbours, function (ind) { - neighbours_status.push({ - name: ind, - url: neighbours[ind].url, - host: neighbours[ind].host, - checked: false, - data: {}, - status: false, - }); + $.ajax(req_params); + }; + + interface.queryNeighbours = function(req_url, on_success, on_error, method, headers, params, req_data) { + $.ajax({ + dataType: "json", + type: "GET", + url: "neighbours", + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", getPassword()); + }, + success: function (data) { + if (jQuery.isEmptyObject(data)) { + neighbours = { + local: { + host: window.location.host, + url: window.location.href + } + }; + } else { + neighbours = data; + } + var neighbours_status = []; + $.each(neighbours, function (ind) { + neighbours_status.push({ + name: ind, + url: neighbours[ind].url, + host: neighbours[ind].host, + checked: false, + data: {}, + status: false, }); - $.each(neighbours_status, function (ind) { - "use strict"; - method = typeof method !== 'undefined' ? method : "GET"; - var req_params = { - type: method, - jsonp: false, - data: req_data, - beforeSend: function (xhr) { - xhr.setRequestHeader("Password", getPassword()); - - if (headers) { - $.each(headers, function(hname, hvalue){ - xhr.setRequestHeader(hname, hvalue); - }); - } - }, - url: neighbours_status[ind].url + req_url, - success: function (data) { - neighbours_status[ind].checked = true; - - if (jQuery.isEmptyObject(data)) { - neighbours_status[ind].status = false; //serv does not work - } else { - neighbours_status[ind].status = true; //serv does not work - neighbours_status[ind].data = data; + }); + $.each(neighbours_status, function (ind) { + "use strict"; + method = typeof method !== "undefined" ? method : "GET"; + var req_params = { + type: method, + jsonp: false, + data: req_data, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", getPassword()); + + if (headers) { + $.each(headers, function(hname, hvalue) { + xhr.setRequestHeader(hname, hvalue); + }); + } + }, + url: neighbours_status[ind].url + req_url, + success: function (data) { + neighbours_status[ind].checked = true; + + if (jQuery.isEmptyObject(data)) { + neighbours_status[ind].status = false; // serv does not work + } else { + neighbours_status[ind].status = true; // serv does not work + neighbours_status[ind].data = data; + } + if (neighbours_status.every(function (elt) { return elt.checked; })) { + if (on_success) { + on_success(neighbours_status); } - if (neighbours_status.every(function (elt) {return elt.checked;})) { - if (on_success) { - on_success(neighbours_status); - } - else { - alertMessage('alert-success', 'Request completed'); - } + else { + alertMessage("alert-success", "Request completed"); } - }, - error: function(jqXHR, textStatus, errorThrown) { - neighbours_status[ind].status = false; - neighbours_status[ind].checked = true; - if (on_error) { - on_error(neighbours_status[ind], - jqXHR, textStatus, errorThrown); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + neighbours_status[ind].status = false; + neighbours_status[ind].checked = true; + if (on_error) { + on_error(neighbours_status[ind], + jqXHR, textStatus, errorThrown); + } + else { + alertMessage("alert-error", "Cannot receive data from " + + neighbours_status[ind].host + ": " + errorThrown); + } + if (neighbours_status.every( + function (elt) { return elt.checked; })) { + if (on_success) { + on_success(neighbours_status); } else { - alertMessage('alert-error', 'Cannot receive data from ' + - neighbours_status[ind].host + ': ' + errorThrown); - } - if (neighbours_status.every( - function (elt) {return elt.checked;})) { - if (on_success) { - on_success(neighbours_status); - } - else { - alertMessage('alert-success', 'Request completed'); - } + alertMessage("alert-success", "Request completed"); } } - //error display - }; - if (params) { - $.each(params, function(k, v) { - req_params[k] = v; - }); } - $.ajax(req_params); - }); - }, - error: function () { - interface.alertMessage('alert-error', 'Cannot receive neighbours data'); - }, - }); - }; - - interface.drawPie = function(obj, id, data, conf) { - if (obj) { - obj.updateProp("data.content", - data.filter(function (elt) { - return elt.value > 0; - }) - ); - } else { - obj = new d3pie(id, - $.extend({}, { - "header": { - "title": { - "text": "Rspamd filter stats", - "fontSize": 24, - "font": "open sans" - }, - "subtitle": { - "color": "#999999", - "fontSize": 12, - "font": "open sans" - }, - "titleSubtitlePadding": 9 + // error display + }; + if (params) { + $.each(params, function(k, v) { + req_params[k] = v; + }); + } + $.ajax(req_params); + }); + }, + error: function () { + interface.alertMessage("alert-error", "Cannot receive neighbours data"); + }, + }); + }; + + interface.drawPie = function(obj, id, data, conf) { + if (obj) { + obj.updateProp("data.content", + data.filter(function (elt) { + return elt.value > 0; + }) + ); + } else { + obj = new d3pie(id, + $.extend({}, { + "header": { + "title": { + "text": "Rspamd filter stats", + "fontSize": 24, + "font": "open sans" }, - "footer": { + "subtitle": { "color": "#999999", - "fontSize": 10, - "font": "open sans", - "location": "bottom-left" + "fontSize": 12, + "font": "open sans" }, - "size": { - "canvasWidth": 600, - "canvasHeight": 400, - "pieInnerRadius": "20%", - "pieOuterRadius": "85%" + "titleSubtitlePadding": 9 + }, + "footer": { + "color": "#999999", + "fontSize": 10, + "font": "open sans", + "location": "bottom-left" + }, + "size": { + "canvasWidth": 600, + "canvasHeight": 400, + "pieInnerRadius": "20%", + "pieOuterRadius": "85%" + }, + "data": { + // "sortOrder": "value-desc", + "content": data.filter(function (elt) { + return elt.value > 0; + }) + }, + "labels": { + "outer": { + "hideWhenLessThanPercentage": 1, + "pieDistance": 30 }, - "data": { - //"sortOrder": "value-desc", - "content": data.filter(function (elt) { - return elt.value > 0; - }) + "inner": { + "hideWhenLessThanPercentage": 4 }, - "labels": { - "outer": { - "hideWhenLessThanPercentage": 1, - "pieDistance": 30 - }, - "inner": { - "hideWhenLessThanPercentage": 4 - }, - "mainLabel": { - "fontSize": 14 - }, - "percentage": { - "color": "#eeeeee", - "fontSize": 14, - "decimalPlaces": 0 - }, - "lines": { - "enabled": true - }, - "truncation": { - "enabled": true - } + "mainLabel": { + "fontSize": 14 }, - "tooltips": { - "enabled": true, - "type": "placeholder", - "string": "{label}: {value} ({percentage}%)" + "percentage": { + "color": "#eeeeee", + "fontSize": 14, + "decimalPlaces": 0 }, - "effects": { - "pullOutSegmentOnClick": { - "effect": "back", - "speed": 400, - "size": 8 - }, - "load": { - "effect": "none" - } + "lines": { + "enabled": true }, - "misc": { - "gradient": { - "enabled": true, - "percentage": 100 - } + "truncation": { + "enabled": true } - }, conf)); - } - return obj; - }; + }, + "tooltips": { + "enabled": true, + "type": "placeholder", + "string": "{label}: {value} ({percentage}%)" + }, + "effects": { + "pullOutSegmentOnClick": { + "effect": "back", + "speed": 400, + "size": 8 + }, + "load": { + "effect": "none" + } + }, + "misc": { + "gradient": { + "enabled": true, + "percentage": 100 + } + } + }, conf)); + } + return obj; + }; - interface.getPassword = getPassword; + interface.getPassword = getPassword; - return interface; + return interface; }); diff --git a/interface/js/app/stats.js b/interface/js/app/stats.js index 3855f4d64..5e5932e8a 100644 --- a/interface/js/app/stats.js +++ b/interface/js/app/stats.js @@ -22,159 +22,159 @@ THE SOFTWARE. */ -define(['jquery', 'd3pie', 'humanize'], -function($, d3pie, Humanize) { +define(["jquery", "d3pie", "humanize"], + function($, d3pie, Humanize) { // @ ms to date - function msToTime(seconds) { + function msToTime(seconds) { years = seconds / 31536000 >> 0; // 3600*24*365 - months = seconds % 31536000 / 2628000 >> 0; //3600*24*365/12 - days = seconds % 31536000 % 2628000 / 86400 >> 0; //24*3600 + months = seconds % 31536000 / 2628000 >> 0; // 3600*24*365/12 + days = seconds % 31536000 % 2628000 / 86400 >> 0; // 24*3600 hours = seconds % 31536000 % 2628000 % 86400 / 3600 >> 0; minutes = seconds % 31536000 % 2628000 % 86400 % 3600 / 60 >> 0; if (years > 0) { - if (months > 0) { - out = years + 'yr ' + months + 'mth'; - } else { - out = years + 'yr ' + days + 'd'; - } + if (months > 0) { + out = years + "yr " + months + "mth"; + } else { + out = years + "yr " + days + "d"; + } } else if (months > 0) { - out = months + 'mth ' + days + 'd'; + out = months + "mth " + days + "d"; } else if (days > 0) { - out = days + 'd ' + hours + 'hr'; + out = days + "d " + hours + "hr"; } else if (hours > 0) { - out = hours + 'hr ' + minutes + 'min'; + out = hours + "hr " + minutes + "min"; } else { - out = minutes + 'min'; + out = minutes + "min"; } return out; - } + } - function displayStatWidgets(checked_server) { - var widgets = $('#statWidgets'); - $(widgets).empty().hide(); + function displayStatWidgets(checked_server) { + var widgets = $("#statWidgets"); + $(widgets).empty().hide(); - var servers = JSON.parse(sessionStorage.getItem('Credentials')); - var data = {}; + var servers = JSON.parse(sessionStorage.getItem("Credentials")); + var data = {}; - if (servers && servers[checked_server]) { - data = servers[checked_server].data; - } - var stat_w = []; - - $.each(data, function (i, item) { - var widget = ''; - if (i == 'auth') {} - else if (i == 'error') {} - else if (i == 'version') { - widget = '<div class="left"><strong>' + item + '</strong>' + - i + '</div>'; - $(widget).appendTo(widgets); - } else if (i == 'uptime') { - widget = '<div class="right"><strong>' + msToTime(item) + - '</strong>' + i + '</div>'; - $(widget).appendTo(widgets); - } else { - var titleAtt = Humanize.intComma(item) + ' ' + i; - widget = '<li class="stat-box"><div class="widget" title="' + titleAtt + '"><strong>' + - Humanize.compactInteger(item) + '</strong>' + i + '</div></li>'; - if (i == 'scanned') { - stat_w[0] = widget; - } else if (i == 'clean') { - stat_w[1] = widget; - } else if (i == 'greylist') { - stat_w[2] = widget; - } else if (i == 'probable') { - stat_w[3] = widget; - } else if (i == 'reject') { - stat_w[4] = widget; - } else if (i == 'learned') { - stat_w[5] = widget; - } - } - }); - $.each(stat_w, function (i, item) { - $(item).appendTo(widgets); - }); - $('#statWidgets .left,#statWidgets .right').wrapAll('<li class="stat-box pull-right"><div class="widget"></div></li>'); - $('#statWidgets').find('li.pull-right').appendTo('#statWidgets'); - - $("#clusterTable tbody").empty(); - $("#selSrv").empty(); - $.each(servers, function (key, val) { - var glyph_status; - var short_id; - if (!('config_id' in val.data)) { - val.data.config_id = ""; - } - if (val.status) { - glyph_status = "glyphicon glyphicon-ok-circle"; - short_id = val.data.config_id.substring(0, 8); - } - else { - glyph_status = "glyphicon glyphicon-remove-circle"; - short_id = "???"; + if (servers && servers[checked_server]) { + data = servers[checked_server].data; } + var stat_w = []; + + $.each(data, function (i, item) { + var widget = ""; + if (i == "auth") {} + else if (i == "error") {} + else if (i == "version") { + widget = "<div class=\"left\"><strong>" + item + "</strong>" + + i + "</div>"; + $(widget).appendTo(widgets); + } else if (i == "uptime") { + widget = "<div class=\"right\"><strong>" + msToTime(item) + + "</strong>" + i + "</div>"; + $(widget).appendTo(widgets); + } else { + var titleAtt = Humanize.intComma(item) + " " + i; + widget = "<li class=\"stat-box\"><div class=\"widget\" title=\"" + titleAtt + "\"><strong>" + + Humanize.compactInteger(item) + "</strong>" + i + "</div></li>"; + if (i == "scanned") { + stat_w[0] = widget; + } else if (i == "clean") { + stat_w[1] = widget; + } else if (i == "greylist") { + stat_w[2] = widget; + } else if (i == "probable") { + stat_w[3] = widget; + } else if (i == "reject") { + stat_w[4] = widget; + } else if (i == "learned") { + stat_w[5] = widget; + } + } + }); + $.each(stat_w, function (i, item) { + $(item).appendTo(widgets); + }); + $("#statWidgets .left,#statWidgets .right").wrapAll("<li class=\"stat-box pull-right\"><div class=\"widget\"></div></li>"); + $("#statWidgets").find("li.pull-right").appendTo("#statWidgets"); + + $("#clusterTable tbody").empty(); + $("#selSrv").empty(); + $.each(servers, function (key, val) { + var glyph_status; + var short_id; + if (!("config_id" in val.data)) { + val.data.config_id = ""; + } + if (val.status) { + glyph_status = "glyphicon glyphicon-ok-circle"; + short_id = val.data.config_id.substring(0, 8); + } + else { + glyph_status = "glyphicon glyphicon-remove-circle"; + short_id = "???"; + } - $('#clusterTable tbody').append('<tr>' + - '<td class="col1" title="Radio"><input type="radio" class="form-control radio" name="clusterName" value="' + key + '"></td>' + - '<td class="col2" title="SNAme">' + key + '</td>' + - '<td class="col3" title="SHost">' + val.host + '</td>' + - '<td class="col4" title="SStatus"><span class="icon"><i class="' + glyph_status + '"></i></span></td>' + - '<td class="col5" title="short_id">' + short_id + '</td></tr>'); + $("#clusterTable tbody").append("<tr>" + + "<td class=\"col1\" title=\"Radio\"><input type=\"radio\" class=\"form-control radio\" name=\"clusterName\" value=\"" + key + "\"></td>" + + "<td class=\"col2\" title=\"SNAme\">" + key + "</td>" + + "<td class=\"col3\" title=\"SHost\">" + val.host + "</td>" + + "<td class=\"col4\" title=\"SStatus\"><span class=\"icon\"><i class=\"" + glyph_status + "\"></i></span></td>" + + "<td class=\"col5\" title=\"short_id\">" + short_id + "</td></tr>"); - $("#selSrv").append( $('<option value="' + key + '">' + key + '</option>')); + $("#selSrv").append( $("<option value=\"" + key + "\">" + key + "</option>")); - if (checked_server == key) { - $('#clusterTable tbody [value="' + key + '"]').prop("checked", true); - $('#selSrv [value="' + key + '"]').prop("selected", true); - } - else if (!val.status) { - $('#clusterTable tbody [value="' + key + '"]').prop("disabled", true); - $('#selSrv [value="' + key + '"]').prop("disabled", true); - } - }); - $(widgets).show(); - } + if (checked_server == key) { + $("#clusterTable tbody [value=\"" + key + "\"]").prop("checked", true); + $("#selSrv [value=\"" + key + "\"]").prop("selected", true); + } + else if (!val.status) { + $("#clusterTable tbody [value=\"" + key + "\"]").prop("disabled", true); + $("#selSrv [value=\"" + key + "\"]").prop("disabled", true); + } + }); + $(widgets).show(); + } - function getChart(rspamd, pie, checked_server) { - var creds = JSON.parse(sessionStorage.getItem('Credentials')); - if (creds && creds[checked_server]) { - var data = creds[checked_server].data; - var new_data = [ { - "color" : "#66CC00", - "label" : "Clean", - "data" : data.clean, - "value" : data.clean - }, { - "color" : "#BF8040", - "label" : "Temporarily rejected", - "data" : data.soft_reject, - "value" : data.soft_reject - }, { - "color" : "#FFAD00", - "label" : "Probable spam", - "data" : data.probable, - "value" : data.probable - }, { - "color" : "#436EEE", - "label" : "Greylisted", - "data" : data.greylist, - "value" : data.greylist - }, { - "color" : "#FF0000", - "label" : "Rejected", - "data" : data.reject, - "value" : data.reject - } ]; - - return rspamd.drawPie(pie, "chart", new_data); + function getChart(rspamd, pie, checked_server) { + var creds = JSON.parse(sessionStorage.getItem("Credentials")); + if (creds && creds[checked_server]) { + var data = creds[checked_server].data; + var new_data = [{ + "color" : "#66CC00", + "label" : "Clean", + "data" : data.clean, + "value" : data.clean + }, { + "color" : "#BF8040", + "label" : "Temporarily rejected", + "data" : data.soft_reject, + "value" : data.soft_reject + }, { + "color" : "#FFAD00", + "label" : "Probable spam", + "data" : data.probable, + "value" : data.probable + }, { + "color" : "#436EEE", + "label" : "Greylisted", + "data" : data.greylist, + "value" : data.greylist + }, { + "color" : "#FF0000", + "label" : "Rejected", + "data" : data.reject, + "value" : data.reject + }]; + + return rspamd.drawPie(pie, "chart", new_data); + } } - } - // Public API - var interface = { - statWidgets: function(rspamd, graphs, checked_server) { - rspamd.queryNeighbours("/auth", function(neighbours_status) { - var neighbours_sum = { + // Public API + var interface = { + statWidgets: function(rspamd, graphs, checked_server) { + rspamd.queryNeighbours("/auth", function(neighbours_status) { + var neighbours_sum = { version: neighbours_status[0].data.version, auth: "ok", uptime: 0, @@ -187,51 +187,51 @@ function($, d3pie, Humanize) { learned: 0, read_only: neighbours_status[0].data.read_only, config_id: "" - }; - var status_count = 0; - for(var e in neighbours_status) { - if(neighbours_status[e].status === true) { + }; + var status_count = 0; + for(var e in neighbours_status) { + if(neighbours_status[e].status === true) { // Remove alert status - localStorage.removeItem(e + '_alerted'); - neighbours_sum.clean += neighbours_status[e].data.clean; - neighbours_sum.probable += neighbours_status[e].data.probable; - neighbours_sum.greylist += neighbours_status[e].data.greylist; - neighbours_sum.reject += neighbours_status[e].data.reject; - neighbours_sum.soft_reject += neighbours_status[e].data.soft_reject; - neighbours_sum.scanned += neighbours_status[e].data.scanned; - neighbours_sum.learned += neighbours_status[e].data.learned; - neighbours_sum.uptime += neighbours_status[e].data.uptime; - status_count++; + localStorage.removeItem(e + "_alerted"); + neighbours_sum.clean += neighbours_status[e].data.clean; + neighbours_sum.probable += neighbours_status[e].data.probable; + neighbours_sum.greylist += neighbours_status[e].data.greylist; + neighbours_sum.reject += neighbours_status[e].data.reject; + neighbours_sum.soft_reject += neighbours_status[e].data.soft_reject; + neighbours_sum.scanned += neighbours_status[e].data.scanned; + neighbours_sum.learned += neighbours_status[e].data.learned; + neighbours_sum.uptime += neighbours_status[e].data.uptime; + status_count++; + } } - } - neighbours_sum.uptime = Math.floor(neighbours_sum.uptime / status_count); - var to_Credentials = {}; - to_Credentials["All SERVERS"] = { name: "All SERVERS", + neighbours_sum.uptime = Math.floor(neighbours_sum.uptime / status_count); + var to_Credentials = {}; + to_Credentials["All SERVERS"] = {name: "All SERVERS", url: "", host: "", checked: true, data: neighbours_sum, status: true - }; - neighbours_status.forEach(function (elmt) { - to_Credentials[elmt.name] = elmt; + }; + neighbours_status.forEach(function (elmt) { + to_Credentials[elmt.name] = elmt; + }); + sessionStorage.setItem("Credentials", JSON.stringify(to_Credentials)); + displayStatWidgets(checked_server); + graphs.chart = getChart(rspamd, graphs.chart, checked_server); + }, + function (serv, jqXHR, textStatus, errorThrown) { + var alert_status = serv.name + "_alerted"; + + if (!(alert_status in sessionStorage)) { + sessionStorage.setItem(alert_status, true); + rspamd.alertMessage("alert-error", "Cannot receive stats data from: " + + serv.name + ", error: " + errorThrown); + } }); - sessionStorage.setItem("Credentials", JSON.stringify(to_Credentials)); - displayStatWidgets(checked_server); - graphs.chart = getChart(rspamd, graphs.chart, checked_server); }, - function (serv, jqXHR, textStatus, errorThrown) { - var alert_status = serv.name + '_alerted'; + }; - if (!(alert_status in sessionStorage)) { - sessionStorage.setItem(alert_status, true); - rspamd.alertMessage('alert-error', 'Cannot receive stats data from: ' + - serv.name + ', error: ' + errorThrown); - } - }); - }, - }; - - return interface; -} + return interface; + } ); diff --git a/interface/js/app/symbols.js b/interface/js/app/symbols.js index 14223c1ab..2699eefbe 100644 --- a/interface/js/app/symbols.js +++ b/interface/js/app/symbols.js @@ -22,265 +22,265 @@ THE SOFTWARE. */ -define(['jquery', 'footable'], -function($) { - var interface = {} - var ft = {} +define(["jquery", "footable"], + function($) { + var interface = {}; + var ft = {}; - function saveSymbols(rspamd, action, id, is_cluster) { - var inputs = $('#' + id + ' :input[data-role="numerictextbox"]'); - var url = action; - var values = []; - $(inputs).each(function () { - values.push({ - name: $(this).attr('id').substring(5), - value: parseFloat($(this).val()) + function saveSymbols(rspamd, action, id, is_cluster) { + var inputs = $("#" + id + " :input[data-role=\"numerictextbox\"]"); + var url = action; + var values = []; + $(inputs).each(function () { + values.push({ + name: $(this).attr("id").substring(5), + value: parseFloat($(this).val()) + }); }); - }); - if (is_cluster) { - rspamd.queryNeighbours(url, function () { - rspamd.alertMessage('alert-modal alert-success', 'Symbols successfully saved'); - }, function (serv, qXHR, textStatus, errorThrown) { - rspamd.alertMessage('alert-modal alert-error', - 'Save symbols error on ' + - serv.name + ': ' + errorThrown); - }, "POST", {}, { - data: JSON.stringify(values), - dataType: "json", - }); - } - else { - $.ajax({ - data: JSON.stringify(values), - dataType: 'json', - type: 'POST', - url: url, - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - success: function () { - rspamd.alertMessage('alert-modal alert-success', 'Symbols successfully saved'); - }, - error: function (data) { - rspamd.alertMessage('alert-modal alert-error', data.statusText); - } - }); + if (is_cluster) { + rspamd.queryNeighbours(url, function () { + rspamd.alertMessage("alert-modal alert-success", "Symbols successfully saved"); + }, function (serv, qXHR, textStatus, errorThrown) { + rspamd.alertMessage("alert-modal alert-error", + "Save symbols error on " + + serv.name + ": " + errorThrown); + }, "POST", {}, { + data: JSON.stringify(values), + dataType: "json", + }); + } + else { + $.ajax({ + data: JSON.stringify(values), + dataType: "json", + type: "POST", + url: url, + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + success: function () { + rspamd.alertMessage("alert-modal alert-success", "Symbols successfully saved"); + }, + error: function (data) { + rspamd.alertMessage("alert-modal alert-error", data.statusText); + } + }); + } } - } - function decimalStep(number) { - var digits = ((+number).toFixed(20)).replace(/^-?\d*\.?|0+$/g, '').length; - if (digits === 0 || digits > 4) { - return 0.1; - } else { - return 1.0 / (Math.pow(10, digits)); + function decimalStep(number) { + var digits = ((+number).toFixed(20)).replace(/^-?\d*\.?|0+$/g, "").length; + if (digits === 0 || digits > 4) { + return 0.1; + } else { + return 1.0 / (Math.pow(10, digits)); + } } - } - function process_symbols_data(data) { - var items = []; - var lookup = {}; - var freqs = []; - var distinct_groups = []; + function process_symbols_data(data) { + var items = []; + var lookup = {}; + var freqs = []; + var distinct_groups = []; - $.each(data, function (i, group) { - $.each(group.rules, function (i, item) { - var max = 20; - var min = -20; - if (item.weight > max) { - max = item.weight * 2; - } - item.group = group.group - if (item.weight < min) { - min = item.weight * 2; - } - var label_class = ''; - if (item.weight < 0) { - label_class = 'scorebar-ham'; - } else if (item.weight > 0) { - label_class = 'scorebar-spam'; - } - item.weight = '<input class="form-control input-sm mb-disabled ' + label_class + - '" data-role="numerictextbox" autocomplete="off" "type="number" class="input" min="' + - min + '" max="' + - max + '" step="' + decimalStep(item.weight) + - '" tabindex="1" value="' + Number(item.weight).toFixed(3) + - '" id="_sym_' + item.symbol + '"></input>' - if (!item.time) { - item.time = 0; - } - item.time = Number(item.time).toFixed(2) + 's' - if (!item.frequency) { - item.frequency = 0; - } - freqs.push(item.frequency); - item.frequency = Number(item.frequency).toFixed(2) - if (!(item.group in lookup)) { - lookup[item.group] = 1; - distinct_groups.push(item.group); - } - item.save = '<button type="button" data-save="local" class="btn btn-primary btn-sm mb-disabled">Save</button>' + - ' <button data-save="cluster" type="button" class="btn btn-primary btn-sm mb-disabled">Save in cluster</button>'; - items.push(item) + $.each(data, function (i, group) { + $.each(group.rules, function (i, item) { + var max = 20; + var min = -20; + if (item.weight > max) { + max = item.weight * 2; + } + item.group = group.group; + if (item.weight < min) { + min = item.weight * 2; + } + var label_class = ""; + if (item.weight < 0) { + label_class = "scorebar-ham"; + } else if (item.weight > 0) { + label_class = "scorebar-spam"; + } + item.weight = "<input class=\"form-control input-sm mb-disabled " + label_class + + "\" data-role=\"numerictextbox\" autocomplete=\"off\" \"type=\"number\" class=\"input\" min=\"" + + min + "\" max=\"" + + max + "\" step=\"" + decimalStep(item.weight) + + "\" tabindex=\"1\" value=\"" + Number(item.weight).toFixed(3) + + "\" id=\"_sym_" + item.symbol + "\"></input>"; + if (!item.time) { + item.time = 0; + } + item.time = Number(item.time).toFixed(2) + "s"; + if (!item.frequency) { + item.frequency = 0; + } + freqs.push(item.frequency); + item.frequency = Number(item.frequency).toFixed(2); + if (!(item.group in lookup)) { + lookup[item.group] = 1; + distinct_groups.push(item.group); + } + item.save = "<button type=\"button\" data-save=\"local\" class=\"btn btn-primary btn-sm mb-disabled\">Save</button>" + + " <button data-save=\"cluster\" type=\"button\" class=\"btn btn-primary btn-sm mb-disabled\">Save in cluster</button>"; + items.push(item); + }); }); - }); - // For better mean calculations - var avg_freq = freqs.sort(function(a, b) { - return Number(a) < Number(b); - }).reduce(function(f1, acc) { - return f1 + acc; - }) / (freqs.length != 0 ? freqs.length : 1.0); - var mult = 1.0; - var exp = 0.0; + // For better mean calculations + var avg_freq = freqs.sort(function(a, b) { + return Number(a) < Number(b); + }).reduce(function(f1, acc) { + return f1 + acc; + }) / (freqs.length != 0 ? freqs.length : 1.0); + var mult = 1.0; + var exp = 0.0; - if (avg_freq > 0.0) { - while (mult * avg_freq < 1.0) { - mult *= 10; - exp ++; + if (avg_freq > 0.0) { + while (mult * avg_freq < 1.0) { + mult *= 10; + exp ++; + } } - } - $.each(items, function (i, item) { - item.frequency = Number(item.frequency) * mult; + $.each(items, function (i, item) { + item.frequency = Number(item.frequency) * mult; - if (exp > 0) { - item.frequency = item.frequency.toFixed(2) + 'e-' + exp; - } - else { - item.frequency = item.frequency.toFixed(2); - } - }); - return [items, distinct_groups] - } - // @get symbols into modal form - interface.getSymbols = function(rspamd, tables, checked_server) { + if (exp > 0) { + item.frequency = item.frequency.toFixed(2) + "e-" + exp; + } + else { + item.frequency = item.frequency.toFixed(2); + } + }); + return [items, distinct_groups]; + } + // @get symbols into modal form + interface.getSymbols = function(rspamd, tables, checked_server) { - $.ajax({ - dataType: 'json', - type: 'GET', - url: 'symbols', - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - success: function (data) { - var items = process_symbols_data(data); - FooTable.groupFilter = FooTable.Filtering.extend({ - construct : function(instance) { - this._super(instance); - this.groups = items[1]; - this.def = 'Any group'; - this.$group = null; - }, - $create : function() { - this._super(); - var self = this, $form_grp = $('<div/>', { - 'class' : 'form-group' - }).append($('<label/>', { - 'class' : 'sr-only', - text : 'Group' - })).prependTo(self.$form); + $.ajax({ + dataType: "json", + type: "GET", + url: "symbols", + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + success: function (data) { + var items = process_symbols_data(data); + FooTable.groupFilter = FooTable.Filtering.extend({ + construct : function(instance) { + this._super(instance); + this.groups = items[1]; + this.def = "Any group"; + this.$group = null; + }, + $create : function() { + this._super(); + var self = this, $form_grp = $("<div/>", { + "class" : "form-group" + }).append($("<label/>", { + "class" : "sr-only", + text : "Group" + })).prependTo(self.$form); - self.$group = $('<select/>', { - 'class' : 'form-control' - }).on('change', { - self : self - }, self._onStatusDropdownChanged).append( - $('<option/>', { - text : self.def - })).appendTo($form_grp); + self.$group = $("<select/>", { + "class" : "form-control" + }).on("change", { + self : self + }, self._onStatusDropdownChanged).append( + $("<option/>", { + text : self.def + })).appendTo($form_grp); - $.each(self.groups, function(i, group) { - self.$group.append($('<option/>').text(group)); - }); - }, - _onStatusDropdownChanged : function(e) { - var self = e.data.self, selected = $(this).val(); - if (selected !== self.def) { - self.addFilter('group', selected, [ 'group' ]); - } else { - self.removeFilter('group'); - } - self.filter(); - }, - draw : function() { - this._super(); - var group = this.find('group'); - if (group instanceof FooTable.Filter) { - this.$group.val(group.query.val()); - } else { - this.$group.val(this.def); - } - } - }); - ft.symbols = FooTable.init("#symbolsTable", { - "columns": [ - {"sorted": true,"direction": "ASC", "name":"group","title":"Group","style":{"font-size":"11px"}}, - {"name":"symbol","title":"Symbol","style":{"font-size":"11px"}}, - {"name":"description","title":"Description","breakpoints":"xs sm","style":{"font-size":"11px"}}, - {"name":"weight","title":"Score","style":{"font-size":"11px"}}, - {"name":"frequency","title":"Frequency","breakpoints":"xs sm","style":{"font-size":"11px"},"sortValue": function(value){return Number(value).toFixed(2)}}, - {"name":"time","title":"Avg. time","breakpoints":"xs sm","style":{"font-size":"11px"}}, - {"name":"save","title":"Save","style":{"font-size":"11px"}}, - ], - "rows": items[0], - "paging": { - "enabled": true, - "limit": 5, - "size": 25 - }, - "filtering": { - "enabled": true, - "position": "left", - "connectors": false - }, - "sorting": { - "enabled": true - }, - components: { - filtering: FooTable.groupFilter - }, - "on": { - "ready.ft.table": function () { - if (rspamd.read_only) { - $(".mb-disabled").attr('disabled', true); + $.each(self.groups, function(i, group) { + self.$group.append($("<option/>").text(group)); + }); + }, + _onStatusDropdownChanged : function(e) { + var self = e.data.self, selected = $(this).val(); + if (selected !== self.def) { + self.addFilter("group", selected, ["group"]); + } else { + self.removeFilter("group"); + } + self.filter(); + }, + draw : function() { + this._super(); + var group = this.find("group"); + if (group instanceof FooTable.Filter) { + this.$group.val(group.query.val()); + } else { + this.$group.val(this.def); + } } + }); + ft.symbols = FooTable.init("#symbolsTable", { + "columns": [ + {"sorted": true, "direction": "ASC", "name":"group", "title":"Group", "style":{"font-size":"11px"}}, + {"name":"symbol", "title":"Symbol", "style":{"font-size":"11px"}}, + {"name":"description", "title":"Description", "breakpoints":"xs sm", "style":{"font-size":"11px"}}, + {"name":"weight", "title":"Score", "style":{"font-size":"11px"}}, + {"name":"frequency", "title":"Frequency", "breakpoints":"xs sm", "style":{"font-size":"11px"}, "sortValue": function(value) { return Number(value).toFixed(2); }}, + {"name":"time", "title":"Avg. time", "breakpoints":"xs sm", "style":{"font-size":"11px"}}, + {"name":"save", "title":"Save", "style":{"font-size":"11px"}}, + ], + "rows": items[0], + "paging": { + "enabled": true, + "limit": 5, + "size": 25 + }, + "filtering": { + "enabled": true, + "position": "left", + "connectors": false + }, + "sorting": { + "enabled": true + }, + components: { + filtering: FooTable.groupFilter + }, + "on": { + "ready.ft.table": function () { + if (rspamd.read_only) { + $(".mb-disabled").attr("disabled", true); + } + } + } + }); + }, + error: function (data) { + rspamd.alertMessage("alert-modal alert-error", data.statusText); + } + }); + $(document).on("click", "#symbolsTable :button", function(event) { + var value = $(this).data("save"); + if (!value) return; + saveSymbols(rspamd, "./savesymbols", "symbolsTable", value == "cluster"); + }); + }; + + interface.setup = function(rspamd, tables) { + $("#updateSymbols").on("click", function (e) { + e.preventDefault(); + $.ajax({ + dataType: "json", + type: "GET", + jsonp: false, + url: "symbols", + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + success: function (data) { + var items = process_symbols_data(data)[0]; + ft.symbols.rows.load(items); + }, + error: function (data) { + rspamd.alertMessage("alert-modal alert-error", data.statusText); } - } }); - }, - error: function (data) { - rspamd.alertMessage('alert-modal alert-error', data.statusText); - } - }); - $(document).on("click", "#symbolsTable :button", function(event){ - var value = $(this).data('save'); - if (!value) return - saveSymbols(rspamd, "./savesymbols", "symbolsTable", value == 'cluster'); - }); - }; - - interface.setup = function(rspamd, tables) { - $('#updateSymbols').on('click', function (e) { - e.preventDefault(); - $.ajax({ - dataType: 'json', - type: 'GET', - jsonp: false, - url: 'symbols', - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - success: function (data) { - var items = process_symbols_data(data)[0]; - ft.symbols.rows.load(items); - }, - error: function (data) { - rspamd.alertMessage('alert-modal alert-error', data.statusText); - } - }); - }); - }; + }); + }; - return interface; -}); + return interface; + }); diff --git a/interface/js/app/upload.js b/interface/js/app/upload.js index f56ff9105..5a3185a0c 100644 --- a/interface/js/app/upload.js +++ b/interface/js/app/upload.js @@ -22,193 +22,193 @@ THE SOFTWARE. */ -define(['jquery'], -function($) { - var interface = {} +define(["jquery"], + function($) { + var interface = {}; - function cleanTextUpload(source) { - $('#' + source + 'TextSource').val(''); - } - - // @upload text - function uploadText(rspamd, data, source, headers) { - var url; - if (source === 'spam') { - url = 'learnspam'; - } else if (source === 'ham') { - url = 'learnham'; - } else if (source == 'fuzzy') { - url = 'fuzzyadd'; - } else if (source === 'scan') { - url = 'scan'; + function cleanTextUpload(source) { + $("#" + source + "TextSource").val(""); } - $.ajax({ - data: data, - dataType: 'json', - type: 'POST', - url: url, - processData: false, - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - $.each(headers, function (name, value) { - xhr.setRequestHeader(name, value); - }); - }, - success: function (data) { - cleanTextUpload(source); - if (data.success) { - rspamd.alertMessage('alert-success', 'Data successfully uploaded'); - } - }, - error: function (xhr, textStatus, errorThrown) { - var errorMsg; - try { - var json = $.parseJSON(xhr.responseText); - errorMsg = $('<a>').text(json.error).html(); - } catch (err) { - errorMsg = $('<a>').text("Error: [" + textStatus + "] " + errorThrown).html(); - } - rspamd.alertMessage('alert-error', errorMsg); + // @upload text + function uploadText(rspamd, data, source, headers) { + var url; + if (source === "spam") { + url = "learnspam"; + } else if (source === "ham") { + url = "learnham"; + } else if (source == "fuzzy") { + url = "fuzzyadd"; + } else if (source === "scan") { + url = "scan"; } - }); - } - // @upload text - function scanText(rspamd, data) { - var url = 'scan'; - var items = []; - $.ajax({ - data: data, - dataType: 'json', - type: 'POST', - url: url, - processData: false, - jsonp: false, - beforeSend: function (xhr) { - xhr.setRequestHeader('Password', rspamd.getPassword()); - }, - success: function (input) { - var data = input; - if (data.action) { - rspamd.alertMessage('alert-success', 'Data successfully scanned'); - var action = ''; - - if (data.action === 'clean' || 'no action') { - action = 'label-success'; - } - else if (data.action === 'rewrite subject' || 'add header' || 'probable spam') { - action = 'label-warning'; - } - else if (data.action === 'spam') { - action = 'label-danger'; + $.ajax({ + data: data, + dataType: "json", + type: "POST", + url: url, + processData: false, + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + $.each(headers, function (name, value) { + xhr.setRequestHeader(name, value); + }); + }, + success: function (data) { + cleanTextUpload(source); + if (data.success) { + rspamd.alertMessage("alert-success", "Data successfully uploaded"); } + }, + error: function (xhr, textStatus, errorThrown) { + var errorMsg; - var score = ''; - if (data.score <= data.required_score) { - score = 'label-success'; - } - else if (data.score >= data.required_score) { - score = 'label-danger'; + try { + var json = $.parseJSON(xhr.responseText); + errorMsg = $("<a>").text(json.error).html(); + } catch (err) { + errorMsg = $("<a>").text("Error: [" + textStatus + "] " + errorThrown).html(); } - $('<tbody id="tmpBody"><tr>' + - '<td><span class="label ' + action + '">' + data.action + '</span></td>' + - '<td><span class="label ' + score + '">' + data.score.toFixed(2) + '/' + data.required_score.toFixed(2) + '</span></td>' + - '</tr></tbody>') - .insertAfter('#scanOutput thead'); - var sym_desc = {}; - var nsym = 0; + rspamd.alertMessage("alert-error", errorMsg); + } + }); + } + // @upload text + function scanText(rspamd, data) { + var url = "scan"; + var items = []; + $.ajax({ + data: data, + dataType: "json", + type: "POST", + url: url, + processData: false, + jsonp: false, + beforeSend: function (xhr) { + xhr.setRequestHeader("Password", rspamd.getPassword()); + }, + success: function (input) { + var data = input; + if (data.action) { + rspamd.alertMessage("alert-success", "Data successfully scanned"); + var action = ""; - $.each(data.symbols, function (i, item) { - if (typeof item == 'object') { - var sym_id = "sym_" + nsym; - if (item.description) { - sym_desc[sym_id] = item.description; - } - items.push('<div class="cell-overflow" tabindex="1"><abbr id="' + sym_id + - '">' + item.name + '</abbr>: ' + item.score.toFixed(2) + '</div>'); - nsym++; + if (data.action === "clean" || "no action") { + action = "label-success"; } - }); - $('<td/>', { - id: 'tmpSymbols', - html: items.join('') - }).appendTo('#scanResult'); - $('#tmpSymbols').insertAfter('#tmpBody td:last').removeAttr('id'); - $('#tmpBody').removeAttr('id'); - $('#scanResult').show(); - // Show tooltips - $.each(sym_desc, function (k, v) { - $('#' + k).tooltip({ - "placement": "bottom", - "title": v + else if (data.action === "rewrite subject" || "add header" || "probable spam") { + action = "label-warning"; + } + else if (data.action === "spam") { + action = "label-danger"; + } + + var score = ""; + if (data.score <= data.required_score) { + score = "label-success"; + } + else if (data.score >= data.required_score) { + score = "label-danger"; + } + $("<tbody id=\"tmpBody\"><tr>" + + "<td><span class=\"label " + action + "\">" + data.action + "</span></td>" + + "<td><span class=\"label " + score + "\">" + data.score.toFixed(2) + "/" + data.required_score.toFixed(2) + "</span></td>" + + "</tr></tbody>") + .insertAfter("#scanOutput thead"); + var sym_desc = {}; + var nsym = 0; + + $.each(data.symbols, function (i, item) { + if (typeof item == "object") { + var sym_id = "sym_" + nsym; + if (item.description) { + sym_desc[sym_id] = item.description; + } + items.push("<div class=\"cell-overflow\" tabindex=\"1\"><abbr id=\"" + sym_id + + "\">" + item.name + "</abbr>: " + item.score.toFixed(2) + "</div>"); + nsym++; + } }); - }); - $('html, body').animate({ - scrollTop: $('#scanResult').offset().top - }, 1000); - } else { - rspamd.alertMessage('alert-error', 'Cannot scan data'); - } - }, - error: function (jqXHR, textStatus, errorThrown) { - rspamd.alertMessage('alert-error', 'Cannot upload data: ' + - textStatus + ", " + errorThrown); - }, - statusCode: { - 404: function () { - rspamd.alertMessage('alert-error', 'Cannot upload data, no server found'); + $("<td/>", { + id: "tmpSymbols", + html: items.join("") + }).appendTo("#scanResult"); + $("#tmpSymbols").insertAfter("#tmpBody td:last").removeAttr("id"); + $("#tmpBody").removeAttr("id"); + $("#scanResult").show(); + // Show tooltips + $.each(sym_desc, function (k, v) { + $("#" + k).tooltip({ + "placement": "bottom", + "title": v + }); + }); + $("html, body").animate({ + scrollTop: $("#scanResult").offset().top + }, 1000); + } else { + rspamd.alertMessage("alert-error", "Cannot scan data"); + } }, - 500: function () { - rspamd.alertMessage('alert-error', 'Cannot tokenize message: no text data'); + error: function (jqXHR, textStatus, errorThrown) { + rspamd.alertMessage("alert-error", "Cannot upload data: " + + textStatus + ", " + errorThrown); }, - 503: function () { - rspamd.alertMessage('alert-error', 'Cannot tokenize message: no text data'); + statusCode: { + 404: function () { + rspamd.alertMessage("alert-error", "Cannot upload data, no server found"); + }, + 500: function () { + rspamd.alertMessage("alert-error", "Cannot tokenize message: no text data"); + }, + 503: function () { + rspamd.alertMessage("alert-error", "Cannot tokenize message: no text data"); + } } - } - }); - } + }); + } - interface.setup = function(rspamd) { - $('textarea').change(function () { - if ($(this).val().length !== '') { - $(this).closest('form').find('button').removeAttr('disabled').removeClass('disabled'); - } else { - $(this).closest('form').find('button').attr('disabled').addClass('disabled'); - } - }); + interface.setup = function(rspamd) { + $("textarea").change(function () { + if ($(this).val().length !== "") { + $(this).closest("form").find("button").removeAttr("disabled").removeClass("disabled"); + } else { + $(this).closest("form").find("button").attr("disabled").addClass("disabled"); + } + }); - $('#scanClean').on('click', function () { - $('#scanTextSource').val(""); - $('#scanResult').hide(); - $('#scanOutput tbody').remove(); - $('html, body').animate({scrollTop: 0}, 1000); - return false; - }); - // @init upload - $('[data-upload]').on('click', function () { - var source = $(this).data('upload'); - var data; - var headers = {}; - data = $('#' + source + 'TextSource').val(); - if (source == 'fuzzy') { - //To access the proper - headers.flag = $('#fuzzyFlagText').val(); - headers.weight = $('#fuzzyWeightText').val(); - } else { - data = $('#' + source + 'TextSource').val(); - } - if (data.length > 0) { - if (source == 'scan') { - scanText(rspamd, data); + $("#scanClean").on("click", function () { + $("#scanTextSource").val(""); + $("#scanResult").hide(); + $("#scanOutput tbody").remove(); + $("html, body").animate({scrollTop: 0}, 1000); + return false; + }); + // @init upload + $("[data-upload]").on("click", function () { + var source = $(this).data("upload"); + var data; + var headers = {}; + data = $("#" + source + "TextSource").val(); + if (source == "fuzzy") { + // To access the proper + headers.flag = $("#fuzzyFlagText").val(); + headers.weight = $("#fuzzyWeightText").val(); } else { - uploadText(rspamd, data, source, headers); + data = $("#" + source + "TextSource").val(); } - } - return false; - }); - }; + if (data.length > 0) { + if (source == "scan") { + scanText(rspamd, data); + } else { + uploadText(rspamd, data, source, headers); + } + } + return false; + }); + }; - return interface; -}); + return interface; + }); diff --git a/interface/js/main.js b/interface/js/main.js index 76ceec468..d9d2840ee 100644 --- a/interface/js/main.js +++ b/interface/js/main.js @@ -1,23 +1,23 @@ requirejs.config({ - baseUrl: 'js/lib', + baseUrl: "js/lib", paths: { - app: '../app', - jquery: 'jquery-3.3.1.min', - visibility: 'visibility.min', - humanize: 'humanize.min', - bootstrap: 'bootstrap.min', - d3: 'd3.min', - d3evolution: 'd3evolution.min', - d3pie: 'd3pie.min', - footable: 'footable.min', - bootstrap: 'bootstrap.min', + app: "../app", + jquery: "jquery-3.3.1.min", + visibility: "visibility.min", + humanize: "humanize.min", + bootstrap: "bootstrap.min", + d3: "d3.min", + d3evolution: "d3evolution.min", + d3pie: "d3pie.min", + footable: "footable.min", + bootstrap: "bootstrap.min", }, shim: { - d3: {exports: 'd3'}, - bootstrap: {exports: 'bootstrap', deps: ['jquery']}, - d3pie: {exports: 'd3pie', deps: ['d3.global', 'jquery']}, - d3evolution: {exports: 'D3Evolution', deps: ['d3', 'd3pie', 'jquery']}, - footable: {deps: ['bootstrap', 'jquery']} + d3: {exports: "d3"}, + bootstrap: {exports: "bootstrap", deps: ["jquery"]}, + d3pie: {exports: "d3pie", deps: ["d3.global", "jquery"]}, + d3evolution: {exports: "D3Evolution", deps: ["d3", "d3pie", "jquery"]}, + footable: {deps: ["bootstrap", "jquery"]} } }); @@ -27,17 +27,17 @@ document.title = window.location.hostname + " - Rspamd Web Interface"; define("d3.global", ["d3"], function(_) { - d3 = _; + d3 = _; }); // Load main UI -require(['domReady'], -function(domReady) { - domReady(function () { - require(['jquery', 'd3', 'app/rspamd'], - function ($, d3, rspamd) { - rspamd.setup(); - rspamd.connect(); - }); +require(["domReady"], + function(domReady) { + domReady(function () { + require(["jquery", "d3", "app/rspamd"], + function ($, d3, rspamd) { + rspamd.setup(); + rspamd.connect(); + }); + }); }); -}); diff --git a/package.json b/package.json new file mode 100644 index 000000000..14ee2bd7b --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "devDependencies": { + "eslint": "*" + }, + "eslintIgnore": ["*.min.js", "interface/js/lib/domReady.js"] +} diff --git a/src/libserver/milter.c b/src/libserver/milter.c index c08513ea6..b6294d999 100644 --- a/src/libserver/milter.c +++ b/src/libserver/milter.c @@ -1807,6 +1807,9 @@ rspamd_milter_send_task_results (struct rspamd_milter_session *session, /* TODO: be more flexible about SMTP messages */ rspamd_milter_send_action (session, RSPAMD_MILTER_QUARANTINE, RSPAMD_MILTER_QUARANTINE_MESSAGE); + + /* Quarantine also requires accept action, all hail Sendmail */ + rspamd_milter_send_action (session, RSPAMD_MILTER_ACCEPT); } else { rcode = rspamd_fstring_new_init (RSPAMD_MILTER_RCODE_REJECT, diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 766d11e5f..7557d9bf7 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -217,7 +217,7 @@ parse_flags (struct fuzzy_rule *rule, } if (sym != NULL) { map = - rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct fuzzy_mapping)); map->symbol = sym; elt = ucl_object_lookup (val, "flag"); @@ -257,7 +257,7 @@ parse_flags (struct fuzzy_rule *rule, static GPtrArray * -parse_mime_types (const gchar *str) +parse_mime_types (struct rspamd_config *cfg, const gchar *str) { gchar **strvec, *p; gint num, i; @@ -272,24 +272,24 @@ parse_mime_types (const gchar *str) g_strstrip (strvec[i]); if ((p = strchr (strvec[i], '/')) != NULL) { - type = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + type = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct fuzzy_mime_type)); type->type_re = rspamd_regexp_from_glob (strvec[i], p - strvec[i], NULL); type->subtype_re = rspamd_regexp_from_glob (p + 1, 0, NULL); - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)rspamd_regexp_unref, type->type_re); - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)rspamd_regexp_unref, type->subtype_re); g_ptr_array_add (res, type); } else { - type = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + type = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct fuzzy_mime_type)); type->type_re = rspamd_regexp_from_glob (strvec[i], 0, NULL); - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)rspamd_regexp_unref, type->type_re); type->subtype_re = NULL; @@ -303,7 +303,7 @@ parse_mime_types (const gchar *str) } static GPtrArray * -parse_fuzzy_headers (const gchar *str) +parse_fuzzy_headers (struct rspamd_config *cfg, const gchar *str) { gchar **strvec; gint num, i; @@ -316,7 +316,7 @@ parse_fuzzy_headers (const gchar *str) for (i = 0; i < num; i++) { g_strstrip (strvec[i]); g_ptr_array_add (res, rspamd_mempool_strdup ( - fuzzy_module_ctx->fuzzy_pool, strvec[i])); + cfg->cfg_pool, strvec[i])); } g_strfreev (strvec); @@ -419,7 +419,7 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, } rule = fuzzy_rule_new (fuzzy_module_ctx->default_symbol, - fuzzy_module_ctx->fuzzy_pool); + cfg->cfg_pool); rule->learn_condition_cb = -1; rule->alg = RSPAMD_SHINGLES_OLD; rule->skip_map = NULL; @@ -441,7 +441,7 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, guint i; gpointer ptr; - tmp = parse_mime_types (ucl_obj_tostring (cur)); + tmp = parse_mime_types (cfg, ucl_obj_tostring (cur)); if (tmp) { if (rule->mime_types) { @@ -458,7 +458,7 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, } if (rule->mime_types) { - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_add_destructor (cfg->cfg_pool, rspamd_ptr_array_free_hard, rule->mime_types); } } @@ -471,7 +471,7 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, guint i; gpointer ptr; - tmp = parse_fuzzy_headers (ucl_obj_tostring (cur)); + tmp = parse_fuzzy_headers (cfg, ucl_obj_tostring (cur)); if (tmp) { if (rule->fuzzy_headers) { @@ -488,11 +488,11 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, } } else { - rule->fuzzy_headers = parse_fuzzy_headers (default_headers); + rule->fuzzy_headers = parse_fuzzy_headers (cfg, default_headers); } if (rule->fuzzy_headers != NULL) { - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t) rspamd_ptr_array_free_hard, rule->fuzzy_headers); } @@ -578,7 +578,7 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, if ((value = ucl_object_lookup (obj, "servers")) != NULL) { rule->servers = rspamd_upstreams_create (cfg->ups_ctx); - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)rspamd_upstreams_destroy, rule->servers); if (!rspamd_upstreams_from_ucl (rule->servers, value, DEFAULT_PORT, NULL)) { @@ -687,7 +687,7 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj, rule->algorithm_str); } - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, fuzzy_free_rule, + rspamd_mempool_add_destructor (cfg->cfg_pool, fuzzy_free_rule, rule); return 0; |