Parcourir la source

Added redirection rule edit function

Toby Chui il y a 1 mois
Parent
commit
8d0bed9052
4 fichiers modifiés avec 158 ajouts et 10 suppressions
  1. 1 0
      api.go
  2. 36 2
      mod/dynamicproxy/redirection/redirection.go
  3. 43 0
      redirect.go
  4. 78 8
      web/components/redirection.html

+ 1 - 0
api.go

@@ -88,6 +88,7 @@ func RegisterRedirectionAPIs(authRouter *auth.RouterDef) {
 	authRouter.HandleFunc("/api/redirect/list", handleListRedirectionRules)
 	authRouter.HandleFunc("/api/redirect/add", handleAddRedirectionRule)
 	authRouter.HandleFunc("/api/redirect/delete", handleDeleteRedirectionRule)
+	authRouter.HandleFunc("/api/redirect/edit", handleEditRedirectionRule)
 	authRouter.HandleFunc("/api/redirect/regex", handleToggleRedirectRegexpSupport)
 }
 

+ 36 - 2
mod/dynamicproxy/redirection/redirection.go

@@ -2,7 +2,6 @@ package redirection
 
 import (
 	"encoding/json"
-	"fmt"
 	"log"
 	"os"
 	"path"
@@ -111,6 +110,42 @@ func (t *RuleTable) AddRedirectRule(redirectURL string, destURL string, forwardP
 	return nil
 }
 
+// Edit an existing redirection rule, the oldRedirectURL is used to find the rule to be edited
+func (t *RuleTable) EditRedirectRule(oldRedirectURL string, newRedirectURL string, destURL string, forwardPathname bool, statusCode int) error {
+	newRule := &RedirectRules{
+		RedirectURL:      newRedirectURL,
+		TargetURL:        destURL,
+		ForwardChildpath: forwardPathname,
+		StatusCode:       statusCode,
+	}
+
+	//Remove the old rule
+	t.DeleteRedirectRule(oldRedirectURL)
+
+	// Convert the redirectURL to a valid filename by replacing "/" with "-" and "." with "_"
+	filename := utils.ReplaceSpecialCharacters(newRedirectURL) + ".json"
+	filepath := path.Join(t.configPath, filename)
+
+	// Create a new file for writing the JSON data
+	file, err := os.Create(filepath)
+	if err != nil {
+		t.log("Error creating file "+filepath, err)
+		return err
+	}
+	defer file.Close()
+
+	err = json.NewEncoder(file).Encode(newRule)
+	if err != nil {
+		t.log("Error encoding JSON to file "+filepath, err)
+		return err
+	}
+
+	// Update the runtime map
+	t.rules.Store(newRedirectURL, newRule)
+
+	return nil
+}
+
 func (t *RuleTable) DeleteRedirectRule(redirectURL string) error {
 	// Convert the redirectURL to a valid filename by replacing "/" with "-" and "." with "_"
 	filename := utils.ReplaceSpecialCharacters(redirectURL) + ".json"
@@ -118,7 +153,6 @@ func (t *RuleTable) DeleteRedirectRule(redirectURL string) error {
 	// Create the full file path by joining the t.configPath with the filename
 	filepath := path.Join(t.configPath, filename)
 
-	fmt.Println(redirectURL, filename, filepath)
 	// Check if the file exists
 	if _, err := os.Stat(filepath); os.IsNotExist(err) {
 		return nil // File doesn't exist, nothing to delete

+ 43 - 0
redirect.go

@@ -78,6 +78,49 @@ func handleDeleteRedirectionRule(w http.ResponseWriter, r *http.Request) {
 	utils.SendOK(w)
 }
 
+func handleEditRedirectionRule(w http.ResponseWriter, r *http.Request) {
+	originalRedirectUrl, err := utils.PostPara(r, "originalRedirectUrl")
+	if err != nil {
+		utils.SendErrorResponse(w, "original redirect url cannot be empty")
+		return
+	}
+
+	newRedirectUrl, err := utils.PostPara(r, "newRedirectUrl")
+	if err != nil {
+		utils.SendErrorResponse(w, "redirect url cannot be empty")
+		return
+	}
+	destUrl, err := utils.PostPara(r, "destUrl")
+	if err != nil {
+		utils.SendErrorResponse(w, "destination url cannot be empty")
+	}
+
+	forwardChildpath, err := utils.PostPara(r, "forwardChildpath")
+	if err != nil {
+		//Assume true
+		forwardChildpath = "true"
+	}
+
+	redirectTypeString, err := utils.PostPara(r, "redirectType")
+	if err != nil {
+		redirectTypeString = "307"
+	}
+
+	redirectionStatusCode, err := strconv.Atoi(redirectTypeString)
+	if err != nil {
+		utils.SendErrorResponse(w, "invalid status code number")
+		return
+	}
+
+	err = redirectTable.EditRedirectRule(originalRedirectUrl, newRedirectUrl, destUrl, forwardChildpath == "true", redirectionStatusCode)
+	if err != nil {
+		utils.SendErrorResponse(w, err.Error())
+		return
+	}
+
+	utils.SendOK(w)
+}
+
 // Toggle redirection regex support. Note that this cost another O(n) time complexity to each page load
 func handleToggleRedirectRegexpSupport(w http.ResponseWriter, r *http.Request) {
 	enabled, err := utils.PostPara(r, "enable")

+ 78 - 8
web/components/redirection.html

@@ -13,7 +13,7 @@
                   <th>Destination URL</th>
                   <th class="no-sort">Copy Pathname</th>
                   <th class="no-sort">Status Code</th>
-                  <th class="no-sort">Remove</th>
+                  <th class="no-sort">Actions</th>
               </tr>
           </thead>
           <tbody id="redirectionRuleList">
@@ -163,13 +163,21 @@
         $("#redirectionRuleList").html("");
         $.get("/api/redirect/list", function(data){
             data.forEach(function(entry){
-                $("#redirectionRuleList").append(`<tr>
-                    <td><a href="${entry.RedirectURL}" target="_blank">${entry.RedirectURL}</a></td>
-                    <td>${entry.TargetURL}</td>
-                    <td>${entry.ForwardChildpath?"<i class='ui green checkmark icon'></i>":"<i class='ui red remove icon'></i>"}</td>
-                    <td>${entry.StatusCode==307?"Temporary Redirect (307)":"Moved Permanently (301)"}</td>
-                    <td><button onclick="deleteRule(this);" rurl="${encodeURIComponent(JSON.stringify(entry.RedirectURL))}" title="Delete redirection rule" class="ui mini red icon basic button"><i class="trash icon"></i></button></td>
-                </tr>`);
+              let encodedEntry = encodeURIComponent(JSON.stringify(entry));
+              let hrefURL = entry.RedirectURL;
+              if (!hrefURL.startsWith("http")){
+                hrefURL = "https://" + hrefURL;
+              }
+              $("#redirectionRuleList").append(`<tr>
+                  <td><a href="${hrefURL}" target="_blank">${entry.RedirectURL}</a></td>
+                  <td>${entry.TargetURL}</td>
+                  <td>${entry.ForwardChildpath?"<i class='ui green checkmark icon'></i>":"<i class='ui red remove icon'></i>"}</td>
+                  <td>${entry.StatusCode==307?"Temporary Redirect (307)":"Moved Permanently (301)"}</td>
+                  <td>
+                    <button onclick="editRule(this);" payload="${encodedEntry}" title="Edit redirection rule" class="ui mini blue icon basic button redirectEditBtn"><i class="edit icon"></i></button>
+                    <button onclick="deleteRule(this);" rurl="${encodeURIComponent(JSON.stringify(entry.RedirectURL))}" title="Delete redirection rule" class="ui mini red icon basic button"><i class="trash icon"></i></button>
+                  </td>
+              </tr>`);
             });
             
             if (data.length == 0){
@@ -180,6 +188,68 @@
     }
     initRedirectionRuleList();
 
+    function editRule(obj){
+      $(".redirectEditBtn").addClass("disabled");
+      let payload = JSON.parse(decodeURIComponent($(obj).attr("payload")));
+      let row = $(obj).closest("tr");
+      let redirectUrl = payload.RedirectURL;
+      let destUrl = payload.TargetURL;
+      let forwardChildpath = payload.ForwardChildpath;
+      let statusCode = payload.StatusCode;
+
+      row.html(`
+        <td>
+          <div class="ui small input">
+            <input type="text" value="${redirectUrl}" id="editRedirectUrl">
+          </div>
+        </td>
+        <td>
+          <div class="ui small input">
+            <input type="text" value="${destUrl}" id="editDestUrl">
+          </div>
+        </td>
+        <td><div class="ui toggle checkbox"><input type="checkbox" ${forwardChildpath ? "checked" : ""} id="editForwardChildpath"><label></label></div></td>
+        <td>
+          <div class="ui radio checkbox"><input type="radio" name="editStatusCode" value="307" ${statusCode == 307 ? "checked" : ""}><label>Temporary Redirect (307)</label></div><br>
+          <div class="ui radio checkbox"><input type="radio" name="editStatusCode" value="301" ${statusCode == 301 ? "checked" : ""}><label>Moved Permanently (301)</label></div>
+        </td>
+        <td>
+          <button onclick="saveEditRule(this);" payload="${encodeURIComponent(JSON.stringify(payload))}" class="ui mini green icon basic button"><i class="save icon"></i></button>
+          <button onclick="initRedirectionRuleList();" class="ui mini icon basic button"><i class="cancel icon"></i></button>
+        </td>
+      `);
+
+      $(".checkbox").checkbox();
+    }
+
+    function saveEditRule(obj){
+      let payload = JSON.parse(decodeURIComponent($(obj).attr("payload")));
+      let redirectUrl = $("#editRedirectUrl").val();
+      let destUrl = $("#editDestUrl").val();
+      let forwardChildpath = $("#editForwardChildpath").is(":checked");
+      let statusCode = parseInt($("input[name='editStatusCode']:checked").val());
+
+      $.cjax({
+        url: "/api/redirect/edit", 
+        method: "POST",
+        data: {
+            originalRedirectUrl: payload.RedirectURL,
+            newRedirectUrl: redirectUrl,
+            destUrl: destUrl,
+            forwardChildpath: forwardChildpath,
+            redirectType: statusCode,
+        },
+        success: function(data){
+            if (data.error != undefined){
+              msgbox(data.error, false);
+            }else{
+              msgbox("Redirection rule updated", true);
+              initRedirectionRuleList();
+            }
+        }
+      });
+    }
+
     function initRegexpSupportToggle(){
       $.get("/api/redirect/regex", function(data){
         //Set the checkbox initial state