*/ | */ | ||||
define(["jquery"], | define(["jquery"], | ||||
function($) { | |||||
var interface = {} | |||||
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 " + | |||||
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); | 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)}, | |||||
}); | |||||
} | |||||
} | |||||
// @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)) { | 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).remove(); | |||||
$("<form class=\"form-horizontal form-map\" method=\"post\" action=\"savemap\" data-type=\"map\" id=\"" + | |||||
item.map + "\" style=\"display:none\">" + | item.map + "\" style=\"display:none\">" + | ||||
"<textarea class=\"list-textarea\"" + disabled + ">" + text + | "<textarea class=\"list-textarea\"" + disabled + ">" + text + | ||||
"</textarea>" + | "</textarea>" + | ||||
"</form").appendTo("#modalBody"); | "</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 | // 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\">" + | |||||
$("#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>" + | "<label class=\"control-label col-sm-2\">" + label + "</label>" + | ||||
"<div class=\"controls slider-controls col-sm-10\">" + | "<div class=\"controls slider-controls col-sm-10\">" + | ||||
"<input class=\"action-scores form-control\" data-id=\"action\" type=\"number\" value=\"" + item.value + "\">" + | "<input class=\"action-scores form-control\" data-id=\"action\" type=\"number\" value=\"" + item.value + "\">" + | ||||
"</div>" + | "</div>" + | ||||
"</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) { | items.map(function (e) { | ||||
return e.html; | return e.html; | ||||
}).join("") + | }).join("") + | ||||
"<button class=\"btn btn-primary\" type=\"button\" id=\"saveActionsBtn\">Save actions</button>" + | "<button class=\"btn btn-primary\" type=\"button\" id=\"saveActionsBtn\">Save actions</button>" + | ||||
"<button class=\"btn btn-primary\" type=\"button\" id=\"saveActionsClusterBtn\">Save cluster</button>" + | "<button class=\"btn btn-primary\" type=\"button\" id=\"saveActionsClusterBtn\">Save cluster</button>" + | ||||
"</div></div></fieldset></form>"); | "</div></div></fieldset></form>"); | ||||
if (rspamd.read_only) { | |||||
$("#saveActionsClusterBtn").attr("disabled", true); | |||||
$("#saveActionsBtn").attr("disabled", true); | |||||
$("#actionsFormField").attr("disabled", true); | |||||
} | |||||
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[1] === null || eltsArray[2] < eltsArray[1]) && | ||||
(eltsArray[0] === null || eltsArray[1] < eltsArray[0]) | (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 | // 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; | |||||
}); |
*/ | */ | ||||
define(["jquery", "d3evolution", "footable"], | 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" | |||||
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 | // 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 | // 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)) { | (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: " + | |||||
if (!(alert_status in sessionStorage)) { | |||||
sessionStorage.setItem(alert_status, true); | |||||
rspamd.alertMessage("alert-error", "Cannot receive RRD data from: " + | |||||
serv.name + ", error: " + errorThrown); | serv.name + ", error: " + errorThrown); | ||||
} | |||||
}, "GET", {}, {}, { | |||||
type: type | |||||
}); | |||||
return; | |||||
} | |||||
} | |||||
}, "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: " + | |||||
$.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); | textStatus + " " + jqXHR.status + " " + errorThrown); | ||||
} | |||||
}); | |||||
}; | |||||
} | |||||
}); | |||||
}; | |||||
interface.setup = function() { | |||||
interface.setup = function() { | |||||
// Handling mouse events on overlapping elements | // 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; | |||||
}); |
*/ | */ | ||||
define(["jquery", "d3pie", "humanize"], | define(["jquery", "d3pie", "humanize"], | ||||
function($, d3pie, Humanize) { | |||||
function($, d3pie, Humanize) { | |||||
// @ ms to date | // @ ms to date | ||||
function msToTime(seconds) { | |||||
function msToTime(seconds) { | |||||
years = seconds / 31536000 >> 0; // 3600*24*365 | years = seconds / 31536000 >> 0; // 3600*24*365 | ||||
months = seconds % 31536000 / 2628000 >> 0; //3600*24*365/12 | months = seconds % 31536000 / 2628000 >> 0; //3600*24*365/12 | ||||
days = seconds % 31536000 % 2628000 / 86400 >> 0; //24*3600 | days = seconds % 31536000 % 2628000 / 86400 >> 0; //24*3600 | ||||
hours = seconds % 31536000 % 2628000 % 86400 / 3600 >> 0; | hours = seconds % 31536000 % 2628000 % 86400 / 3600 >> 0; | ||||
minutes = seconds % 31536000 % 2628000 % 86400 % 3600 / 60 >> 0; | minutes = seconds % 31536000 % 2628000 % 86400 % 3600 / 60 >> 0; | ||||
if (years > 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) { | } else if (months > 0) { | ||||
out = months + "mth " + days + "d"; | |||||
out = months + "mth " + days + "d"; | |||||
} else if (days > 0) { | } else if (days > 0) { | ||||
out = days + "d " + hours + "hr"; | |||||
out = days + "d " + hours + "hr"; | |||||
} else if (hours > 0) { | } else if (hours > 0) { | ||||
out = hours + "hr " + minutes + "min"; | |||||
out = hours + "hr " + minutes + "min"; | |||||
} else { | } else { | ||||
out = minutes + "min"; | |||||
out = minutes + "min"; | |||||
} | } | ||||
return out; | 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>" + | |||||
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>"; | i + "</div>"; | ||||
$(widget).appendTo(widgets); | |||||
} else if (i == "uptime") { | |||||
widget = "<div class=\"right\"><strong>" + msToTime(item) + | |||||
$(widget).appendTo(widgets); | |||||
} else if (i == "uptime") { | |||||
widget = "<div class=\"right\"><strong>" + msToTime(item) + | |||||
"</strong>" + i + "</div>"; | "</strong>" + i + "</div>"; | ||||
$(widget).appendTo(widgets); | |||||
} else { | |||||
var titleAtt = Humanize.intComma(item) + " " + i; | |||||
widget = "<li class=\"stat-box\"><div class=\"widget\" title=\"" + titleAtt + "\"><strong>" + | |||||
$(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>"; | 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; | |||||
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 = "???"; | |||||
} | } | ||||
} | |||||
}); | |||||
$.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>" + | |||||
$("#clusterTable tbody").append("<tr>" + | |||||
"<td class=\"col1\" title=\"Radio\"><input type=\"radio\" class=\"form-control radio\" name=\"clusterName\" value=\"" + key + "\"></td>" + | "<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=\"col2\" title=\"SNAme\">" + key + "</td>" + | ||||
"<td class=\"col3\" title=\"SHost\">" + val.host + "</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=\"col4\" title=\"SStatus\"><span class=\"icon\"><i class=\"" + glyph_status + "\"></i></span></td>" + | ||||
"<td class=\"col5\" title=\"short_id\">" + short_id + "</td></tr>"); | "<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, | version: neighbours_status[0].data.version, | ||||
auth: "ok", | auth: "ok", | ||||
uptime: 0, | uptime: 0, | ||||
learned: 0, | learned: 0, | ||||
read_only: neighbours_status[0].data.read_only, | read_only: neighbours_status[0].data.read_only, | ||||
config_id: "" | 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 | // 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: "", | url: "", | ||||
host: "", | host: "", | ||||
checked: true, | checked: true, | ||||
data: neighbours_sum, | data: neighbours_sum, | ||||
status: true | 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; | |||||
} | |||||
); | ); |
*/ | */ | ||||
define(["jquery", "footable"], | define(["jquery", "footable"], | ||||
function($) { | |||||
var interface = {} | |||||
var ft = {} | |||||
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", | |||||
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 " + | "Save symbols error on " + | ||||
serv.name + ": " + errorThrown); | 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); | |||||
} | |||||
}); | |||||
}, "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 + | |||||
$.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=\"" + | "\" data-role=\"numerictextbox\" autocomplete=\"off\" \"type=\"number\" class=\"input\" min=\"" + | ||||
min + "\" max=\"" + | min + "\" max=\"" + | ||||
max + "\" step=\"" + decimalStep(item.weight) + | max + "\" step=\"" + decimalStep(item.weight) + | ||||
"\" tabindex=\"1\" value=\"" + Number(item.weight).toFixed(3) + | "\" tabindex=\"1\" value=\"" + Number(item.weight).toFixed(3) + | ||||
"\" id=\"_sym_" + item.symbol + "\"></input>" | "\" 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>" + | |||||
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>"; | " <button data-save=\"cluster\" type=\"button\" class=\"btn btn-primary btn-sm mb-disabled\">Save in cluster</button>"; | ||||
items.push(item) | |||||
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; | |||||
}); |
*/ | */ | ||||
define(["jquery"], | define(["jquery"], | ||||
function($) { | |||||
var interface = {} | |||||
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"; | |||||
try { | |||||
var json = $.parseJSON(xhr.responseText); | |||||
errorMsg = $("<a>").text(json.error).html(); | |||||
} catch (err) { | |||||
errorMsg = $("<a>").text("Error: [" + textStatus + "] " + errorThrown).html(); | |||||
} | } | ||||
else if (data.score >= data.required_score) { | |||||
score = "label-danger"; | |||||
} | |||||
$("<tbody id=\"tmpBody\"><tr>" + | |||||
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 = ""; | |||||
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"; | |||||
} | |||||
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 " + action + "\">" + data.action + "</span></td>" + | ||||
"<td><span class=\"label " + score + "\">" + data.score.toFixed(2) + "/" + data.required_score.toFixed(2) + "</span></td>" + | "<td><span class=\"label " + score + "\">" + data.score.toFixed(2) + "/" + data.required_score.toFixed(2) + "</span></td>" + | ||||
"</tr></tbody>") | "</tr></tbody>") | ||||
.insertAfter("#scanOutput thead"); | |||||
var sym_desc = {}; | |||||
var nsym = 0; | |||||
.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 + | |||||
$.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>"); | "\">" + item.name + "</abbr>: " + item.score.toFixed(2) + "</div>"); | ||||
nsym++; | |||||
} | |||||
}); | |||||
$("<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 | |||||
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 { | |||||
$("#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(); | data = $("#" + source + "TextSource").val(); | ||||
} | |||||
if (data.length > 0) { | |||||
if (source == "scan") { | |||||
scanText(rspamd, data); | |||||
if (source == "fuzzy") { | |||||
//To access the proper | |||||
headers.flag = $("#fuzzyFlagText").val(); | |||||
headers.weight = $("#fuzzyWeightText").val(); | |||||
} else { | } 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; | |||||
}); |
" - Rspamd Web Interface"; | " - Rspamd Web Interface"; | ||||
define("d3.global", ["d3"], function(_) { | define("d3.global", ["d3"], function(_) { | ||||
d3 = _; | |||||
d3 = _; | |||||
}); | }); | ||||
// Load main UI | // Load main UI | ||||
require(["domReady"], | require(["domReady"], | ||||
function(domReady) { | |||||
domReady(function () { | |||||
require(["jquery", "d3", "app/rspamd"], | |||||
function ($, d3, rspamd) { | |||||
rspamd.setup(); | |||||
rspamd.connect(); | |||||
}); | |||||
function(domReady) { | |||||
domReady(function () { | |||||
require(["jquery", "d3", "app/rspamd"], | |||||
function ($, d3, rspamd) { | |||||
rspamd.setup(); | |||||
rspamd.connect(); | |||||
}); | |||||
}); | |||||
}); | }); | ||||
}); |