diff --git a/Netdisco/lib/Netdisco/DB/Result/Device.pm b/Netdisco/lib/Netdisco/DB/Result/Device.pm index b1f330fa..5c3221c3 100644 --- a/Netdisco/lib/Netdisco/DB/Result/Device.pm +++ b/Netdisco/lib/Netdisco/DB/Result/Device.pm @@ -82,6 +82,7 @@ __PACKAGE__->set_primary_key("ip"); # Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-07 14:20:02 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:671/XuuvsO2aMB1+IRWFjg +__PACKAGE__->has_many( device_ips => 'Netdisco::DB::Result::DeviceIp', 'ip' ); __PACKAGE__->has_many( vlans => 'Netdisco::DB::Result::DeviceVlan', 'ip' ); __PACKAGE__->has_many( ports => 'Netdisco::DB::Result::DevicePort', 'ip' ); __PACKAGE__->has_many( diff --git a/Netdisco/lib/Netdisco/DB/Result/DeviceIp.pm b/Netdisco/lib/Netdisco/DB/Result/DeviceIp.pm index c49f7d6b..97667f05 100644 --- a/Netdisco/lib/Netdisco/DB/Result/DeviceIp.pm +++ b/Netdisco/lib/Netdisco/DB/Result/DeviceIp.pm @@ -34,6 +34,6 @@ __PACKAGE__->set_primary_key("ip", "alias"); # Created by DBIx::Class::Schema::Loader v0.07015 @ 2012-01-07 14:20:02 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/ugGtBSGyrJ7s6yqJ9bclQ +__PACKAGE__->belongs_to( device => 'Netdisco::DB::Result::Device', 'ip' ); -# You can replace this text with custom code or comments, and it will be preserved on regeneration 1; diff --git a/Netdisco/lib/Netdisco/DB/ResultSet/Device.pm b/Netdisco/lib/Netdisco/DB/ResultSet/Device.pm index e28b1d96..6dc34a53 100644 --- a/Netdisco/lib/Netdisco/DB/ResultSet/Device.pm +++ b/Netdisco/lib/Netdisco/DB/ResultSet/Device.pm @@ -1,6 +1,97 @@ package Netdisco::DB::ResultSet::Device; use base 'DBIx::Class::ResultSet'; +use NetAddr::IP::Lite ':lower'; + +# finds distinct values of a col for use in form selections +sub get_distinct { + my ($set, $col) = @_; + return $set unless $col; + + return $set->search({}, + { + columns => [$col], + order_by => $col, + distinct => 1 + } + )->get_column($col)->all; +} + +sub by_field { + my ($set, $p) = @_; + return $set unless ref {} eq ref $p; + my $op = $p->{matchall} ? '-and' : '-or'; + + # this is a bit of a dreadful hack to catch junk entry + # whilst avoiding returning all devices in the DB + my $ip = ($p->{ip} ? + (NetAddr::IP::Lite->new($p->{ip}) || NetAddr::IP::Lite->new('255.255.255.255')) + : undef); + + return $set->search( + { + $op => [ + ($p->{name} ? ('me.name' => + { '-ilike' => "\%$p->{name}\%" }) : ()), + ($p->{location} ? ('me.location' => + { '-ilike' => "\%$p->{location}\%" }) : ()), + ($p->{description} ? ('me.description' => + { '-ilike' => "\%$p->{description}\%" }) : ()), + ($p->{model} ? ('me.model' => + { '-in' => $p->{model} }) : ()), + ($p->{os_ver} ? ('me.os_ver' => + { '-in' => $p->{os_ver} }) : ()), + ($p->{vendor} ? ('me.vendor' => + { '-in' => $p->{vendor} }) : ()), + ($p->{dns} ? ( + -or => [ + 'me.dns' => { '-ilike' => "\%$p->{dns}\%" }, + 'device_ips.dns' => { '-ilike' => "\%$p->{dns}\%" }, + ]) : ()), + ($ip ? ( + -or => [ + 'me.ip' => { '<<=' => $ip->cidr }, + 'device_ips.alias' => { '<<=' => $ip->cidr }, + ]) : ()), + ], + }, + { + join => 'device_ips', + group_by => 'me.ip', + } + ); +} + +sub by_any { + my ($set, $q) = @_; + return $set unless $q; + $q = "\%$q\%" if $q !~ m/\%/; + + return $set->search( + { + -or => [ + 'me.contact' => { '-ilike' => $q }, + 'me.serial' => { '-ilike' => $q }, + 'me.location' => { '-ilike' => $q }, + 'me.name' => { '-ilike' => $q }, + 'me.description' => { '-ilike' => $q }, + -or => [ + 'me.dns' => { '-ilike' => $q }, + 'device_ips.dns' => { '-ilike' => $q }, + ], + -or => [ + 'me.ip::text' => { '-ilike' => $q }, + 'device_ips.alias::text' => { '-ilike' => $q }, + ], + ], + }, + { + join => 'device_ips', + group_by => 'me.ip', + } + ); +} + sub carrying_vlan { my ($set, $vlan) = @_; return $set unless $vlan and $vlan =~ m/^\d+$/; @@ -19,5 +110,4 @@ sub carrying_vlan { ); } - 1; diff --git a/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm b/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm index deeb3c3e..605d169a 100644 --- a/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm +++ b/Netdisco/lib/Netdisco/DB/ResultSet/DevicePort.pm @@ -26,6 +26,7 @@ sub by_mac { sub by_name { my ($set, $name) = @_; return $set unless $name; + $name = "\%$name\%" if $name !~ m/\%/; return $set->search( { diff --git a/Netdisco/lib/Netdisco/Web.pm b/Netdisco/lib/Netdisco/Web.pm index 91a04690..fdc5519a 100644 --- a/Netdisco/lib/Netdisco/Web.pm +++ b/Netdisco/lib/Netdisco/Web.pm @@ -8,6 +8,7 @@ use Digest::MD5 (); use Socket6 (); # to ensure dependency is met use NetAddr::IP::Lite ':lower'; use Net::MAC (); +use List::MoreUtils (); hook 'before' => sub { if (! session('user') && request->path !~ m{^/login}) { @@ -20,20 +21,50 @@ hook 'before' => sub { if (not param('tab') or param('tab') ne 'node') { params->{'stamps'} = 'checked'; } + if (not param('tab') or param('tab') ne 'device') { + params->{'matchall'} = 'matchall'; + } - # set up query string defaults for templates + # set up query string defaults, + # only for templates which link to themselves (node) var('query_defaults' => { map { ($_ => "tab=$_") } qw/node/ }); var('query_defaults')->{node} .= "\&$_=". (param($_) || '') for qw/stamps vendor archived partial/; + + # set up property lists for device search + var('model_list' => [ + schema('netdisco')->resultset('Device')->get_distinct('model') + ]); + var('os_ver_list' => [ + schema('netdisco')->resultset('Device')->get_distinct('os_ver') + ]); + var('vendor_list' => [ + schema('netdisco')->resultset('Device')->get_distinct('vendor') + ]); }; -get '/' => sub { - template 'index'; -}; +# device with various properties or a default match-all +ajax '/ajax/content/search/device' => sub { + my $has_opt = List::MoreUtils::any {param($_)} + qw/name location dns ip description model os_ver vendor/; + my $set; + + if ($has_opt) { + $set = schema('netdisco')->resultset('Device')->by_field(scalar params); + return unless $set->count; + } + else { + my $q = param('q'); + return unless $q; + + $set = schema('netdisco')->resultset('Device')->by_any($q); + return unless $set->count; + } -ajax '/ajax/content/search/:thing' => sub { content_type('text/html'); - return '

