%PDF- %PDF-
| Direktori : /www/varak.net/dmarc.varak.net/public/js/ |
| Current File : /www/varak.net/dmarc.varak.net/public/js/status.js |
/**
* dmarc-srg - A php parser, viewer and summary report generator for incoming DMARC reports.
* Copyright (C) 2020-2024 Aleksey Andreev (liuch)
*
* Available at:
* https://github.com/liuch/dmarc-srg
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
class Status {
constructor() {
this._data = {};
this._hint = null;
this._use_filter = null;
}
update(params) {
return this._fetch(params || {}).then(function(data) {
return data;
}).catch(function(err) {
Common.displayError(err);
});
}
reset() {
this._data.emails = null;
this._data.error_code = 0;
this._update_block();
}
error() {
return this._data.error_code && this._data.error_code !== 0 || false;
}
_fetch(params) {
let url = new URL("status.php", document.location);
let fields = [ "state", "user" ];
let s_list = params.settings || [];
if (params.page !== "list") this._use_filter = false;
if (this._use_filter === null || (params.settings && params.settings.length)) {
fields.push("settings");
if (this._use_filter === null) s_list.push("status.emails-filter-when-list-filtered");
}
url.searchParams.set("fields", fields.join(","));
if (s_list.length) url.searchParams.set("settings", s_list.join(","));
return window.fetch(url, {
method: "GET",
cache: "no-store",
headers: HTTP_HEADERS,
credentials: "same-origin"
}).then(function(resp) {
if (!resp.ok) throw new Error("Failed to fetch the status");
return resp.json();
}).then(function(data) {
User.name = data.user && data.user.name || null;
User.level = data.user && data.user.level || null;
User.auth_type = data.auth_type;
this._data = {
state: data.state,
error_code: data.error_code,
message: data.message,
emails: null
};
this._update_block();
if (data.error_code === -2) LoginDialog.start();
if (!this.error()) {
if (data.settings) {
let uf = data.settings["status.emails-filter-when-list-filtered"] || null;
this._use_filter = (uf === "yes");
}
this._fetch_statistics();
}
return data;
}.bind(this)).catch(function(err) {
this._data = {
state: "Err",
error_code: -100,
message: err.message
};
this._update_block();
throw err;
}.bind(this));
}
_fetch_statistics() {
let url = new URL("status.php", document.location);
url.searchParams.set("fields", "emails");
if (this._use_filter) {
(new URL(document.location)).searchParams.getAll("filter[]").forEach(function(fval) {
url.searchParams.append("filter[]", fval);
});
}
window.fetch(url, {
method: "GET",
cache: "no-store",
headers: HTTP_HEADERS,
credentials: "same-origin"
}).then(function(resp) {
if (!resp.ok) throw new Error("Failed to fetch statistics");
return resp.json();
}).then(function(data) {
Common.checkResult(data);
this._data.emails = data.emails;
this._update_block();
}.bind(this)).catch(function(err) {
Common.displayError(err);
this._update_block();
Notification.add({ text: err.message || "Error!", type: "error" });
}.bind(this));
}
_update_block() {
if (this._hint) this._hint.reset();
this._ensure_element_created();
if (this._data.error_code) {
let p = { text: "[" + this._data.error_code + "] " + this._data.message, type: "error" };
if (this._data.error_code === -2)
p.name = "auth";
Notification.add(p);
}
if (!this._data.emails) {
this._data.emails = {
days: 0,
total: -1,
spf_aligned: 0,
dkim_aligned: 0,
dkim_spf_aligned: 0
};
}
const data = this._data.emails;
const tf = (data.total !== undefined && data.total !== -1);
const vals = this._format_statistic_values();
Status._element_list.forEach((id, pos) => {
this._set_element_value(id, null, vals[pos], tf && Status._element_data[id].color || null);
});
const el = document.getElementById("stat-block");
if (typeof(data.days) === "string") {
el.setAttribute("title", "Statistics for " + data.days);
}
else {
el.removeAttribute("title");
}
}
_formatted_statistic(val, total) {
if (total === -1)
return "?";
if (!total)
return "-";
if (val === 0)
return "0";
let rval = Math.round(val / total * 100);
return (val > 0 && rval === 0 && "+" || "" ) + rval + "%";
}
_set_element_value(c_el, v_el, value, cname) {
if (typeof(c_el) == "string") c_el = document.getElementById("stat-" + c_el);
if (cname) {
c_el.setAttribute("class", "state-" + cname);
} else {
c_el.removeAttribute("class");
}
(v_el || c_el.querySelector(".stat-val")).textContent = value;
}
_format_statistic_values() {
const de = this._data.emails;
const total = de.total;
const vals = [ (total === -1 || total === undefined) && "?" || Common.abbrNumber(total, 10000) ];
[
de.dkim_spf_aligned,
de.dkim_aligned + de.spf_aligned,
(total || 0) - de.dkim_spf_aligned - de.dkim_aligned - de.spf_aligned
].forEach(v => vals.push(this._formatted_statistic(v, total)));
return vals;
}
_ensure_element_created() {
let block = document.getElementById("stat-block");
if (block && block.children.length === 0) {
const ul = block.appendChild(document.createElement("ul"));
Status._element_list.forEach(function(id) {
let li = document.createElement("li");
let div = document.createElement("div");
div.setAttribute("id", "stat-" + id);
let val = document.createElement("span");
val.setAttribute("class", "stat-val state-text");
val.appendChild(document.createTextNode("?"));
let msg = document.createElement("span");
msg.setAttribute("class", "stat-msg");
msg.appendChild(document.createTextNode(Status._element_data[id].text));
div.appendChild(val);
div.appendChild(msg);
li.appendChild(div);
ul.appendChild(li);
});
const hli = ul.appendChild(document.createElement("li"));
hli.classList.add("hint");
if (!this._hint) this._hint = new HintButton({ content: this._make_hint_content.bind(this) });
hli.append(this._hint.element());
}
}
_make_hint_content() {
const data = this._data.emails;
const el = document.createElement("div");
const hd = el.appendChild(document.createElement("h4"));
const tf = (data.total !== undefined && data.total !== -1);
hd.textContent = tf && ("Statistics for " + data.days) || "n/a";
const ul = el.appendChild(document.createElement("ul"));
const vals = this._format_statistic_values();
Status._element_list.forEach((id, pos) => {
const li = ul.appendChild(document.createElement("li"));
li.appendChild(document.createElement("span")).textContent = Status._element_data[id].text + ": ";
const vl = li.appendChild(document.createElement("span"));
vl.classList.add("stat-val", "state-text");
this._set_element_value(li, vl, vals[pos], tf && Status._element_data[id].color || null);
});
return el;
}
}
Status.instance = function() {
if (!this._instance)
this._instance = new Status();
return this._instance;
}
Status._element_list = [ "processed", "passed", "forwarded", "failed" ];
Status._element_data = {
processed: {
text: "Emails processed",
color: "blue"
},
passed: {
text: "Fully aligned",
color: "green"
},
forwarded: {
text: "Partially aligned",
color: "green"
},
failed: {
text: "Not aligned",
color: "red"
}
};