xo: enable strict mode

Signed-off-by: XhmikosR <xhmikosr@gmail.com>
This commit is contained in:
XhmikosR
2025-03-25 21:39:11 +02:00
parent f598a8e35c
commit 756239a6dd
29 changed files with 140 additions and 86 deletions

View File

@@ -75,6 +75,9 @@
"trailingComma": "es5"
},
"xo": {
"parserOptions": {
"sourceType": "script"
},
"envs": [
"browser",
"jquery"
@@ -82,10 +85,6 @@
"extends": [
"plugin:compat/recommended"
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "script"
},
"prettier": true,
"space": 2,
"ignores": [
@@ -109,6 +108,7 @@
"no-console": "error",
"prefer-arrow-callback": "error",
"spaced-comment": "off",
"strict": "error",
"unicorn/no-anonymous-default-export": "off",
"unicorn/no-document-cookie": "off",
"unicorn/no-negated-condition": "off",

View File

@@ -7,6 +7,8 @@
/* global upstreams:false */
"use strict";
// eslint-disable-next-line no-unused-vars
const THEME_COLORS = [
"#f56954",

View File

@@ -7,6 +7,8 @@
/* global utils:false, moment:false */
"use strict";
globalThis._isLoginPage = false;
const REFRESH_INTERVAL = {

View File

@@ -5,6 +5,8 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
"use strict";
function eventsource() {
const alInfo = $("#alInfo");
const alSuccess = $("#alSuccess");

View File

@@ -8,6 +8,8 @@
/* global utils:false, groups:false, apiFailure:false, updateFtlInfo:false, getGroups:false, processGroupResult:false, delGroupItems:false */
/* exported initTable */
"use strict";
let table;
function reloadClientSuggestions() {

View File

@@ -7,6 +7,8 @@
/* global apiFailure:false, utils:false, initTable:false, updateFtlInfo:false */
"use strict";
let groups = [];
function populateGroupSelect(selectEl) {

View File

@@ -8,6 +8,8 @@
/* global utils:false, groups:false, getGroups:false, updateFtlInfo:false, apiFailure:false, processGroupResult:false, delGroupItems:false */
/* exported initTable */
"use strict";
let table;
let GETDict = {};

View File

@@ -8,6 +8,8 @@
/* global utils:false, groups:false, apiFailure:false, updateFtlInfo:false, getGroups:false, processGroupResult:false, delGroupItems:false */
/* exported initTable */
"use strict";
let table;
let GETDict = {};

View File

@@ -7,6 +7,8 @@
/* global utils:false, apiFailure:false, updateFtlInfo:false, processGroupResult:false, delGroupItems:false */
"use strict";
let table;
function handleAjaxError(xhr, textStatus) {

View File

@@ -7,6 +7,8 @@
/* global utils:false, Chart:false, apiFailure:false, THEME_COLORS:false, customTooltips:false, htmlLegendPlugin:false,doughnutTooltip:false, ChartDeferred:false, REFRESH_INTERVAL: false, updateQueryFrequency: false */
"use strict";
// Define global variables
let timeLineChart;
let clientsChart;

View File

@@ -7,6 +7,8 @@
/* global utils: false */
"use strict";
$(() => {
$.ajax({
url: document.body.dataset.apiurl + "/network/gateway",
@@ -32,14 +34,14 @@ $(() => {
const masterInterfaces = {};
// For each interface in data.interface, create a new object and push it to json
for (const interface of data.interfaces) {
const carrierColor = interface.carrier ? "text-green" : "text-red";
let stateText = interface.state.toUpperCase();
if (stateText === "UNKNOWN" && interface.flags !== undefined && interface.flags.length > 0) {
if (interface.flags.includes("pointopoint")) {
for (const iface of data.interfaces) {
const carrierColor = iface.carrier ? "text-green" : "text-red";
let stateText = iface.state.toUpperCase();
if (stateText === "UNKNOWN" && iface.flags !== undefined && iface.flags.length > 0) {
if (iface.flags.includes("pointopoint")) {
// WireGuards, etc. -> the typo is intentional
stateText = "P2P";
} else if (interface.flags.includes("loopback")) {
} else if (iface.flags.includes("loopback")) {
// Loopback interfaces
stateText = "LOOPBACK";
}
@@ -48,9 +50,9 @@ $(() => {
const status = `<span class="${carrierColor}">${stateText}</span>`;
let master = null;
if (interface.master !== undefined) {
if (iface.master !== undefined) {
// Find interface.master in data.interfaces
master = data.interfaces.find(obj => obj.index === interface.master).name;
master = data.interfaces.find(obj => obj.index === iface.master).name;
}
// Show an icon for indenting slave interfaces
@@ -58,8 +60,8 @@ $(() => {
master === null ? "" : "<span class='child-interface-icon'>&nbsp;&rdca;</span> ";
const obj = {
text: indentIcon + interface.name + " - " + status,
class: gateways.has(interface.name) ? "text-bold" : null,
text: indentIcon + iface.name + " - " + status,
class: gateways.has(iface.name) ? "text-bold" : null,
icon: master === null ? "fa fa-network-wired fa-fw" : "",
nodes: [],
};
@@ -71,57 +73,56 @@ $(() => {
});
if (master in masterInterfaces) {
masterInterfaces[master].push(interface.name);
masterInterfaces[master].push(iface.name);
} else {
masterInterfaces[master] = [interface.name];
masterInterfaces[master] = [iface.name];
}
}
if (interface.speed) {
if (iface.speed) {
obj.nodes.push({
text: "Speed: " + intl.format(interface.speed) + " Mbit/s",
text: "Speed: " + intl.format(iface.speed) + " Mbit/s",
icon: "fa fa-tachometer-alt fa-fw",
});
}
if (interface.type !== undefined) {
if (iface.type !== undefined) {
obj.nodes.push({
text: "Type: " + utils.escapeHtml(interface.type),
text: "Type: " + utils.escapeHtml(iface.type),
icon: "fa fa-network-wired fa-fw",
});
}
if (interface.flags !== undefined && interface.flags.length > 0) {
if (iface.flags !== undefined && iface.flags.length > 0) {
obj.nodes.push({
text: "Flags: " + utils.escapeHtml(interface.flags.join(", ")),
text: "Flags: " + utils.escapeHtml(iface.flags.join(", ")),
icon: "fa fa-flag fa-fw",
});
}
if (interface.address !== undefined) {
if (iface.address !== undefined) {
let extra = "";
if (interface.perm_address !== undefined && interface.perm_address !== interface.address) {
extra = " (permanent: <code>" + utils.escapeHtml(interface.perm_address) + "</code>)";
if (iface.perm_address !== undefined && iface.perm_address !== iface.address) {
extra = " (permanent: <code>" + utils.escapeHtml(iface.perm_address) + "</code>)";
}
obj.nodes.push({
text:
"Hardware address: <code>" + utils.escapeHtml(interface.address) + "</code>" + extra,
text: "Hardware address: <code>" + utils.escapeHtml(iface.address) + "</code>" + extra,
icon: "fa fa-map-marker-alt fa-fw",
});
}
if (interface.addresses !== undefined) {
if (iface.addresses !== undefined) {
const addrs = {
text:
interface.addresses.length +
(interface.addresses.length === 1 ? " address" : " addresses") +
iface.addresses.length +
(iface.addresses.length === 1 ? " address" : " addresses") +
" connected to interface",
icon: "fa fa-map-marker-alt fa-fw",
nodes: [],
};
for (const addr of interface.addresses) {
for (const addr of iface.addresses) {
let extraaddr = "";
if (addr.prefixlen !== undefined) {
extraaddr += " / <code>" + addr.prefixlen + "</code>";
@@ -214,107 +215,107 @@ $(() => {
obj.nodes.push(addrs);
}
if (interface.stats !== undefined) {
if (iface.stats !== undefined) {
const stats = {
text: "Statistics",
icon: "fa fa-chart-line fa-fw",
expanded: false,
nodes: [],
};
if (interface.stats.rx_bytes !== undefined) {
if (iface.stats.rx_bytes !== undefined) {
stats.nodes.push({
text:
"RX bytes: " +
intl.format(interface.stats.rx_bytes.value) +
intl.format(iface.stats.rx_bytes.value) +
" " +
interface.stats.rx_bytes.unit,
iface.stats.rx_bytes.unit,
icon: "fa fa-download fa-fw",
});
}
if (interface.stats.tx_bytes !== undefined) {
if (iface.stats.tx_bytes !== undefined) {
stats.nodes.push({
text:
"TX bytes: " +
intl.format(interface.stats.tx_bytes.value) +
intl.format(iface.stats.tx_bytes.value) +
" " +
interface.stats.tx_bytes.unit,
iface.stats.tx_bytes.unit,
icon: "fa fa-upload fa-fw",
});
}
if (interface.stats.rx_packets !== undefined) {
if (iface.stats.rx_packets !== undefined) {
stats.nodes.push({
text: "RX packets: " + intl.format(interface.stats.rx_packets),
text: "RX packets: " + intl.format(iface.stats.rx_packets),
icon: "fa fa-download fa-fw",
});
}
if (interface.stats.rx_errors !== undefined) {
if (iface.stats.rx_errors !== undefined) {
stats.nodes.push({
text:
"RX errors: " +
intl.format(interface.stats.rx_errors) +
intl.format(iface.stats.rx_errors) +
" (" +
((interface.stats.rx_errors / interface.stats.rx_packets) * 100).toFixed(1) +
((iface.stats.rx_errors / iface.stats.rx_packets) * 100).toFixed(1) +
"%)",
icon: "fa fa-download fa-fw",
});
}
if (interface.stats.rx_dropped !== undefined) {
if (iface.stats.rx_dropped !== undefined) {
stats.nodes.push({
text:
"RX dropped: " +
intl.format(interface.stats.rx_dropped) +
intl.format(iface.stats.rx_dropped) +
" (" +
((interface.stats.rx_dropped / interface.stats.rx_packets) * 100).toFixed(1) +
((iface.stats.rx_dropped / iface.stats.rx_packets) * 100).toFixed(1) +
"%)",
icon: "fa fa-download fa-fw",
});
}
if (interface.stats.tx_packets !== undefined) {
if (iface.stats.tx_packets !== undefined) {
stats.nodes.push({
text: "TX packets: " + intl.format(interface.stats.tx_packets),
text: "TX packets: " + intl.format(iface.stats.tx_packets),
icon: "fa fa-upload fa-fw",
});
}
if (interface.stats.tx_errors !== undefined) {
if (iface.stats.tx_errors !== undefined) {
stats.nodes.push({
text:
"TX errors: " +
intl.format(interface.stats.tx_errors) +
intl.format(iface.stats.tx_errors) +
" (" +
((interface.stats.tx_errors / interface.stats.tx_packets) * 100).toFixed(1) +
((iface.stats.tx_errors / iface.stats.tx_packets) * 100).toFixed(1) +
"%)",
icon: "fa fa-upload fa-fw",
});
}
if (interface.stats.tx_dropped !== undefined) {
if (iface.stats.tx_dropped !== undefined) {
stats.nodes.push({
text:
"TX dropped: " +
intl.format(interface.stats.tx_dropped) +
intl.format(iface.stats.tx_dropped) +
" (" +
((interface.stats.tx_dropped / interface.stats.tx_packets) * 100).toFixed(1) +
((iface.stats.tx_dropped / iface.stats.tx_packets) * 100).toFixed(1) +
"%)",
icon: "fa fa-upload fa-fw",
});
}
if (interface.stats.multicast !== undefined) {
if (iface.stats.multicast !== undefined) {
stats.nodes.push({
text: "Multicast: " + intl.format(interface.stats.multicast),
text: "Multicast: " + intl.format(iface.stats.multicast),
icon: "fa fa-broadcast-tower fa-fw",
});
}
if (interface.stats.collisions !== undefined) {
if (iface.stats.collisions !== undefined) {
stats.nodes.push({
text: "Collisions: " + intl.format(interface.stats.collisions),
text: "Collisions: " + intl.format(iface.stats.collisions),
icon: "fa fa-exchange-alt fa-fw",
});
}
@@ -333,81 +334,78 @@ $(() => {
{
text:
"Carrier: " +
(interface.carrier
(iface.carrier
? "<span class='text-green'>Connected</span>"
: "<span class='text-red'>Disconnected</span>"),
icon: "fa fa-link fa-fw",
},
{
text: "State: " + utils.escapeHtml(interface.state.toUpperCase()),
text: "State: " + utils.escapeHtml(iface.state.toUpperCase()),
icon: "fa fa-server fa-fw",
}
);
if (interface.parent_dev_name !== undefined) {
if (iface.parent_dev_name !== undefined) {
let extra = "";
if (interface.parent_dev_bus_name !== undefined) {
extra = " @ " + utils.escapeHtml(interface.parent_dev_bus_name);
if (iface.parent_dev_bus_name !== undefined) {
extra = " @ " + utils.escapeHtml(iface.parent_dev_bus_name);
}
furtherDetails.nodes.push({
text:
"Parent device: <code>" +
utils.escapeHtml(interface.parent_dev_name) +
extra +
"</code>",
"Parent device: <code>" + utils.escapeHtml(iface.parent_dev_name) + extra + "</code>",
icon: "fa fa-network-wired fa-fw",
});
}
if (interface.carrier_changes !== undefined) {
if (iface.carrier_changes !== undefined) {
furtherDetails.nodes.push({
text: "Carrier changes: " + intl.format(interface.carrier_changes),
text: "Carrier changes: " + intl.format(iface.carrier_changes),
icon: "fa fa-exchange-alt fa-fw",
});
}
if (interface.broadcast) {
if (iface.broadcast) {
furtherDetails.nodes.push({
text: "Broadcast: <code>" + utils.escapeHtml(interface.broadcast) + "</code>",
text: "Broadcast: <code>" + utils.escapeHtml(iface.broadcast) + "</code>",
icon: "fa fa-broadcast-tower fa-fw",
});
}
if (interface.mtu) {
if (iface.mtu) {
let extra = "";
if (interface.min_mtu !== undefined && interface.max_mtu !== undefined) {
if (iface.min_mtu !== undefined && iface.max_mtu !== undefined) {
extra +=
" (min: " +
intl.format(interface.min_mtu) +
intl.format(iface.min_mtu) +
" bytes, max: " +
intl.format(interface.max_mtu) +
intl.format(iface.max_mtu) +
" bytes)";
}
furtherDetails.nodes.push({
text: "MTU: " + intl.format(interface.mtu) + " bytes" + extra,
text: "MTU: " + intl.format(iface.mtu) + " bytes" + extra,
icon: "fa fa-arrows-alt-h fa-fw",
});
}
if (interface.txqlen) {
if (iface.txqlen) {
furtherDetails.nodes.push({
text: "TX queue length: " + intl.format(interface.txqlen),
text: "TX queue length: " + intl.format(iface.txqlen),
icon: "fa fa-file-upload fa-fw",
});
}
if (interface.promiscuity !== undefined) {
if (iface.promiscuity !== undefined) {
furtherDetails.nodes.push({
text: "Promiscuity mode: " + (interface.promiscuity ? "Yes" : "No"),
text: "Promiscuity mode: " + (iface.promiscuity ? "Yes" : "No"),
icon: "fa fa-eye fa-fw",
});
}
if (interface.qdisc !== undefined) {
if (iface.qdisc !== undefined) {
furtherDetails.nodes.push({
text: "Scheduler: " + utils.escapeHtml(interface.qdisc),
text: "Scheduler: " + utils.escapeHtml(iface.qdisc),
icon: "fa fa-network-wired fa-fw",
});
}
@@ -416,7 +414,7 @@ $(() => {
obj.nodes.push(furtherDetails);
}
interfaces[interface.name] = obj;
interfaces[iface.name] = obj;
}
// Sort interfaces based on masterInterfaces. If an item is found in

View File

@@ -5,6 +5,8 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
"use strict";
// This code has been taken from
// https://datatables.net/plug-ins/sorting/ip-address
// and was modified by the Pi-hole team to support

View File

@@ -7,6 +7,8 @@
/* global utils:false, NProgress:false */
"use strict";
globalThis._isLoginPage = true;
function redirect() {

View File

@@ -7,6 +7,8 @@
/* global utils:false */
"use strict";
document.addEventListener("DOMContentLoaded", () => {
const logoutButton = document.getElementById("logout-button");
const logoutUrl = document.body.dataset.webhome + "login";

View File

@@ -6,6 +6,9 @@
* Please see LICENSE file for your rights under this license. */
/* global utils: false */
"use strict";
let table;
const toasts = {};

View File

@@ -7,6 +7,8 @@
/* global utils:false, apiFailure:false */
"use strict";
let tableApi;
// How many IPs do we show at most per device?

View File

@@ -7,6 +7,8 @@
/* global moment:false, utils:false, REFRESH_INTERVAL:false */
"use strict";
const beginningOfTime = 1_262_304_000; // Jan 01 2010, 00:00 in seconds
const endOfTime = 2_147_483_647; // Jan 19, 2038, 03:14 in seconds
let from = beginningOfTime;

View File

@@ -6,6 +6,9 @@
* Please see LICENSE file for your rights under this license. */
/* global utils:false, apiFailure:false */
"use strict";
let GETDict = {};
$(() => {

View File

@@ -8,6 +8,8 @@
/* global utils:false, apiFailure: false, applyCheckboxRadioStyle: false, saveSettings:false */
/* exported createDynamicConfigTabs */
"use strict";
function addAllowedValues(allowed) {
if (typeof allowed === "object") {
return (

View File

@@ -7,6 +7,8 @@
/* global utils:false, setConfigValues: false, apiFailure: false, QRious: false */
"use strict";
let apiSessionsTable = null;
let ownSessionID = null;
let deleted = 0;

View File

@@ -7,6 +7,8 @@
/* global utils:false, setConfigValues: false, apiFailure: false */
"use strict";
let dhcpLeaesTable = null;
const toasts = {};

View File

@@ -7,6 +7,8 @@
/* global utils: false, apiFailure:false, setConfigValues: false */
"use strict";
function hostsDomain(data) {
// Split record in format IP NAME1 [NAME2 [NAME3 [NAME...]]]
// We split both on spaces and tabs to support both formats

View File

@@ -7,6 +7,8 @@
/* global applyCheckboxRadioStyle:false, setConfigValues: false, apiFailure: false */
"use strict";
// Remove an element from an array (inline)
function removeFromArray(arr, what) {
let found = arr.indexOf(what);
@@ -99,9 +101,9 @@ function fillDNSupstreams(value, servers) {
applyCheckboxRadioStyle();
}
function setInterfaceName(interface) {
$("#interface-name-1").text(interface);
$("#interface-name-2").text(interface);
function setInterfaceName(name) {
$("#interface-name-1").text(name);
$("#interface-name-2").text(name);
}
// Update the textfield with all (incl. custom) upstream servers

View File

@@ -7,6 +7,8 @@
/* global setConfigValues: false, apiFailure: false */
"use strict";
function getConfig() {
$.ajax({
url: document.body.dataset.apiurl + "/config/?detailed=true",

View File

@@ -7,6 +7,8 @@
/* global apiFailure:false, Chart:false, THEME_COLORS:false, customTooltips:false, htmlLegendPlugin:false,doughnutTooltip:false, ChartDeferred:false, REFRESH_INTERVAL: false, utils: false */
"use strict";
let hostinfoTimer = null;
let cachePieChart = null;
let cacheSize = 0;

View File

@@ -7,6 +7,8 @@
/* global utils:false */
"use strict";
// Add event listener to import button
document.getElementById("submit-import").addEventListener("click", () => {
importZIP();

View File

@@ -7,6 +7,8 @@
/* global utils:false, apiFailure:false*/
"use strict";
$(() => {
// Handle hiding of alerts
$("[data-hide]").on("click", function () {

View File

@@ -7,6 +7,8 @@
/* global moment: false, apiFailure: false, utils: false, REFRESH_INTERVAL: false */
"use strict";
let nextID = 0;
let lastPID = -1;

View File

@@ -7,6 +7,8 @@
/* global moment:false, apiFailure: false, updateFtlInfo: false, NProgress:false, WaitMe:false */
"use strict";
$(() => {
// CSRF protection for AJAX requests, this has to be configured globally
// because we are using the jQuery $.ajax() function directly in some cases