App-Netdisco

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

2.072001 - 2024-01-15

  [BUG FIXES]

  * revert set is_uplink on ports with multiple vlans

2.072000 - 2024-01-14

  [ENHANCEMENTS]

  * add port_vlans API endpoint to device ports
  * set device ports with multiple vlans to be uplinks
  * removed the redundant portctl_vlans setting (handled by portctl_uplinks)
  * renamed vlanctl to be portctl_native_vlan

  [BUG FIXES]

  * #1150 rewritten port control acls

2.071003 - 2024-01-10

lib/App/Netdisco/Web/AuthN.pm  view on Meta::CPAN


  # may synthesize a user if validate_remote_user=false
  return $provider->get_user_details($username);
}

# Dancer will create a session if it sees its own cookie. For the API and also
# various auto login options we need to bootstrap the session instead. If no
# auth data passed, then the hook simply returns, no session is set, and the
# user is redirected to login page.
hook 'before' => sub {
    # return if request is for endpoints not requiring a session
    return if (
      request->path eq uri_for('/login')->path
      or request->path eq uri_for('/logout')->path
      or request->path eq uri_for('/swagger.json')->path
      or index(request->path, uri_for('/swagger-ui')->path) == 0
    );

    # Dancer will issue a cookie to the client which could be returned and
    # cause API calls to succeed without passing token. Kill the session.
    session->destroy if request_is_api;

lib/App/Netdisco/Web/GenericReport.pm  view on Meta::CPAN


foreach my $report (@{setting('reports')}) {
  my $r = $report->{tag};

  register_report({
    tag => $r,
    label => $report->{label},
    category => ($report->{category} || 'My Reports'),
    ($report->{hidden} ? (hidden => true) : ()),
    provides_csv => true,
    api_endpoint => true,
    bind_params  => $report->{bind_params},
    api_parameters => $report->{api_parameters},
  });

  get "/ajax/content/report/$r" => require_login sub {
      # TODO: this should be done by creating a new Virtual Result class on
      # the fly (package...) and then calling DBIC register_class on it.

      my $schema = ($report->{database} || vars->{'tenant'});
      my $rs = schema($schema)->resultset('Virtual::GenericReport')->result_source;

lib/App/Netdisco/Web/Plugin.pm  view on Meta::CPAN

      }
  }

  push @{ $stash }, $config;
}

