Add bulk import for global firewall allow/block lists
Paste-in import: one CIDR/IP per line, optional comment after '#', blank/comment-only lines ignored - matches the format used by common public blocklist feeds (Spamhaus DROP, blocklist.de, etc.) so those can mostly be pasted in directly. Whole batch gets one list_type (allow or block). Reuses the existing single-entry validation, skips duplicates (by list_type+CIDR, including within the same paste), caps at 5000 lines, and reports imported/skipped/invalid counts plus per-line errors. New route: POST /firewall-lists/entries/import (admin-only). UI: a collapsible "Bulk import" section on the Global Firewall Lists page. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
eb1913d400
commit
77ba2b4799
@@ -47,6 +47,28 @@ Global Firewall Lists
|
||||
<button type="submit" class="btn btn-primary btn-sm mb-1">Add entry</button>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
<p><a data-toggle="collapse" href="#collapse_bulk_import" role="button" aria-expanded="false" aria-controls="collapse_bulk_import">Bulk import ▼</a></p>
|
||||
<div class="collapse" id="collapse_bulk_import">
|
||||
<div class="card card-body">
|
||||
<form id="frm_iplist_import">
|
||||
<div class="form-group">
|
||||
<label for="_iplist_import_type">List type for this batch</label>
|
||||
<select class="form-control form-control-sm" id="_iplist_import_type" style="width:10em">
|
||||
<option value="block">block</option>
|
||||
<option value="allow">allow</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="_iplist_import_text">Entries (one CIDR/IP per line)</label>
|
||||
<textarea class="form-control" id="_iplist_import_text" rows="10"
|
||||
placeholder="One CIDR or IP per line. Optional comment after '#'. Blank lines and lines starting with '#' are ignored. 203.0.113.0/24 198.51.100.5 # known scanner # this whole line is a comment"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-sm">Import</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p class="text-muted mb-1">Ruleset preview:</p>
|
||||
<pre id="_iplist_preview_text" style="max-height: 30vh; overflow:auto;"></pre>
|
||||
@@ -135,6 +157,39 @@ Global Firewall Lists
|
||||
});
|
||||
});
|
||||
|
||||
$("#frm_iplist_import").on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const data = {
|
||||
list_type: $("#_iplist_import_type").val(),
|
||||
text: $("#_iplist_import_text").val()
|
||||
};
|
||||
$.ajax({
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
url: '{{.basePath}}/firewall-lists/entries/import',
|
||||
dataType: 'json',
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(data),
|
||||
success: function (result) {
|
||||
let summary = "Imported " + result.imported + ", skipped " + result.skipped_duplicates + " duplicates";
|
||||
if (result.invalid_count > 0) {
|
||||
summary += ", " + result.invalid_count + " invalid lines";
|
||||
console.warn("Bulk import invalid lines:", result.invalid_lines);
|
||||
toastr.warning(summary);
|
||||
} else {
|
||||
toastr.success(summary);
|
||||
}
|
||||
$("#_iplist_import_text").val("");
|
||||
loadIPList();
|
||||
refreshGlobalPreview();
|
||||
},
|
||||
error: function (jqXHR) {
|
||||
const responseJson = jQuery.parseJSON(jqXHR.responseText);
|
||||
toastr.error(responseJson['message'] || "Import failed");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#_iplist_tbody").on('click', '.btn-delete-iplist', function () {
|
||||
const id = $(this).data('id');
|
||||
if (!confirm("Delete this entry?")) return;
|
||||
|
||||
Reference in New Issue
Block a user