diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Unbound/Api/OverviewController.php b/src/opnsense/mvc/app/controllers/OPNsense/Unbound/Api/OverviewController.php index 09e3961b8b..7c51262d8b 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Unbound/Api/OverviewController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Unbound/Api/OverviewController.php @@ -36,23 +36,10 @@ use OPNsense\Firewall\Util; class OverviewController extends ApiControllerBase { private $mdl = null; - private $types = []; - private $nodes = []; public function __construct() { $this->mdl = new \OPNsense\Unbound\Unbound(); - $this->types = $this->mdl->dnsbl->blocklist->getTemplateNode()->type->getNodeData(); - $this->nodes = $this->mdl->dnsbl->blocklist->getNodes(); - } - - private function getBlocklistDescription($shortcode) - { - if (array_key_exists($shortcode, $this->types)) { - return $this->types[$shortcode]['value']; - } - - return null; } public function isEnabledAction() @@ -65,7 +52,8 @@ class OverviewController extends ApiControllerBase /* XXX deprecated and to be removed for 26.7 */ public function isBlockListEnabledAction() { - return ['enabled' => (bool)array_filter($this->nodes, fn($v) => $v['enabled'])]; + $nodes = $this->mdl->dnsbl->blocklist->getNodes(); + return ['enabled' => (bool)array_filter($nodes, fn($v) => $v['enabled'])]; } public function RollingAction($timeperiod, $clients = '0') @@ -108,10 +96,12 @@ class OverviewController extends ApiControllerBase } $parsed = json_decode($response, true) ?? []; + $policies = $this->getPoliciesAction(); + $types = $this->mdl->dnsbl->blocklist->getTemplateNode()->type->getNodeData(); foreach ($parsed as $idx => $query) { - $parsed[$idx]['blocklist'] ??= $this->getBlocklistDescription($query['blocklist']); - + $parsed[$idx]['blocklist'] = $types[$query['blocklist']]['value'] ?? $query['blocklist']; + $parsed[$idx]['policy'] = $policies[$query['uuid']]['description'] ?? ''; /* Handle front-end color status mapping, start off with OK */ $parsed[$idx]['status'] = 0; @@ -133,21 +123,14 @@ class OverviewController extends ApiControllerBase return $response; } - public function getPoliciesAction($uuid = null) + public function getPoliciesAction() { - $response = ['policies' => []]; + $response = []; foreach ($this->mdl->dnsbl->blocklist->iterateItems() as $policy_uuid => $policy) { - if ($uuid !== null && $uuid == $policy_uuid) { - $response = $policy->getNodeContent(); - $response['uuid'] = $policy_uuid; - break; - } - - $response['policies'][$policy_uuid] = $policy->getNodeContent(); + $response[$policy_uuid] = $policy->getNodeContent(); } - $response['blocklistDescriptions'] = $this->types; return $response; } } diff --git a/src/opnsense/mvc/app/views/OPNsense/Unbound/overview.volt b/src/opnsense/mvc/app/views/OPNsense/Unbound/overview.volt index e90b7f8bd1..99ea34f612 100644 --- a/src/opnsense/mvc/app/views/OPNsense/Unbound/overview.volt +++ b/src/opnsense/mvc/app/views/OPNsense/Unbound/overview.volt @@ -381,7 +381,7 @@ function createTopList(id, data, type, maxDomains = 10) { ajaxGet('/api/unbound/overview/get_policies', {}, function(policies, status) { - const enabled = Object.values(policies.policies).some(v => v.enabled === "1"); + const enabled = Object.values(policies).some(v => v.enabled === "1"); for (let i = 0; i < maxDomains; i++) { let category = type === 'block' ? data.top_blocked : data.top; let domain = Object.keys(category)[i]; @@ -411,7 +411,7 @@ openPoliciesDialog(domain, uuid, action, statObj?.blocklist ?? ""); }); - let bl = (uuid && uuid in policies.policies) ? `(${policies.policies[uuid].description})` : ''; + let bl = (uuid && uuid in policies) ? `(${policies[uuid].description})` : ''; let $li = $(`
  • @@ -564,20 +564,29 @@ const cleanDomain = domain.replace(/\.$/, ""); ajaxGet('/api/unbound/overview/get_policies', {}, function (data, status) { + let $container = $('
    '); + const enabled = Object.values(data).some(v => v.enabled === "1"); + + if (!enabled) { + $container.html(` + {{ lang._('There are no blocklist policies defined. You can create them %shere%s') | format('', '') }} + `); + dialogRef.setMessage($container); + return; + } + const $table = $(''); const $tbody = $(''); const $thead = $('').append( $('').append( - $(' +
    ').text("{{ lang._('Blocklist') }}"), + $('').text("{{ lang._('Policy') }}"), $('').text("{{ lang._('Source net(s)') }}"), $('').text("{{ lang._('Action') }}") ) ); $table.append($thead, $tbody); - const descriptions = data['blocklistDescriptions']; - - for (const [policy_uuid, policy] of Object.entries(data.policies)) { + for (const [policy_uuid, policy] of Object.entries(data)) { if (policy.enabled == '0') continue; const description = @@ -618,12 +627,14 @@ $tbody.append($tr); } - const blocklistMatch = descriptions[blocklist]?.value ?? blocklist; - $container = $(` -
    - {{ lang._('Blocklist match:')}} ${blocklistMatch} -
    - `); + if (blocklist != "") { + $container = $(` +
    + {{ lang._('Blocklist match:')}} ${blocklist} +
    + `); + } + $container.append($table); dialogRef.setMessage($container); @@ -663,108 +674,92 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { if (e.target.id == 'query_details_tab') { $("#grid-queries").bootgrid('destroy'); - ajaxGet('/api/unbound/overview/get_policies', {}, function(policies, status) { - const enabled = Object.values(policies.policies).some(v => v.enabled === "1"); - let grid_queries = $("#grid-queries").UIBootgrid({ - search:'/api/unbound/overview/search_queries/', - commands: { - action: { - title: "{{ lang._('Quick action') }}", - classname: 'fa fa-cogs', - sequence: 100, - filter: function(cell) { - const data = cell.getData(); - return enabled && (data.action == 'Pass' || data.action == 'Block'); - }, - onRendered: function(cell) { - const $el = $(this); - const data = cell.getData(); - const uuid = data.uuid; - const domain = data.domain; - const appliedAction = data.action; - const blocklist = data.blocklist; + let grid_queries = $("#grid-queries").UIBootgrid({ + search:'/api/unbound/overview/search_queries/', + commands: { + action: { + title: "{{ lang._('Quick action') }}", + classname: 'fa fa-cogs', + sequence: 100, + filter: function(cell) { + const data = cell.getData(); + return data.action == 'Pass' || data.action == 'Block'; + }, + onRendered: function(cell) { + const $el = $(this); + const data = cell.getData(); + const uuid = data.uuid; + const domain = data.domain; + const appliedAction = data.action; + const blocklist = data.blocklist; - $el.click(function() { - openPoliciesDialog(domain, uuid, appliedAction, blocklist); - }); - } + $el.click(function() { + openPoliciesDialog(domain, uuid, appliedAction, blocklist); + }); + } + } + }, + options: { + virtualDOM: true, + rowSelect: false, + multiSelect: false, + selection: false, + useRequestHandlerOnGet: true, + requestHandler: function(request) { + if (g_clientFilter != null && g_timeFilter != null) { + let timestamp = g_timeFilter / 1000; + let interval = $("#timeperiod-clients").val() == 1 ? 60 : 600; + + request['client'] = g_clientFilter; + request['timeStart'] = timestamp; + request['timeEnd'] = timestamp + interval; + } + + return request; + }, + formatters: { + "timeformatter": function (column, row) { + return moment.unix(row.time).local().format('YYYY-MM-DD HH:mm:ss'); + }, + "resolveformatter": function (column, row) { + return row.resolve_time_ms + 'ms'; + }, + "domain": function (column, row) { + return row.domain; } }, - options: { - virtualDOM: true, - rowSelect: false, - multiSelect: false, - selection: false, - useRequestHandlerOnGet: true, - requestHandler: function(request) { - if (g_clientFilter != null && g_timeFilter != null) { - let timestamp = g_timeFilter / 1000; - let interval = $("#timeperiod-clients").val() == 1 ? 60 : 600; - - request['client'] = g_clientFilter; - request['timeStart'] = timestamp; - request['timeEnd'] = timestamp + interval; - } - - return request; - }, - formatters: { - "timeformatter": function (column, row) { - return moment.unix(row.time).local().format('YYYY-MM-DD HH:mm:ss'); - }, - "resolveformatter": function (column, row) { - return row.resolve_time_ms + 'ms'; - }, - "domain": function (column, row) { - return row.domain; - }, - "blocklist": function (column, row) { - if (row.uuid && policies.policies[row.uuid]) { - return policies.policies[row.uuid].description; - } - - return ''; - } - }, - statusMapping: { - 0: "query-success", - 1: "query-info", - 2: "query-warning", - 3: "query-danger", - 4: "query-error" - } + statusMapping: { + 0: "query-success", + 1: "query-info", + 2: "query-warning", + 3: "query-danger", + 4: "query-error" } - }).on("loaded.rs.jquery.bootgrid", function (e) { - if (g_clientFilter != null && g_timeFilter != null && !$('#searchFilter').length) { - // Add a badge to signify we're in a drill-down - let label = (typeof g_labelFilter != 'undefined') ? g_labelFilter : g_clientFilter; - $('div.actionBar').prepend($('
    ')); - let timeStart = moment.unix(g_timeFilter / 1000).local().format('MM-DD HH:mm'); - let interval = $("#timeperiod-clients").val() == 1 ? 60 : 600; - let timeEnd = moment.unix((g_timeFilter / 1000) + interval).local().format('MM-DD HH:mm'); - $('#searchFilter').append('' + - label + ' (' + timeStart + ' - ' + timeEnd + ')' + - ''); + } + }).on("loaded.rs.jquery.bootgrid", function (e) { + if (g_clientFilter != null && g_timeFilter != null && !$('#searchFilter').length) { + // Add a badge to signify we're in a drill-down + let label = (typeof g_labelFilter != 'undefined') ? g_labelFilter : g_clientFilter; + $('div.actionBar').prepend($('
    ')); + let timeStart = moment.unix(g_timeFilter / 1000).local().format('MM-DD HH:mm'); + let interval = $("#timeperiod-clients").val() == 1 ? 60 : 600; + let timeEnd = moment.unix((g_timeFilter / 1000) + interval).local().format('MM-DD HH:mm'); + $('#searchFilter').append('' + + label + ' (' + timeStart + ' - ' + timeEnd + ')' + + ''); - $('#removeFilter').click(function(e) { - // Reset filters set by a client drill-down - g_clientFilter = null; - g_timeFilter = null; - g_labelFilter = null; - $('#searchFilter').remove(); - $('#grid-queries').bootgrid('reload'); - }) - } - - if (!enabled) { - $(".hide-col").css("display", "none"); - } else { - $(".hide-col").css('display', ''); - } - $(".domain-content").tooltip({placement: "auto left"}); - }); - }) + $('#removeFilter').click(function(e) { + // Reset filters set by a client drill-down + g_clientFilter = null; + g_timeFilter = null; + g_labelFilter = null; + $('#searchFilter').remove(); + $('#grid-queries').bootgrid('reload'); + }) + } + $(".domain-content").tooltip({placement: "auto left"}); + }); } if (e.target.id == 'query_overview_tab') { // Reset filters set by a client drill-down @@ -963,6 +958,7 @@
    {{ lang._('Resolve time') }} {{ lang._('TTL') }} {{ lang._('Blocklist') }}{{ lang._('Policy') }} {{ lang._('Commands') }}