1
0
Эх сурвалжийг харах

auto update script executed

Toby Chui 1 жил өмнө
parent
commit
8d4a6e8947

+ 1 - 0
api.go

@@ -45,6 +45,7 @@ func initAPIs() {
 	authRouter.HandleFunc("/api/proxy/add", ReverseProxyHandleAddEndpoint)
 	authRouter.HandleFunc("/api/proxy/status", ReverseProxyStatus)
 	authRouter.HandleFunc("/api/proxy/list", ReverseProxyList)
+	authRouter.HandleFunc("/api/proxy/edit", ReverseProxyHandleEditEndpoint)
 	authRouter.HandleFunc("/api/proxy/del", DeleteProxyEndpoint)
 	authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
 	authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)

+ 2 - 2
main.go

@@ -38,9 +38,9 @@ var ztAuthToken = flag.String("ztauth", "", "ZeroTier authtoken for the local no
 var ztAPIPort = flag.Int("ztport", 9993, "ZeroTier controller API port")
 var (
 	name        = "Zoraxy"
-	version     = "2.6"
+	version     = "2.7"
 	nodeUUID    = "generic"
-	development = false //Set this to false to use embedded web fs
+	development = true //Set this to false to use embedded web fs
 
 	/*
 		Binary Embedding File System

+ 35 - 1
mod/dynamicproxy/dynamicproxy.go

@@ -242,10 +242,44 @@ func (router *Router) AddVirtualDirectoryProxyService(options *VdirOptions) erro
 
 	router.ProxyEndpoints.Store(options.RootName, &endpointObject)
 
-	log.Println("Adding Proxy Rule: ", options.RootName+" to "+domain)
+	log.Println("Registered Proxy Rule: ", options.RootName+" to "+domain)
 	return nil
 }
 
+/*
+Load routing from RP
+*/
+func (router *Router) LoadProxy(ptype string, key string) (*ProxyEndpoint, error) {
+	if ptype == "vdir" {
+		proxy, ok := router.ProxyEndpoints.Load(key)
+		if !ok {
+			return nil, errors.New("target proxy not found")
+		}
+		return proxy.(*ProxyEndpoint), nil
+	} else if ptype == "subd" {
+		proxy, ok := router.SubdomainEndpoint.Load(key)
+		if !ok {
+			return nil, errors.New("target proxy not found")
+		}
+		return proxy.(*ProxyEndpoint), nil
+	}
+
+	return nil, errors.New("unsupported ptype")
+}
+
+/*
+Save routing from RP
+*/
+func (router *Router) SaveProxy(ptype string, key string, newConfig *ProxyEndpoint) {
+	if ptype == "vdir" {
+		router.ProxyEndpoints.Store(key, newConfig)
+
+	} else if ptype == "subd" {
+		router.SubdomainEndpoint.Store(key, newConfig)
+	}
+
+}
+
 /*
 Remove routing from RP
 */

+ 97 - 0
reverseproxy.go

@@ -281,7 +281,104 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
 	}
 
 	utils.SendOK(w)
+}
+
+/*
+ReverseProxyHandleEditEndpoint handles proxy endpoint edit
+This endpoint do not handle
+basic auth credential update. The credential
+will be loaded from old config and reused
+*/
+func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
+	eptype, err := utils.PostPara(r, "type") //Support root, vdir and subd
+	if err != nil {
+		utils.SendErrorResponse(w, "type not defined")
+		return
+	}
+
+	rootNameOrMatchingDomain, err := utils.PostPara(r, "rootname")
+	if err != nil {
+		utils.SendErrorResponse(w, "Target proxy rule not defined")
+		return
+	}
+
+	endpoint, err := utils.PostPara(r, "ep")
+	if err != nil {
+		utils.SendErrorResponse(w, "endpoint not defined")
+		return
+	}
+
+	tls, _ := utils.PostPara(r, "tls")
+	if tls == "" {
+		tls = "false"
+	}
+
+	useTLS := (tls == "true")
+
+	stv, _ := utils.PostPara(r, "tlsval")
+	if stv == "" {
+		stv = "false"
+	}
+
+	skipTlsValidation := (stv == "true")
+
+	rba, _ := utils.PostPara(r, "bauth")
+	if rba == "" {
+		rba = "false"
+	}
 
