Merge of og-work branch, many new features.
Squashed commit of the following: commita43c98962aAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jun 3 20:37:39 2013 +0100 Missing mibdirs causes all MIBs to be loaded (with a warning) commit09829a25b8Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jun 3 20:07:31 2013 +0100 local plugins site_plugins dir commitb0e804e558Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jun 3 19:59:04 2013 +0100 use send_error and redirect from Dancer commit3d1185261aAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jun 3 19:13:40 2013 +0100 support path config option commit31ca119f84Merge:9a798554d2b3a5Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jun 3 00:06:17 2013 +0100 Merge remote-tracking branch 'origin/og-work' into og-work g-work" This reverts commit9a79855361, reversing changes made to6fd6118354. Conflicts: Netdisco/share/views/plugin/device_port_column/c_observiumsparklines.tt commit9a79855361Merge:6fd6118c8c3b82Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jun 3 00:03:32 2013 +0100 Merge remote-tracking branch 'origin/master' into og-work commit6fd6118354Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jun 2 15:47:45 2013 +0100 extra note about behind proxy commit798086ca29Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jun 2 15:30:26 2013 +0100 complete the observium plugin commit66b3ced179Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jun 2 12:48:06 2013 +0100 Plugins can have CSS and Javascript loaded within <head> commit4d2b3a5307Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 08:50:16 2013 +0100 get device dns to port template commited1bfa1ae7Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 08:17:02 2013 +0100 observium sparklines plugin; support X:: namespace commit76b7636c74Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 06:30:06 2013 +0100 rename private settings keys commitfdac8f6c33Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 05:59:53 2013 +0100 add macwalk and arpnip buttons to device details commit3d688c7d83Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 05:57:20 2013 +0100 Revert "reduce refresh to 5sec" This reverts commit8ea9ec7dd9. commitdc62382112Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 05:50:34 2013 +0100 support for arpwalk and macwalk and all jobs via web commit8bc7d83c98Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 30 05:35:41 2013 +0100 simplify discover options to only discoverall and discover commit8ea9ec7dd9Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 20:23:08 2013 +0100 reduce refresh to 5sec commit8c54e6c58bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 20:11:06 2013 +0100 show undiscovered neighbor properly commite0ee25628fAuthor: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 19:54:09 2013 +0100 avoid unecessary log for queueing commitd5565423f2Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 19:51:37 2013 +0100 avoid warning on undefined remote type commit5d9b58a6b2Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 19:48:22 2013 +0100 avoid explosion when not admin commit377bb942e0Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 19:46:52 2013 +0100 avoid undefined warning commit08806dcfa2Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 19:46:42 2013 +0100 get_db_version will be 0 at first deploy commit9511c17056Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 29 19:15:55 2013 +0100 fix name of Template module commiteb0288de35Author: Oliver Gorwits <oliver@cpan.org> Date: Tue May 28 07:17:07 2013 +0100 initial config settings documentation commit7f2ea7f8dcAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon May 27 15:18:15 2013 +0100 remove check_mac to own module, use in macsuck too commitb995cf6398Author: Oliver Gorwits <oliver@cpan.org> Date: Mon May 27 15:01:29 2013 +0100 show probable but undiscovered neighbor is ports display commitdd8d461188Author: Oliver Gorwits <oliver@cpan.org> Date: Mon May 27 14:52:41 2013 +0100 new schema version for is_uplink and is_uplink_admin commit3f6a7b5aa2Author: Oliver Gorwits <oliver@cpan.org> Date: Mon May 27 14:47:59 2013 +0100 make sure device_port is updated when manual_topo is set commit33bf9a6599Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 26 19:51:49 2013 +0100 export store_arp and store_node commit0ed356d560Author: Oliver Gorwits <oliver@cpan.org> Date: Sat May 25 17:12:31 2013 +0100 use row lock not table lock commitf830bc3a3bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat May 25 16:38:33 2013 +0100 move macsuck/arpnip/discover to ::Core namespace commitbe40788987Author: Oliver Gorwits <oliver@cpan.org> Date: Fri May 24 21:10:34 2013 +0100 add maybe_uplink to device_port; more macsuck implementation commit88371026d5Author: Oliver Gorwits <oliver@cpan.org> Date: Fri May 24 14:34:58 2013 +0100 start on macsuck; tweak update locking commit6f7c87ac07Author: Oliver Gorwits <oliver@cpan.org> Date: Fri May 24 13:10:58 2013 +0100 ORDER BY ... FOR UPDATE will allow us to avoid table lock commit7c438e01fcAuthor: Oliver Gorwits <oliver@cpan.org> Date: Fri May 24 12:12:46 2013 +0100 yet more efficient arpnip commitc74c56dc02Author: Oliver Gorwits <oliver@cpan.org> Date: Fri May 24 11:34:23 2013 +0100 guard against race with *_or_* DBIC methods commitd50c54972eAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon May 20 23:42:41 2013 +0100 more efficient arpnip commit73c8979130Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 19 22:52:15 2013 +0100 fix confusing name commitbf78e82411Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 19 22:37:22 2013 +0100 fix mistake in DBIx::Class schema commit6a5af95836Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 19 22:06:27 2013 +0100 arpnip implementation commit594abd3f82Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 16 00:00:50 2013 +0100 PostgreSQL explicit locking support. Squashed commit of the following: commit76e1539102Author: Oliver Gorwits <oliver@cpan.org> Date: Wed May 15 23:54:25 2013 +0100 finished explicit locking module commit369387258bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue May 14 23:50:42 2013 +0100 initial implementation of locking from schema object commit55c6d4fe63Author: Oliver Gorwits <oliver@cpan.org> Date: Tue May 14 21:05:01 2013 +0100 add discover button to device details page commit11fd8bf964Author: Oliver Gorwits <oliver@cpan.org> Date: Tue May 14 20:43:43 2013 +0100 fix typo and clear port box on autocomplete dropdown commita00f9b5c2eAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue May 14 20:38:54 2013 +0100 move admin tasks and remove JobControl package commit74bc0023dfAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat May 11 18:25:04 2013 +0100 complete job queue delete and kill running timers properly when reloading page commitdd6947f38dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat May 11 16:51:28 2013 +0100 fix improper use of bootstrap table class commitcd5b83f71eAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat May 11 15:55:45 2013 +0100 fix update view icon in sidebar commite9349f325dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat May 11 11:57:19 2013 +0100 css audit commit201470275dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Thu May 9 23:48:05 2013 +0100 add job queue to standard plugins list commita18a3c72a3Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 9 23:37:43 2013 +0100 fix table headings and improve Action display in Job Queue commit70f5da8bb6Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 9 23:30:32 2013 +0100 implement "no devices" prompt for admin users to do first discover commit2e8ac83173Author: Oliver Gorwits <oliver@cpan.org> Date: Thu May 9 21:53:39 2013 +0100 more js refactoring for report and search commit479ac0e55dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Thu May 9 21:50:29 2013 +0100 refactor js for device tabs commit6a17fe5d6cAuthor: Oliver Gorwits <oliver@cpan.org> Date: Thu May 9 21:05:42 2013 +0100 fix crazy races with javasacript by using global delegations commite94e3cef3bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Wed May 8 23:06:41 2013 +0100 remove Try::Tiny from web runtime commitc746e68b9bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue May 7 21:54:11 2013 +0100 make topo autocomplete more responsive commit24c511786fAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue May 7 21:52:17 2013 +0100 display name and IP for device typeahead commit52ab7d1266Author: Oliver Gorwits <oliver@cpan.org> Date: Tue May 7 21:47:05 2013 +0100 add drop-down control for the topo form fields commit5744b6845fAuthor: Oliver Gorwits <oliver@cpan.org> Date: Tue May 7 21:25:30 2013 +0100 complete the topology editor (add/delete) commitb510fbe8c5Author: Oliver Gorwits <oliver@cpan.org> Date: Tue May 7 00:59:11 2013 +0100 add new admin tasks to default plugins list commit11d55e0129Author: Oliver Gorwits <oliver@cpan.org> Date: Tue May 7 00:56:19 2013 +0100 Manual Device Topology Needed to add the 'autocomplete' jQuery UI component because it can do minLength=0 properly. Used the smoothness UI theme. Added typeahead AJAX calls to support the topology searching. Added new plugin and template for the topology editing page. commitbf7a419d08Author: Oliver Gorwits <oliver@cpan.org> Date: Mon May 6 22:16:24 2013 +0100 add a little colour to lone tab titles commit9690a31f19Author: Oliver Gorwits <oliver@cpan.org> Date: Mon May 6 22:01:13 2013 +0100 complete Manage Pseudo Devices commit024f4d9a83Author: Oliver Gorwits <oliver@cpan.org> Date: Mon May 6 00:49:47 2013 +0100 use bootstrap font colour instead of css commitf75f1e5cbfAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon May 6 00:45:18 2013 +0100 add frontend update/del forms, and display port count commitf0899e16b3Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 23:53:20 2013 +0100 add frontend pseudo device add form commit3271c01931Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 21:45:17 2013 +0100 complete the code for admin tasks page loading commit38f70624f3Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 17:04:30 2013 +0100 set up file paths consistently in all scripts commitc761ca839bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 17:00:30 2013 +0100 Helper script to import the Netdisco 1.x Topology file to the database commitf468b48049Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 16:20:39 2013 +0100 Handle whitespace ahead of OUI data commit5c8a5754f6Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 16:16:20 2013 +0100 also set neighbor info when discovering device interfaces commitacb988b6afAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 15:34:20 2013 +0100 try to avoid duplicate execution of scheduled jobs commitc6bcaf66c5Author: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 14:16:25 2013 +0100 do not clobber manual topo when discovering neighbors commitd9a6a1882aAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun May 5 13:02:45 2013 +0100 User icon color indicates port_control/admin ability commit2cdcb9db7eAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Apr 29 23:34:27 2013 +0100 add support for admin tasks as plugins commit075a770c9aAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Apr 29 22:23:20 2013 +0100 skip pseudo devices (vendor netdisco) commit045c022d42Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Apr 29 21:58:33 2013 +0100 incorporate manual topo info from the topology db table commit09285d42b4Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 18:39:12 2013 +0100 add unique constraints to topology table commit2780b72e49Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 15:38:05 2013 +0100 muted help text in sidebar commit733d4f83fbAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:39:54 2013 +0100 sorry, testing hook changes commit71e366e352Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:34:36 2013 +0100 sorry, testing hook changes commit7f9eaa99f5Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:33:44 2013 +0100 sorry, testing hook changes commit5215fd632dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:30:07 2013 +0100 sorry, testing hook changes commitbe817d60c2Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:21:45 2013 +0100 sorry, testing hook changes commit1fd3695358Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:18:57 2013 +0100 sorry, testing hook changes commitac448c4a91Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:13:03 2013 +0100 sorry, testing hook changes commitc563b8d9afAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:08:54 2013 +0100 sorry, testing hook changes commit3abcfb01d5Author: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:06:25 2013 +0100 sorry, testing hook changes commit877a81facfAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sat Apr 27 14:05:25 2013 +0100 sorry, testing hook changes
This commit is contained in:
80
Netdisco/lib/App/Netdisco/Web/AdminTask.pm
Normal file
80
Netdisco/lib/App/Netdisco/Web/AdminTask.pm
Normal file
@@ -0,0 +1,80 @@
|
||||
package App::Netdisco::Web::AdminTask;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
use Try::Tiny;
|
||||
|
||||
sub add_job {
|
||||
my ($jobtype, $device) = @_;
|
||||
|
||||
if ($device) {
|
||||
$device = NetAddr::IP::Lite->new($device);
|
||||
return send_error('Bad device', 400)
|
||||
if ! $device or $device->addr eq '0.0.0.0';
|
||||
}
|
||||
|
||||
try {
|
||||
# job might already be in the queue, so this could die
|
||||
schema('netdisco')->resultset('Admin')->create({
|
||||
($device ? (device => $device->addr) : ()),
|
||||
action => $jobtype,
|
||||
status => 'queued',
|
||||
username => session('user'),
|
||||
userip => request->remote_address,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
# we have a separate list for jobs needing a device to avoid queueing
|
||||
# such a job when there's no device param (it could still be duff, tho).
|
||||
my %jobs = map { $_ => 1} qw/
|
||||
discover
|
||||
macsuck
|
||||
arpnip
|
||||
/;
|
||||
my %jobs_all = map {$_ => 1} qw/
|
||||
discoverall
|
||||
macwalk
|
||||
arpwalk
|
||||
/;
|
||||
|
||||
foreach my $jobtype (keys %jobs_all, keys %jobs) {
|
||||
ajax "/ajax/control/admin/$jobtype" => sub {
|
||||
send_error('Forbidden', 403)
|
||||
unless var('user')->admin;
|
||||
send_error('Missing device', 400)
|
||||
if exists $jobs{$jobtype} and not param('device');
|
||||
|
||||
add_job($jobtype, param('device'));
|
||||
};
|
||||
|
||||
post "/admin/$jobtype" => sub {
|
||||
send_error('Forbidden', 403)
|
||||
unless var('user')->admin;
|
||||
send_error('Missing device', 400)
|
||||
if exists $jobs{$jobtype} and not param('device');
|
||||
|
||||
add_job($jobtype, param('device'));
|
||||
redirect uri_for('/admin/jobqueue')->path_query;
|
||||
};
|
||||
}
|
||||
|
||||
get '/admin/*' => sub {
|
||||
my ($tag) = splat;
|
||||
|
||||
if (! eval { var('user')->admin }) {
|
||||
return redirect uri_for('/')->path_query;
|
||||
}
|
||||
|
||||
# trick the ajax into working as if this were a tabbed page
|
||||
params->{tab} = $tag;
|
||||
|
||||
var(nav => 'admin');
|
||||
template 'admintask', {
|
||||
task => setting('_admin_tasks')->{ $tag },
|
||||
};
|
||||
};
|
||||
|
||||
true;
|
||||
@@ -18,30 +18,31 @@ hook 'before' => sub {
|
||||
if (session('user') && session->id) {
|
||||
var(user => schema('netdisco')->resultset('User')
|
||||
->find(session('user')));
|
||||
|
||||
# really just for dev work, to quieten the logs
|
||||
var('user')->port_control(0) if setting('no_port_control');
|
||||
}
|
||||
};
|
||||
|
||||
post '/login' => sub {
|
||||
status(302);
|
||||
|
||||
if (param('username') and param('password')) {
|
||||
my $user = schema('netdisco')->resultset('User')->find(param('username'));
|
||||
|
||||
if ($user) {
|
||||
my $sum = Digest::MD5::md5_hex(param('password'));
|
||||
if (($sum and $user->password) and ($sum eq $user->password)) {
|
||||
session(user => $user->username);
|
||||
header(Location => uri_for('/inventory')->path_query());
|
||||
return;
|
||||
return redirect uri_for('/inventory')->path_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
header(Location => uri_for('/', {failed => 1})->path_query());
|
||||
|
||||
redirect uri_for('/', {failed => 1})->path_query;
|
||||
};
|
||||
|
||||
get '/logout' => sub {
|
||||
session->destroy;
|
||||
status(302);
|
||||
header(Location => uri_for('/', {logout => 1})->path_query());
|
||||
redirect uri_for('/', {logout => 1})->path_query;
|
||||
};
|
||||
|
||||
true;
|
||||
|
||||
@@ -5,10 +5,12 @@ use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
hook 'before' => sub {
|
||||
# list of port detail columns
|
||||
var('port_columns' => [
|
||||
{ name => 'c_admin', label => 'Admin Controls', default => '' },
|
||||
my @default_port_columns_left = (
|
||||
{ name => 'c_admin', label => 'Port Controls', default => '' },
|
||||
{ name => 'c_port', label => 'Port', default => 'on' },
|
||||
);
|
||||
|
||||
my @default_port_columns_right = (
|
||||
{ name => 'c_descr', label => 'Description', default => '' },
|
||||
{ name => 'c_type', label => 'Type', default => '' },
|
||||
{ name => 'c_duplex', label => 'Duplex', default => '' },
|
||||
@@ -24,7 +26,21 @@ hook 'before' => sub {
|
||||
{ name => 'c_neighbors', label => 'Connected Devices', default => 'on' },
|
||||
{ name => 'c_stp', label => 'Spanning Tree', default => '' },
|
||||
{ name => 'c_up', label => 'Status', default => '' },
|
||||
]);
|
||||
);
|
||||
|
||||
# build list of port detail columns
|
||||
my @port_columns = ();
|
||||
|
||||
push @port_columns,
|
||||
grep {$_->{position} eq 'left'} @{ setting('_extra_device_port_cols') };
|
||||
push @port_columns, @default_port_columns_left;
|
||||
push @port_columns,
|
||||
grep {$_->{position} eq 'mid'} @{ setting('_extra_device_port_cols') };
|
||||
push @port_columns, @default_port_columns_right;
|
||||
push @port_columns,
|
||||
grep {$_->{position} eq 'right'} @{ setting('_extra_device_port_cols') };
|
||||
|
||||
var('port_columns' => \@port_columns);
|
||||
|
||||
# view settings for port connected devices
|
||||
var('connected_properties' => [
|
||||
@@ -100,9 +116,7 @@ get '/device' => sub {
|
||||
});
|
||||
|
||||
if (!defined $dev) {
|
||||
status(302);
|
||||
header(Location => uri_for('/', {nosuchdevice => 1})->path_query());
|
||||
return;
|
||||
return redirect uri_for('/', {nosuchdevice => 1})->path_query;
|
||||
}
|
||||
|
||||
params->{'tab'} ||= 'details';
|
||||
|
||||
@@ -4,12 +4,16 @@ use Dancer ':syntax';
|
||||
use Dancer::Plugin;
|
||||
|
||||
set(
|
||||
'navbar_items' => [],
|
||||
'search_tabs' => [],
|
||||
'device_tabs' => [],
|
||||
'reports_menu' => {},
|
||||
'reports' => {},
|
||||
'report_order' => [qw/Device Port Node VLAN Network Wireless/],
|
||||
'_additional_css' => [],
|
||||
'_additional_javascript' => [],
|
||||
'_extra_device_port_cols' => [],
|
||||
'_navbar_items' => [],
|
||||
'_search_tabs' => [],
|
||||
'_device_tabs' => [],
|
||||
'_admin_tasks' => {},
|
||||
'_reports_menu' => {},
|
||||
'_reports' => {},
|
||||
'_report_order' => [qw/Device Port Node VLAN Network Wireless/],
|
||||
);
|
||||
|
||||
# this is what Dancer::Template::TemplateToolkit does by default
|
||||
@@ -19,8 +23,7 @@ register 'register_template_path' => sub {
|
||||
my ($self, $path) = plugin_args(@_);
|
||||
|
||||
if (!length $path) {
|
||||
error "bad template path to register_template_paths";
|
||||
return;
|
||||
return error "bad template path to register_template_paths";
|
||||
}
|
||||
|
||||
unshift
|
||||
@@ -28,6 +31,49 @@ register 'register_template_path' => sub {
|
||||
$path;
|
||||
};
|
||||
|
||||
sub _register_include {
|
||||
my ($type, $plugin) = @_;
|
||||
|
||||
if (!length $type) {
|
||||
return error "bad type to _register_include";
|
||||
}
|
||||
|
||||
if (!length $plugin) {
|
||||
return error "bad plugin name to register_$type";
|
||||
}
|
||||
|
||||
push @{ setting("_additional_$type") }, $plugin;
|
||||
}
|
||||
|
||||
register 'register_css' => sub {
|
||||
my ($self, $plugin) = plugin_args(@_);
|
||||
_register_include('css', $plugin);
|
||||
};
|
||||
|
||||
register 'register_javascript' => sub {
|
||||
my ($self, $plugin) = plugin_args(@_);
|
||||
_register_include('javascript', $plugin);
|
||||
};
|
||||
|
||||
register 'register_device_port_column' => sub {
|
||||
my ($self, $config) = plugin_args(@_);
|
||||
$config->{default} ||= '';
|
||||
$config->{position} ||= 'right';
|
||||
|
||||
if (!length $config->{name} or !length $config->{label}) {
|
||||
return error "bad config to register_device_port_column";
|
||||
}
|
||||
|
||||
foreach my $item (@{ setting('_extra_device_port_cols') }) {
|
||||
if ($item->{name} eq $config->{name}) {
|
||||
$item = $config;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
push @{ setting('_extra_device_port_cols') }, $config;
|
||||
};
|
||||
|
||||
register 'register_navbar_item' => sub {
|
||||
my ($self, $config) = plugin_args(@_);
|
||||
|
||||
@@ -35,29 +81,39 @@ register 'register_navbar_item' => sub {
|
||||
or !length $config->{path}
|
||||
or !length $config->{label}) {
|
||||
|
||||
error "bad config to register_navbar_item";
|
||||
return;
|
||||
return error "bad config to register_navbar_item";
|
||||
}
|
||||
|
||||
foreach my $item (@{ setting('navbar_items') }) {
|
||||
foreach my $item (@{ setting('_navbar_items') }) {
|
||||
if ($item->{tag} eq $config->{tag}) {
|
||||
$item = $config;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
push @{ setting('navbar_items') }, $config;
|
||||
push @{ setting('_navbar_items') }, $config;
|
||||
};
|
||||
|
||||
sub _register_tab {
|
||||
my ($nav, $config) = @_;
|
||||
my $stash = setting("${nav}_tabs");
|
||||
register 'register_admin_task' => sub {
|
||||
my ($self, $config) = plugin_args(@_);
|
||||
|
||||
if (!length $config->{tag}
|
||||
or !length $config->{label}) {
|
||||
|
||||
error "bad config to register_${nav}_item";
|
||||
return;
|
||||
return error "bad config to register_admin_task";
|
||||
}
|
||||
|
||||
setting('_admin_tasks')->{ $config->{tag} } = $config;
|
||||
};
|
||||
|
||||
sub _register_tab {
|
||||
my ($nav, $config) = @_;
|
||||
my $stash = setting("_${nav}_tabs");
|
||||
|
||||
if (!length $config->{tag}
|
||||
or !length $config->{label}) {
|
||||
|
||||
return error "bad config to register_${nav}_item";
|
||||
}
|
||||
|
||||
foreach my $item (@{ $stash }) {
|
||||
@@ -82,26 +138,25 @@ register 'register_device_tab' => sub {
|
||||
|
||||
register 'register_report' => sub {
|
||||
my ($self, $config) = plugin_args(@_);
|
||||
my @categories = @{ setting('report_order') };
|
||||
my @categories = @{ setting('_report_order') };
|
||||
|
||||
if (!length $config->{category}
|
||||
or !length $config->{tag}
|
||||
or !length $config->{label}
|
||||
or 0 == scalar grep {$config->{category} eq $_} @categories) {
|
||||
|
||||
error "bad config to register_report";
|
||||
return;
|
||||
return error "bad config to register_report";
|
||||
}
|
||||
|
||||
foreach my $item (@{setting('reports_menu')->{ $config->{category} }}) {
|
||||
foreach my $item (@{setting('_reports_menu')->{ $config->{category} }}) {
|
||||
if ($item eq $config->{tag}) {
|
||||
setting('reports')->{$config->{tag}} = $config;
|
||||
setting('_reports')->{$config->{tag}} = $config;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
push @{setting('reports_menu')->{ $config->{category} }}, $config->{tag};
|
||||
setting('reports')->{$config->{tag}} = $config;
|
||||
push @{setting('_reports_menu')->{ $config->{category} }}, $config->{tag};
|
||||
setting('_reports')->{$config->{tag}} = $config;
|
||||
};
|
||||
|
||||
register_plugin;
|
||||
|
||||
37
Netdisco/lib/App/Netdisco/Web/Plugin/AdminTask/JobQueue.pm
Normal file
37
Netdisco/lib/App/Netdisco/Web/Plugin/AdminTask/JobQueue.pm
Normal file
@@ -0,0 +1,37 @@
|
||||
package App::Netdisco::Web::Plugin::AdminTask::JobQueue;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
|
||||
register_admin_task({
|
||||
tag => 'jobqueue',
|
||||
label => 'Job Queue',
|
||||
});
|
||||
|
||||
ajax '/ajax/control/admin/jobqueue/del' => sub {
|
||||
send_error('Forbidden', 403) unless var('user')->admin;
|
||||
send_error('Missing job', 400) unless length param('job');
|
||||
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my $device = schema('netdisco')->resultset('Admin')
|
||||
->search({job => param('job')})->delete;
|
||||
});
|
||||
};
|
||||
|
||||
ajax '/ajax/content/admin/jobqueue' => sub {
|
||||
send_error('Forbidden', 403) unless var('user')->admin;
|
||||
|
||||
my $set = schema('netdisco')->resultset('Admin')
|
||||
->with_times
|
||||
->search({}, {order_by => { -desc => [qw/entered device action/] }});
|
||||
|
||||
content_type('text/html');
|
||||
template 'ajax/admintask/jobqueue.tt', {
|
||||
results => $set,
|
||||
}, { layout => undef };
|
||||
};
|
||||
|
||||
true;
|
||||
103
Netdisco/lib/App/Netdisco/Web/Plugin/AdminTask/PseudoDevice.pm
Normal file
103
Netdisco/lib/App/Netdisco/Web/Plugin/AdminTask/PseudoDevice.pm
Normal file
@@ -0,0 +1,103 @@
|
||||
package App::Netdisco::Web::Plugin::AdminTask::PseudoDevice;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
use NetAddr::IP::Lite ':lower';
|
||||
|
||||
register_admin_task({
|
||||
tag => 'pseudodevice',
|
||||
label => 'Pseudo Devices',
|
||||
});
|
||||
|
||||
sub _sanity_ok {
|
||||
return 0 unless var('user') and var('user')->admin;
|
||||
|
||||
return 0 unless length param('dns')
|
||||
and param('dns') =~ m/^[[:print:]]+$/
|
||||
and param('dns') !~ m/[[:space:]]/;
|
||||
|
||||
my $ip = NetAddr::IP::Lite->new(param('ip'));
|
||||
return 0 unless ($ip and$ip->addr ne '0.0.0.0');
|
||||
|
||||
return 0 unless length param('ports')
|
||||
and param('ports') =~ m/^[[:digit:]]+$/;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ajax '/ajax/control/admin/pseudodevice/add' => sub {
|
||||
send_error('Bad Request', 400) unless _sanity_ok();
|
||||
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->create({
|
||||
ip => param('ip'),
|
||||
dns => param('dns'),
|
||||
vendor => 'netdisco',
|
||||
last_discover => \'now()',
|
||||
});
|
||||
return unless $device;
|
||||
|
||||
$device->ports->populate([
|
||||
['port'],
|
||||
map {["Port$_"]} @{[1 .. param('ports')]},
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
ajax '/ajax/control/admin/pseudodevice/del' => sub {
|
||||
send_error('Bad Request', 400) unless _sanity_ok();
|
||||
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->find({ip => param('ip')});
|
||||
|
||||
$device->ports->delete;
|
||||
$device->delete;
|
||||
});
|
||||
};
|
||||
|
||||
ajax '/ajax/control/admin/pseudodevice/update' => sub {
|
||||
send_error('Bad Request', 400) unless _sanity_ok();
|
||||
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->with_port_count->find({ip => param('ip')});
|
||||
return unless $device;
|
||||
my $count = $device->port_count;
|
||||
|
||||
if (param('ports') > $count) {
|
||||
my $start = $count + 1;
|
||||
$device->ports->populate([
|
||||
['port'],
|
||||
map {["Port$_"]} @{[$start .. param('ports')]},
|
||||
]);
|
||||
}
|
||||
elsif (param('ports') < $count) {
|
||||
my $start = param('ports') + 1;
|
||||
$device->ports
|
||||
->single({port => "Port$_"})->delete
|
||||
for ($start .. $count);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ajax '/ajax/content/admin/pseudodevice' => sub {
|
||||
send_error('Forbidden', 403) unless var('user')->admin;
|
||||
|
||||
my $set = schema('netdisco')->resultset('Device')
|
||||
->search(
|
||||
{vendor => 'netdisco'},
|
||||
{order_by => { -desc => 'last_discover' }},
|
||||
)->with_port_count;
|
||||
|
||||
content_type('text/html');
|
||||
template 'ajax/admintask/pseudodevice.tt', {
|
||||
results => $set,
|
||||
}, { layout => undef };
|
||||
};
|
||||
|
||||
true;
|
||||
103
Netdisco/lib/App/Netdisco/Web/Plugin/AdminTask/Topology.pm
Normal file
103
Netdisco/lib/App/Netdisco/Web/Plugin/AdminTask/Topology.pm
Normal file
@@ -0,0 +1,103 @@
|
||||
package App::Netdisco::Web::Plugin::AdminTask::Topology;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
use App::Netdisco::Web::Plugin;
|
||||
use NetAddr::IP::Lite ':lower';
|
||||
|
||||
register_admin_task({
|
||||
tag => 'topology',
|
||||
label => 'Manual Device Topology',
|
||||
});
|
||||
|
||||
sub _sanity_ok {
|
||||
return 0 unless var('user') and var('user')->admin;
|
||||
|
||||
my $dev1 = NetAddr::IP::Lite->new(param('dev1'));
|
||||
return 0 unless ($dev1 and $dev1->addr ne '0.0.0.0');
|
||||
|
||||
my $dev2 = NetAddr::IP::Lite->new(param('dev2'));
|
||||
return 0 unless ($dev2 and $dev2->addr ne '0.0.0.0');
|
||||
|
||||
return 0 unless length param('port1');
|
||||
return 0 unless length param('port2');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ajax '/ajax/control/admin/topology/add' => sub {
|
||||
send_error('Bad Request', 400) unless _sanity_ok();
|
||||
|
||||
my $device = schema('netdisco')->resultset('Topology')
|
||||
->create({
|
||||
dev1 => param('dev1'),
|
||||
port1 => param('port1'),
|
||||
dev2 => param('dev2'),
|
||||
port2 => param('port2'),
|
||||
});
|
||||
|
||||
# re-set remote device details in affected ports
|
||||
# could fail for bad device or port names
|
||||
try {
|
||||
schema('netdisco')->txn_do(sub {
|
||||
# only work on root_ips
|
||||
my $left = get_device(param('dev1'));
|
||||
my $right = get_device(param('dev2'));
|
||||
|
||||
# skip bad entries
|
||||
return unless ($left->in_storage and $right->in_storage);
|
||||
|
||||
$left->ports
|
||||
->single({port => param('port1')}, {for => 'update'})
|
||||
->update({
|
||||
remote_ip => param('dev2'),
|
||||
remote_port => param('port2'),
|
||||
remote_type => undef,
|
||||
remote_id => undef,
|
||||
is_uplink => \"true",
|
||||
manual_topo => \"true",
|
||||
});
|
||||
|
||||
$right->ports
|
||||
->single({port => param('port2')}, {for => 'update'})
|
||||
->update({
|
||||
remote_ip => param('dev1'),
|
||||
remote_port => param('port1'),
|
||||
remote_type => undef,
|
||||
remote_id => undef,
|
||||
is_uplink => \"true",
|
||||
manual_topo => \"true",
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
ajax '/ajax/control/admin/topology/del' => sub {
|
||||
send_error('Bad Request', 400) unless _sanity_ok();
|
||||
|
||||
schema('netdisco')->txn_do(sub {
|
||||
my $device = schema('netdisco')->resultset('Topology')
|
||||
->search({
|
||||
dev1 => param('dev1'),
|
||||
port1 => param('port1'),
|
||||
dev2 => param('dev2'),
|
||||
port2 => param('port2'),
|
||||
})->delete;
|
||||
});
|
||||
};
|
||||
|
||||
ajax '/ajax/content/admin/topology' => sub {
|
||||
send_error('Forbidden', 403) unless var('user')->admin;
|
||||
|
||||
my $set = schema('netdisco')->resultset('Topology')
|
||||
->search({},{order_by => [qw/dev1 dev2 port1/]});
|
||||
|
||||
content_type('text/html');
|
||||
template 'ajax/admintask/topology.tt', {
|
||||
results => $set,
|
||||
}, { layout => undef };
|
||||
};
|
||||
|
||||
true;
|
||||
@@ -13,7 +13,7 @@ ajax '/ajax/content/device/addresses' => sub {
|
||||
my $q = param('q');
|
||||
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->search_for_device($q) or return;
|
||||
->search_for_device($q) or send_error('Bad device', 400);
|
||||
|
||||
my $set = $device->device_ips->search({}, {order_by => 'alias'});
|
||||
return unless $set->count;
|
||||
|
||||
@@ -12,7 +12,7 @@ register_device_tab({ tag => 'details', label => 'Details' });
|
||||
ajax '/ajax/content/device/details' => sub {
|
||||
my $q = param('q');
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->with_times()->search_for_device($q) or return;
|
||||
->with_times()->search_for_device($q) or send_error('Bad device', 400);
|
||||
|
||||
content_type('text/html');
|
||||
template 'ajax/device/details.tt', {
|
||||
|
||||
@@ -43,7 +43,7 @@ get '/ajax/data/device/netmap' => sub {
|
||||
my $q = param('q');
|
||||
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->search_for_device($q) or return;
|
||||
->search_for_device($q) or send_error('Bad device', 400);
|
||||
my $start = $device->ip;
|
||||
|
||||
my @devices = schema('netdisco')->resultset('Device')->search({}, {
|
||||
@@ -72,7 +72,7 @@ get '/ajax/data/device/netmap' => sub {
|
||||
_add_children($tree{children}, var('links')->{$start});
|
||||
|
||||
content_type('application/json');
|
||||
return to_json(\%tree);
|
||||
to_json(\%tree);
|
||||
};
|
||||
|
||||
ajax '/ajax/data/device/alldevicelinks' => sub {
|
||||
@@ -93,7 +93,7 @@ ajax '/ajax/data/device/alldevicelinks' => sub {
|
||||
}
|
||||
|
||||
content_type('application/json');
|
||||
return to_json(\%tree);
|
||||
to_json(\%tree);
|
||||
};
|
||||
|
||||
true;
|
||||
|
||||
@@ -14,7 +14,7 @@ ajax '/ajax/content/device/ports' => sub {
|
||||
my $q = param('q');
|
||||
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->search_for_device($q) or return;
|
||||
->search_for_device($q) or send_error('Bad device', 400);
|
||||
my $set = $device->ports;
|
||||
|
||||
# refine by ports if requested
|
||||
@@ -77,7 +77,7 @@ ajax '/ajax/content/device/ports' => sub {
|
||||
template 'ajax/device/ports.tt', {
|
||||
results => $results,
|
||||
nodes => $nodes_name,
|
||||
device => $device->ip,
|
||||
device => $device,
|
||||
}, { layout => undef };
|
||||
};
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ ajax '/ajax/content/search/device' => sub {
|
||||
}
|
||||
else {
|
||||
my $q = param('q');
|
||||
return unless $q;
|
||||
send_error('Missing query', 400) unless $q;
|
||||
|
||||
$set = schema('netdisco')->resultset('Device')->search_fuzzy($q);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ register_search_tab({ tag => 'node', label => 'Node' });
|
||||
# nodes matching the param as an IP or DNS hostname or MAC
|
||||
ajax '/ajax/content/search/node' => sub {
|
||||
my $node = param('q');
|
||||
return unless $node;
|
||||
send_error('Missing node', 400) unless $node;
|
||||
content_type('text/html');
|
||||
|
||||
my $mac = Net::MAC->new(mac => $node, 'die' => 0, verbose => 0);
|
||||
|
||||
@@ -11,7 +11,7 @@ register_search_tab({ tag => 'port', label => 'Port' });
|
||||
# device ports with a description (er, name) matching
|
||||
ajax '/ajax/content/search/port' => sub {
|
||||
my $q = param('q');
|
||||
return unless $q;
|
||||
send_error('Missing query', 400) unless $q;
|
||||
my $set;
|
||||
|
||||
if ($q =~ m/^\d+$/) {
|
||||
|
||||
@@ -11,7 +11,7 @@ register_search_tab({ tag => 'vlan', label => 'VLAN' });
|
||||
# devices carrying vlan xxx
|
||||
ajax '/ajax/content/search/vlan' => sub {
|
||||
my $q = param('q');
|
||||
return unless $q;
|
||||
send_error('Missing query', 400) unless $q;
|
||||
my $set;
|
||||
|
||||
if ($q =~ m/^\d+$/) {
|
||||
|
||||
@@ -4,42 +4,43 @@ use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
use Try::Tiny;
|
||||
|
||||
ajax '/ajax/portcontrol' => sub {
|
||||
try {
|
||||
my $log = sprintf 'd:[%s] p:[%s] f:[%s]. a:[%s] v[%s]',
|
||||
param('device'), (param('port') || ''), param('field'),
|
||||
(param('action') || ''), (param('value') || '');
|
||||
send_error('Forbidden', 403)
|
||||
unless var('user')->port_control;
|
||||
send_error('No device/port/field', 400)
|
||||
unless param('device') and param('port') and param('field');
|
||||
|
||||
my %action_map = (
|
||||
'location' => 'location',
|
||||
'contact' => 'contact',
|
||||
'c_port' => 'portcontrol',
|
||||
'c_name' => 'portname',
|
||||
'c_vlan' => 'vlan',
|
||||
'c_power' => 'power',
|
||||
);
|
||||
my $log = sprintf 'd:[%s] p:[%s] f:[%s]. a:[%s] v[%s]',
|
||||
param('device'), (param('port') || ''), param('field'),
|
||||
(param('action') || ''), (param('value') || '');
|
||||
|
||||
my $action = $action_map{ param('field') };
|
||||
my $subaction = ($action =~ m/^(?:power|portcontrol)/
|
||||
? (param('action') ."-other")
|
||||
: param('value'));
|
||||
my %action_map = (
|
||||
'location' => 'location',
|
||||
'contact' => 'contact',
|
||||
'c_port' => 'portcontrol',
|
||||
'c_name' => 'portname',
|
||||
'c_vlan' => 'vlan',
|
||||
'c_power' => 'power',
|
||||
);
|
||||
|
||||
schema('netdisco')->resultset('Admin')->create({
|
||||
device => param('device'),
|
||||
port => param('port'),
|
||||
action => $action,
|
||||
subaction => $subaction,
|
||||
status => 'queued',
|
||||
username => session('user'),
|
||||
userip => request->remote_address,
|
||||
log => $log,
|
||||
});
|
||||
}
|
||||
catch {
|
||||
send_error('Failed to parse params or add DB record');
|
||||
};
|
||||
send_error('No action/value', 400)
|
||||
unless (param('action') or param('value'));
|
||||
|
||||
my $action = $action_map{ param('field') };
|
||||
my $subaction = ($action =~ m/^(?:power|portcontrol)/
|
||||
? (param('action') ."-other")
|
||||
: param('value'));
|
||||
|
||||
schema('netdisco')->resultset('Admin')->create({
|
||||
device => param('device'),
|
||||
port => param('port'),
|
||||
action => $action,
|
||||
subaction => $subaction,
|
||||
status => 'queued',
|
||||
username => session('user'),
|
||||
userip => request->remote_address,
|
||||
log => $log,
|
||||
});
|
||||
|
||||
content_type('application/json');
|
||||
to_json({});
|
||||
@@ -47,7 +48,7 @@ ajax '/ajax/portcontrol' => sub {
|
||||
|
||||
ajax '/ajax/userlog' => sub {
|
||||
my $user = session('user');
|
||||
send_error('No username') unless $user;
|
||||
send_error('No username', 400) unless $user;
|
||||
|
||||
my $rs = schema('netdisco')->resultset('Admin')->search({
|
||||
username => $user,
|
||||
|
||||
@@ -10,7 +10,7 @@ get '/report/*' => sub {
|
||||
|
||||
var(nav => 'reports');
|
||||
template 'report', {
|
||||
report => setting('reports')->{ $tag },
|
||||
report => setting('_reports')->{ $tag },
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -65,9 +65,7 @@ get '/search' => sub {
|
||||
|
||||
if (not param('tab')) {
|
||||
if (not $q) {
|
||||
status(302);
|
||||
header(Location => uri_for('/')->path_query());
|
||||
return;
|
||||
return redirect uri_for('/')->path_query;
|
||||
}
|
||||
|
||||
# pick most likely tab for initial results
|
||||
@@ -80,13 +78,11 @@ get '/search' => sub {
|
||||
if ($nd and $nd->count) {
|
||||
if ($nd->count == 1) {
|
||||
# redirect to device details for the one device
|
||||
status(302);
|
||||
header(Location => uri_for('/device', {
|
||||
return redirect uri_for('/device', {
|
||||
tab => 'details',
|
||||
q => ($nd->first->dns || $nd->first->ip),
|
||||
f => '',
|
||||
})->path_query());
|
||||
return;
|
||||
})->path_query;
|
||||
}
|
||||
|
||||
# multiple devices
|
||||
|
||||
30
Netdisco/lib/App/Netdisco/Web/Static.pm
Normal file
30
Netdisco/lib/App/Netdisco/Web/Static.pm
Normal file
@@ -0,0 +1,30 @@
|
||||
package App::Netdisco::Web::Static;
|
||||
|
||||
use Dancer ':syntax';
|
||||
use Path::Class;
|
||||
|
||||
get '/plugin/*/*.js' => sub {
|
||||
my ($plugin) = splat;
|
||||
|
||||
my $content = template
|
||||
"plugin/$plugin/$plugin.js", {},
|
||||
{ layout => undef };
|
||||
|
||||
send_file \$content,
|
||||
content_type => 'application/javascript',
|
||||
filename => "$plugin.js";
|
||||
};
|
||||
|
||||
get '/plugin/*/*.css' => sub {
|
||||
my ($plugin) = splat;
|
||||
|
||||
my $content = template
|
||||
"plugin/$plugin/$plugin.css", {},
|
||||
{ layout => undef };
|
||||
|
||||
send_file \$content,
|
||||
content_type => 'text/css',
|
||||
filename => "$plugin.css";
|
||||
};
|
||||
|
||||
true;
|
||||
@@ -4,13 +4,51 @@ use Dancer ':syntax';
|
||||
use Dancer::Plugin::Ajax;
|
||||
use Dancer::Plugin::DBIC;
|
||||
|
||||
# support typeahead with simple AJAX query for device names
|
||||
ajax '/ajax/data/device/typeahead' => sub {
|
||||
my $q = param('query');
|
||||
use App::Netdisco::Util::Web (); # for sort_port
|
||||
|
||||
ajax '/ajax/data/devicename/typeahead' => sub {
|
||||
my $q = param('query') || param('term');
|
||||
my $set = schema('netdisco')->resultset('Device')->search_fuzzy($q);
|
||||
|
||||
content_type 'application/json';
|
||||
return to_json [map {$_->dns || $_->name || $_->ip} $set->all];
|
||||
to_json [map {$_->dns || $_->name || $_->ip} $set->all];
|
||||
};
|
||||
|
||||
ajax '/ajax/data/deviceip/typeahead' => sub {
|
||||
my $q = param('query') || param('term');
|
||||
my $set = schema('netdisco')->resultset('Device')->search_fuzzy($q);
|
||||
|
||||
my @data = ();
|
||||
while (my $d = $set->next) {
|
||||
my $label = $d->ip;
|
||||
if ($d->dns or $d->name) {
|
||||
$label = sprintf '%s (%s)',
|
||||
($d->dns || $d->name), $d->ip;
|
||||
}
|
||||
push @data, {label => $label, value => $d->ip};
|
||||
}
|
||||
|
||||
content_type 'application/json';
|
||||
to_json \@data;
|
||||
};
|
||||
|
||||
ajax '/ajax/data/port/typeahead' => sub {
|
||||
my $dev = param('dev1') || param('dev2');
|
||||
my $port = param('port1') || param('port2');
|
||||
send_error('Missing device', 400) unless length $dev;
|
||||
|
||||
my $device = schema('netdisco')->resultset('Device')
|
||||
->find({ip => $dev});
|
||||
send_error('Bad device', 400) unless $device;
|
||||
|
||||
my $set = $device->ports({},{order_by => 'port'});
|
||||
$set = $set->search({port => { -ilike => "\%$port\%" }})
|
||||
if length $port;
|
||||
|
||||
my $results = [ sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } $set->all ];
|
||||
|
||||
content_type 'application/json';
|
||||
to_json [map {$_->port} @$results];
|
||||
};
|
||||
|
||||
true;
|
||||
|
||||
Reference in New Issue
Block a user