mirror of
https://github.com/opnsense/core.git
synced 2026-02-18 18:18:13 -05:00
Firewall: Rules [new]: Add a command button to open the live log with prefilled rule ID (#9770)
fw_log.volt: Uses a url hash inside fw_log.volt to set a filter when opening it through a link from filter_rule.volt The url hash can set any type of a single filter, so it can be reused in other pages as well. Combine entry point of addCombinedFilter and addFilter, decide via array in field what type it is. Change init entrypoint to always go through the filterChange() pipeline, but have a fast path in there that initializes without a filter. This adds the filter immediately when loading with the page with the URL hash Make sure we want for tableBuilt to prevent replaceData errors filter_rule.volt Only show the log search button when row.log is 1 or true Change fa icon in the lookup rule reference button in dnat as well for consistency Use URLSearchParams() --------- Co-authored-by: Stephan de Wit <stephan.de.wit@deciso.com>
This commit is contained in:
parent
c6db10f564
commit
63e0b92278
3 changed files with 69 additions and 44 deletions
|
|
@ -273,8 +273,11 @@
|
|||
}
|
||||
|
||||
_init() {
|
||||
// pushes this.bufferSize entries to the models' buffer
|
||||
this.bucket.copyTo(this.viewBuffer, this.bufferSize);
|
||||
/**
|
||||
* Rebuild the view buffer from the raw bucket using the current filter state.
|
||||
* Acts as the single pipeline for init, filter updates, and bucket resets.
|
||||
*/
|
||||
this._filterChange();
|
||||
}
|
||||
|
||||
_onBucketEvent(event) {
|
||||
|
|
@ -437,10 +440,11 @@
|
|||
* search string modified). This function is idempotent.
|
||||
*/
|
||||
_filterChange() {
|
||||
const { fn, reset } = this._buildFilterFn();
|
||||
const { fn, isNoop } = this._buildFilterFn();
|
||||
|
||||
if (reset) {
|
||||
this._init();
|
||||
if (isNoop) {
|
||||
// pure init without any filters
|
||||
this.bucket.copyTo(this.viewBuffer, this.bufferSize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -490,21 +494,15 @@
|
|||
/**
|
||||
* Example: { field: 'src', operator: '=', value: '192.168.1.1', format:'RFC1918' (optional) }
|
||||
* The optional 'format' parameter replaces the value for display purposes only
|
||||
* Combined filters are inferred when `field` is an array (e.g. ['src','dst'])
|
||||
*/
|
||||
addFilter(filter) {
|
||||
const id = this._hashFilter(filter);
|
||||
this.filterStore.filters[id] = filter;
|
||||
this._filterChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: { field: ['src', 'dst'], operator: '!=', value: '192.168.1.1' }
|
||||
* The meaning of a combined filter is dependent on the operator. In the case of a
|
||||
* positive operator, "OR" is used, otherwise "AND".
|
||||
*/
|
||||
addCombinedFilter(filter) {
|
||||
const id = this._hashFilter(filter);
|
||||
this.filterStore.combinedFilters[id] = filter;
|
||||
if (Array.isArray(filter.field)) {
|
||||
this.filterStore.combinedFilters[id] = filter;
|
||||
} else {
|
||||
this.filterStore.filters[id] = filter;
|
||||
}
|
||||
this._filterChange();
|
||||
}
|
||||
|
||||
|
|
@ -888,6 +886,18 @@
|
|||
location.reload();
|
||||
});
|
||||
|
||||
table.on('tableBuilt', () => {
|
||||
const params = new URLSearchParams(window.location.hash.slice(1));
|
||||
const field = params.get('field');
|
||||
const operator = params.get('operator');
|
||||
const value = params.get('value');
|
||||
|
||||
if (field && operator && value) {
|
||||
filterVM.addFilter({ field, operator, value });
|
||||
history.replaceState(null, '', location.pathname);
|
||||
}
|
||||
});
|
||||
|
||||
$apply.on('click', function () {
|
||||
const field = $filterField.val();
|
||||
const operator = $filterOperator.val();
|
||||
|
|
@ -896,10 +906,10 @@
|
|||
|
||||
switch (field) {
|
||||
case '__addr__':
|
||||
filterVM.addCombinedFilter({field: ['src', 'dst'], operator: operator, value: searchString});
|
||||
filterVM.addFilter({field: ['src', 'dst'], operator: operator, value: searchString});
|
||||
break;
|
||||
case '__port__':
|
||||
filterVM.addCombinedFilter({field: ['srcport', 'dstport'], operator: operator, value: searchString});
|
||||
filterVM.addFilter({field: ['srcport', 'dstport'], operator: operator, value: searchString});
|
||||
break;
|
||||
case 'interface':
|
||||
filterVM.addFilter({field: field, operator: operator, value: $interfaceSelect.val(), format: $interfaceSelect.find('option:selected').text()});
|
||||
|
|
@ -1207,11 +1217,7 @@
|
|||
};
|
||||
const {filters, mode} = parseTemplate(tmpl);
|
||||
for (const filter of filters) {
|
||||
if (Array.isArray(filter.field)) {
|
||||
filterVM.addCombinedFilter(filter);
|
||||
} else {
|
||||
filterVM.addFilter(filter);
|
||||
}
|
||||
filterVM.addFilter(filter);
|
||||
}
|
||||
filterVM.setFilterMode(mode);
|
||||
if (mode === 'OR') {
|
||||
|
|
|
|||
|
|
@ -139,10 +139,10 @@
|
|||
|
||||
if (!rowId.includes('-')) {
|
||||
return `
|
||||
<a href="/system_advanced_firewall.php"
|
||||
<a href="/system_advanced_firewall.php" target="_blank" rel="noopener noreferrer"
|
||||
class="btn btn-xs btn-default bootgrid-tooltip"
|
||||
title="{{ lang._('Lookup Rule') }}">
|
||||
<span class="fa fa-fw fa-search"></span>
|
||||
title="{{ lang._('Lookup rule reference') }}">
|
||||
<span class="fa fa-fw fa-link"></span>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,29 +235,46 @@
|
|||
},
|
||||
},
|
||||
formatters:{
|
||||
// Only show command buttons for rules that have a uuid, internal rules will not have one
|
||||
commands: function (column, row) {
|
||||
// All formatters except category must skip processing bucket rows in tree view
|
||||
if (row.isGroup) {
|
||||
return "";
|
||||
}
|
||||
let rowId = row.uuid;
|
||||
const rowId = row.uuid || "";
|
||||
const hasUuid = rowId.includes("-");
|
||||
|
||||
const logSearchCommand = (rid, log) => {
|
||||
const loggingEnabled = log === '1' || log === true;
|
||||
if (!loggingEnabled) return '';
|
||||
|
||||
return `
|
||||
<a href="/ui/diagnostics/firewall/log#${new URLSearchParams({field:'rid',operator:'=',value:rid})}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-xs btn-default bootgrid-tooltip"
|
||||
title="{{ lang._('View log entries for this rule') }}">
|
||||
<i class="fa fa-fw fa-search"></i>
|
||||
</a>
|
||||
`;
|
||||
};
|
||||
|
||||
// If UUID is invalid, its an internal rule, use the #ref field to show a lookup button.
|
||||
if (!rowId || !rowId.includes('-')) {
|
||||
let ref = row["ref"] || "";
|
||||
if (ref.trim().length > 0) {
|
||||
let url = `/${ref}`;
|
||||
return `
|
||||
<a href="${url}"
|
||||
class="btn btn-xs btn-default bootgrid-tooltip"
|
||||
title="{{ lang._('Lookup Rule') }}">
|
||||
<span class="fa fa-fw fa-search"></span>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
// If ref is empty
|
||||
return "";
|
||||
if (!hasUuid) {
|
||||
const ref = (row["ref"] || "");
|
||||
|
||||
// optional lookup button if ref exists
|
||||
const lookupRefCommand = ref ? `
|
||||
<a href="/${ref}" target="_blank" rel="noopener noreferrer"
|
||||
class="btn btn-xs btn-default bootgrid-tooltip"
|
||||
title="{{ lang._('Lookup rule reference') }}">
|
||||
<i class="fa fa-fw fa-link"></i>
|
||||
</a>
|
||||
` : '';
|
||||
|
||||
return `
|
||||
${logSearchCommand(rowId, row.log)}
|
||||
${lookupRefCommand}
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
|
|
@ -292,6 +309,8 @@
|
|||
title="{{ lang._('Delete') }}">
|
||||
<span class="fa fa-fw fa-trash-o"></span>
|
||||
</button>
|
||||
|
||||
${logSearchCommand(rowId, row.log)}
|
||||
`;
|
||||
},
|
||||
// Disable rowtoggle for internal rules
|
||||
|
|
@ -1129,7 +1148,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- grid -->
|
||||
{{ partial('layout_partials/base_bootgrid_table', formGridFilterRule + {'command_width': '150'}+ {
|
||||
{{ partial('layout_partials/base_bootgrid_table', formGridFilterRule + {'command_width': '180'}+ {
|
||||
'grid_commands': {
|
||||
'upload_rules': {
|
||||
'title': lang._('Import csv'),
|
||||
|
|
|
|||
Loading…
Reference in a new issue