+	requireBasicAuth := (rba == "true")
+
+	//Load the previous basic auth credentials from current proxy rules
+	targetProxyEntry, err := dynamicProxyRouter.LoadProxy(eptype, rootNameOrMatchingDomain)
+	if err != nil {
+		utils.SendErrorResponse(w, "Target proxy config not found or could not be loaded")
+		return
+	}
+
+	if eptype == "vdir" {
+		thisOption := dynamicproxy.VdirOptions{
+			RootName:             targetProxyEntry.RootOrMatchingDomain,
+			Domain:               endpoint,
+			RequireTLS:           useTLS,
+			SkipCertValidations:  skipTlsValidation,
+			RequireBasicAuth:     requireBasicAuth,
+			BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
+		}
+		dynamicProxyRouter.AddVirtualDirectoryProxyService(&thisOption)
+
+	} else if eptype == "subd" {
+		thisOption := dynamicproxy.SubdOptions{
+			MatchingDomain:       targetProxyEntry.RootOrMatchingDomain,
+			Domain:               endpoint,
+			RequireTLS:           useTLS,
+			SkipCertValidations:  skipTlsValidation,
+			RequireBasicAuth:     requireBasicAuth,
+			BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
+		}
+		dynamicProxyRouter.AddSubdomainRoutingService(&thisOption)
+	}
+
+	//Save it to file
+	thisProxyConfigRecord := Record{
+		ProxyType:            eptype,
+		Rootname:             targetProxyEntry.RootOrMatchingDomain,
+		ProxyTarget:          endpoint,
+		UseTLS:               useTLS,
+		SkipTlsValidation:    skipTlsValidation,
+		RequireBasicAuth:     requireBasicAuth,
+		BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
+	}
+	SaveReverseProxyConfig(&thisProxyConfigRecord)
+
+	//Update the current running config
+	targetProxyEntry.Domain = endpoint
+	targetProxyEntry.RequireTLS = useTLS
+	targetProxyEntry.SkipCertValidations = skipTlsValidation
+	targetProxyEntry.RequireBasicAuth = requireBasicAuth
+	dynamicProxyRouter.SaveProxy(eptype, targetProxyEntry.RootOrMatchingDomain, targetProxyEntry)
+
+	utils.SendOK(w)
 }
 
 func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {

+ 132 - 0
web/components/rules.html

@@ -299,4 +299,136 @@
         const regex = /^(localhost|[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,}|[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,}\.)$/i;
         return regex.test(str);
     } 
+
+
+    /*
+        Inline editor for subd.html and vdir.html
+    */
+
+    function editEndpoint(endpointType, uuid) {
+        var row = $('tr[eptuuid="' + uuid + '"]');
+        var columns = row.find('td[data-label]');
+        var payload = $(row).attr("payload");
+        payload = JSON.parse(decodeURIComponent(payload));
+     
+        console.log(payload);
+        columns.each(function(index) {
+            var column = $(this);
+            var oldValue = column.text().trim();
+
+            if ($(this).attr("editable") == "false"){
+                //This col do not allow edit. Skip
+                return;
+            }
+
+            // Create an input element based on the column content
+            var input;
+            var datatype = $(this).attr("datatype");
+            if (datatype == "domain"){
+                let domain = payload.Domain;
+                let tls = payload.RequireTLS;
+                if (tls){
+                    tls = "checked";
+                }else{
+                    tls = "";
+                }
+                input = `
+                    <div class="ui mini fluid input">
+                        <input type="text" class="Domain" value="${domain}">
+                    </div>
+                    <div class="ui checkbox" style="margin-top: 0.4em;">
+                        <input type="checkbox" class="RequireTLS" ${tls}>
+                        <label>Require TLS</label>
+                    </div>
+                `;
+                column.empty().append(input);
+
+            }else if (datatype == "skipver"){
+                let skipTLSValidation = payload.SkipCertValidations;
+                let checkstate = "";
+                if (skipTLSValidation){
+                    checkstate = "checked";
+                }
+                column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
+                    <input type="checkbox" class="SkipCertValidations" ${checkstate}>
+                    <label>Skip Verification</label>
+                    <small>Check this if you are using self signed certificates</small>
+                </div>`);
+            }else if (datatype == "basicauth"){
+                let requireBasicAuth = payload.RequireBasicAuth;
+                let checkstate = "";
+                if (requireBasicAuth){
+                    checkstate = "checked";
+                }
+                column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
+                    <input type="checkbox" class="RequireBasicAuth" ${checkstate}>
+                    <label>Require Basic Auth</label>
+                </div><button class="ui basic tiny right floated button"><i class="ui blue lock icon"></i> Edit Credentials</button>`);
+
+            }else if (datatype == 'action'){
+                column.empty().append(`<button onclick="saveProxyInlineEdit('${uuid}');" class="ui tiny basic button"><i class="ui green save icon"></i> Save</button>`);
+            }else{
+                //Unknown field. Leave it untouched
+
+            }
+            if (column.find('i.green.check.icon').length > 0) {
+                // Create a checkbox input for boolean options
+                var checked = (oldValue === '✓'); // Assuming '✓' indicates a checked state
+                input = $('<input>').attr('type', 'checkbox').prop('checked', checked);
+            } else {
+                // Create a regular text input for other fields
+                input = $('<input>').attr('type', 'text').val(oldValue);
+            }
+
+            // Set focus on the input element
+            input.focus();
+
+        });
+    }
+
+    function saveProxyInlineEdit(uuid){
+        var row = $('tr[eptuuid="' + uuid + '"]');
+        if (row.length == 0){
+            return;
+        }
+
+        var epttype = $(row).attr("class");
+        if (epttype == "subdEntry"){
+            epttype = "subd";
+        }else if (epttype == "vdirEntry"){
+            epttype = "vdir";
+        }
+
+        let newDomain =  $(row).find(".Domain").val();
+        let requireTLS = $(row).find(".RequireTLS")[0].checked;
+        let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked;
+        let requireBasicAuth = $(row).find(".RequireBasicAuth")[0].checked;
+
+        console.log(newDomain, requireTLS, skipCertValidations, requireBasicAuth)
+
+        $.ajax({
+            url: "/api/proxy/edit",
+            method: "POST",
+            data: {
+                "type": epttype,
+                "rootname": uuid,
+                "ep":newDomain,
+                "tls" :requireTLS,
+                "tlsval": skipCertValidations,
+                "bauth" :requireBasicAuth,
+            },
+            success: function(data){
+                if (data.error !== undefined){
+                    msgbox(data.error, false, 6000);
+                }else{
+                    msgbox("Proxy endpoint updated");
+                    if (epttype == "subd"){
+                        listSubd();
+                    }else if (epttype == "vdir"){
+                        listVdirs();
+                    }
+                }
+            }
+        })
+    }
 </script>