register 'register_search_tab' => sub {
  my ($self, $config) = plugin_args(@_);
  _register_tab('search', $config);

  if ($config->{api_endpoint}) {
      my $tag = $config->{tag};
      swagger_path {
        tags => ['Search'],
        path => setting('api_base')."/search/$tag",
        description => $config->{label} .' Search',
        parameters  => $config->{api_parameters},
        responses =>
          ($config->{api_responses} || { default => {} }),
      }, get "/api/v1/search/$tag" => require_role api => sub {
        forward "/ajax/content/search/$tag";

lib/App/Netdisco/Web/Plugin/Report/ApClients.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/apclients' => require_login sub {
    my @results = schema(vars->{'tenant'})->resultset('Device')->search(
        { 'nodes.time_last' => { '>=', \'me.last_macsuck' },
          'ports.port' => { '-in' => schema(vars->{'tenant'})->resultset('DevicePortWireless')->get_column('port')->as_query },
        },
        {   select => [ 'ip', 'model', 'ports.port', 'ports.name', 'ports.type' ],
            join       => { 'ports' =>  'nodes' },

lib/App/Netdisco/Web/Plugin/Report/ApRadioChannelPower.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/apradiochannelpower/data' => require_login sub {
    send_error( 'Missing parameter', 400 )
        unless ( param('draw') && param('draw') =~ /\d+/ );

    my $rs = schema(vars->{'tenant'})->resultset('Virtual::ApRadioChannelPower');
    my $exp_params = expand_hash( scalar params );
    my $recordsTotal = $rs->count;

lib/App/Netdisco/Web/Plugin/Report/DeviceAddrNoDNS.pm  view on Meta::CPAN

use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;

register_report(
    {   category     => 'Device',
        tag          => 'deviceaddrnodns',
        label        => 'IPs without DNS Entries',
        provides_csv => 1,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/deviceaddrnodns' => require_login sub {
    my @results = schema(vars->{'tenant'})->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/] },

lib/App/Netdisco/Web/Plugin/Report/DeviceByLocation.pm  view on Meta::CPAN

use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;

register_report(
    {   category     => 'Device',
        tag          => 'devicebylocation',
        label        => 'Inventory by Location',
        provides_csv => 1,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/devicebylocation' => require_login sub {
    my @results
        = schema(vars->{'tenant'})->resultset('Device')
        ->columns(  [qw/ ip dns name location vendor model /] )
        ->order_by( [qw/ location name ip vendor model /] )->hri->all;

    return unless scalar @results;

lib/App/Netdisco/Web/Plugin/Report/DeviceDnsMismatch.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/devicednsmismatch' => require_login sub {

    (my $suffix = '***:'. setting('domain_suffix')) =~ s|\Q(?^\Eu?|(?|g;

    my @results
        = schema(vars->{'tenant'})->resultset('Virtual::DeviceDnsMismatch')
        ->search( undef, { bind => [ $suffix, $suffix ] } )

lib/App/Netdisco/Web/Plugin/Report/DevicePoeStatus.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/devicepoestatus/data' => require_login sub {
    send_error( 'Missing parameter', 400 )
        unless ( param('draw') && param('draw') =~ /\d+/ );

    my $rs = schema(vars->{'tenant'})->resultset('Virtual::DevicePoeStatus');

    my $exp_params = expand_hash( scalar params );

lib/App/Netdisco/Web/Plugin/Report/DuplexMismatch.pm  view on Meta::CPAN

use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;

register_report(
    {   category     => 'Port',
        tag          => 'duplexmismatch',
        label        => 'Mismatched Duplex',
        provides_csv => 1,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/duplexmismatch' => require_login sub {
    my @results
        = schema(vars->{'tenant'})->resultset('Virtual::DuplexMismatch')->hri->all;

    return unless scalar @results;

    if ( request->is_ajax ) {

lib/App/Netdisco/Web/Plugin/Report/HalfDuplex.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/halfduplex' => require_login sub {
    my @results
        = schema(vars->{'tenant'})->resultset('DevicePort')
        ->columns( [qw/ ip port name duplex /] )->search(
        { up => 'up', duplex => { '-ilike' => 'half' } },
        {   '+columns' => [qw/ device.dns device.name /],
            join       => [qw/ device /],

lib/App/Netdisco/Web/Plugin/Report/IpInventory.pm  view on Meta::CPAN


use App::Netdisco::Web::Plugin;
use NetAddr::IP::Lite ':lower';
use POSIX qw/strftime/;

register_report(
    {   category     => 'IP',
        tag          => 'ipinventory',
        label        => 'IP Inventory',
        provides_csv => 1,
        api_endpoint => 1,
        api_parameters => [
          subnet => {
            description => 'IP Prefix to search',
            required => 1,
          },
          daterange => {
            description => 'Date range to search',
            default => ('1970-01-01 to '. strftime('%Y-%m-%d', gmtime)),
          },
          age_invert => {

lib/App/Netdisco/Web/Plugin/Report/NodeMultiIPs.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/nodemultiips' => require_login sub {
    my @results = schema(vars->{'tenant'})->resultset('Node')->search(
        {},
        {   select     => [ 'mac', 'switch', 'port' ],
            join       => [qw/device ips manufacturer/],
            '+columns' => [
                { 'dns'      => 'device.dns' },

lib/App/Netdisco/Web/Plugin/Report/NodesDiscovered.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
        api_parameters => [
          remote_id => {
            description => 'Host Name reported',
          },
          remote_type => {
            description => 'Platform reported',
          },
          aps => {
            description => 'Include Wireless APs in the report',
            type => 'boolean',

lib/App/Netdisco/Web/Plugin/Report/PortAdminDown.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/portadmindown' => require_login sub {
    my @results = schema(vars->{'tenant'})->resultset('Device')->search(
        { 'up_admin' => 'down' },
        {   select       => [ 'ip', 'dns', 'name' ],
            join       => [ 'ports' ],
            '+columns' => [
                { 'port'        => 'ports.port' },

lib/App/Netdisco/Web/Plugin/Report/PortBlocking.pm  view on Meta::CPAN

use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;

register_report(
    {   category     => 'Port',
        tag          => 'portblocking',
        label        => 'Blocked - Spanning Tree',
        provides_csv => 1,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/portblocking' => require_login sub {
    my @results = schema(vars->{'tenant'})->resultset('Device')->search(
        { 'stp' => [ 'blocking', 'broken' ], 'up' => { '!=', 'down' } },
        {   select       => [ 'ip', 'dns', 'name' ],
            join         => ['ports'],
            '+columns'   => [
                { 'port'        => 'ports.port' },

lib/App/Netdisco/Web/Plugin/Report/PortMultiNodes.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
        api_parameters => [
          vlan => {
            description => 'Filter by VLAN',
            type => 'integer',
          },
        ],
    }
);

get '/ajax/content/report/portmultinodes' => require_login sub {

lib/App/Netdisco/Web/Plugin/Report/PortSsid.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
        api_parameters => [
          ssid => {
            description => 'Get details for this SSID',
          },
        ],
    }
);

hook 'before_template' => sub {
    my $tokens = shift;

lib/App/Netdisco/Web/Plugin/Report/PortUtilization.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
        api_parameters => [
          age_num => {
            description => 'Mark as Free if down for (quantity)',
            enum => [1 .. 31],
            default => '3',
          },
          age_unit => {
            description => 'Mark as Free if down for (period)',
            enum => [qw/days weeks months years/],
            default => 'months',

lib/App/Netdisco/Web/Plugin/Report/PortVLANMismatch.pm  view on Meta::CPAN

use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;
use List::MoreUtils qw/listcmp sort_by/;

register_report(
    {   category => 'Port',
        tag      => 'portvlanmismatch',
        label    => 'Mismatched VLANs',
        provides_csv => 1,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/portvlanmismatch' => require_login sub {
    return unless schema(vars->{'tenant'})->resultset('Device')->count;
    my @results = schema(vars->{'tenant'})
      ->resultset('Virtual::PortVLANMismatch')->search({},{
          bind => [ setting('sidebar_defaults')->{'device_ports'}->{'p_hide1002'}->{'default'}
                      ? (1002, 1003, 1004, 1005) : (0, 0, 0, 0) ],
      })

lib/App/Netdisco/Web/Plugin/Report/SsidInventory.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/ssidinventory' => require_login sub {
    my @results = schema(vars->{'tenant'})->resultset('DevicePortSsid')
        ->get_ssids->hri->all;

    return unless scalar @results;

    if ( request->is_ajax ) {

lib/App/Netdisco/Web/Plugin/Report/SubnetUtilization.pm  view on Meta::CPAN

use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;
use POSIX qw/strftime/;

register_report({
  category     => 'IP',
  tag          => 'subnets',
  label        => 'Subnet Utilization',
  provides_csv => 1,
  api_endpoint => 1,
  api_parameters => [
    subnet => {
      description => 'IP Prefix to search',
      default => '0.0.0.0/32',
    },
    daterange => {
      description => 'Date range to search',
      default => ('1970-01-01 to '. strftime('%Y-%m-%d', gmtime)),
    },
    age_invert => {

lib/App/Netdisco/Web/Plugin/Report/VlanInventory.pm  view on Meta::CPAN

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,
        api_endpoint => 1,
    }
);

get '/ajax/content/report/vlaninventory' => require_login sub {
    my @results = schema(vars->{'tenant'})->resultset('DeviceVlan')->search(
        { 'me.description' => { '!=', 'NULL' },
          'me.vlan' => { '>' => 0 },
          'ports.vlan' => { '>' => 0 },
        },
        {   join   => { 'ports' => 'vlan_entry' },

lib/App/Netdisco/Web/Plugin/Search/Node.pm  view on Meta::CPAN

use NetAddr::MAC ();
use POSIX qw/strftime/;

use App::Netdisco::Web::Plugin;
use App::Netdisco::Util::DNS 'ipv4_from_hostname';
use App::Netdisco::Util::Web 'sql_match';

register_search_tab({
    tag => 'node',
    label => 'Node',
    api_endpoint => 1,
    api_parameters => [
      q => {
        description => 'MAC Address or IP Address or Hostname (without Domain Suffix) of a Node (supports SQL or "*" wildcards)',
        required => 1,
      },
      partial => {
        description => 'Partially match the "q" parameter (wildcard characters not required)',
        type => 'boolean',
        default => 'false',
      },

lib/App/Netdisco/Web/Plugin/Search/Port.pm  view on Meta::CPAN

use App::Netdisco::Util::Port 'to_speed';
use App::Netdisco::Util::Web 'sql_match';

use Regexp::Common 'net';
use NetAddr::MAC ();

register_search_tab({
    tag => 'port',
    label => 'Port',
    provides_csv => 1,
    api_endpoint => 1,
    api_parameters => [
      q => {
        description => 'Port name, VLAN, or MAC address',
        required => 1,
      },
      partial => {
        description => 'Search for a partial match on parameter "q"',
        type => 'boolean',
        default => 'true',
      },

lib/App/Netdisco/Web/Plugin/Search/VLAN.pm  view on Meta::CPAN

use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Web::Plugin;

register_search_tab({
    tag => 'vlan',
    label => 'VLAN',
    provides_csv => 1,
    api_endpoint => 1,
    api_parameters => [
      q => {
        description => 'VLAN name or number',
        required => 1,
      },
    ],
});

# devices carrying vlan xxx
get '/ajax/content/search/vlan' => require_login sub {

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 1.613 second using v1.00-cache-2.02-grep-82fe00e-cpan-4673cadbf75 )