1package App::Netdisco::Web::Plugin::AdminTask::OrphanedDevices;
2
3use strict;
4use warnings;
5use Dancer ':syntax';
6use Dancer::Plugin::DBIC;
7use Dancer::Plugin::Auth::Extensible;
8
9use App::Netdisco::Web::Plugin;
10
11register_admin_task(
12    {   tag          => 'orphaned',
13        label        => 'Orphaned Devices / Networks',
14        provides_csv => 1,
15    }
16);
17
18get '/ajax/content/admin/orphaned' => require_role admin => sub {
19
20    my @tree = schema('netdisco')->resultset('Virtual::UnDirEdgesAgg')
21        ->search( undef, { prefetch => 'device' } )->hri->all;
22
23    my @orphans
24        = schema('netdisco')->resultset('Virtual::OrphanedDevices')->search()
25        ->order_by('ip')->hri->all;
26
27    return unless ( scalar @tree || scalar @orphans );
28
29    my @ordered;
30
31    if ( scalar @tree ) {
32        my %tree = map { $_->{'left_ip'} => $_ } @tree;
33
34        my $current_graph = 0;
35        my %visited       = ();
36        my @to_visit      = ();
37        foreach my $node ( keys %tree ) {
38            next if exists $visited{$node};
39
40            $current_graph++;
41            @to_visit = ($node);
42            while (@to_visit) {
43                my $node_to_visit = shift @to_visit;
44
45                $visited{$node_to_visit} = $current_graph;
46
47                push @to_visit,
48                    grep { !exists $visited{$_} }
49                    @{ $tree{$node_to_visit}->{'links'} };
50            }
51        }
52
53        my @graphs = ();
54        foreach my $key ( keys %visited ) {
55            push @{ $graphs[ $visited{$key} - 1 ] }, $tree{$key}->{'device'};
56        }
57
58        @ordered = sort { scalar @{$b} <=> scalar @{$a} } @graphs;
59    }
60
61    return if ( scalar @ordered < 2 && !scalar @tree );
62
63    if ( request->is_ajax ) {
64        template 'ajax/admintask/orphaned.tt',
65            {
66            orphans => \@orphans,
67            graphs  => \@ordered,
68            },
69            { layout => undef };
70    }
71    else {
72        header( 'Content-Type' => 'text/comma-separated-values' );
73        template 'ajax/admintask/orphaned_csv.tt',
74            {
75            orphans => \@orphans,
76            graphs  => \@ordered,
77            },
78            { layout => undef };
79    }
80};
81
821;
83