+ 7 - 6
web/components/subd.html

@@ -37,15 +37,16 @@
             }else{
                 data.forEach(subd => {
                     let tlsIcon = "";
+                    let subdData = encodeURIComponent(JSON.stringify(subd));
                     if (subd.RequireTLS){
                         tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
                     }
-                    $("#subdList").append(`<tr>
-                        <td data-label="">${subd.RootOrMatchingDomain}</td>
-                        <td data-label="">${subd.Domain} ${tlsIcon}</td>
-                        <td data-label="">${!subd.SkipCertValidations?`<i class="ui green check icon"></i>`:`<i class="ui yellow exclamation circle icon" title="TLS/SSL Verification will be skipped on this host"></i>`}</td>
-                        <td data-label="">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
-                        <td class="center aligned" data-label="">
+                    $("#subdList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
+                        <td data-label="" editable="false">${subd.RootOrMatchingDomain}</td>
+                        <td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
+                        <td data-label="" editable="true" datatype="skipver">${!subd.SkipCertValidations?`<i class="ui green check icon"></i>`:`<i class="ui yellow exclamation circle icon" title="TLS/SSL Verification will be skipped on this host"></i>`}</td>
+                        <td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
+                        <td class="center aligned" editable="true" datatype="action" data-label="">
                             <button class="ui circular mini basic icon button" onclick='editEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
                             <button class="ui circular mini red basic icon button" onclick='deleteEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="trash icon"></i></button>
                         </td>

+ 7 - 6
web/components/vdir.html

@@ -40,15 +40,16 @@
             }else{
                 data.forEach(vdir => {
                     let tlsIcon = "";
+                    let vdirData = encodeURIComponent(JSON.stringify(vdir));
                     if (vdir.RequireTLS){
                         tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
                     }
-                    $("#vdirList").append(`<tr>
-                        <td data-label="">${vdir.RootOrMatchingDomain}</td>
-                        <td data-label="">${vdir.Domain} ${tlsIcon}</td>
-                        <td data-label="">${!subd.SkipCertValidations?`<i class="ui green check icon"></i>`:`<i class="ui yellow exclamation circle icon" title="TLS/SSL Verification will be skipped on this host"></i>`}</td>
-                        <td data-label="">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
-                        <td class="center aligned" data-label="">
+                    $("#vdirList").append(`<tr eptuuid="${vdir.RootOrMatchingDomain}" payload="${vdirData}" class="vdirEntry">
+                        <td data-label="" editable="false">${vdir.RootOrMatchingDomain}</td>
+                        <td data-label="" editable="true" datatype="domain">${vdir.Domain} ${tlsIcon}</td>
+                        <td data-label="" editable="true" datatype="skipver">${!vdir.SkipCertValidations?`<i class="ui green check icon"></i>`:`<i class="ui yellow exclamation circle icon" title="TLS/SSL Verification will be skipped on this host"></i>`}</td>
+                        <td data-label="" editable="true" datatype="basicauth">${vdir.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
+                        <td class="center aligned" editable="true" datatype="action" data-label="">
                             <button class="ui circular mini basic icon button" onclick='editEndpoint("vdir","${vdir.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
                             <button class="ui circular mini red basic icon button"  onclick='deleteEndpoint("vdir","${vdir.RootOrMatchingDomain}")'><i class="trash icon"></i></button>
                         </td>