- Added csrf middleware to management portal mux
- Added csrf token to all html templates
- Added csrf validation to all endpoints
- Optimized some old endpoints implementation
This commit is contained in:
Toby Chui
2024-07-24 21:58:44 +08:00
parent b1c5bc2963
commit f595da92a1
45 changed files with 535 additions and 307 deletions

View File

@@ -1000,7 +1000,7 @@
*/
function enableBlacklist() {
var isChecked = $('#enableBlacklist').is(':checked');
$.ajax({
$.cjax({
type: 'POST',
url: '/api/blacklist/enable',
data: { enable: isChecked, id: currentEditingAccessRule},
@@ -1028,9 +1028,10 @@
let counter = 0;
for(var i = 0; i < ccs.length; i++){
let thisCountryCode = ccs[i];
$.ajax({
$.cjax({
type: "POST",
url: "/api/blacklist/country/add",
method: "POST",
data: { cc: thisCountryCode, id: currentEditingAccessRule},
success: function(response) {
if (response.error != undefined){
@@ -1066,7 +1067,7 @@
function removeFromBannedList(countryCode){
countryCode = countryCode.toLowerCase();
let countryName = getCountryName(countryCode);
$.ajax({
$.cjax({
url: "/api/blacklist/country/remove",
method: "POST",
data: { cc: countryCode, id: currentEditingAccessRule},
@@ -1097,7 +1098,7 @@
}
}
$.ajax({
$.cjax({
url: "/api/blacklist/ip/add",
type: "POST",
data: {ip: targetIp.toLowerCase(), id: currentEditingAccessRule},
@@ -1119,7 +1120,7 @@
function removeIpBlacklist(ipaddr){
if (confirm("Confirm remove blacklist for " + ipaddr + " ?")){
$.ajax({
$.cjax({
url: "/api/blacklist/ip/remove",
type: "POST",
data: {ip: ipaddr.toLowerCase(), id: currentEditingAccessRule},
@@ -1143,7 +1144,7 @@
*/
function enableWhitelist() {
var isChecked = $('#enableWhitelist').is(':checked');
$.ajax({
$.cjax({
type: 'POST',
url: '/api/whitelist/enable',
data: { enable: isChecked , id: currentEditingAccessRule},
@@ -1165,7 +1166,7 @@
let counter = 0;
for(var i = 0; i < ccs.length; i++){
let thisCountryCode = ccs[i];
$.ajax({
$.cjax({
type: "POST",
url: "/api/whitelist/country/add",
data: { cc: thisCountryCode , id: currentEditingAccessRule},
@@ -1199,7 +1200,7 @@
function removeFromWhiteList(countryCode){
if (confirm("Confirm removing " + getCountryName(countryCode) + " from whitelist?")){
countryCode = countryCode.toLowerCase();
$.ajax({
$.cjax({
url: "/api/whitelist/country/remove",
method: "POST",
data: { cc: countryCode , id: currentEditingAccessRule},
@@ -1230,7 +1231,7 @@
}
}
$.ajax({
$.cjax({
url: "/api/whitelist/ip/add",
type: "POST",
data: {ip: targetIp.toLowerCase(), "comment": remarks, id: currentEditingAccessRule},
@@ -1253,7 +1254,7 @@
function removeIpWhitelist(ipaddr){
if (confirm("Confirm remove whitelist for " + ipaddr + " ?")){
$.ajax({
$.cjax({
url: "/api/whitelist/ip/remove",
type: "POST",
data: {ip: ipaddr.toLowerCase(), id: currentEditingAccessRule},

View File

@@ -257,7 +257,7 @@
//Delete the certificate by its domain
function deleteCertificate(domain){
if (confirm("Confirm delete certificate for " + domain + " ?")){
$.ajax({
$.cjax({
url: "/api/cert/delete",
method: "POST",
data: {domain: domain},
@@ -316,7 +316,7 @@
return;
}
$.ajax({
$.cjax({
url: "/api/acme/autoRenew/email",
method: "POST",
data: {"set": newDefaultEmail},
@@ -330,7 +330,7 @@
}
});
$.ajax({
$.cjax({
url: "/api/acme/autoRenew/ca",
data: {"set": newDefaultCA},
method: "POST",

View File

@@ -87,7 +87,7 @@
}
function addGANet() {
$.ajax({
$.cjax({
url: "/api/gan/network/add",
type: "POST",
dataType: "json",
@@ -191,7 +191,7 @@
//Remove the given GANet
function removeGANet(netid){
if (confirm("Confirm remove Network " + netid + " PERMANENTLY ?"))
$.ajax({
$.cjax({
url: "/api/gan/network/remove",
type: "POST",
dataType: "json",

View File

@@ -214,7 +214,7 @@
//Get CIDR from selected range group
var cidr = $(".iprange.active").attr("cidr");
$.ajax({
$.cjax({
url: "/api/gan/network/setRange",
metohd: "POST",
data:{
@@ -240,7 +240,7 @@
if (object != undefined){
$(object).addClass("loading");
}
$.ajax({
$.cjax({
url: "/api/gan/network/name",
method: "POST",
data: {
@@ -287,7 +287,7 @@
//Handle delete IP from memeber
function deleteIpFromMemeber(memberid, ip){
$.ajax({
$.cjax({
url: "/api/gan/members/ip",
metohd: "POST",
data: {
@@ -334,7 +334,7 @@
return
}
$.ajax({
$.cjax({
url: "/api/gan/members/ip",
metohd: "POST",
data: {
@@ -461,7 +461,7 @@
$(".memberName").each(function(){
let addr = $(this).attr("addr");
let targetDOM = $(this);
$.ajax({
$.cjax({
url: "/api/gan/members/name",
method: "POST",
data: {
@@ -487,7 +487,7 @@
let newname = prompt("Enter a easy manageable name for " + targetMemberAddr, "");
if (newname != null && newname.trim() != "") {
$.ajax({
$.cjax({
url: "/api/gan/members/name",
method: "POST",
data: {
@@ -553,7 +553,7 @@
function handleMemberAuth(object){
let targetMemberAddr = $(object).attr("addr");
let isAuthed = object.checked;
$.ajax({
$.cjax({
url: "/api/gan/members/authorize",
method: "POST",
data: {
@@ -580,7 +580,7 @@
function handleMemberDelete(addr){
if (confirm("Confirm delete member " + addr + " ?")){
$.ajax({
$.cjax({
url: "/api/gan/members/delete",
method: "POST",
data: {
@@ -605,7 +605,7 @@
$(".addControllerToNetworkBtn").addClass("disabled");
$(".addControllerToNetworkBtn").addClass("loading");
$.ajax({
$.cjax({
url: "/api/gan/network/join",
method: "POST",
data: {
@@ -630,7 +630,7 @@
$(".removeControllerFromNetworkBtn").addClass("disabled");
$(".removeControllerFromNetworkBtn").addClass("loading");
$.ajax({
$.cjax({
url: "/api/gan/network/leave",
method: "POST",
data: {

View File

@@ -400,7 +400,7 @@
let rateLimit = $(row).find(".RateLimit").val();
let bypassGlobalTLS = $(row).find(".BypassGlobalTLS")[0].checked;
$.ajax({
$.cjax({
url: "/api/proxy/edit",
method: "POST",
data: {
@@ -422,6 +422,28 @@
}
})
}
//Generic functions for delete rp endpoints
function deleteEndpoint(epoint){
epoint = decodeURIComponent(epoint).hexDecode();
if (confirm("Confirm remove proxy for :" + epoint + "?")){
$.cjax({
url: "/api/proxy/del",
method: "POST",
data: {ep: epoint},
success: function(data){
if (data.error == undefined){
listProxyEndpoints();
msgbox("Proxy Rule Deleted", true);
reloadUptimeList();
}else{
msgbox(data.error, false);
}
}
})
}
}
/* button events */
function editBasicAuthCredentials(uuid){
@@ -474,7 +496,7 @@
function handleProxyRuleToggle(object){
let endpointUUID = $(object).attr("eptuuid");
let isChecked = object.checked;
$.ajax({
$.cjax({
url: "/api/proxy/toggle",
data: {
"ep": endpointUUID,

View File

@@ -339,7 +339,7 @@ function setWoLAddress() {
$("#wol_mac").parent().removeClass("error");
}
$.ajax({
$.cjax({
url: wake_on_lan_API,
type: "POST",
data: {
@@ -363,7 +363,7 @@ function setWoLAddress() {
function delWoLAddr(mac, name) {
if (confirm(`Confirm remove WoL record for ${name} (${mac}) ?`)){
$.ajax({
$.cjax({
url: wake_on_lan_API,
type: "POST",
data: {
@@ -385,7 +385,7 @@ function wakeWoL(mac, object=undefined) {
if (object != undefined){
$(object).addClass("loading").addClass("disabled");
}
$.ajax({
$.cjax({
url: wake_on_lan_API,
type: "POST",
data: {
@@ -594,7 +594,7 @@ function initForwardProxyInfo(){
initForwardProxyInfo();
function toggleForwadProxy(enabled){
$.ajax({
$.cjax({
url: "/api/tools/fwdproxy/enable",
method: "POST",
data: {
@@ -620,7 +620,7 @@ function updateForwardProxyPort(){
$("#newPortNumber").parent().removeClass('error');
}
$.ajax({
$.cjax({
url: "/api/tools/fwdproxy/port",
method: "POST",
data: {

View File

@@ -116,7 +116,7 @@
let forwardChildpath = document.querySelector('input[name="forward-childpath"]').checked;
let redirectType = document.querySelector('input[name="redirect-type"]:checked').value;
$.ajax({
$.cjax({
url: "/api/redirect/add",
method: "POST",
data: {
@@ -141,7 +141,7 @@
let targetURL = $(obj).attr("rurl");
targetURL = JSON.parse(decodeURIComponent(targetURL));
if (confirm("Confirm remove redirection from " + targetURL + " ?")){
$.ajax({
$.cjax({
url: "/api/redirect/delete",
method: "POST",
data: {
@@ -191,8 +191,9 @@
//Bind event to the checkbox
$("#redirectRegex").on("change", function(){
$.ajax({
$.cjax({
url: "/api/redirect/regex",
method: "POST",
data: {"enable": $(this)[0].checked},
success: function(data){
if (data.error != undefined){

View File

@@ -181,8 +181,9 @@
targetDomain = targetDomain.substring(8);
$("#proxyRoot").val(targetDomain);
}
$.ajax({
$.cjax({
url: "/api/proxy/tlscheck",
method: "POST",
data: {url: targetDomain},
success: function(data){
if (data.error != undefined){
@@ -232,7 +233,7 @@
}
//Create the endpoint by calling add
$.ajax({
$.cjax({
url: "/api/proxy/add",
data: {
"type": "root",

View File

@@ -212,8 +212,9 @@
}
//Create the endpoint by calling add
$.ajax({
$.cjax({
url: "/api/proxy/add",
method: "POST",
data: {
type: "host",
rootname: rootname,
@@ -270,22 +271,6 @@
}
//Generic functions for delete rp endpoints
function deleteEndpoint(epoint){
epoint = decodeURIComponent(epoint).hexDecode();
if (confirm("Confirm remove proxy for :" + epoint + "?")){
$.ajax({
url: "/api/proxy/del",
data: {ep: epoint, },
success: function(){
listProxyEndpoints();
msgbox("Proxy Rule Deleted", true);
reloadUptimeList();
}
})
}
}
//Clearn the proxy target value, make sure user do not enter http:// or https://
//and auto select TLS checkbox if https:// exists
function autoFillTargetTLS(input){
@@ -307,12 +292,12 @@
//Automatic check if the site require TLS and check the checkbox if needed
function autoCheckTls(targetDomain){
$.ajax({
$.cjax({
url: "/api/proxy/tlscheck",
data: {url: targetDomain},
success: function(data){
if (data.error != undefined){
msgbox(data.error, false);
}else if (data == "https"){
$("#reqTls").parent().checkbox("set checked");
}else if (data == "http"){

View File

@@ -315,26 +315,39 @@
//Start and stop service button
function startService(){
$.post("/api/proxy/enable", {enable: true}, function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
$.cjax({
url: "/api/proxy/enable",
method: "POST",
data: {enable: true},
success: function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
}
initRPStaste();
}
initRPStaste();
});
}
function stopService(){
$.post("/api/proxy/enable", {enable: false}, function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
$.cjax({
url: "/api/proxy/enable",
method: "POST",
data: {enable: false},
success: function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
}
initRPStaste();
}
initRPStaste();
});
}
function handleP80ListenerStateChange(enabled){
$.ajax({
$.cjax({
url: "/api/proxy/listenPort80",
method: "POST",
data: {"enable": enabled},
success: function(data){
if (data.error != undefined){
@@ -361,16 +374,21 @@
return;
}
$.post("/api/proxy/setIncoming", {incoming: newPortValue}, function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
return;
}
msgbox("Listening Port Updated");
initRPStaste();
$.cjax({
url: "/api/proxy/setIncoming",
method: "POST",
data: {incoming: newPortValue},
success: function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
return;
}
msgbox("Listening Port Updated");
initRPStaste();
//Hide the reminder text
$("#applyButtonReminder").hide();
//Hide the reminder text
$("#applyButtonReminder").hide();
}
});
}
@@ -402,8 +420,9 @@
//Initiate the input listener on the checkbox
$("#redirect").find("input").on("change", function(){
let thisValue = $("#redirect").checkbox("is checked");
$.ajax({
$.cjax({
url: "/api/proxy/useHttpsRedirect",
method: "POST",
data: {set: thisValue},
success: function(data){
if (data.error != undefined){
@@ -440,9 +459,10 @@
//Bind events to the checkbox
$("#tlsMinVer").find("input").on("change", function(){
let thisValue = $("#tlsMinVer").checkbox("is checked");
$.ajax({
$.cjax({
url: "/api/cert/tlsRequireLatest",
data: {"set": thisValue},
method: "POST",
success: function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
@@ -498,15 +518,15 @@
}else{
$(".tlsEnabledOnly").addClass('disabled');
}
$.ajax({
$.cjax({
url: "/api/cert/tls",
method: "POST",
data: {set: thisValue},
success: function(data){
if (data.error != undefined){
alert(data.error);
msgbox(data.error, false);
}else{
//Updated
//Check for case if the port is invalid default ports
if ($("#incomingPort").val() == "80" && thisValue == true){
confirmBox("Change listen port to :443?", function(choice){

View File

@@ -100,7 +100,7 @@
}
// Send the AJAX POST request
$.ajax({
$.cjax({
type: 'POST',
url: '/api/streamprox/config/add',
data: form.serialize(),
@@ -285,7 +285,7 @@
}
// Send the AJAX POST request
$.ajax({
$.cjax({
type: 'POST',
url: '/api/streamprox/config/edit',
method: "POST",
@@ -316,7 +316,7 @@
}
function deleteTCPProxyConfig(configUUID){
$.ajax({
$.cjax({
url: "/api/streamprox/config/delete",
method: "POST",
data: {uuid: configUUID},
@@ -333,7 +333,7 @@
//Start a TCP proxy by their config UUID
function startStreamProx(configUUID){
$.ajax({
$.cjax({
url: "/api/streamprox/config/start",
method: "POST",
data: {uuid: configUUID},
@@ -351,7 +351,7 @@
//Stop a TCP proxy by their config UUID
function stopStreamProx(configUUID){
$.ajax({
$.cjax({
url: "/api/streamprox/config/stop",
method: "POST",
data: {uuid: configUUID},

View File

@@ -233,7 +233,7 @@
const newPassword = document.getElementsByName('newPassword')[0].value;
const confirmNewPassword = document.getElementsByName('confirmNewPassword')[0].value;
$.ajax({
$.cjax({
type: "POST",
url: "/api/auth/changePassword",
data: {
@@ -279,7 +279,7 @@
return;
}
$.ajax({
$.cjax({
type: "POST",
url: "/api/tools/smtp/set",
data: data,

View File

@@ -190,7 +190,7 @@
function updateVDTargetTLSState(){
var targetDomain = $("#virtualDirectoryDomain").val().trim();
if (targetDomain != ""){
$.ajax({
$.cjax({
url: "/api/proxy/tlscheck",
data: {url: targetDomain},
success: function(data){
@@ -252,7 +252,7 @@
}
//Create a virtual directory endpoint
$.ajax({
$.cjax({
url: "/api/proxy/vdir/add",
method: "POST",
data: {
@@ -295,7 +295,7 @@
epType = "root";
path = "";
}
$.ajax({
$.cjax({
url: "/api/proxy/vdir/del",
method: "POST",
data: {
@@ -384,7 +384,7 @@
//console.log(mathingPath, newDomain, requireTLS, skipValidation);
$.ajax({
$.cjax({
url: "/api/proxy/vdir/edit",
method: "POST",
data: {

View File

@@ -164,7 +164,7 @@
$("#webserv_enableDirList").off("change").on("change", function(){
let enable = $(this)[0].checked;
$.ajax({
$.cjax({
url: "/api/webserv/setDirList",
method: "POST",
data: {"enable": enable},
@@ -186,7 +186,7 @@
confirmBox("This setting might cause port conflict. Continue Anyway?", function(choice){
if (choice == true){
//Continue anyway
$.ajax({
$.cjax({
url: "/api/webserv/setPort",
method: "POST",
data: {"port": newPort},
@@ -206,7 +206,7 @@
}
});
}else{
$.ajax({
$.cjax({
url: "/api/webserv/setPort",
method: "POST",
data: {"port": newPort},

View File

@@ -5,6 +5,7 @@
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
<meta charset="UTF-8">
<meta name="theme-color" content="#4b75ff">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="icon" type="image/png" href="./favicon.png" />
<title>Control Panel | Zoraxy</title>
<link rel="stylesheet" href="script/semantic/semantic.min.css">

View File

@@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="robots" content="noindex" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="icon" type="image/png" href="./favicon.png" />
<title>Login | Zoraxy</title>
<link rel="stylesheet" href="script/semantic/semantic.min.css">
@@ -250,10 +251,10 @@
});
$("#regsiterbtn").on("click", function(event){
var username = $("#username").val();
var magic = $("#magic").val();
var repeatMagic = $("#repeatMagic").val();
let username = $("#username").val();
let magic = $("#magic").val();
let repeatMagic = $("#repeatMagic").val();
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
if (magic !== repeatMagic) {
alert("Password does not match");
return;
@@ -262,6 +263,9 @@
$.ajax({
url: "/api/auth/register",
method: "POST",
beforeSend: function(request) {
request.setRequestHeader("X-CSRF-Token",csrfToken);
},
data: {
username: username,
password: magic
@@ -297,29 +301,45 @@
//Login system with the given username and password
function login(){
var username = $("#username").val();
var magic = $("#magic").val();
var rmbme = document.getElementById("rmbme").checked;
let username = $("#username").val();
let magic = $("#magic").val();
let rmbme = document.getElementById("rmbme").checked;
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
$("#errmsg").stop().finish().slideUp("fast");
$("input").addClass('disabled');
$.post(loginAddress, {"username": username, "password": magic, "rmbme": rmbme}).done(function(data){
if (data.error !== undefined){
//Something went wrong during the login
$("#errmsg").html(`<i class="red remove icon"></i> ${data.error}`);
$("#errmsg").stop().finish().slideDown('fast');
}else if(data.redirect !== undefined){
//LDAP Related Code
window.location.href = data.redirect;
}else{
//Login succeed
if (redirectionAddress == ""){
//Redirect back to index
window.location.href = "./";
$.ajax({
url: loginAddress,
type: "POST",
beforeSend: function(request) {
request.setRequestHeader("X-CSRF-Token",csrfToken);
},
data: {
"username": username,
"password": magic,
"rmbme": rmbme,
},
success: function(data){
if (data.error !== undefined){
//Something went wrong during the login
$("#errmsg").html(`<i class="red remove icon"></i> ${data.error}`);
$("#errmsg").stop().finish().slideDown('fast');
}else if(data.redirect !== undefined){
//LDAP Related Code
window.location.href = data.redirect;
}else{
window.location.href = redirectionAddress;
//Login succeed
if (redirectionAddress == ""){
//Redirect back to index
window.location.href = "./";
}else{
window.location.href = redirectionAddress;
}
}
$("input").removeClass('disabled');
},
error: function(){
alert("Something went wrong.")
}
$("input").removeClass('disabled');
});
}

View File

@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<meta name="robots" content="noindex" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="./favicon.png" />
@@ -255,25 +256,36 @@
}
// Send POST request with input values as data
$.post('/api/account/new', { username: username, token: token, newpw: newPassword })
.done(function(data) {
// Handle successful response
if (data.error != undefined){
$("#errmsg").html(`<i class="red circle times icon"></i> ` + data.error);
$("#errmsg").show();
}else{
$("#errmsg").hide();
$("#countdown").hide();
$("#succmsg").show();
setTimeout(function(){
window.location.href = "/";
}, 3000);
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
$.ajax({
url: "/api/account/new",
method: "POST",
data: {
username: username,
token: token,
newpw: newPassword
},
headers: {
"X-CSRF-Token": csrfToken,
},
success: function(data){
// Handle successful response
if (data.error != undefined){
$("#errmsg").html(`<i class="red circle times icon"></i> ` + data.error);
$("#errmsg").show();
}else{
$("#errmsg").hide();
$("#countdown").hide();
$("#succmsg").show();
setTimeout(function(){
window.location.href = "/";
}, 3000);
}
},
error: function(){
console.error(error);
}
})
.fail(function(error) {
// Handle error response
console.error(error);
});
});

View File

@@ -26,4 +26,18 @@ Object.defineProperty(String.prototype, 'capitalize', {
return this.charAt(0).toUpperCase() + this.slice(1);
},
enumerable: false
});
});
//Add a new function to jquery for ajax override with csrf token injected
$.cjax = function(payload){
let requireTokenMethod = ["POST", "PUT", "DELETE"];;
if (requireTokenMethod.includes(payload.method) || requireTokenMethod.includes(payload.type)){
//csrf token is required
let csrfToken = document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content");
payload.headers = {
"X-CSRF-Token": csrfToken,
}
}
$.ajax(payload);
}

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
<style>
#refreshAccessRuleListBtn{
position: absolute;
@@ -94,7 +96,7 @@
$("#accessRuleForm input[name='accessRuleName']").val("");
$("#accessRuleForm textarea[name='description']").val("");
$.ajax({
$.cjax({
url: "/api/access/create",
method: "POST",
data: {
@@ -162,7 +164,7 @@
console.log('Access Rule Name:', accessRuleName);
console.log('Description:', description);
$.ajax({
$.cjax({
url: "/api/access/update",
method: "POST",
data: {
@@ -238,7 +240,7 @@
}
let accessRuleName = $("#modifyRuleInfo input[name='accessRuleName']").val();
if (confirm("Confirm removing access rule " + accessRuleName + "?")){
$.ajax({
$.cjax({
url: "/api/access/remove",
data: {
"id": accessRuleUUID

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
<style>
.disabled.table{
opacity: 0.5;
@@ -234,8 +236,9 @@
initRenewerConfigFromFile();
function saveEmailToConfig(btn){
$.ajax({
$.cjax({
url: "/api/acme/autoRenew/email",
method: "POST",
data: {set: $("#caRegisterEmail").val()},
success: function(data){
if (data.error != undefined){
@@ -256,27 +259,29 @@
function toggleAutoRenew(){
var enabled = $("#enableCertAutoRenew").parent().checkbox("is checked");
$.post("/api/acme/autoRenew/enable?enable=" + enabled, function(data){
if (data.error){
parent.msgbox(data.error, false, 5000);
if (enabled){
enableTrigerOnChangeEvent = false;
$("#enableCertAutoRenew").parent().checkbox("set unchecked");
enableTrigerOnChangeEvent = true;
}
if (parent && parent.setACMEEnableStates){
parent.setACMEEnableStates(!enabled);
}
}else{
$("#enableToggleSucc").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
if (parent && parent.setACMEEnableStates){
parent.setACMEEnableStates(enabled);
$.cjax({
url: "/api/acme/autoRenew/enable",
method: "POST",
data: {"enable": enabled},
success: function(data){
if (data.error){
parent.msgbox(data.error, false, 5000);
if (enabled){
enableTrigerOnChangeEvent = false;
$("#enableCertAutoRenew").parent().checkbox("set unchecked");
enableTrigerOnChangeEvent = true;
}
if (parent && parent.setACMEEnableStates){
parent.setACMEEnableStates(!enabled);
}
}else{
$("#enableToggleSucc").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
if (parent && parent.setACMEEnableStates){
parent.setACMEEnableStates(enabled);
}
}
}
});
}
//Render the domains table that exists in this zoraxy host
@@ -630,7 +635,7 @@
return;
}
$.ajax({
$.cjax({
url: "/api/acme/autoRenew/setDNS",
method: "POST",
data: {
@@ -843,8 +848,9 @@
function saveAutoRenewPolicy(){
let autoRenewAll = $("#renewAllSupported").parent().checkbox("is checked");
if (autoRenewAll == true){
$.ajax({
$.cjax({
url: "/api/acme/autoRenew/setDomains",
method: "POST",
data: {opr: "setAuto"},
success: function(data){
parent.msgbox("Renew policy rule updated")
@@ -856,8 +862,9 @@
checkedNames.push($(this).attr('name'));
});
$.ajax({
$.cjax({
url: "/api/acme/autoRenew/setDomains",
method: "POST",
data: {opr: "setSelected", domains: JSON.stringify(checkedNames)},
success: function(data){
parent.msgbox("Renew policy rule updated")

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
</head>
<body>
<br>
@@ -46,7 +48,7 @@
function handleResetStats(){
if (confirm("Confirm remove statistics from " + startDate + " to " + endDate +"?")){
$.ajax({
$.cjax({
url: "/api/analytic/resetRange?start=" + startDate + "&end=" + endDate,
method: "DELETE",
success: function(data){

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
</head>
<body>
<br>
@@ -71,7 +73,7 @@
}
function initAliasNames(){
$.ajax({
$.cjax({
url: "/api/proxy/detail",
method: "POST",
data: {
@@ -130,7 +132,7 @@
}
function saveCurrentAliasList(callback=undefined){
$.ajax({
$.cjax({
url: "/api/proxy/setAlias",
method: "POST",
data:{

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
</head>
<body>
<br>
@@ -174,7 +176,7 @@
parent.msgbox("Matching prefix cannot be empty!", false, 5000);
return;
}
$.ajax({
$.cjax({
url: "/api/proxy/auth/exceptions/add",
data:{
ep: editingEndpoint.ep,
@@ -195,7 +197,7 @@
function removeExceptionPath(object){
let matchingPrefix = $(object).attr("prefix");
$.ajax({
$.cjax({
url: "/api/proxy/auth/exceptions/delete",
data:{
ep: editingEndpoint.ep,
@@ -290,7 +292,7 @@
}
function saveCredentials(){
$.ajax({
$.cjax({
url: "/api/proxy/updateCredentials",
method: "POST",
data: {

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
</head>
<body>
<br>
@@ -70,10 +72,10 @@
}
}
document.getElementById("uploadForm").addEventListener("submit", function(event) {
$("#uploadForm").submit(function(event) {
event.preventDefault(); // Prevent the form from submitting normally
var fileInput = document.getElementById("fileInput");
var fileInput = $("#fileInput")[0];
var file = fileInput.files[0];
if (!file) {
alert("Missing file.");
@@ -83,18 +85,19 @@
var formData = new FormData();
formData.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/conf/import", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
parent.msgbox("Config restore succeed. Restart Zoraxy to apply changes.")
} else {
parent.msgbox("Restore failed: " + xhr.responseText, false, 5000);
}
$.cjax({
url: "/api/conf/import",
type: "POST",
data: formData,
processData: false, // Not to process the data
contentType: false, // Not to set contentType
success: function(response) {
parent.msgbox("Config restore succeed. Restart Zoraxy to apply changes.");
},
error: function(xhr) {
parent.msgbox("Restore failed: " + xhr.responseText, false, 5000);
}
};
xhr.send(formData);
});
});
</script>
</body>

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
<style>
.ui.tabular.menu .item.narrowpadding{
padding: 0.6em !important;
@@ -92,9 +94,6 @@
</div>
<div class="content">
<br>
<div class="ui yellow message">
<p><i class="exclamation triangle icon"></i>Settings in this section are for advanced users. Invalid settings might cause werid, unexpected behavior.</p>
</div>
<div class="ui container">
<h4>Overwrite Host Header</h4>
<p>Manual override the automatic "Host" header rewrite logic. Leave empty for automatic.</p>
@@ -112,7 +111,9 @@
<label>Remove Hop-by-hop Header<br>
<small>This should be ON by default</small></label>
</div>
<div class="ui divider"></div>
<div class="ui yellow message">
<p><i class="exclamation triangle icon"></i>Settings in this section are for advanced users. Invalid settings might cause werid, unexpected behavior.</p>
</div>
</div>
</div>
</div>
@@ -247,8 +248,9 @@
}
}
$.ajax({
$.cjax({
url: "/api/proxy/header/add",
method: "POST",
data: {
"type": getHeaderEditMode(),
"domain": editingEndpoint.ep,
@@ -279,10 +281,10 @@
}
function deleteCustomHeader(name){
$.ajax({
$.cjax({
url: "/api/proxy/header/remove",
method: "POST",
data: {
//"type": editingEndpoint.ept,
"domain": editingEndpoint.ep,
"name": name,
},
@@ -299,6 +301,7 @@
$("#headerTable").html(`<tr><td colspan="3"><i class="ui loading spinner icon"></i> Loading</td></tr>`);
$.ajax({
url: "/api/proxy/header/list",
method: "GET",
data: {
"type": editingEndpoint.ept,
"domain": editingEndpoint.ep,
@@ -307,7 +310,6 @@
if (data.error != undefined){
alert(data.error);
}else{
$("#headerTable").html("");
data.forEach(header => {
let editModeIcon = header.IsRemove?`<i class="ui red times circle icon"></i>`:`<i class="ui green add circle icon"></i>`;
@@ -351,7 +353,7 @@
/* Bind events to toggles */
$("#enableHSTS").on("change", function(){
let HSTSEnabled = $("#enableHSTS")[0].checked;
$.ajax({
$.cjax({
url: "/api/proxy/header/handleHSTS",
method: "POST",
data: {
@@ -426,7 +428,7 @@
$("#permissionPolicyEditor").addClass("disabled");
}
$.ajax({
$.cjax({
url: "/api/proxy/header/handlePermissionPolicy",
method: "POST",
data: {
@@ -532,7 +534,7 @@
let permissionPolicy = generatePermissionPolicyObject();
let domain = editingEndpoint.ep;
$.ajax({
$.cjax({
url: "/api/proxy/header/handlePermissionPolicy",
method: "PUT",
data: {
@@ -576,7 +578,7 @@
function updateManualHostOverwriteVal(callback=undefined){
let newHostname = $("#manualHostOverwrite").val().trim();
$.ajax({
$.cjax({
url: "/api/proxy/header/handleHostOverwrite",
method: "POST",
data: {
@@ -615,7 +617,7 @@
//Bind event to the checkbox
$("#removeHopByHop").on("change", function(evt){
let isChecked = $(this)[0].checked;
$.ajax({
$.cjax({
url: "/api/proxy/header/handleHopByHop",
method: "POST",
data: {

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
<style>
.accessRule{
cursor: pointer;
@@ -124,12 +126,10 @@
}
}
});
}
initAccessRuleList(function(){
$.ajax({
$.cjax({
url: "/api/proxy/detail",
method: "POST",
data: {"type":"host", "epname": editingEndpoint.ep },
@@ -160,7 +160,7 @@
function applyChangeAndClose(){
let newAccessRuleID = $(".accessRule.active").attr("ruleid");
let targetEndpoint = editingEndpoint.ep;
$.ajax({
$.cjax({
url: "/api/access/attach",
method: "POST",
data: {

View File

@@ -2,9 +2,11 @@
<html>
<head>
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
<style>
body{
height: 100%;

View File

@@ -3,9 +3,11 @@
<head>
<!-- Notes: This should be open in its original path-->
<meta charset="utf-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
<script src="../script/jquery-3.6.0.min.js"></script>
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/utils.js"></script>
<style>
.upstreamActions{
position: absolute;
@@ -133,7 +135,7 @@
function initOriginList(){
$.ajax({
url: "/api/proxy/upstream/list",
method: "POST",
method: "GET",
data: {
"type":"host",
"ep": editingEndpoint.ep
@@ -284,8 +286,9 @@
}else{
//URL does not contains https or http protocol tag
//sniff header
$.ajax({
$.cjax({
url: "/api/proxy/tlscheck",
method: "POST",
data: {url: targetDomain},
success: function(data){
if (data.error != undefined){
@@ -313,7 +316,7 @@
return;
}
$.ajax({
$.cjax({
url: "/api/proxy/upstream/add",
method: "POST",
data:{
@@ -365,7 +368,7 @@
let newConfig = getUpstreamSettingFromDOM(targetDOM);
let isActive = $(targetDOM).find(".enableState")[0].checked;
console.log(newConfig);
$.ajax({
$.cjax({
url: "/api/proxy/upstream/update",
method: "POST",
data: {
@@ -418,8 +421,9 @@
}else{
//URL does not contains https or http protocol tag
//sniff header
$.ajax({
$.cjax({
url: "/api/proxy/tlscheck",
method: "POST",
data: {url: targetDomain},
success: function(data){
if (data.error != undefined){
@@ -460,7 +464,7 @@
//Set a weight of a upstream
function setUpstreamWeight(originIP, newWeight){
$.ajax({
$.cjax({
url: "/api/proxy/upstream/setPriority",
method: "POST",
data: {
@@ -489,7 +493,7 @@
return;
}
//Remove the upstream
$.ajax({
$.cjax({
url: "/api/proxy/upstream/remove",
method: "POST",
data: {

View File

@@ -2,12 +2,14 @@
<head>
<title>File Manager</title>
<meta charset="UTF-8">
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js"></script>
<link rel="stylesheet" href="fs.css">
<script src="../script/utils.js"></script>
<script>
</script>
@@ -199,7 +201,7 @@
let counter = $(".fileObject.selected").length;
$(".fileObject.selected").each(function(){
let thisFilepath = $(this).attr("filepath");
$.ajax({
$.cjax({
url: "/api/fs/del?target=" + thisFilepath,
method: "POST",
success: function(data){
@@ -241,22 +243,9 @@
let filename = $(this).attr("filename");
if (ftype != "folder"){
let ext = filepath.split(".").pop();
if (isCodeFiles(ext)){
editableCodeFiles.push({
"filename": filename,
"filepath": filepath
});
}else{
openthis($(this), evt);
}
openthis($(this), evt);
}
});
if (editableCodeFiles.length > 0){
let hash = encodeURIComponent(JSON.stringify(editableCodeFiles))
window.open("notepad/index.html#" + hash);
}
}
function refresh(){
@@ -571,12 +560,19 @@
return;
}
$.post("/api/fs/newFolder?path=" + currentPath + folderName, function(data){
if (data.error != undefined){
msgbox(data.error, false);
}else{
msgbox("Folder Created");
refresh();
$.cjax({
url: "/api/fs/newFolder",
method: "POST",
data: {
"path": currentPath + folderName,
},
success: function(data){
if (data.error != undefined){
msgbox(data.error, false);
}else{
msgbox("Folder Created");
refresh();
}
}
});
}
@@ -597,8 +593,12 @@
if (newName && newName != oldName) {
// User entered a new name, perform renaming logic here
console.log(oldPath, currentPath + newName);
$.ajax({
url: "/api/fs/move?srcpath=" + oldPath + "&destpath=" + currentPath + newName,
$.cjax({
url: "/api/fs/move",
data: {
"srcpath": oldPath,
"destpath": currentPath + newName
},
method: "POST",
success: function(data){
if (data.error != undefined){
@@ -826,6 +826,7 @@
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "/api/fs/upload?dir=" + dir);
ajax.setRequestHeader("X-CSRF-Token", document.getElementsByTagName("meta")["zoraxy.csrf.Token"].getAttribute("content"));
ajax.send(formdata);
}
@@ -914,8 +915,12 @@
let filename = fileToPaste.filename;
let filepath = fileToPaste.filepath;
$.ajax({
url: "/api/fs/move?srcpath=" + filepath + "&destpath=" + currentPath + filename,
$.cjax({
url: "/api/fs/move",
data:{
"srcpath": filepath,
"destpath": currentPath + filename,
},
method: "POST",
success: function(data){
if (data.error != undefined){
@@ -939,7 +944,7 @@
function copyFirstItemInQueueUntilAllCopied(){
let file = copyPendingFiles.shift();
let startingDir = currentPath;
$.ajax({
$.cjax({
url: "/api/fs/copy",
method: "POST",
data: {

View File

@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
<meta charset="UTF-8">
@@ -13,6 +14,7 @@
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/tablesort.js"></script>
<link rel="stylesheet" href="../main.css">
<script src="../script/utils.js"></script>
<style>
.offlinehost{
display: none;
@@ -86,9 +88,14 @@
<div class="ui basic segment" align="center">
<i class="loading spinner icon"></i> Scanning
</div>`);
$.post("/api/tools/ipscan", {start: start, end: end}, function(data) {
displayResults(data);
$(".scanbtn").removeClass("disabled");
$.cjax({
url: "/api/tools/ipscan",
data: {start: start, end: end},
method: "POST",
success: function(data){
displayResults(data);
$(".scanbtn").removeClass("disabled");
}
});
});
@@ -109,9 +116,14 @@
<div class="ui basic segment" align="center">
<i class="loading spinner icon"></i> Scanning
</div>`);
$.post("/api/tools/ipscan", {cidr: cidr}, function(data) {
displayResults(data);
$(".scanbtn").removeClass("disabled");
$.cjax({
url: "/api/tools/ipscan",
method: "POST",
data: {cidr: cidr},
success: function(data) {
displayResults(data);
$(".scanbtn").removeClass("disabled");
}
});
});

View File

@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
<meta charset="UTF-8">
@@ -13,6 +14,7 @@
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/tablesort.js"></script>
<link rel="stylesheet" href="../main.css">
<script src="../script/utils.js"></script>
<style>
body{
overflow-x: auto;
@@ -54,7 +56,7 @@
var domain = $("#domain").val();
$("#discover").addClass("loading").addClass('disabled');
setCountdown();
$.ajax({
$.cjax({
type: "POST",
url: "/api/mdns/discover",
data: { domain: domain },

View File

@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
<meta charset="UTF-8">
@@ -13,6 +14,7 @@
<script src="../script/semantic/semantic.min.js"></script>
<script src="../script/tablesort.js"></script>
<link rel="stylesheet" href="../main.css">
<script src="../script/utils.js"></script>
<style>
#loadingUI{
width: 100%;
@@ -153,7 +155,7 @@
//Try to ask the server side to create a ssh proxy object
function createSSHProxy(remoteAddr, remotePort, username){
//Request to create a ssh session instance
$.ajax({
$.cjax({
url: "/api/tools/webssh",
data: {ipaddr: remoteAddr, port: remotePort, username:username},
method: "POST",