]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[WebUI] Add deletion of specific fuzzy hashes
authorAlexander Moisseev <moiseev@mezonplus.ru>
Thu, 8 May 2025 15:31:38 +0000 (18:31 +0300)
committerAlexander Moisseev <moiseev@mezonplus.ru>
Thu, 8 May 2025 15:31:38 +0000 (18:31 +0300)
interface/index.html
interface/js/app/upload.js

index 8329a74ddd1502337c8d486e27587c2f605c855c..14dd880dccc3a73f5da18ab4b1666f517efb0f38 100644 (file)
                                                </div>
                                        </div>
                                        <div class="card-body">
-                                               <div class="row">
-                                                       <div class="col-lg-6">
+                                               <div class="row g-3">
+                                                       <div class="col-lg-auto d-flex">
                                                                <div class="card bg-light shadow card-body card p-2">
                                                                        <p>Learn Bayesian classifier:</p>
                                                                        <form>
                                                                        </form>
                                                                </div>
                                                        </div>
-                                                       <div class="col-lg-6">
-                                                               <div class="card bg-light shadow card-body card p-2">
+                                                       <div class="col-lg d-flex">
+                                                               <div class="card bg-light shadow card-body p-2">
                                                                        <p>Fuzzy hash storage management:</p>
-                                                                       <form class="d-flex">
-                                                                               <div class="d-flex align-items-center">
-                                                                                       <label for="fuzzyFlagText">Flag:</label>
-                                                                                       <input name="fuzzyFlagText" id="fuzzyFlagText" class="form-control ms-1" type="number" value="1"/>
+                                                                       <div class="row g-2 align-items-center">
+                                                                               <div class="col-auto d-flex align-items-center me-1">
+                                                                                       <label for="fuzzyFlagText" class="me-1">Flag:</label>
+                                                                                       <input id="fuzzyFlagText" class="form-control" type="number" value="1"/>
                                                                                </div>
-                                                                               <div class="d-flex align-items-center ms-2">
-                                                                                       <label for="fuzzyWeightText">Weight:</label>
-                                                                                       <input name="fuzzyWeightText" id="fuzzyWeightText" class="form-control ms-1" type="number" value="1"/>
+                                                                               <div class="col-auto d-flex align-items-center me-2">
+                                                                                       <label for="fuzzyWeightText" class="me-1">Weight:</label>
+                                                                                       <input id="fuzzyWeightText" class="form-control" type="number" value="1"/>
                                                                                </div>
-                                                                               <button class="btn btn-warning ms-2 d-flex align-items-center" data-upload="fuzzyadd" disabled><i class="fas fa-circle-plus me-2"></i>Add hash</button>
-                                                                               <button class="btn btn-danger ms-2 d-flex align-items-center" data-upload="fuzzydel" disabled><i class="fas fa-trash-can me-2"></i>Delete hash</button>
-                                                                       </form>
+                                                                               <div class="col-auto">
+                                                                                       <button class="btn btn-warning me-1" data-upload="fuzzyadd" disabled><i class="fas fa-circle-plus me-2"></i>Add to storage</button>
+                                                                                       <button class="btn btn-danger" data-upload="fuzzydel" disabled><i class="fas fa-trash-can me-2"></i>Delete from storage</button>
+                                                                               </div>
+                                                                       </div>
+                                                                       <div class="row mt-3">
+                                                                               <div class="col">
+                                                                                       <label for="fuzzyDelList" class="form-label">Hashes to delete</label>
+                                                                                       <textarea class="form-control" id="fuzzyDelList" rows="3" placeholder="Enter one hash per line, or separate with commas, semicolons, or spaces."></textarea>
+                                                                               </div>
+                                                                       </div>
+                                                                       <div class="row mt-2">
+                                                                               <div class="col d-flex justify-content-end">
+                                                                                       <button class="btn btn-danger me-2" id="deleteHashesBtn" disabled>
+                                                                                               <i class="fas fa-trash-can me-2"></i><span class="btn-label">Delete hashes</span>
+                                                                                       </button>
+                                                                                       <button class="btn btn-secondary" id="clearHashesBtn" disabled>
+                                                                                               <i class="fas fa-eraser me-2"></i>Clear
+                                                                                       </button>
+                                                                               </div>
+                                                                       </div>
                                                                </div>
                                                        </div>
                                                </div>
