relocate repo files so ND2 is the only code

This commit is contained in:
Oliver Gorwits
2017-04-14 23:08:55 +01:00
parent 9a016ea6ba
commit d23b32500f
469 changed files with 0 additions and 6920 deletions

View File

@@ -0,0 +1,41 @@
package App::Netdisco::Web::Plugin::Report::ApChannelDist;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Wireless',
tag => 'apchanneldist',
label => 'Access Point Channel Distribution',
provides_csv => 1,
}
);
get '/ajax/content/report/apchanneldist' => require_login sub {
my @results = schema('netdisco')->resultset('DevicePortWireless')->search(
{ channel => { '!=', '0' } },
{ select => [ 'channel', { count => 'channel' } ],
as => [qw/ channel ch_count /],
group_by => [qw/channel/],
order_by => { -desc => [qw/count/] },
},
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/apchanneldist.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/apchanneldist_csv.tt', { results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,51 @@
package App::Netdisco::Web::Plugin::Report::ApClients;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Wireless',
tag => 'apclients',
label => 'Access Point Client Count',
provides_csv => 1,
}
);
get '/ajax/content/report/apclients' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(
{ 'nodes.time_last' => { '>=', \'me.last_macsuck' } },
{ select => [ 'ip', 'dns', 'name', 'model', 'location' ],
join => { 'ports' => { 'ssid' => 'nodes' } },
'+columns' => [
{ 'port' => 'ports.port' },
{ 'description' => 'ports.name' },
{ 'ssid' => 'ssid.ssid' },
{ 'mac_count' => { count => 'nodes.mac' } },
],
group_by => [
'me.ip', 'me.dns', 'me.name', 'me.model',
'me.location', 'ports.port', 'ports.descr', 'ports.name', 'ssid.ssid',
],
order_by => { -desc => [qw/count/] },
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/apclients.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/apclients_csv.tt',
{ results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,58 @@
package App::Netdisco::Web::Plugin::Report::ApRadioChannelPower;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Util::ExpandParams 'expand_hash';
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Wireless',
tag => 'apradiochannelpower',
label => 'Access Point Radios Channel and Power',
provides_csv => 1,
}
);
get '/ajax/content/report/apradiochannelpower/data' => require_login sub {
send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('Virtual::ApRadioChannelPower');
my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count;
my @data = $rs->get_datatables_data($exp_params)->hri->all;
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
content_type 'application/json';
return to_json(
{ draw => int( param('draw') ),
recordsTotal => int($recordsTotal),
recordsFiltered => int($recordsFiltered),
data => \@data,
}
);
};
get '/ajax/content/report/apradiochannelpower' => require_login sub {
if ( request->is_ajax ) {
template 'ajax/report/apradiochannelpower.tt', {},
{ layout => undef };
}
else {
my @results
= schema('netdisco')->resultset('Virtual::ApRadioChannelPower')
->hri->all;
return unless scalar @results;
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/apradiochannelpower_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,42 @@
package App::Netdisco::Web::Plugin::Report::DeviceAddrNoDNS;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Device',
tag => 'deviceaddrnodns',
label => 'Addresses without DNS Entries',
provides_csv => 1,
}
);
get '/ajax/content/report/deviceaddrnodns' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(
{ 'device_ips.dns' => undef },
{ select => [ 'ip', 'dns', 'name', 'location', 'contact' ],
join => [qw/device_ips/],
'+columns' => [ { 'alias' => 'device_ips.alias' }, ],
order_by => { -asc => [qw/me.ip device_ips.alias/] },
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json (\@results);
template 'ajax/report/deviceaddrnodns.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/deviceaddrnodns_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,38 @@
package App::Netdisco::Web::Plugin::Report::DeviceByLocation;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Device',
tag => 'devicebylocation',
label => 'By Location',
provides_csv => 1,
}
);
get '/ajax/content/report/devicebylocation' => require_login sub {
my @results
= schema('netdisco')->resultset('Device')
->columns( [qw/ ip dns name location vendor model /] )
->order_by( [qw/ location name ip vendor model /] )->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/devicebylocation.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/devicebylocation_csv.tt',
{ results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,41 @@
package App::Netdisco::Web::Plugin::Report::DeviceDnsMismatch;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Device',
tag => 'devicednsmismatch',
label => 'Device Name / DNS Mismatches',
provides_csv => 1,
}
);
get '/ajax/content/report/devicednsmismatch' => require_login sub {
my $suffix = setting('domain_suffix') || '';
my @results
= schema('netdisco')->resultset('Virtual::DeviceDnsMismatch')
->search( undef, { bind => [ $suffix, $suffix ] } )
->columns( [qw/ ip dns name location contact /] )->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/devicednsmismatch.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/devicednsmismatch_csv.tt',
{ results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,58 @@
package App::Netdisco::Web::Plugin::Report::DevicePoeStatus;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Util::ExpandParams 'expand_hash';
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Device',
tag => 'devicepoestatus',
label => 'Power over Ethernet (PoE) Status',
provides_csv => 1,
}
);
get '/ajax/content/report/devicepoestatus/data' => require_login sub {
send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('Virtual::DevicePoeStatus');
my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count;
my @data = $rs->get_datatables_data($exp_params)->hri->all;
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
content_type 'application/json';
return to_json(
{ draw => int( param('draw') ),
recordsTotal => int($recordsTotal),
recordsFiltered => int($recordsFiltered),
data => \@data,
}
);
};
get '/ajax/content/report/devicepoestatus' => require_login sub {
if ( request->is_ajax ) {
template 'ajax/report/devicepoestatus.tt', {}, { layout => undef };
}
else {
my @results
= schema('netdisco')->resultset('Virtual::DevicePoeStatus')
->hri->all;
return unless scalar @results;
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/devicepoestatus_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,36 @@
package App::Netdisco::Web::Plugin::Report::DuplexMismatch;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Port',
tag => 'duplexmismatch',
label => 'Duplex Mismatches Between Devices',
provides_csv => 1,
}
);
get '/ajax/content/report/duplexmismatch' => require_login sub {
my @results
= schema('netdisco')->resultset('Virtual::DuplexMismatch')->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/duplexmismatch.tt', { results => $json, },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/duplexmismatch_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,44 @@
package App::Netdisco::Web::Plugin::Report::HalfDuplex;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Port',
tag => 'halfduplex',
label => 'Ports in Half Duplex Mode',
provides_csv => 1,
}
);
get '/ajax/content/report/halfduplex' => require_login sub {
my $format = param('format');
my @results
= schema('netdisco')->resultset('DevicePort')
->columns( [qw/ ip port name duplex /] )->search(
{ up => 'up', duplex => { '-ilike' => 'half' } },
{ '+columns' => [qw/ device.dns device.name /],
join => [qw/ device /],
collapse => 1,
}
)->order_by( [qw/ device.dns port /] )->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/halfduplex.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/halfduplex_csv.tt',
{ results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,30 @@
package App::Netdisco::Web::Plugin::Report::InventoryByModelByOS;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Device',
tag => 'inventorybymodelbyos',
label => 'Inventory by Model by OS',
provides_csv => 0,
}
);
get '/ajax/content/report/inventorybymodelbyos' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(undef, {
columns => [qw/vendor model os os_ver/],
select => [ { count => 'os_ver' } ],
as => [qw/ os_ver_count /],
group_by => [qw/ vendor model os os_ver /],
order_by => ['vendor', 'model', { -desc => 'count' }, 'os_ver'],
})->hri->all;
template 'ajax/report/inventorybymodelbyos.tt', { results => \@results, },
{ layout => undef };
};
1;

