/*
Technitium DNS Server
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
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, or
(at your option) any later version.
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 .
*/
var zoneOptionsAvailableTsigKeyNames;
$(function () {
$("input[type=radio][name=rdAddZoneType]").change(function () {
$("#divAddZonePrimaryNameServerAddresses").hide();
$("#divAddZoneZoneTransferProtocol").hide();
$("#divAddZoneTsigKeyName").hide();
$("#divAddZoneForwarderProtocol").hide();
$("#divAddZoneForwarder").hide();
$("#divAddZoneForwarderDnssecValidation").hide();
$("#divAddZoneForwarderProxy").hide();
var zoneType = $('input[name=rdAddZoneType]:checked').val();
switch (zoneType) {
case "Primary":
break;
case "Secondary":
$("#divAddZonePrimaryNameServerAddresses").show();
$("#divAddZoneZoneTransferProtocol").show();
$("#divAddZoneTsigKeyName").show();
loadTsigKeyNames($("#optAddZoneTsigKeyName"), null, $("#divAddZoneAlert"));
break;
case "Stub":
$("#divAddZonePrimaryNameServerAddresses").show();
break;
case "Forwarder":
$("#divAddZoneForwarderProtocol").show();
$("#divAddZoneForwarder").show();
$("#divAddZoneForwarderDnssecValidation").show();
$("#divAddZoneForwarderProxy").show();
break;
}
});
$("input[type=radio][name=rdAddZoneForwarderProtocol]").change(function () {
var protocol = $('input[name=rdAddZoneForwarderProtocol]:checked').val();
switch (protocol) {
case "Udp":
case "Tcp":
$("#txtAddZoneForwarder").attr("placeholder", "8.8.8.8 or [2620:fe::10]")
break;
case "Tls":
$("#txtAddZoneForwarder").attr("placeholder", "dns.quad9.net (9.9.9.9:853)")
break;
case "Https":
case "HttpsJson":
$("#txtAddZoneForwarder").attr("placeholder", "https://cloudflare-dns.com/dns-query (1.1.1.1)")
break;
}
});
$("input[type=radio][name=rdAddZoneForwarderProxyType]").change(function () {
var proxyType = $('input[name=rdAddZoneForwarderProxyType]:checked').val();
$("#txtAddZoneForwarderProxyAddress").prop("disabled", (proxyType === "None"));
$("#txtAddZoneForwarderProxyPort").prop("disabled", (proxyType === "None"));
$("#txtAddZoneForwarderProxyUsername").prop("disabled", (proxyType === "None"));
$("#txtAddZoneForwarderProxyPassword").prop("disabled", (proxyType === "None"));
});
$("input[type=radio][name=rdZoneTransfer]").change(function () {
var zoneTransfer = $('input[name=rdZoneTransfer]:checked').val();
switch (zoneTransfer) {
case "AllowOnlySpecifiedNameServers":
case "AllowBothZoneAndSpecifiedNameServers":
$("#txtZoneTransferNameServers").prop("disabled", false);
break;
default:
$("#txtZoneTransferNameServers").prop("disabled", true);
break;
}
});
$("input[type=radio][name=rdZoneNotify]").change(function () {
var zoneNotify = $('input[name=rdZoneNotify]:checked').val();
switch (zoneNotify) {
case "SpecifiedNameServers":
case "BothZoneAndSpecifiedNameServers":
$("#txtZoneNotifyNameServers").prop("disabled", false);
break;
default:
$("#txtZoneNotifyNameServers").prop("disabled", true);
break;
}
});
$("input[type=radio][name=rdDynamicUpdate]").change(function () {
var dynamicUpdate = $('input[name=rdDynamicUpdate]:checked').val();
switch (dynamicUpdate) {
case "AllowOnlySpecifiedIpAddresses":
case "AllowBothZoneNameServersAndSpecifiedIpAddresses":
$("#txtDynamicUpdateIpAddresses").prop("disabled", false);
break;
default:
$("#txtDynamicUpdateIpAddresses").prop("disabled", true);
break;
}
});
$("input[type=radio][name=rdDnssecSignZoneAlgorithm]").change(function () {
var algorithm = $("input[name=rdDnssecSignZoneAlgorithm]:checked").val();
switch (algorithm) {
case "RSA":
$("#divDnssecSignZoneRsaParameters").show();
$("#divDnssecSignZoneEcdsaParameters").hide();
break;
case "ECDSA":
$("#divDnssecSignZoneRsaParameters").hide();
$("#divDnssecSignZoneEcdsaParameters").show();
break;
}
});
$("input[type=radio][name=rdDnssecSignZoneNxProof]").change(function () {
var nxProof = $("input[name=rdDnssecSignZoneNxProof]:checked").val();
switch (nxProof) {
case "NSEC":
$("#divDnssecSignZoneNSEC3Parameters").hide();
break;
case "NSEC3":
$("#divDnssecSignZoneNSEC3Parameters").show();
break;
}
});
$("#optDnssecPropertiesGenerateKeyKeyType").change(function () {
var keyType = $("#optDnssecPropertiesGenerateKeyKeyType").val();
switch (keyType) {
case "ZoneSigningKey":
$("#divDnssecPropertiesGenerateKeyAutomaticRollover").show();
$("#txtDnssecPropertiesGenerateKeyAutomaticRollover").val(90);
break;
default:
$("#divDnssecPropertiesGenerateKeyAutomaticRollover").hide();
$("#txtDnssecPropertiesGenerateKeyAutomaticRollover").val(0);
break;
}
});
$("#optDnssecPropertiesGenerateKeyAlgorithm").change(function () {
var algorithm = $("#optDnssecPropertiesGenerateKeyAlgorithm").val();
switch (algorithm) {
case "RSA":
$("#divDnssecPropertiesGenerateKeyRsaParameters").show();
$("#divDnssecPropertiesGenerateKeyEcdsaParameters").hide();
break;
case "ECDSA":
$("#divDnssecPropertiesGenerateKeyRsaParameters").hide();
$("#divDnssecPropertiesGenerateKeyEcdsaParameters").show();
break;
}
});
$("input[type=radio][name=rdDnssecPropertiesNxProof]").change(function () {
var nxProof = $("input[name=rdDnssecPropertiesNxProof]:checked").val();
switch (nxProof) {
case "NSEC":
$("#divDnssecPropertiesNSEC3Parameters").hide();
break;
case "NSEC3":
$("#divDnssecPropertiesNSEC3Parameters").show();
break;
}
});
$("#chkAddEditRecordDataPtr").click(function () {
var addPtrRecord = $("#chkAddEditRecordDataPtr").prop('checked');
$("#chkAddEditRecordDataCreatePtrZone").prop('disabled', !addPtrRecord);
});
$("input[type=radio][name=rdAddEditRecordDataForwarderProtocol]").change(updateAddEditFormForwarderPlaceholder);
$("input[type=radio][name=rdAddEditRecordDataForwarderProxyType]").change(updateAddEditFormForwarderProxyType);
$("#optAddEditRecordDataAppName").change(function () {
if (appsList == null)
return;
var appName = $("#optAddEditRecordDataAppName").val();
var optClassPaths = "";
for (var i = 0; i < appsList.length; i++) {
if (appsList[i].name == appName) {
for (var j = 0; j < appsList[i].dnsApps.length; j++) {
if (appsList[i].dnsApps[j].isAppRecordRequestHandler)
optClassPaths += "";
}
break;
}
}
$("#optAddEditRecordDataClassPath").html(optClassPaths);
$("#txtAddEditRecordDataData").val("");
});
$("#optAddEditRecordDataClassPath").change(function () {
if (appsList == null)
return;
var appName = $("#optAddEditRecordDataAppName").val();
var classPath = $("#optAddEditRecordDataClassPath").val();
for (var i = 0; i < appsList.length; i++) {
if (appsList[i].name == appName) {
for (var j = 0; j < appsList[i].dnsApps.length; j++) {
if (appsList[i].dnsApps[j].classPath == classPath) {
$("#txtAddEditRecordDataData").val(appsList[i].dnsApps[j].recordDataTemplate);
return;
}
}
}
}
$("#txtAddEditRecordDataData").val("");
});
$("#optZoneOptionsQuickTsigKeyNames").change(function () {
var selectedOption = $("#optZoneOptionsQuickTsigKeyNames").val();
switch (selectedOption) {
case "blank":
break;
case "none":
$("#txtZoneOptionsZoneTransferTsigKeyNames").val("");
break;
default:
var existingList = $("#txtZoneOptionsZoneTransferTsigKeyNames").val();
if (existingList.indexOf(selectedOption) < 0) {
existingList += selectedOption + "\n";
$("#txtZoneOptionsZoneTransferTsigKeyNames").val(existingList);
}
break;
}
});
});
function refreshZones(checkDisplay) {
if (checkDisplay == null)
checkDisplay = false;
var divViewZones = $("#divViewZones");
if (checkDisplay && (divViewZones.css('display') === "none"))
return;
var divViewZonesLoader = $("#divViewZonesLoader");
var divEditZone = $("#divEditZone");
divViewZones.hide();
divEditZone.hide();
divViewZonesLoader.show();
HTTPRequest({
url: "/api/zones/list?token=" + sessionData.token,
success: function (responseJSON) {
var zones = responseJSON.response.zones;
var tableHtmlRows = "";
for (var i = 0; i < zones.length; i++) {
var id = Math.floor(Math.random() * 10000);
var name = zones[i].name;
if (name === "")
name = ".";
var type;
if (zones[i].internal)
type = "Internal";
else
type = "" + zones[i].type + "";
var dnssecStatus = "";
switch (zones[i].dnssecStatus) {
case "SignedWithNSEC":
case "SignedWithNSEC3":
dnssecStatus = "DNSSEC";
break;
}
var status = "";
if (zones[i].disabled)
status = "Disabled";
else if (zones[i].isExpired)
status = "Expired";
else if (zones[i].syncFailed)
status = "Sync Failed";
else if (zones[i].notifyFailed)
status = "Notify Failed";
else
status = "Enabled";
var expiry = zones[i].expiry;
if (expiry == null)
expiry = " ";
else
expiry = moment(expiry).local().format("YYYY-MM-DD HH:mm");
var isReadOnlyZone = zones[i].internal;
var hideOptionsMenu;
switch (zones[i].type) {
case "Primary":
case "Secondary":
hideOptionsMenu = zones[i].internal;
break;
default:
hideOptionsMenu = true;
break;
}
tableHtmlRows += "
";
}
$("#tableZonesBody").html(tableHtmlRows);
if (zones.length > 0)
$("#tableZonesFooter").html("
Total Zones: " + zones.length + "
");
else
$("#tableZonesFooter").html("
No Zones Found
");
divViewZonesLoader.hide();
divViewZones.show();
},
error: function () {
divViewZonesLoader.hide();
divViewZones.show();
},
invalidToken: function () {
showPageLogin();
},
objLoaderPlaceholder: divViewZonesLoader
});
}
function enableZoneMenu(objMenuItem) {
var mnuItem = $(objMenuItem);
var id = mnuItem.attr("data-id");
var zone = mnuItem.attr("data-zone");
var btn = $("#btnZoneRowOption" + id);
var originalBtnHtml = btn.html();
btn.prop("disabled", true);
btn.html("");
HTTPRequest({
url: "/api/zones/enable?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
btn.prop("disabled", false);
btn.html(originalBtnHtml);
$("#mnuEnableZone" + id).hide();
$("#mnuDisableZone" + id).show();
$("#tdZoneStatus" + id).attr("class", "label label-success");
$("#tdZoneStatus" + id).html("Enabled");
showAlert("success", "Zone Enabled!", "Zone '" + zone + "' was enabled successfully.");
},
error: function () {
btn.prop("disabled", false);
btn.html(originalBtnHtml);
},
invalidToken: function () {
showPageLogin();
}
});
}
function enableZone(objBtn) {
var zone = $("#titleEditZone").attr("data-zone");
var btn = $(objBtn);
btn.button('loading');
HTTPRequest({
url: "/api/zones/enable?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
btn.button('reset');
$("#btnEnableZoneEditZone").hide();
$("#btnDisableZoneEditZone").show();
$("#titleStatusEditZone").attr("class", "label label-success");
$("#titleStatusEditZone").html("Enabled");
showAlert("success", "Zone Enabled!", "Zone '" + zone + "' was enabled successfully.");
},
error: function () {
btn.button('reset');
},
invalidToken: function () {
showPageLogin();
}
});
}
function disableZoneMenu(objMenuItem) {
var mnuItem = $(objMenuItem);
var id = mnuItem.attr("data-id");
var zone = mnuItem.attr("data-zone");
if (!confirm("Are you sure you want to disable the zone '" + zone + "'?"))
return;
var btn = $("#btnZoneRowOption" + id);
var originalBtnHtml = btn.html();
btn.prop("disabled", true);
btn.html("");
HTTPRequest({
url: "/api/zones/disable?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
btn.prop("disabled", false);
btn.html(originalBtnHtml);
$("#mnuEnableZone" + id).show();
$("#mnuDisableZone" + id).hide();
$("#tdZoneStatus" + id).attr("class", "label label-warning");
$("#tdZoneStatus" + id).html("Disabled");
showAlert("success", "Zone Disabled!", "Zone '" + zone + "' was disabled successfully.");
},
error: function () {
btn.prop("disabled", false);
btn.html(originalBtnHtml);
},
invalidToken: function () {
showPageLogin();
}
});
}
function disableZone(objBtn) {
var zone = $("#titleEditZone").attr("data-zone");
if (!confirm("Are you sure you want to disable the zone '" + zone + "'?"))
return;
var btn = $(objBtn);
btn.button('loading');
HTTPRequest({
url: "/api/zones/disable?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
btn.button('reset');
$("#btnEnableZoneEditZone").show();
$("#btnDisableZoneEditZone").hide();
$("#titleStatusEditZone").attr("class", "label label-warning");
$("#titleStatusEditZone").html("Disabled");
showAlert("success", "Zone Disabled!", "Zone '" + zone + "' was disabled successfully.");
},
error: function () {
btn.button('reset');
},
invalidToken: function () {
showPageLogin();
}
});
}
function deleteZoneMenu(objMenuItem) {
var mnuItem = $(objMenuItem);
var id = mnuItem.attr("data-id");
var zone = mnuItem.attr("data-zone");
if (!confirm("Are you sure you want to permanently delete the zone '" + zone + "' and all its records?"))
return;
var btn = $("#btnZoneRowOption" + id);
var originalBtnHtml = btn.html();
btn.prop("disabled", true);
btn.html("");
HTTPRequest({
url: "/api/zones/delete?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
$("#trZone" + id).remove();
var totalZones = $('#tableZones >tbody >tr').length;
if (totalZones > 0)
$("#tableZonesFooter").html("
Total Zones: " + totalZones + "
");
else
$("#tableZonesFooter").html("
No Zones Found
");
showAlert("success", "Zone Deleted!", "Zone '" + zone + "' was deleted successfully.");
},
error: function () {
btn.prop("disabled", false);
btn.html(originalBtnHtml);
},
invalidToken: function () {
showPageLogin();
}
});
}
function deleteZone(objBtn) {
var zone = $("#titleEditZone").attr("data-zone");
if (!confirm("Are you sure you want to permanently delete the zone '" + zone + "' and all its records?"))
return;
var btn = $(objBtn);
btn.button('loading');
HTTPRequest({
url: "/api/zones/delete?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
btn.button('reset');
refreshZones();
showAlert("success", "Zone Deleted!", "Zone '" + zone + "' was deleted successfully.");
},
error: function () {
btn.button('reset');
},
invalidToken: function () {
showPageLogin();
}
});
}
function addZoneOptionsDynamicUpdatesSecurityPolicyRow(id, tsigKeyName, domain, allowedTypes) {
var tbodyDynamicUpdateSecurityPolicy = $("#tbodyDynamicUpdateSecurityPolicy");
if (id == null) {
id = Math.floor(Math.random() * 10000);
if (tbodyDynamicUpdateSecurityPolicy.is(":empty")) {
tsigKeyName = null;
domain = $("#lblZoneOptionsZoneName").attr("data-zone");
allowedTypes = 'A,AAAA'.split(',');
}
}
var tableHtmlRow = "
";
tableHtmlRow += "
";
tableHtmlRow += "
";
tableHtmlRow += "
";
tbodyDynamicUpdateSecurityPolicy.append(tableHtmlRow);
}
function showZoneOptionsModal(zone) {
var divZoneOptionsAlert = $("#divZoneOptionsAlert");
var divZoneOptionsLoader = $("#divZoneOptionsLoader");
var divZoneOptions = $("#divZoneOptions");
$("#lblZoneOptionsZoneName").text(zone === "." ? "" : zone);
$("#lblZoneOptionsZoneName").attr("data-zone", zone);
divZoneOptionsLoader.show();
divZoneOptions.hide();
$("#modalZoneOptions").modal("show");
HTTPRequest({
url: "/api/zones/options/get?token=" + sessionData.token + "&zone=" + zone + "&includeAvailableTsigKeyNames=true",
success: function (responseJSON) {
$("#txtZoneTransferNameServers").prop("disabled", true);
$("#txtZoneNotifyNameServers").prop("disabled", true);
$("#txtDynamicUpdateIpAddresses").prop("disabled", true);
//zone transfer
switch (responseJSON.response.zoneTransfer) {
case "Allow":
$("#rdZoneTransferAllow").prop("checked", true);
break;
case "AllowOnlyZoneNameServers":
$("#rdZoneTransferAllowOnlyZoneNameServers").prop("checked", true);
break;
case "AllowOnlySpecifiedNameServers":
$("#rdZoneTransferAllowOnlySpecifiedNameServers").prop("checked", true);
$("#txtZoneTransferNameServers").prop("disabled", false);
break;
case "AllowBothZoneAndSpecifiedNameServers":
$("#rdZoneTransferAllowBothZoneAndSpecifiedNameServers").prop("checked", true);
$("#txtZoneTransferNameServers").prop("disabled", false);
break;
case "Deny":
default:
$("#rdZoneTransferDeny").prop("checked", true);
break;
}
{
var value = "";
for (var i = 0; i < responseJSON.response.zoneTransferNameServers.length; i++)
value += responseJSON.response.zoneTransferNameServers[i] + "\r\n";
$("#txtZoneTransferNameServers").val(value);
}
{
var value = "";
if (responseJSON.response.zoneTransferTsigKeyNames != null) {
for (var i = 0; i < responseJSON.response.zoneTransferTsigKeyNames.length; i++) {
value += responseJSON.response.zoneTransferTsigKeyNames[i] + "\r\n";
}
}
$("#txtZoneOptionsZoneTransferTsigKeyNames").val(value);
}
{
var options = "";
if (responseJSON.response.availableTsigKeyNames != null) {
for (var i = 0; i < responseJSON.response.availableTsigKeyNames.length; i++) {
options += "";
}
}
$("#optZoneOptionsQuickTsigKeyNames").html(options);
}
//notify
switch (responseJSON.response.notify) {
case "ZoneNameServers":
$("#rdZoneNotifyZoneNameServers").prop("checked", true);
break;
case "SpecifiedNameServers":
$("#rdZoneNotifySpecifiedNameServers").prop("checked", true);
$("#txtZoneNotifyNameServers").prop("disabled", false);
break;
case "BothZoneAndSpecifiedNameServers":
$("#rdZoneNotifyBothZoneAndSpecifiedNameServers").prop("checked", true);
$("#txtZoneNotifyNameServers").prop("disabled", false);
break;
case "None":
default:
$("#rdZoneNotifyNone").prop("checked", true);
break;
}
{
var value = "";
for (var i = 0; i < responseJSON.response.notifyNameServers.length; i++)
value += responseJSON.response.notifyNameServers[i] + "\r\n";
$("#txtZoneNotifyNameServers").val(value);
}
if (responseJSON.response.type == "Primary") {
//dynamic update
switch (responseJSON.response.update) {
case "Allow":
$("#rdDynamicUpdateAllow").prop("checked", true);
break;
case "AllowOnlyZoneNameServers":
$("#rdDynamicUpdateAllowOnlyZoneNameServers").prop("checked", true);
break;
case "AllowOnlySpecifiedIpAddresses":
$("#rdDynamicUpdateAllowOnlySpecifiedIpAddresses").prop("checked", true);
$("#txtDynamicUpdateIpAddresses").prop("disabled", false);
break;
case "AllowBothZoneNameServersAndSpecifiedIpAddresses":
$("#rdDynamicUpdateAllowBothZoneNameServersAndSpecifiedIpAddresses").prop("checked", true);
$("#txtDynamicUpdateIpAddresses").prop("disabled", false);
break;
case "Deny":
default:
$("#rdDynamicUpdateDeny").prop("checked", true);
break;
}
{
var value = "";
for (var i = 0; i < responseJSON.response.updateIpAddresses.length; i++)
value += responseJSON.response.updateIpAddresses[i] + "\r\n";
$("#txtDynamicUpdateIpAddresses").val(value);
}
{
$("#tbodyDynamicUpdateSecurityPolicy").html("");
zoneOptionsAvailableTsigKeyNames = responseJSON.response.availableTsigKeyNames;
if (responseJSON.response.updateSecurityPolicies != null) {
for (var i = 0; i < responseJSON.response.updateSecurityPolicies.length; i++)
addZoneOptionsDynamicUpdatesSecurityPolicyRow(i, responseJSON.response.updateSecurityPolicies[i].tsigKeyName, responseJSON.response.updateSecurityPolicies[i].domain, responseJSON.response.updateSecurityPolicies[i].allowedTypes);
}
}
$("#tabListZoneOptionsUpdate").show();
}
else {
$("#tabListZoneOptionsUpdate").hide();
$("#rdDynamicUpdateDeny").prop("checked", true);
$("#txtDynamicUpdateIpAddresses").val("");
$("#tbodyDynamicUpdateSecurityPolicy").html("");
}
$("#tabListZoneOptionsZoneTranfer").addClass("active");
$("#tabPaneZoneOptionsZoneTransfer").addClass("active");
$("#tabListZoneOptionsNotify").removeClass("active");
$("#tabPaneZoneOptionsNotify").removeClass("active");
$("#tabListZoneOptionsUpdate").removeClass("active");
$("#tabPaneZoneOptionsUpdate").removeClass("active");
divZoneOptionsLoader.hide();
divZoneOptions.show();
},
error: function () {
divZoneOptionsLoader.hide();
},
invalidToken: function () {
$("#modalZoneOptions").modal("hide");
showPageLogin();
},
objAlertPlaceholder: divZoneOptionsAlert,
objLoaderPlaceholder: divZoneOptionsLoader
});
}
function saveZoneOptions() {
var divZoneOptionsAlert = $("#divZoneOptionsAlert");
var divZoneOptionsLoader = $("#divZoneOptionsLoader");
var zone = $("#lblZoneOptionsZoneName").attr("data-zone");
//zone transfer
var zoneTransfer = $("input[name=rdZoneTransfer]:checked").val();
var zoneTransferNameServers = cleanTextList($("#txtZoneTransferNameServers").val());
if ((zoneTransferNameServers.length === 0) || (zoneTransferNameServers === ","))
zoneTransferNameServers = false;
else
$("#txtZoneTransferNameServers").val(zoneTransferNameServers.replace(/,/g, "\n"));
var zoneTransferTsigKeyNames = cleanTextList($("#txtZoneOptionsZoneTransferTsigKeyNames").val());
if ((zoneTransferTsigKeyNames.length === 0) || (zoneTransferTsigKeyNames === ","))
zoneTransferTsigKeyNames = false;
else
$("#txtZoneOptionsZoneTransferTsigKeyNames").val(zoneTransferTsigKeyNames.replace(/,/g, "\n"));
//notify
var notify = $("input[name=rdZoneNotify]:checked").val();
var notifyNameServers = cleanTextList($("#txtZoneNotifyNameServers").val());
if ((notifyNameServers.length === 0) || (notifyNameServers === ","))
notifyNameServers = false;
else
$("#txtZoneNotifyNameServers").val(notifyNameServers.replace(/,/g, "\n"));
//dynamic update
var update = $("input[name=rdDynamicUpdate]:checked").val();
var updateIpAddresses = cleanTextList($("#txtDynamicUpdateIpAddresses").val());
if ((updateIpAddresses.length === 0) || (updateIpAddresses === ","))
updateIpAddresses = false;
else
$("#txtDynamicUpdateIpAddresses").val(updateIpAddresses.replace(/,/g, "\n"));
var updateSecurityPolicies = serializeTableData($("#tableDynamicUpdateSecurityPolicy"), 3, divZoneOptionsAlert);
if (updateSecurityPolicies === false)
return;
if (updateSecurityPolicies.length === 0)
updateSecurityPolicies = false;
var btn = $("#btnSaveZoneOptions");
btn.button('loading');
HTTPRequest({
url: "/api/zones/options/set?token=" + sessionData.token + "&zone=" + zone
+ "&zoneTransfer=" + zoneTransfer + "&zoneTransferNameServers=" + encodeURIComponent(zoneTransferNameServers) + "&zoneTransferTsigKeyNames=" + encodeURIComponent(zoneTransferTsigKeyNames)
+ "¬ify=" + notify + "¬ifyNameServers=" + encodeURIComponent(notifyNameServers)
+ "&update=" + update + "&updateIpAddresses=" + encodeURIComponent(updateIpAddresses) + "&updateSecurityPolicies=" + encodeURIComponent(updateSecurityPolicies),
success: function (responseJSON) {
btn.button('reset');
$("#modalZoneOptions").modal("hide");
showAlert("success", "Options Saved!", "Zone options were saved successfully.");
},
error: function () {
btn.button('reset');
divZoneOptionsLoader.hide();
},
invalidToken: function () {
btn.button('reset');
$("#modalZoneOptions").modal("hide");
showPageLogin();
},
objAlertPlaceholder: divZoneOptionsAlert,
objLoaderPlaceholder: divZoneOptionsLoader
});
}
function showZonePermissionsModal(zone) {
var divEditPermissionsAlert = $("#divEditPermissionsAlert");
var divEditPermissionsLoader = $("#divEditPermissionsLoader");
var divEditPermissionsViewer = $("#divEditPermissionsViewer");
$("#lblEditPermissionsName").text("Zones / " + (zone === "." ? "" : zone));
$("#tbodyEditPermissionsUser").html("");
$("#tbodyEditPermissionsGroup").html("");
divEditPermissionsLoader.show();
divEditPermissionsViewer.hide();
var btnEditPermissionsSave = $("#btnEditPermissionsSave");
btnEditPermissionsSave.attr("onclick", "saveZonePermissions(this); return false;");
btnEditPermissionsSave.show();
var modalEditPermissions = $("#modalEditPermissions");
modalEditPermissions.modal("show");
HTTPRequest({
url: "/api/zones/permissions/get?token=" + sessionData.token + "&zone=" + htmlEncode(zone) + "&includeUsersAndGroups=true",
success: function (responseJSON) {
$("#lblEditPermissionsName").text(responseJSON.response.section + " / " + (responseJSON.response.subItem == "." ? "" : responseJSON.response.subItem));
//user permissions
for (var i = 0; i < responseJSON.response.userPermissions.length; i++) {
addEditPermissionUserRow(i, responseJSON.response.userPermissions[i].username, responseJSON.response.userPermissions[i].canView, responseJSON.response.userPermissions[i].canModify, responseJSON.response.userPermissions[i].canDelete);
}
//load users list
var userListHtml = "";
for (var i = 0; i < responseJSON.response.users.length; i++) {
userListHtml += "";
}
$("#optEditPermissionsUserList").html(userListHtml);
//group permissions
for (var i = 0; i < responseJSON.response.groupPermissions.length; i++) {
addEditPermissionGroupRow(i, responseJSON.response.groupPermissions[i].name, responseJSON.response.groupPermissions[i].canView, responseJSON.response.groupPermissions[i].canModify, responseJSON.response.groupPermissions[i].canDelete);
}
//load groups list
var groupListHtml = "";
for (var i = 0; i < responseJSON.response.groups.length; i++) {
groupListHtml += "";
}
$("#optEditPermissionsGroupList").html(groupListHtml);
btnEditPermissionsSave.attr("data-zone", responseJSON.response.subItem);
divEditPermissionsLoader.hide();
divEditPermissionsViewer.show();
},
error: function () {
divEditPermissionsLoader.hide();
},
invalidToken: function () {
modalEditPermissions.modal("hide");
showPageLogin();
},
objAlertPlaceholder: divEditPermissionsAlert,
objLoaderPlaceholder: divEditPermissionsLoader
});
}
function saveZonePermissions(objBtn) {
var btn = $(objBtn);
var divEditPermissionsAlert = $("#divEditPermissionsAlert");
var zone = btn.attr("data-zone");
var userPermissions = serializeTableData($("#tableEditPermissionsUser"), 4);
var groupPermissions = serializeTableData($("#tableEditPermissionsGroup"), 4);
var apiUrl = "/api/zones/permissions/set?token=" + sessionData.token + "&zone=" + encodeURIComponent(zone) + "&userPermissions=" + encodeURIComponent(userPermissions) + "&groupPermissions=" + encodeURIComponent(groupPermissions);
btn.button('loading');
HTTPRequest({
url: apiUrl,
success: function (responseJSON) {
btn.button('reset');
$("#modalEditPermissions").modal("hide");
showAlert("success", "Permissions Saved!", "Zone permissions were saved successfully.");
},
error: function () {
btn.button('reset');
},
invalidToken: function () {
btn.button('reset');
$("#modalEditPermissions").modal("hide");
showPageLogin();
},
objAlertPlaceholder: divEditPermissionsAlert
});
}
function resyncZone(objBtn, zone) {
if ($("#titleEditZoneType").text() == "Secondary") {
if (!confirm("The resync action will perform a full zone transfer (AXFR). You will need to check the logs to confirm if the resync action was successful.\r\n\r\nAre you sure you want to resync the '" + zone + "' zone?"))
return;
}
else {
if (!confirm("The resync action will perform a full zone refresh. You will need to check the logs to confirm if the resync action was successful.\r\n\r\nAre you sure you want to resync the '" + zone + "' zone?"))
return;
}
var btn = $(objBtn);
btn.button('loading');
HTTPRequest({
url: "/api/zones/resync?token=" + sessionData.token + "&zone=" + zone,
success: function (responseJSON) {
btn.button('reset');
showAlert("success", "Resync Triggered!", "Zone '" + zone + "' resync was triggered successfully. Please check the Logs for confirmation.");
},
error: function () {
btn.button('reset');
},
invalidToken: function () {
btn.button('reset');
showPageLogin();
}
});
}
function showAddZoneModal() {
$("#divAddZoneAlert").html("");
$("#txtAddZone").val("");
$("#rdAddZoneTypePrimary").prop("checked", true);
$("#txtAddZonePrimaryNameServerAddresses").val("");
$("#rdAddZoneZoneTransferProtocolTcp").prop("checked", true);
$("#optAddZoneTsigKeyName").val("");
$("input[name=rdAddZoneForwarderProtocol]:radio").attr("disabled", false);
$("#rdAddZoneForwarderProtocolUdp").prop("checked", true);
$("#chkAddZoneForwarderThisServer").prop("checked", false);
$("#txtAddZoneForwarder").prop("disabled", false);
$("#txtAddZoneForwarder").attr("placeholder", "8.8.8.8 or [2620:fe::10]")
$("#txtAddZoneForwarder").val("");
$("#chkAddZoneForwarderDnssecValidation").prop("checked", $("#chkDnssecValidation").prop("checked"));
$("#rdAddZoneForwarderProxyTypeNone").prop("checked", true);
$("#txtAddZoneForwarderProxyAddress").prop("disabled", true);
$("#txtAddZoneForwarderProxyPort").prop("disabled", true);
$("#txtAddZoneForwarderProxyUsername").prop("disabled", true);
$("#txtAddZoneForwarderProxyPassword").prop("disabled", true);
$("#txtAddZoneForwarderProxyAddress").val("");
$("#txtAddZoneForwarderProxyPort").val("");
$("#txtAddZoneForwarderProxyUsername").val("");
$("#txtAddZoneForwarderProxyPassword").val("");
$("#divAddZonePrimaryNameServerAddresses").hide();
$("#divAddZoneZoneTransferProtocol").hide();
$("#divAddZoneTsigKeyName").hide();
$("#divAddZoneForwarderProtocol").hide();
$("#divAddZoneForwarder").hide();
$("#divAddZoneForwarderDnssecValidation").hide();
$("#divAddZoneForwarderProxy").hide();
$("#btnAddZone").button('reset');
$("#modalAddZone").modal("show");
setTimeout(function () {
$("#txtAddZone").focus();
}, 1000);
}
function loadTsigKeyNames(jqDropDown, currentValue, divAlertPlaceholder) {
jqDropDown.prop("disabled", true);
if (currentValue == null)
currentValue = "";
if (currentValue.length == 0) {
jqDropDown.html("");
}
else {
jqDropDown.html("");
jqDropDown.val(currentValue);
}
HTTPRequest({
url: "/api/settings/getTsigKeyNames?token=" + sessionData.token,
success: function (responseJSON) {
var optionsHtml;
if (currentValue.length == 0)
optionsHtml = "";
else
optionsHtml = "";
for (var i = 0; i < responseJSON.response.tsigKeyNames.length; i++) {
optionsHtml += "";
}
jqDropDown.html(optionsHtml);
jqDropDown.prop("disabled", false);
},
error: function () {
jqDropDown.prop("disabled", false);
},
invalidToken: function () {
jqDropDown.prop("disabled", false);
showPageLogin();
},
objAlertPlaceholder: divAlertPlaceholder
});
}
function updateAddZoneFormForwarderThisServer() {
var useThisServer = $("#chkAddZoneForwarderThisServer").prop('checked');
if (useThisServer) {
$("input[name=rdAddZoneForwarderProtocol]:radio").attr("disabled", true);
$("#rdAddZoneForwarderProtocolUdp").prop("checked", true);
$("#txtAddZoneForwarder").attr("placeholder", "8.8.8.8 or [2620:fe::10]")
$("#txtAddZoneForwarder").prop("disabled", true);
$("#txtAddZoneForwarder").val("this-server");
$("#divAddZoneForwarderProxy").hide();
}
else {
$("input[name=rdAddZoneForwarderProtocol]:radio").attr("disabled", false);
$("#txtAddZoneForwarder").prop("disabled", false);
$("#txtAddZoneForwarder").val("");
$("#divAddZoneForwarderProxy").show();
}
}
function addZone() {
var divAddZoneAlert = $("#divAddZoneAlert");
var zone = $("#txtAddZone").val();
if ((zone == null) || (zone === "")) {
showAlert("warning", "Missing!", "Please enter a domain name to add zone.", divAddZoneAlert);
$("#txtAddZone").focus();
return;
}
var type = $('input[name=rdAddZoneType]:checked').val();
var parameters;
switch (type) {
case "Secondary":
var tsigKeyName = $("#optAddZoneTsigKeyName").val();
parameters = "&primaryNameServerAddresses=" + encodeURIComponent(cleanTextList($("#txtAddZonePrimaryNameServerAddresses").val()));
parameters += "&zoneTransferProtocol=" + $("input[name=rdAddZoneZoneTransferProtocol]:checked").val();
parameters += "&tsigKeyName=" + encodeURIComponent(tsigKeyName);
break;
case "Stub":
parameters = "&primaryNameServerAddresses=" + encodeURIComponent(cleanTextList($("#txtAddZonePrimaryNameServerAddresses").val()));
break;
case "Forwarder":
var forwarder = $("#txtAddZoneForwarder").val();
if ((forwarder == null) || (forwarder === "")) {
showAlert("warning", "Missing!", "Please enter a forwarder server name to add zone.", divAddZoneAlert);
$("#txtAddZoneForwarder").focus();
return;
}
var dnssecValidation = $("#chkAddZoneForwarderDnssecValidation").prop("checked");
parameters = "&protocol=" + $("input[name=rdAddZoneForwarderProtocol]:checked").val() + "&forwarder=" + encodeURIComponent(forwarder) + "&dnssecValidation=" + dnssecValidation;
if (forwarder !== "this-server") {
var proxyType = $("input[name=rdAddZoneForwarderProxyType]:checked").val();
parameters += "&proxyType=" + proxyType;
if (proxyType != "None") {
var proxyAddress = $("#txtAddZoneForwarderProxyAddress").val();
var proxyPort = $("#txtAddZoneForwarderProxyPort").val();
var proxyUsername = $("#txtAddZoneForwarderProxyUsername").val();
var proxyPassword = $("#txtAddZoneForwarderProxyPassword").val();
if ((proxyAddress == null) || (proxyAddress === "")) {
showAlert("warning", "Missing!", "Please enter a domain name or IP address for Proxy Server Address to add zone.", divAddZoneAlert);
$("#txtAddZoneForwarderProxyAddress").focus();
return;
}
if ((proxyPort == null) || (proxyPort === "")) {
showAlert("warning", "Missing!", "Please enter a port number for Proxy Server Port to add zone.", divAddZoneAlert);
$("#txtAddZoneForwarderProxyPort").focus();
return;
}
parameters += "&proxyAddress=" + encodeURIComponent(proxyAddress) + "&proxyPort=" + proxyPort + "&proxyUsername=" + encodeURIComponent(proxyUsername) + "&proxyPassword=" + encodeURIComponent(proxyPassword);
}
}
break;
default:
parameters = "";
break;
}
var btn = $("#btnAddZone").button('loading');
HTTPRequest({
url: "/api/zones/create?token=" + sessionData.token + "&zone=" + zone + "&type=" + type + parameters,
success: function (responseJSON) {
$("#modalAddZone").modal("hide");
showEditZone(responseJSON.response.domain);
showAlert("success", "Zone Added!", "Zone was added successfully.");
},
error: function () {
btn.button('reset');
},
invalidToken: function () {
$("#modalAddZone").modal("hide");
showPageLogin();
},
objAlertPlaceholder: divAddZoneAlert
});
}
function toggleHideDnssecRecords(hideDnssecRecords) {
localStorage.setItem("zoneHideDnssecRecords", hideDnssecRecords);
showEditZone($("#titleEditZone").attr("data-zone"));
}
function showEditZone(zone) {
var divViewZonesLoader = $("#divViewZonesLoader");
var divViewZones = $("#divViewZones");
var divEditZone = $("#divEditZone");
divViewZones.hide();
divEditZone.hide();
divViewZonesLoader.show();
HTTPRequest({
url: "/api/zones/records/get?token=" + sessionData.token + "&domain=" + zone,
success: function (responseJSON) {
var zoneType;
if (responseJSON.response.zone.internal)
zoneType = "Internal";
else
zoneType = responseJSON.response.zone.type;
switch (responseJSON.response.zone.dnssecStatus) {
case "SignedWithNSEC":
case "SignedWithNSEC3":
$("#titleDnssecStatusEditZone").show();
break;
default:
$("#titleDnssecStatusEditZone").hide();
break;
}
var status;
if (responseJSON.response.zone.disabled)
status = "Disabled";
else if (responseJSON.response.zone.isExpired)
status = "Expired";
else if (responseJSON.response.zone.syncFailed)
status = "Sync Failed";
else if (responseJSON.response.zone.notifyFailed)
status = "Notify Failed";
else
status = "Enabled";
var expiry = responseJSON.response.zone.expiry;
if (expiry == null)
expiry = " ";
else
expiry = "Expiry: " + moment(expiry).local().format("YYYY-MM-DD HH:mm:ss");
$("#titleEditZoneType").html(zoneType);
$("#titleStatusEditZone").html(status);
$("#titleEditZoneExpiry").html(expiry);
if (responseJSON.response.zone.internal)
$("#titleEditZoneType").attr("class", "label label-default");
else
$("#titleEditZoneType").attr("class", "label label-primary");
switch (status) {
case "Disabled":
case "Sync Failed":
case "Notify Failed":
$("#titleStatusEditZone").attr("class", "label label-warning");
break;
case "Expired":
$("#titleStatusEditZone").attr("class", "label label-danger");
break;
case "Enabled":
$("#titleStatusEditZone").attr("class", "label label-success");
break;
}
switch (zoneType) {
case "Internal":
case "Secondary":
case "Stub":
$("#btnEditZoneAddRecord").hide();
break;
case "Forwarder":
$("#btnEditZoneAddRecord").show();
$("#optAddEditRecordTypeDs").hide();
$("#optAddEditRecordTypeSshfp").hide();
$("#optAddEditRecordTypeTlsa").hide();
$("#optAddEditRecordTypeAName").show();
$("#optAddEditRecordTypeFwd").show();
$("#optAddEditRecordTypeApp").show();
break;
case "Primary":
$("#btnEditZoneAddRecord").show();
$("#optAddEditRecordTypeFwd").hide();
switch (responseJSON.response.zone.dnssecStatus) {
case "SignedWithNSEC":
case "SignedWithNSEC3":
$("#optAddEditRecordTypeDs").show();
$("#optAddEditRecordTypeSshfp").show();
$("#optAddEditRecordTypeTlsa").show();
$("#optAddEditRecordTypeAName").hide();
$("#optAddEditRecordTypeApp").hide();
break;
default:
$("#optAddEditRecordTypeDs").hide();
$("#optAddEditRecordTypeSshfp").hide();
$("#optAddEditRecordTypeTlsa").hide();
$("#optAddEditRecordTypeAName").show();
$("#optAddEditRecordTypeApp").show();
break;
}
break;
}
if (responseJSON.response.zone.internal) {
$("#btnEnableZoneEditZone").hide();
$("#btnDisableZoneEditZone").hide();
$("#btnEditZoneDeleteZone").hide();
}
else if (responseJSON.response.zone.disabled) {
$("#btnEnableZoneEditZone").show();
$("#btnDisableZoneEditZone").hide();
$("#btnEditZoneDeleteZone").show();
}
else {
$("#btnEnableZoneEditZone").hide();
$("#btnDisableZoneEditZone").show();
$("#btnEditZoneDeleteZone").show();
}
switch (zoneType) {
case "Secondary":
case "Stub":
$("#btnZoneResync").show();
break;
default:
$("#btnZoneResync").hide();
break;
}
switch (zoneType) {
case "Primary":
case "Secondary":
$("#btnZoneOptions").show();
break;
default:
$("#btnZoneOptions").hide();
break;
}
switch (zoneType) {
case "Primary":
case "Secondary":
case "Stub":
case "Forwarder":
$("#btnZonePermissions").show();
break;
default:
$("#btnZonePermissions").hide();
break;
}
var zoneHideDnssecRecords = (localStorage.getItem("zoneHideDnssecRecords") == "true");
switch (zoneType) {
case "Primary":
$("#divZoneDnssecOptions").show();
switch (responseJSON.response.zone.dnssecStatus) {
case "SignedWithNSEC":
case "SignedWithNSEC3":
$("#lnkZoneDnssecSignZone").hide();
if (zoneHideDnssecRecords) {
$("#lnkZoneDnssecHideRecords").hide();
$("#lnkZoneDnssecShowRecords").show();
}
else {
$("#lnkZoneDnssecHideRecords").show();
$("#lnkZoneDnssecShowRecords").hide();
}
$("#lnkZoneDnssecProperties").show();
$("#lnkZoneDnssecUnsignZone").show();
break;
default:
$("#lnkZoneDnssecSignZone").show();
$("#lnkZoneDnssecHideRecords").hide();
$("#lnkZoneDnssecShowRecords").hide();
$("#lnkZoneDnssecProperties").hide();
$("#lnkZoneDnssecUnsignZone").hide();
break;
}
break;
case "Secondary":
switch (responseJSON.response.zone.dnssecStatus) {
case "SignedWithNSEC":
case "SignedWithNSEC3":
$("#divZoneDnssecOptions").show();
$("#lnkZoneDnssecSignZone").hide();
if (zoneHideDnssecRecords) {
$("#lnkZoneDnssecHideRecords").hide();
$("#lnkZoneDnssecShowRecords").show();
}
else {
$("#lnkZoneDnssecHideRecords").show();
$("#lnkZoneDnssecShowRecords").hide();
}
$("#lnkZoneDnssecProperties").hide();
$("#lnkZoneDnssecUnsignZone").hide();
break;
default:
$("#divZoneDnssecOptions").hide();
break;
}
break;
default:
$("#divZoneDnssecOptions").hide();
break;
}
var records = responseJSON.response.records;
var tableHtmlRows = "";
var recordCount = 0;
for (var i = 0; i < records.length; i++) {
if (zoneHideDnssecRecords) {
switch (records[i].type.toUpperCase()) {
case "RRSIG":
case "NSEC":
case "DNSKEY":
case "NSEC3":
case "NSEC3PARAM":
continue;
}
}
recordCount++;
tableHtmlRows += getZoneRecordRowHtml(i, zone, zoneType, records[i]);
}
$("#titleEditZone").text(zone === "." ? "" : zone);
$("#titleEditZone").attr("data-zone", zone);
$("#tableEditZoneBody").html(tableHtmlRows);
if (recordCount > 0)
$("#tableEditZoneFooter").html("
Total Records: " + recordCount + "
");
else
$("#tableEditZoneFooter").html("
No Records Found
");
divViewZonesLoader.hide();
divEditZone.show();
},
error: function () {
divViewZonesLoader.hide();
divViewZones.show();
},
invalidToken: function () {
showPageLogin();
},
objLoaderPlaceholder: divViewZonesLoader
});
}
function getZoneRecordRowHtml(id, zone, zoneType, record) {
var name = record.name.toLowerCase();
if (name === "")
name = ".";
if (name === zone)
name = "@";
else
name = name.replace("." + zone, "");
var tableHtmlRow = "
" + htmlEncode(name) + "
";
tableHtmlRow += "
" + record.type + "
";
tableHtmlRow += "
" + record.ttl + "
";
var lastUsedOn;
if (record.lastUsedOn == "0001-01-01T00:00:00")
lastUsedOn = moment(record.lastUsedOn).local().format("YYYY-MM-DD HH:mm:ss") + " (never)";
else
lastUsedOn = moment(record.lastUsedOn).local().format("YYYY-MM-DD HH:mm:ss") + " (" + moment(record.lastUsedOn).fromNow() + ")";
var additionalDataAttributes = "";
switch (record.type.toUpperCase()) {
case "A":
case "AAAA":
tableHtmlRow += "