Hello '. param('thing') .'.

'; + template 'ajax/device.tt', { + results => $set, + }, { layout => undef }; }; # nodes matching the param as an IP or DNS hostname or MAC @@ -111,6 +142,10 @@ ajax '/ajax/content/search/port' => sub { }, { layout => undef }; }; +get '/' => sub { + template 'index'; +}; + get '/search' => sub { my $q = param('q'); if ($q and not param('tab')) { diff --git a/Netdisco/views/ajax/device.tt b/Netdisco/views/ajax/device.tt new file mode 100644 index 00000000..7b31c6d0 --- /dev/null +++ b/Netdisco/views/ajax/device.tt @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + [% WHILE (row = results.next) %] + + + + + + + + + + + + [% END %] + +
DeviceContactLocationSystem NameModelOS VersionManagement IPSerial
[% row.dns.remove(settings.domain_suffix) %][% row.contact %][% row.location %][% row.name %][% row.model %][% row.os_ver %][% row.ip %][% row.serial %]
diff --git a/Netdisco/views/ajax/port.tt b/Netdisco/views/ajax/port.tt index ecfa0ba7..230fa836 100644 --- a/Netdisco/views/ajax/port.tt +++ b/Netdisco/views/ajax/port.tt @@ -2,20 +2,20 @@ Name + Port Description Vlan - Port [% WHILE (row = results.next) %] [% row.name %] - [% row.descr %] - [% row.vlan %] [% row.ip %] [ [% row.port %] ] [% ' (' _ row.device.dns.remove(settings.domain_suffix) _ ')' IF row.device.dns %] - + + [% row.descr %] + [% row.vlan %] [% END %] diff --git a/Netdisco/views/inc/search/device.tt b/Netdisco/views/inc/search/device.tt new file mode 100644 index 00000000..b4adc672 --- /dev/null +++ b/Netdisco/views/inc/search/device.tt @@ -0,0 +1,62 @@ + +

Device Search Options

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
diff --git a/Netdisco/views/layouts/main.tt b/Netdisco/views/layouts/main.tt index 8ae718dc..ce45639e 100644 --- a/Netdisco/views/layouts/main.tt +++ b/Netdisco/views/layouts/main.tt @@ -19,7 +19,7 @@