299 lines
8.7 KiB
JavaScript
299 lines
8.7 KiB
JavaScript
/* Pi-hole: A black hole for Internet advertisements
|
|
* (c) 2023 Pi-hole, LLC (https://pi-hole.net)
|
|
* Network-wide ad blocking via your own hardware.
|
|
*
|
|
* This file is copyright under the latest version of the EUPL.
|
|
* Precord see LICENSE file for your rights under this license. */
|
|
|
|
/* global utils: false, apiFailure:false, setConfigValues: false, i18n */
|
|
|
|
"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
|
|
// Also, we remove any comments after the name(s)
|
|
const name = data
|
|
.split(/[\t ]+/)
|
|
.slice(1)
|
|
.join(" ")
|
|
.split("#")[0]
|
|
.trim();
|
|
return name;
|
|
}
|
|
|
|
function hostsIP(data) {
|
|
// Split record in format IP NAME1 [NAME2 [NAME3 [NAME...]]]
|
|
// We split both on spaces and tabs to support both formats
|
|
const ip = data.split(/[\t ]+/)[0].trim();
|
|
return ip;
|
|
}
|
|
|
|
function CNAMEdomain(data) {
|
|
// Split record in format <cname>,<target>[,<TTL>]
|
|
const CNAMEarr = data.split(",");
|
|
return CNAMEarr[0].trim();
|
|
}
|
|
|
|
function CNAMEtarget(data) {
|
|
// Split record in format <cname>,<target>[,<TTL>]
|
|
const CNAMEarr = data.split(",");
|
|
return CNAMEarr[1].trim();
|
|
}
|
|
|
|
function CNAMEttl(data) {
|
|
// Split record in format <cname>,<target>[,<TTL>]
|
|
const CNAMEarr = data.split(",");
|
|
return CNAMEarr.length > 2 ? CNAMEarr[2] : "-";
|
|
}
|
|
|
|
function populateDataTable(endpoint) {
|
|
let columns = "";
|
|
if (endpoint === "hosts") {
|
|
columns = [
|
|
{ data: null, render: hostsDomain },
|
|
{ data: null, type: "ip-address", render: hostsIP },
|
|
{ data: null, width: "22px", orderable: false },
|
|
];
|
|
} else {
|
|
columns = [
|
|
{ data: null, render: CNAMEdomain },
|
|
{ data: null, render: CNAMEtarget },
|
|
{ data: null, width: "40px", render: CNAMEttl },
|
|
{ data: null, width: "22px", orderable: false },
|
|
];
|
|
}
|
|
|
|
const setByEnv = false;
|
|
$.ajax({
|
|
url: document.body.dataset.apiurl + "/config/dns/" + endpoint + "?detailed=true",
|
|
}).done(data => {
|
|
// Set the title icons if needed
|
|
setConfigValues("dns", "dns", data.config.dns);
|
|
|
|
// disable input fields if set by env var
|
|
if (data.config.dns[endpoint].flags.env_var) {
|
|
$(`.${endpoint}`).prop("disabled", true);
|
|
}
|
|
});
|
|
|
|
$(`#${endpoint}-Table`).DataTable({
|
|
ajax: {
|
|
url: document.body.dataset.apiurl + "/config/dns/" + endpoint,
|
|
type: "GET",
|
|
dataSrc: `config.dns.${endpoint}`,
|
|
},
|
|
autoWidth: false,
|
|
columns,
|
|
columnDefs: [
|
|
{
|
|
targets: "_all",
|
|
render: $.fn.dataTable.render.text(),
|
|
},
|
|
],
|
|
drawCallback() {
|
|
$(`button[id^="delete${endpoint}"]`).on("click", deleteRecord);
|
|
|
|
// Remove visible dropdown to prevent orphaning
|
|
$("body > .bootstrap-select.dropdown").remove();
|
|
},
|
|
rowCallback(row, data) {
|
|
$(row).attr("data-id", data);
|
|
const button = `<button type="button"
|
|
class="btn btn-danger btn-xs"
|
|
id="delete${endpoint}${utils.hexEncode(data)}"
|
|
data-tag="${data}"
|
|
data-type="${endpoint}"
|
|
${setByEnv ? "disabled" : ""}>
|
|
<span class="far fa-trash-alt"></span>
|
|
</button>`;
|
|
$(`td:eq(${endpoint === "hosts" ? 2 : 3})`, row).html(button);
|
|
},
|
|
dom:
|
|
"<'row'<'col-sm-5'l><'col-sm-7'f>>" +
|
|
"<'row'<'col-sm-12'p>>" +
|
|
"<'row'<'col-sm-12'<'table-responsive'tr>>>" +
|
|
"<'row'<'col-sm-12'p>>" +
|
|
"<'row'<'col-sm-12'i>>",
|
|
lengthMenu: [
|
|
[10, 25, 50, 100, -1],
|
|
[10, 25, 50, 100, i18n.t("shared.all")],
|
|
],
|
|
language: {
|
|
emptyTable() {
|
|
return endpoint === "hosts"
|
|
? i18n.t("settings.dnsrecords.no_dns_records")
|
|
: i18n.t("settings.dnsrecords.no_cname_records");
|
|
},
|
|
},
|
|
stateSave: true,
|
|
stateDuration: 0,
|
|
processing: true,
|
|
stateSaveCallback(settings, data) {
|
|
utils.stateSaveCallback(`${endpoint}-records-table`, data);
|
|
},
|
|
stateLoadCallback() {
|
|
const data = utils.stateLoadCallback(`${endpoint}-records-table`);
|
|
// Return if not available
|
|
if (data === null) {
|
|
return null;
|
|
}
|
|
|
|
// Apply loaded state to table
|
|
return data;
|
|
},
|
|
});
|
|
}
|
|
|
|
i18n.waitForTranslations(() => {
|
|
populateDataTable("hosts");
|
|
populateDataTable("cnameRecords");
|
|
});
|
|
|
|
function deleteRecord() {
|
|
if ($(this).attr("data-type") === "hosts") delHosts($(this).attr("data-tag"));
|
|
else delCNAME($(this).attr("data-tag"));
|
|
}
|
|
|
|
function delHosts(elem) {
|
|
utils.disableAll();
|
|
utils.showAlert("info", "", i18n.t("settings.dnsrecords.deleting_dns_records"), elem);
|
|
const url = document.body.dataset.apiurl + "/config/dns/hosts/" + encodeURIComponent(elem);
|
|
|
|
$.ajax({
|
|
url,
|
|
method: "DELETE",
|
|
})
|
|
.done(() => {
|
|
utils.enableAll();
|
|
utils.showAlert(
|
|
"success",
|
|
"fas fa-trash-alt",
|
|
i18n.t("settings.dnsrecords.successfully_deleted_dns_record"),
|
|
elem
|
|
);
|
|
$("#hosts-Table").DataTable().ajax.reload(null, false);
|
|
})
|
|
.fail((data, exception) => {
|
|
utils.enableAll();
|
|
apiFailure(data);
|
|
utils.showAlert(
|
|
"error",
|
|
"",
|
|
i18n.tf("settings.dnsrecords.error_deleting_dns_record", "<code>" + elem + "</code>"),
|
|
data.responseText
|
|
);
|
|
console.log(exception); // eslint-disable-line no-console
|
|
});
|
|
}
|
|
|
|
function delCNAME(elem) {
|
|
utils.disableAll();
|
|
utils.showAlert("info", "", i18n.t("settings.dnsrecords.deleting_cname_record"), elem);
|
|
const url = document.body.dataset.apiurl + "/config/dns/cnameRecords/" + encodeURIComponent(elem);
|
|
|
|
$.ajax({
|
|
url,
|
|
method: "DELETE",
|
|
})
|
|
.done(() => {
|
|
utils.enableAll();
|
|
utils.showAlert(
|
|
"success",
|
|
"fas fa-trash-alt",
|
|
i18n.t("settings.dnsrecords.successfully_deleted_cname_record"),
|
|
elem
|
|
);
|
|
$("#cnameRecords-Table").DataTable().ajax.reload(null, false);
|
|
})
|
|
.fail((data, exception) => {
|
|
utils.enableAll();
|
|
apiFailure(data);
|
|
utils.showAlert(
|
|
"error",
|
|
"",
|
|
i18n.tf("settings.dnsrecords.error_deleting_cname_record", "<code>" + elem + "</code>"),
|
|
data.responseText
|
|
);
|
|
console.log(exception); // eslint-disable-line no-console
|
|
});
|
|
}
|
|
|
|
i18n.waitForTranslations(() => {
|
|
$("#btnAdd-host").on("click", () => {
|
|
utils.disableAll();
|
|
const elem = $("#Hip").val() + " " + $("#Hdomain").val();
|
|
const url = document.body.dataset.apiurl + "/config/dns/hosts/" + encodeURIComponent(elem);
|
|
utils.showAlert("info", "", i18n.t("settings.dnsrecords.adding_dns_record"), elem);
|
|
$.ajax({
|
|
url,
|
|
method: "PUT",
|
|
})
|
|
.done(() => {
|
|
utils.enableAll();
|
|
utils.showAlert(
|
|
"success",
|
|
"fas fa-plus",
|
|
i18n.t("settings.dnsrecords.successfully_added_dns_record"),
|
|
elem
|
|
);
|
|
$("#Hdomain").val("");
|
|
$("#Hip").val("");
|
|
$("#hosts-Table").DataTable().ajax.reload(null, false);
|
|
})
|
|
.fail((data, exception) => {
|
|
utils.enableAll();
|
|
apiFailure(data);
|
|
utils.showAlert(
|
|
"error",
|
|
"",
|
|
i18n.t("settings.dnsrecords.error_adding_dns_record"),
|
|
data.responseText
|
|
);
|
|
console.log(exception); // eslint-disable-line no-console
|
|
});
|
|
});
|
|
|
|
$("#btnAdd-cname").on("click", () => {
|
|
utils.disableAll();
|
|
let elem = $("#Cdomain").val() + "," + $("#Ctarget").val();
|
|
const ttlVal = Number.parseInt($("#Cttl").val(), 10);
|
|
// TODO Fix eslint
|
|
// eslint-disable-next-line unicorn/prefer-number-properties
|
|
if (isFinite(ttlVal) && ttlVal >= 0) elem += "," + ttlVal;
|
|
const url =
|
|
document.body.dataset.apiurl + "/config/dns/cnameRecords/" + encodeURIComponent(elem);
|
|
utils.showAlert("info", "", i18n.t("settings.dnsrecords.adding_cname_record"), elem);
|
|
$.ajax({
|
|
url,
|
|
method: "PUT",
|
|
})
|
|
.done(() => {
|
|
utils.enableAll();
|
|
utils.showAlert(
|
|
"success",
|
|
"fas fa-plus",
|
|
i18n.t("settings.dnsrecords.successfully_added_cname_record"),
|
|
elem
|
|
);
|
|
$("#Cdomain").val("");
|
|
$("#Ctarget").val("");
|
|
$("#cnameRecords-Table").DataTable().ajax.reload(null, false);
|
|
})
|
|
.fail((data, exception) => {
|
|
utils.enableAll();
|
|
apiFailure(data);
|
|
utils.showAlert(
|
|
"error",
|
|
"",
|
|
i18n.t("settings.dnsrecords.error_adding_cname_record"),
|
|
data.responseText
|
|
);
|
|
console.log(exception); // eslint-disable-line no-console
|
|
});
|
|
});
|
|
|
|
// Add a small legend below the CNAME table
|
|
$("#cnameRecords-Table").after(`<small>${i18n.t("settings.dnsrecords.ttl_in_seconds")}</small>`);
|
|
});
|