improve searchable generic report fields (#1133)
* implement links on all v4/v6/mac found in _searchable fields * word boundaries on matching
This commit is contained in:
1
Build.PL
1
Build.PL
@@ -79,6 +79,7 @@ Module::Build->new(
|
|||||||
'Plack::Middleware::ReverseProxy' => '0.15',
|
'Plack::Middleware::ReverseProxy' => '0.15',
|
||||||
'Pod::Usage' => 0,
|
'Pod::Usage' => 0,
|
||||||
'Regexp::Common' => 2017060201,
|
'Regexp::Common' => 2017060201,
|
||||||
|
'Regexp::Common::net::CIDR' => 0,
|
||||||
'Role::Tiny' => '1.002005',
|
'Role::Tiny' => '1.002005',
|
||||||
'Scope::Guard' => 0,
|
'Scope::Guard' => 0,
|
||||||
'Sereal' => '0',
|
'Sereal' => '0',
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ use Path::Class 'file';
|
|||||||
use Storable 'dclone';
|
use Storable 'dclone';
|
||||||
use Safe;
|
use Safe;
|
||||||
|
|
||||||
|
use HTML::Entities 'encode_entities';
|
||||||
|
use Regexp::Common qw( RE_net_IPv4 RE_net_IPv6 RE_net_MAC RE_net_domain );
|
||||||
|
use Regexp::Common::net::CIDR ();
|
||||||
|
|
||||||
our ($config, @data);
|
our ($config, @data);
|
||||||
|
|
||||||
foreach my $report (@{setting('reports')}) {
|
foreach my $report (@{setting('reports')}) {
|
||||||
@@ -72,6 +76,48 @@ foreach my $report (@{setting('reports')}) {
|
|||||||
my @results = ((-f $munger) ? $compartment->rdo( $munger ) : @data);
|
my @results = ((-f $munger) ? $compartment->rdo( $munger ) : @data);
|
||||||
return if $@ or (0 == scalar @results);
|
return if $@ or (0 == scalar @results);
|
||||||
|
|
||||||
|
# searchable field support..
|
||||||
|
|
||||||
|
my $recidr4 = $RE{net}{CIDR}{IPv4}{-keep}; #RE_net_CIDR_IPv4(-keep);
|
||||||
|
my $rev4 = RE_net_IPv4(-keep);
|
||||||
|
my $rev6 = RE_net_IPv6(-keep);
|
||||||
|
my $remac = RE_net_MAC(-keep);
|
||||||
|
#my $redom = RE_net_domain(-keep, -nospace, -rfc1101);
|
||||||
|
|
||||||
|
foreach my $row (@results) {
|
||||||
|
foreach my $col (@column_order) {
|
||||||
|
next unless $column_config{$col}->{_searchable};
|
||||||
|
my $fields = (ref $row->{$col} ? $row->{$col} : [$row->{$col}]);
|
||||||
|
|
||||||
|
foreach my $f (@$fields) {
|
||||||
|
# seems too sensitive match to be useful :-(
|
||||||
|
#$f =~ s!\b${redom}\b!'<a href="'.
|
||||||
|
# uri_for('/search', {q => $1 .($2 ? "/$2" : '')})->path_query
|
||||||
|
# .'">'. encode_entities($1 .($2 ? "/$2" : '')) .'</a>'!gex;
|
||||||
|
|
||||||
|
$f =~ s!\b${recidr4}\b!'<a href="'.
|
||||||
|
uri_for('/search', {q => "$1/$2"})->path_query
|
||||||
|
.'">'. encode_entities("$1/$2") .'</a>'!gex;
|
||||||
|
|
||||||
|
if (not $1 and not $2) {
|
||||||
|
$f =~ s!\b${rev4}\b!'<a href="'.
|
||||||
|
uri_for('/search', {q => $1})->path_query
|
||||||
|
.'">'. encode_entities($1) .'</a>'!gex;
|
||||||
|
}
|
||||||
|
|
||||||
|
$f =~ s!\b${rev6}\b!'<a href="'.
|
||||||
|
uri_for('/search', {q => $1})->path_query
|
||||||
|
.'">'. encode_entities($1) .'</a>'!gex;
|
||||||
|
|
||||||
|
$f =~ s!\b${remac}\b!'<a href="'.
|
||||||
|
uri_for('/search', {q => $1})->path_query
|
||||||
|
.'">'. encode_entities($1) .'</a>'!gex;
|
||||||
|
|
||||||
|
$row->{$col} = $f if not ref $row->{$col};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (request->is_ajax) {
|
if (request->is_ajax) {
|
||||||
template 'ajax/report/generic_report.tt',
|
template 'ajax/report/generic_report.tt',
|
||||||
{ results => \@results,
|
{ results => \@results,
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ system_reports:
|
|||||||
label: 'Blocked - Error-Disabled'
|
label: 'Blocked - Error-Disabled'
|
||||||
category: Port
|
category: Port
|
||||||
columns:
|
columns:
|
||||||
- { ip: Device }
|
- { ip: Device, _searchable: true }
|
||||||
- { dns: DNS }
|
- { dns: DNS }
|
||||||
- { port: Port }
|
- { port: Port }
|
||||||
- { name: Description }
|
- { name: Description }
|
||||||
@@ -259,12 +259,12 @@ system_reports:
|
|||||||
HAVING count(vlan) > COALESCE(NULLIF(?,''), '1') ::integer
|
HAVING count(vlan) > COALESCE(NULLIF(?,''), '1') ::integer
|
||||||
ORDER BY vlans DESC, ip ASC, port ASC
|
ORDER BY vlans DESC, ip ASC, port ASC
|
||||||
- tag: duplicateprivatenetworks
|
- tag: duplicateprivatenetworks
|
||||||
category: Port
|
category: IP
|
||||||
label: 'Duplicate Private Networks'
|
label: 'Duplicate Private Networks'
|
||||||
columns:
|
columns:
|
||||||
- { subnet: 'Subnet', _searchable: true }
|
- { subnet: 'Subnet', _searchable: true }
|
||||||
- { count: 'Instances' }
|
- { count: 'Instances' }
|
||||||
- { seen: 'Where Seen' }
|
- { seen: 'Where Seen', _searchable: true }
|
||||||
query: |
|
query: |
|
||||||
SELECT subnet, count(subnet), array_agg(host(alias)::text || ' on ' || host(ip)::text) AS seen
|
SELECT subnet, count(subnet), array_agg(host(alias)::text || ' on ' || host(ip)::text) AS seen
|
||||||
FROM device_ip
|
FROM device_ip
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<td>
|
<td>
|
||||||
[% FOREACH record IN row.item(col) %]
|
[% FOREACH record IN row.item(col) %]
|
||||||
[% IF column_options.$col._searchable %]
|
[% IF column_options.$col._searchable %]
|
||||||
<a href="[% uri_for('/search') | none %]?q=[% record | uri %]">[% record | html_entity %]</a>
|
[% record | none %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
[% record | html_entity %]
|
[% record | html_entity %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|||||||
Reference in New Issue
Block a user