index d8519629649f7fb058948a1b814fcffebaac05cd..2ad3153841794abcd7de85369ab8191d8eaa308b 100644 (file)
@@ -36,7 +36,9 @@ define(["jquery", "app/common", "app/libft"],
             $("#" + source + "TextSource").val("");
         }
 
-        function uploadText(data, source, headers) {
+        function uploadText(data, source, headers, method = "POST") {
+            const deferred = new $.Deferred();
+
             let url = null;
             if (source === "spam") {
                 url = "learnspam";
@@ -46,6 +48,8 @@ define(["jquery", "app/common", "app/libft"],
                 url = "fuzzyadd";
             } else if (source === "fuzzydel") {
                 url = "fuzzydel";
+            } else if (source === "fuzzydelhash") {
+                url = "fuzzydelhash";
             } else if (source === "scan") {
                 url = "checkv2";
             }
@@ -64,7 +68,7 @@ define(["jquery", "app/common", "app/libft"],
                 params: {
                     processData: false,
                 },
-                method: "POST",
+                method: method,
                 headers: headers,
                 success: function (json, jqXHR) {
                     cleanTextUpload(source);
@@ -72,13 +76,17 @@ define(["jquery", "app/common", "app/libft"],
                     if (jqXHR.status !== 200) {
                         common.alertMessage("alert-info", jqXHR.statusText);
                     }
+                    deferred.resolve();
                 },
+                complete: () => deferred.resolve(),
                 server: server()
             });
+
+            return deferred.promise();
         }
 
         function enable_disable_scan_btn(disable) {
-            $("#scan button:not(#cleanScanHistory, #scanOptionsToggle, .ft-columns-btn)")
+            $("#scan button:not(#cleanScanHistory, #deleteHashesBtn, #scanOptionsToggle, .ft-columns-btn)")
                 .prop("disabled", (disable || $.trim($("textarea").val()).length === 0));
         }
 
@@ -265,6 +273,57 @@ define(["jquery", "app/common", "app/libft"],
             return false;
         });
 
+
+        function setDelhashButtonsDisabled(disabled = true) {
+            ["#deleteHashesBtn", "#clearHashesBtn"].forEach((s) => $(s).prop("disabled", disabled));
+        }
+
+        /**
+         * Parse a textarea (or any input) value into an array of non-empty tokens.
+         * Splits on commas, semicolons or any whitespace (space, tab, newline).
+         *
+         * @param {string} selector - jQuery selector for the input element.
+         * @returns {string[]} - Trimmed, non-empty tokens.
+         */
+        function parseHashes(selector) {
+            return $(selector).val()
+                .split(/[,\s;]+/)
+                .map((t) => t.trim())
+                .filter((t) => t.length > 0);
+        }
+
+        $("#fuzzyDelList").on("input", () => {
+            const hasTokens = parseHashes("#fuzzyDelList").length > 0;
+            setDelhashButtonsDisabled(!hasTokens);
+        });
+
+        $("#deleteHashesBtn").on("click", () => {
+            $("#fuzzyDelList").prop("disabled", true);
+            setDelhashButtonsDisabled();
+            $("#deleteHashesBtn").find(".btn-label").text("Deleting…");
+
+            const hashes = parseHashes("#fuzzyDelList");
+            const promises = hashes.map((h) => {
+                const headers = {
+                    flag: $("#fuzzyFlagText").val(),
+                    Hash: h
+                };
+                return uploadText(null, "fuzzydelhash", headers, "GET");
+            });
+
+            $.when.apply($, promises).always(() => {
+                $("#fuzzyDelList").prop("disabled", false);
+                setDelhashButtonsDisabled(false);
+                $("#deleteHashesBtn").find(".btn-label").text("Delete hashes");
+            });
+        });
+
+        $("#clearHashesBtn").on("click", () => {
+            $("#fuzzyDelList").val("").focus();
+            setDelhashButtonsDisabled();
+        });
+
+
         function fileInputHandler(obj) {
             ({files} = obj);
             filesIdx = 0;