View File

@@ -0,0 +1,168 @@
package App::Netdisco::Web::Plugin::Report::IpInventory;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
use NetAddr::IP::Lite ':lower';
register_report(
{ category => 'IP',
tag => 'ipinventory',
label => 'IP Inventory',
provides_csv => 1,
}
);
get '/ajax/content/report/ipinventory' => require_login sub {
# Default to something simple with no results to prevent
# "Search failed!" error
my $subnet = param('subnet') || '0.0.0.0/32';
$subnet = NetAddr::IP::Lite->new($subnet);
$subnet = NetAddr::IP::Lite->new('0.0.0.0/32')
if (! $subnet) or ($subnet->addr eq '0.0.0.0');
my $agenot = param('age_invert') || '0';
my ( $start, $end ) = param('daterange') =~ /(\d+-\d+-\d+)/gmx;
my $limit = param('limit') || 256;
my $never = param('never') || '0';
my $order = [{-desc => 'age'}, {-asc => 'ip'}];
# We need a reasonable limit to prevent a potential DoS, especially if
# 'never' is true. TODO: Need better input validation, both JS and
# server-side to provide user feedback
$limit = 8192 if $limit > 8192;
my $rs1 = schema('netdisco')->resultset('DeviceIp')->search(
undef,
{ join => 'device',
select => [
'alias AS ip',
\'NULL as mac',
'creation AS time_first',
'device.last_discover AS time_last',
'dns',
\'true AS active',
\'false AS node',
\qq/replace( date_trunc( 'minute', age( now(), device.last_discover ) ) ::text, 'mon', 'month') AS age/
],
as => [qw( ip mac time_first time_last dns active node age)],
}
)->hri;
my $rs2 = schema('netdisco')->resultset('NodeIp')->search(
undef,
{ columns => [qw( ip mac time_first time_last dns active)],
'+select' => [ \'true AS node',
\qq/replace( date_trunc( 'minute', age( now(), time_last ) ) ::text, 'mon', 'month') AS age/
],
'+as' => [ 'node', 'age' ],
}
)->hri;
my $rs3 = schema('netdisco')->resultset('NodeNbt')->search(
undef,
{ columns => [qw( ip mac time_first time_last )],
'+select' => [
'nbname AS dns', 'active',
\'true AS node',
\qq/replace( date_trunc( 'minute', age( now(), time_last ) ) ::text, 'mon', 'month') AS age/
],
'+as' => [ 'dns', 'active', 'node', 'age' ],
}
)->hri;
my $rs_union = $rs1->union( [ $rs2, $rs3 ] );
if ( $never ) {
$subnet = NetAddr::IP::Lite->new('0.0.0.0/32') if ($subnet->bits ne 32);
my $rs4 = schema('netdisco')->resultset('Virtual::CidrIps')->search(
undef,
{ bind => [ $subnet->cidr ],
columns => [qw( ip mac time_first time_last dns active)],
'+select' => [ \'false AS node',
\qq/replace( date_trunc( 'minute', age( now(), time_last ) ) ::text, 'mon', 'month') AS age/
],
'+as' => [ 'node', 'age' ],
}
)->hri;
$rs_union = $rs_union->union( [$rs4] );
}
my $rs_sub = $rs_union->search(
{ ip => { '<<' => $subnet->cidr } },
{ select => [
\'DISTINCT ON (ip) ip',
'mac',
'dns',
\qq/date_trunc('second', time_last) AS time_last/,
\qq/date_trunc('second', time_first) AS time_first/,
'active',
'node',
'age'
],
as => [
'ip', 'mac', 'dns', 'time_last', 'time_first',
'active', 'node', 'age'
],
order_by => [{-asc => 'ip'}, {-desc => 'active'}],
}
)->as_query;
my $rs;
if ( $start && $end ) {
$start = $start . ' 00:00:00';
$end = $end . ' 23:59:59';
if ( $agenot ) {
$rs = $rs_union->search(
{ -or => [
time_first => [ undef ],
time_last => [ { '<', $start }, { '>', $end } ]
]
},
{ from => { me => $rs_sub }, }
);
}
else {
$rs = $rs_union->search(
{ -or => [
-and => [
time_first => undef,
time_last => undef,
],
-and => [
time_last => { '>=', $start },
time_last => { '<=', $end },
],
],
},
{ from => { me => $rs_sub }, }
);
}
}
else {
$rs = $rs_union->search( undef, { from => { me => $rs_sub }, } );
}
my @results = $rs->order_by($order)->limit($limit)->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/ipinventory.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/ipinventory_csv.tt', { results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,166 @@
package App::Netdisco::Web::Plugin::Report::ModuleInventory;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Util::ExpandParams 'expand_hash';
use App::Netdisco::Web::Plugin;
use List::MoreUtils ();
register_report(
{ category => 'Device',
tag => 'moduleinventory',
label => 'Module Inventory',
provides_csv => 1,
}
);
hook 'before' => sub {
return
unless (
request->path eq uri_for('/report/moduleinventory')->path
or index( request->path,
uri_for('/ajax/content/report/moduleinventory')->path ) == 0
);
# view settings
var('module_options' => [
{ name => 'fruonly',
label => 'FRU Only',
default => 'on'
},
{ name => 'matchall',
label => 'Match All Options',
default => 'on'
},
]
);
};
hook 'before_template' => sub {
my $tokens = shift;
return
unless (
request->path eq uri_for('/report/moduleinventory')->path
or index( request->path,
uri_for('/ajax/content/report/moduleinventory')->path ) == 0
);
# used in the search sidebar template to set selected items
foreach my $opt (qw/class/) {
my $p = (
ref [] eq ref param($opt)
? param($opt)
: ( param($opt) ? [ param($opt) ] : [] )
);
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
}
};
get '/ajax/content/report/moduleinventory/data' => require_login sub {
send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ );
my $rs = schema('netdisco')->resultset('DeviceModule');
$rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
if ( param('device') ) {
my @ips = schema('netdisco')->resultset('Device')
->search_fuzzy( param('device') )->get_column('ip')->all;
params->{'ips'} = \@ips;
}
$rs = $rs->search_by_field( scalar params )->columns(
[ 'ip', 'description', 'name', 'class',
'type', 'serial', 'hw_ver', 'fw_ver',
'sw_ver', 'model'
]
)->search(
{},
{ '+columns' => [qw/ device.dns device.name /],
join => 'device',
collapse => 1,
}
);
my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count;
my @data = $rs->get_datatables_data($exp_params)->hri->all;
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
content_type 'application/json';
return to_json(
{ draw => int( param('draw') ),
recordsTotal => int($recordsTotal),
recordsFiltered => int($recordsFiltered),
data => \@data,
}
);
};
get '/ajax/content/report/moduleinventory' => require_login sub {
my $has_opt = List::MoreUtils::any { param($_) }
qw/device description name type model serial class/;
my $rs = schema('netdisco')->resultset('DeviceModule');
$rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
my @results;
if ( $has_opt && !request->is_ajax ) {
if ( param('device') ) {
my @ips = schema('netdisco')->resultset('Device')
->search_fuzzy( param('device') )->get_column('ip')->all;
params->{'ips'} = \@ips;
}
@results = $rs->search_by_field( scalar params )->columns(
[ 'ip', 'description', 'name', 'class',
'type', 'serial', 'hw_ver', 'fw_ver',
'sw_ver', 'model'
]
)->search(
{},
{ '+columns' => [qw/ device.dns device.name /],
join => 'device',
collapse => 1,
}
)->hri->all;
return unless scalar @results;
}
elsif ( !$has_opt ) {
@results = $rs->search(
{ class => { '!=', undef } },
{ select => [ 'class', { count => 'class' } ],
as => [qw/ class count /],
group_by => [qw/ class /]
}
)->order_by( { -desc => 'count' } )->hri->all;
return unless scalar @results;
}
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/moduleinventory.tt',
{ results => $json, opt => $has_opt },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/moduleinventory_csv.tt',
{ results => \@results, opt => $has_opt },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,110 @@
package App::Netdisco::Web::Plugin::Report::Netbios;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Util::ExpandParams 'expand_hash';
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Node',
tag => 'netbios',
label => 'NetBIOS Inventory',
provides_csv => 1,
}
);
hook 'before_template' => sub {
my $tokens = shift;
return
unless ( request->path eq uri_for('/report/netbios')->path
or
index( request->path, uri_for('/ajax/content/report/netbios')->path )
== 0 );
# used in the search sidebar template to set selected items
foreach my $opt (qw/domain/) {
my $p = (
ref [] eq ref param($opt)
? param($opt)
: ( param($opt) ? [ param($opt) ] : [] )
);
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
}
};
get '/ajax/content/report/netbios/data' => require_login sub {
send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ );
my $domain = param('domain');
my $rs = schema('netdisco')->resultset('NodeNbt');
my $search = $domain eq 'blank' ? '' : $domain;
$rs = $rs->search( { domain => $search } )
->order_by( [ { -asc => 'domain' }, { -desc => 'time_last' } ] );
my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count;
my @data = $rs->get_datatables_data($exp_params)->hri->all;
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
content_type 'application/json';
return to_json(
{ draw => int( param('draw') ),
recordsTotal => int($recordsTotal),
recordsFiltered => int($recordsFiltered),
data => \@data,
}
);
};
get '/ajax/content/report/netbios' => require_login sub {
my $domain = param('domain');
my $rs = schema('netdisco')->resultset('NodeNbt');
my @results;
if ( defined $domain && !request->is_ajax ) {
my $search = $domain eq 'blank' ? '' : $domain;
@results
= $rs->search( { domain => $search } )
->order_by( [ { -asc => 'domain' }, { -desc => 'time_last' } ] )
->hri->all;
return unless scalar @results;
}
elsif ( !defined $domain ) {
@results = $rs->search(
{},
{ select => [ 'domain', { count => 'domain' } ],
as => [qw/ domain count /],
group_by => [qw/ domain /]
}
)->order_by( { -desc => 'count' } )->hri->all;
return unless scalar @results;
}
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/netbios.tt',
{ results => $json, opt => $domain },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/netbios_csv.tt',
{ results => \@results, opt => $domain },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,51 @@
package App::Netdisco::Web::Plugin::Report::NodeMultiIPs;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Node',
tag => 'nodemultiips',
label => 'Nodes with multiple active IP addresses',
provides_csv => 1,
}
);
get '/ajax/content/report/nodemultiips' => require_login sub {
my @results = schema('netdisco')->resultset('Node')->search(
{},
{ select => [ 'mac', 'switch', 'port' ],
join => [qw/device ips oui/],
'+columns' => [
{ 'dns' => 'device.dns' },
{ 'name' => 'device.name' },
{ 'ip_count' => { count => 'ips.ip' } },
{ 'vendor' => 'oui.company' }
],
group_by => [
qw/ me.mac me.switch me.port device.dns device.name oui.company/
],
having => \[ 'count(ips.ip) > ?', [ count => 1 ] ],
order_by => { -desc => [qw/count/] },
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/nodemultiips.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/nodemultiips_csv.tt',
{ results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,133 @@
package App::Netdisco::Web::Plugin::Report::NodeVendor;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Util::ExpandParams 'expand_hash';
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Node',
tag => 'nodevendor',
label => 'Node Vendor Inventory',
provides_csv => 1,
}
);
hook 'before_template' => sub {
my $tokens = shift;
return
unless (
request->path eq uri_for('/report/nodevendor')->path
or index( request->path,
uri_for('/ajax/content/report/nodevendor')->path ) == 0
);
# used in the search sidebar template to set selected items
foreach my $opt (qw/vendor/) {
my $p = (
ref [] eq ref param($opt)
? param($opt)
: ( param($opt) ? [ param($opt) ] : [] )
);
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
}
};
get '/ajax/content/report/nodevendor/data' => require_login sub {
send_error( 'Missing parameter', 400 )
unless ( param('draw') && param('draw') =~ /\d+/ );
my $vendor = param('vendor');
my $rs = schema('netdisco')->resultset('Node');
my $match = $vendor eq 'blank' ? undef : $vendor;
$rs = $rs->search( { 'oui.abbrev' => $match },
{ '+columns' => [qw/ device.dns device.name oui.abbrev /],
join => [qw/ oui device /],
collapse => 1,
});
unless ( param('archived') ) {
$rs = $rs->search( { -bool => 'me.active' } );
}
my $exp_params = expand_hash( scalar params );
my $recordsTotal = $rs->count;
my @data = $rs->get_datatables_data($exp_params)->hri->all;
my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
content_type 'application/json';
return to_json(
{ draw => int( param('draw') ),
recordsTotal => int($recordsTotal),
recordsFiltered => int($recordsFiltered),
data => \@data,
}
);
};
get '/ajax/content/report/nodevendor' => require_login sub {
my $vendor = param('vendor');
my $rs = schema('netdisco')->resultset('Node');
my @results;
if ( defined $vendor && !request->is_ajax ) {
my $match = $vendor eq 'blank' ? undef : $vendor;
$rs = $rs->search( { 'oui.abbrev' => $match },
{ '+columns' => [qw/ device.dns device.name oui.abbrev /],
join => [qw/ oui device /],
collapse => 1,
});
unless ( param('archived') ) {
$rs = $rs->search( { -bool => 'me.active' } );
}
@results = $rs->hri->all;
return unless scalar @results;
}
elsif ( !defined $vendor ) {
$rs = $rs->search(
{ },
{ join => 'oui',
select => [ 'oui.abbrev', { count => 'me.mac' } ],
as => [qw/ vendor count /],
group_by => [qw/ oui.abbrev /]
}
)->order_by( { -desc => 'count' } );
unless ( param('archived') ) {
$rs = $rs->search( { -bool => 'me.active' } );
}
@results = $rs->hri->all;
return unless scalar @results;
}
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/nodevendor.tt',
{ results => $json, opt => $vendor },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/nodevendor_csv.tt',
{ results => \@results, opt => $vendor },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,54 @@
package App::Netdisco::Web::Plugin::Report::NodesDiscovered;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
use App::Netdisco::Util::Web 'sql_match';
register_report(
{ category => 'Node',
tag => 'nodesdiscovered',
label => 'Nodes discovered through LLDP/CDP',
provides_csv => 1,
}
);
get '/ajax/content/report/nodesdiscovered' => require_login sub {
my $op = param('matchall') ? '-and' : '-or';
my @results = schema('netdisco')->resultset('Virtual::NodesDiscovered')
->search({
$op => [
(param('aps') ?
('me.remote_type' => { -ilike => 'AP:%' }) : ()),
(param('phones') ?
('me.remote_type' => { -ilike => '%ip_phone%' }) : ()),
(param('remote_id') ?
('me.remote_id' => { -ilike => scalar sql_match(param('remote_id')) }) : ()),
(param('remote_type') ? ('-or' => [
map {( 'me.remote_type' => { -ilike => scalar sql_match($_) } )}
grep { $_ }
(ref param('remote_type') ? @{param('remote_type')} : param('remote_type'))
]) : ()),
],
})
->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/nodesdiscovered.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/nodesdiscovered_csv.tt',
{ results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,45 @@
package App::Netdisco::Web::Plugin::Report::PortAdminDown;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Port',
tag => 'portadmindown',
label => 'Ports administratively disabled',
provides_csv => 1,
}
);
get '/ajax/content/report/portadmindown' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(
{ 'up_admin' => 'down' },
{ select => [ 'ip', 'dns', 'name' ],
join => [ 'ports' ],
'+columns' => [
{ 'port' => 'ports.port' },
{ 'description' => 'ports.name' },
{ 'up_admin' => 'ports.up_admin' },
]
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json (\@results);
template 'ajax/report/portadmindown.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portadmindown_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,45 @@
package App::Netdisco::Web::Plugin::Report::PortBlocking;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Port',
tag => 'portblocking',
label => 'Ports that are blocking',
provides_csv => 1,
}
);
get '/ajax/content/report/portblocking' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(
{ 'stp' => [ 'blocking', 'broken' ], 'up' => { '!=', 'down' } },
{ select => [ 'ip', 'dns', 'name' ],
join => ['ports'],
'+columns' => [
{ 'port' => 'ports.port' },
{ 'description' => 'ports.name' },
{ 'stp' => 'ports.stp' },
]
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json (\@results);
template 'ajax/report/portblocking.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portblocking_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,66 @@
package App::Netdisco::Web::Plugin::Report::PortLog;
use Dancer ':syntax';
use Dancer::Plugin::Ajax;
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report({
tag => 'portlog',
label => 'Port Control Log',
category => 'Port', # not used
hidden => true,
});
sub _sanity_ok {
return 0 unless
param('ip') =~ m/^[[:print:]]+$/
and param('port') =~ m/^[[:print:]]+$/
and param('log') =~ m/^[[:print:]]+$/;
return 1;
}
ajax '/ajax/control/report/portlog/add' => require_login sub {
send_error('Bad Request', 400) unless _sanity_ok();
schema('netdisco')->txn_do(sub {
my $user = schema('netdisco')->resultset('DevicePortLog')
->create({
ip => param('ip'),
port => param('port'),
reason => 'other',
log => param('log'),
username => session('logged_in_user'),
userip => request->remote_address,
action => 'comment',
});
});
};
ajax '/ajax/content/report/portlog' => require_login sub {
my $device = param('q');
my $port = param('f');
send_error('Bad Request', 400) unless $device and $port;
$device = schema('netdisco')->resultset('Device')
->search_for_device($device);
return unless $device;
my $set = schema('netdisco')->resultset('DevicePortLog')->search({
ip => $device->ip,
port => $port,
}, {
order_by => { -desc => [qw/creation/] },
rows => 200,
})->with_times;
content_type('text/html');
template 'ajax/report/portlog.tt', {
results => $set,
}, { layout => undef };
};
true;

View File

@@ -0,0 +1,53 @@
package App::Netdisco::Web::Plugin::Report::PortMultiNodes;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Port',
tag => 'portmultinodes',
label => 'Ports with multiple nodes attached',
provides_csv => 1,
}
);
get '/ajax/content/report/portmultinodes' => require_login sub {
my @results = schema('netdisco')->resultset('Device')->search(
{ 'ports.remote_ip' => undef,
(param('vlan') ?
('ports.vlan' => param('vlan'), 'nodes.vlan' => param('vlan')) : ()),
'nodes.active' => 1,
'wireless.port' => undef
},
{ select => [ 'ip', 'dns', 'name' ],
join => { 'ports' => [ 'wireless', 'nodes' ] },
'+columns' => [
{ 'port' => 'ports.port' },
{ 'description' => 'ports.name' },
{ 'mac_count' => { count => 'nodes.mac' } },
],
group_by => [qw/me.ip me.dns me.name ports.port ports.name/],
having => \[ 'count(nodes.mac) > ?', [ count => 1 ] ],
order_by => { -desc => [qw/count/] },
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json (\@results);
template 'ajax/report/portmultinodes.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portmultinodes_csv.tt',
{ results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,79 @@
package App::Netdisco::Web::Plugin::Report::PortSsid;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Port',
tag => 'portssid',
label => 'Port SSID Inventory',
provides_csv => 1,
}
);
hook 'before_template' => sub {
my $tokens = shift;
return
unless (
request->path eq uri_for('/report/portssid')->path
or index(
request->path, uri_for('/ajax/content/report/portssid')->path
) == 0
);
# used in the search sidebar template to set selected items
foreach my $opt (qw/ssid/) {
my $p = (
ref [] eq ref param($opt)
? param($opt)
: ( param($opt) ? [ param($opt) ] : [] )
);
$tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
}
};
get '/ajax/content/report/portssid' => require_login sub {
my $ssid = param('ssid');
my $rs = schema('netdisco')->resultset('DevicePortSsid');
if ( defined $ssid ) {
$rs = $rs->search(
{ ssid => $ssid },
{ '+columns' => [
qw/ device.dns device.name device.model device.vendor port.port/
],
join => [qw/ device port /],
collapse => 1,
}
)->order_by( [qw/ port.ip port.port /] )->hri;
}
else {
$rs = $rs->get_ssids->hri;
}
my @results = $rs->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/portssid.tt',
{ results => $json, opt => $ssid },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portssid_csv.tt',
{ results => \@results, opt => $ssid },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,33 @@
package App::Netdisco::Web::Plugin::Report::PortUtilization;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Device',
tag => 'portutilization',
label => 'Port Utilization',
provides_csv => 1,
}
);
get '/ajax/content/report/portutilization' => require_login sub {
return unless schema('netdisco')->resultset('Device')->count;
my @results = schema('netdisco')->resultset('Virtual::PortUtilization')->hri->all;
if (request->is_ajax) {
my $json = to_json (\@results);
template 'ajax/report/portutilization.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portutilization_csv.tt', { results => \@results, },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,35 @@
package App::Netdisco::Web::Plugin::Report::SsidInventory;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'Wireless',
tag => 'ssidinventory',
label => 'SSID Inventory',
provides_csv => 1,
}
);
get '/ajax/content/report/ssidinventory' => require_login sub {
my @results = schema('netdisco')->resultset('DevicePortSsid')
->get_ssids->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json( \@results );
template 'ajax/report/portssid.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/portssid_csv.tt', { results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,42 @@
package App::Netdisco::Web::Plugin::Report::SubnetUtilization;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report({
category => 'IP',
tag => 'subnets',
label => 'Subnet Utilization',
provides_csv => 1,
});
get '/ajax/content/report/subnets' => require_login sub {
my $subnet = param('subnet') || '0.0.0.0/32';
my $agenot = param('age_invert') || '0';
my ( $start, $end ) = param('daterange') =~ /(\d+-\d+-\d+)/gmx;
$start = $start . ' 00:00:00';
$end = $end . ' 23:59:59';
my @results = schema('netdisco')->resultset('Virtual::SubnetUtilization')
->search(undef,{
bind => [ $subnet, $start, $end, $start, $subnet, $start, $start ],
})->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
template 'ajax/report/subnets.tt', { results => \@results },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/subnets_csv.tt', { results => \@results },
{ layout => undef };
}
};
1;

View File

@@ -0,0 +1,46 @@
package App::Netdisco::Web::Plugin::Report::VlanInventory;
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use App::Netdisco::Web::Plugin;
register_report(
{ category => 'VLAN',
tag => 'vlaninventory',
label => 'VLAN Inventory',
provides_csv => 1,
}
);
get '/ajax/content/report/vlaninventory' => require_login sub {
my @results = schema('netdisco')->resultset('DeviceVlan')->search(
{ 'me.description' => { '!=', 'NULL' } },
{ join => { 'ports' => 'vlan' },
select => [
'me.vlan',
'me.description',
{ count => { distinct => 'me.ip' } },
{ count => 'ports.vlan' }
],
as => [qw/ vlan description dcount pcount /],
group_by => [qw/ me.vlan me.description /],
}
)->hri->all;
return unless scalar @results;
if ( request->is_ajax ) {
my $json = to_json (\@results);
template 'ajax/report/vlaninventory.tt', { results => $json },
{ layout => undef };
}
else {
header( 'Content-Type' => 'text/comma-separated-values' );
template 'ajax/report/vlaninventory_csv.tt', { results => \@results },
{ layout => undef };
}
};
true;