diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/LvtemplateController.php b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/LvtemplateController.php
new file mode 100644
index 000000000..b19958bd9
--- /dev/null
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/LvtemplateController.php
@@ -0,0 +1,71 @@
+searchBase(
+ "templates.template",
+ array('name', 'filters', 'or'), "name", null, SORT_NATURAL|SORT_FLAG_CASE
+ );
+ }
+
+ public function setItemAction($uuid)
+ {
+ return $this->setBase("template", "templates.template", $uuid);
+ }
+
+ public function addItemAction()
+ {
+ return $this->addBase("template", "templates.template");
+ }
+
+ public function getItemAction($uuid = null)
+ {
+ return $this->getBase("template", "templates.template", $uuid);
+ }
+
+ public function delItemAction($uuid)
+ {
+ return $this->delBase("templates.template", $uuid);
+ }
+
+}
diff --git a/src/opnsense/mvc/app/models/OPNsense/Diagnostics/Lvtemplate.php b/src/opnsense/mvc/app/models/OPNsense/Diagnostics/Lvtemplate.php
new file mode 100644
index 000000000..40262ed97
--- /dev/null
+++ b/src/opnsense/mvc/app/models/OPNsense/Diagnostics/Lvtemplate.php
@@ -0,0 +1,36 @@
+
+ //OPNsense/Firewall/Lvtemplate
+ 0.0.1
+ Firewall Live View filter templates
+
+
+
+
+ Y
+ /^.{1,255}$/u
+ Should be a string between 1 and 255 characters.
+
+
+ 0
+ Y
+
+
+ Y
+
+
+
+
+
diff --git a/src/opnsense/mvc/app/views/OPNsense/Diagnostics/fw_log.volt b/src/opnsense/mvc/app/views/OPNsense/Diagnostics/fw_log.volt
index 416e57d5f..06b60b69d 100644
--- a/src/opnsense/mvc/app/views/OPNsense/Diagnostics/fw_log.volt
+++ b/src/opnsense/mvc/app/views/OPNsense/Diagnostics/fw_log.volt
@@ -1,6 +1,6 @@
{#
#
- # Copyright (c) 2014-2016 Deciso B.V.
+ # Copyright (c) 2014-2021 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@@ -37,7 +37,7 @@
let hostnameMap = {};
/**
- * reverse lookup address fields (replace adres part for hostname if found)
+ * reverse lookup address fields (replace address part for hostname if found)
*/
function reverse_lookup() {
let to_fetch = [];
@@ -74,6 +74,139 @@
}
}
+ /**
+ * set new selection
+ * @param items list of lexical expressions
+ * @param operator enable or disable global OR operator
+ */
+ function set_selection(items, operator)
+ {
+ // remove old selection
+ $("#filters > span.badge").click();
+ // collect valid condition types
+ let conditions = [];
+ $("#filter_condition > option").each(function(){
+ conditions.push($(this).val());
+ });
+ items.forEach(function(value) {
+ let parts = value.split(new RegExp("("+conditions.join("|")+")(.+)$"));
+ if (parts.length >= 3 && $("#filter_tag").val(parts[0]).val() === parts[0] ) {
+ $("#filter_tag").val(parts[0]);
+ $("#filter_condition").val(parts[1]);
+ $("#filter_value").val(parts[2]);
+ $("#add_filter_condition").click();
+ } else if (value.toLowerCase() == "or=1") {
+ operator = "1";
+ }
+ });
+ $("#filter_or_type").prop('checked', operator === "1" ? true : false);
+ $(".selectpicker").selectpicker('refresh');
+ $("#filter_tag").change();
+ }
+
+ /**
+ * add new filters template
+ * @param t_data template's parameters
+ */
+ function addTemplate(t_data) {
+ ajaxCall('/api/diagnostics/lvtemplate/addItem/', t_data, function(data, status) {
+ if (data.result == "saved") {
+ fetchTemplates(data.uuid);
+ } else {
+ BootstrapDialog.show({
+ type: BootstrapDialog.TYPE_DANGER,
+ title: "{{ lang._('Add filters template') }}",
+ message: "{{ lang._('Template save failed. Message: ') }}" + data.result,
+ buttons: [{
+ label: "{{ lang._('Close') }}",
+ action: function (dialogRef) {
+ dialogRef.close();
+ }
+ }]
+ });
+ fetchTemplates("00000");
+ }
+ })
+ }
+
+ /**
+ * set template new values
+ * @param t_id template uuid
+ * @param t_data template's parameters
+ */
+ function editTemplate(t_id, t_data) {
+ ajaxCall('/api/diagnostics/lvtemplate/setItem/' + t_id, t_data, function(data, status) {
+ if (data.result == "saved") {
+ fetchTemplates(t_id);
+ } else {
+ BootstrapDialog.show({
+ type: BootstrapDialog.TYPE_DANGER,
+ title: "{{ lang._('Filters template edit') }}",
+ message: "{{ lang._('Template edit failed. Message: ') }}" + data.result,
+ buttons: [{
+ label: "{{ lang._('Close') }}",
+ action: function (dialogRef) {
+ dialogRef.close();
+ }
+ }]
+ });
+ fetchTemplates(t_id);
+ }
+ })
+ }
+
+ /**
+ * delete filters template
+ * @param t_id template uuid
+ */
+ function delTemplate(t_id) {
+ ajaxCall('/api/diagnostics/lvtemplate/delItem/' + t_id, {}, function(data, status) {
+ if (data.result == "deleted") {
+ //don't reset current filters so template can be restored right after delete
+ $("#templates option[value=" + t_id + "]").remove();
+ $("#templates").val("").selectpicker('refresh');
+ } else {
+ BootstrapDialog.show({
+ type: BootstrapDialog.TYPE_DANGER,
+ title: "{{ lang._('Filters template delete') }}",
+ message: "{{ lang._('Template delete failed. Result: ') }}" + data.result,
+ buttons: [{
+ label: "{{ lang._('Close') }}",
+ action: function (dialogRef) {
+ dialogRef.close();
+ }
+ }]
+ });
+ }
+ })
+ }
+
+ /**
+ * fetch templates from config
+ * @param opt select value to make :selected and apply
+ */
+ function fetchTemplates(opt) {
+ opt = opt || "00000";
+ //apply = apply || true;
+ $('#templ_name').val("");
+ $('#templates').empty();
+ $('#templates').append($('', {value: "00000", text: "None"}).data('template', {'filters': "0", 'or': "0"}).addClass("disp_none_opt templates"));
+ $('#templates').append($('', {value: "00001", text: "New"}).data('template', {'filters': "0", 'or': "0"}).data('icon','glyphicon-file').addClass("add_new_opt templ_save"));
+ $('#templates').selectpicker('refresh');
+ $('.templates').show();
+ $('.templ_save').hide();
+ ajaxGet('/api/diagnostics/lvtemplate/searchItem/', {}, function(data, status) {
+ let templates = data.rows;
+ $.each(templates, function(i, template) {
+ $('#templates').append(template.uuid == opt ? $('', {value:template.uuid, text:template.name, selected: "selected" }).data('template', template) : $('', {value:template.uuid, text:template.name }).data('template', template));
+ });
+ $('#templates').selectpicker('refresh');
+ $('.badge').click();
+ $("#templates").change();
+ });
+ }
+
+
function fetch_log() {
var record_spec = [];
// read heading, contains field specs
@@ -354,6 +487,95 @@
fetch_log();
});
+ // templates actions
+ $("#templates").change(function () {
+ if ($('#templ_save_start').is(':visible')) {
+ //apply chosen template
+ let t_data = $(this).find('option:selected').data('template') ? $(this).find('option:selected').data('template') : {'filters': "0", 'or': "0"};
+ set_selection(t_data.filters.split(','), t_data.or);
+ } else {
+ //choose template to modify or create new one. Show Name input if New option clicked
+ if ($('#templates').val() === "00001") {
+ $('#templates').selectpicker('hide');
+ $('#templ_name').show().focus();
+ }
+ }
+ });
+
+ $('#templ_save_start').click(function () {
+ if ($(".badge").text() == '') {
+ BootstrapDialog.show({
+ type: BootstrapDialog.TYPE_DANGER,
+ title: "{{ lang._('Save filters template') }}",
+ message: "{{ lang._('Filters not set') }}",
+ buttons: [{
+ label: "{{ lang._('Close') }}",
+ action: function (dialogRef) {
+ dialogRef.close();
+ }
+ }]
+ });
+ } else {
+ $('.templates').hide();
+ $('.templ_save').show();
+ $('#templ_name').focus();
+ if ($("#templates option").length == 3){
+ //no stored templates. skip to new template name
+ $('#templates').val("00001").selectpicker('refresh').change();
+ }
+ }
+ });
+
+ $("#templ_save_cancel").click(function () {
+ $('#templ_name').val("").hide();
+ $('.templ_save').hide();
+ $('.templates').show();
+ $('#templates').val('').selectpicker('refresh').selectpicker('show');
+ });
+
+ $("#templ_name").on('keyup', function (e) {
+ if (e.key === 'Enter' || e.keyCode === 13) {
+ $('#templ_save_apply').click();
+ } else if (e.keyCode === 27) {
+ $('#templ_name').val("").hide();
+ $('#templates').val('').selectpicker('refresh').selectpicker('show');
+ }
+ });
+
+ $("#templ_save_apply").click(function () {
+ let fltrs = "";
+ $('.badge').each(function () {
+ fltrs += $(this).text() + ",";
+ });
+ fltrs = fltrs.slice(0, -1);
+ let or = $('#filter_or_type').prop("checked") ? "1" : "0";
+ let t_data = {
+ 'template': {
+ 'filters': fltrs,
+ 'or': or
+ }
+ };
+ $('#templates').selectpicker('refresh').selectpicker('show');
+ if ($("#templ_name").val().length >= 1 && $("#templ_name").is(':visible')) {
+ //new template
+ t_data.template.name = $("#templ_name").val();
+ $('#templ_name').val("").hide();
+ addTemplate(t_data);
+ } else if ($("#templ_name").val().length == 0 && $("#templ_name").is(':hidden') && $("#templates").val().length == 36) {
+ //edit template
+ let t_id = $("#templates").val();
+ t_data.template.name = $("#templates option:selected").text();
+ editTemplate(t_id, t_data);
+ }
+ });
+
+ $("#template_delete").click(function () {
+ let t_id = $('#templates').val();
+ if (t_id.length == 36) {
+ delTemplate(t_id);
+ }
+ });
+
// fetch interface mappings on load
ajaxGet('/api/diagnostics/interface/getInterfaceNames', {}, function(data, status) {
interface_descriptions = data;
@@ -389,36 +611,14 @@
filter_value.show();
}
}).change();
+ fetchTemplates("00000");
}
});
+
});
- /**
- * set new selection
- * @param items list of lexical expressions
- */
- function set_selection(items)
- {
- // remove old selection
- $("#filters > span.badge").click();
- // collect valid condition types
- let conditions = [];
- $("#filter_condition > option").each(function(){
- conditions.push($(this).val());
- });
- items.forEach(function(value) {
- let parts = value.split(new RegExp("("+conditions.join("|")+")(.+)$"));
- if (parts.length >= 3 && $("#filter_tag").val(parts[0]).val() === parts[0] ) {
- $("#filter_tag").val(parts[0]);
- $("#filter_condition").val(parts[1]);
- $("#filter_value").val(parts[2]);
- $("#add_filter_condition").click();
- }
- });
- }
-
// get and apply url params. ie11 compat
- set_selection(window.location.search.substring(1).split("&"));
+ set_selection(window.location.search.substring(1).split("&"), "0");
// startup poller
poller();
@@ -473,7 +673,7 @@
- |