view release on metacpan or search on metacpan
[ENHANCEMENTS]
* #1044 faster PortVLANMismatch query
* #1045 custom fields are now indexed in the DB
* add "phone" to phone_platforms default config
* swagger-ui allows adding X-REMOTE_USER header when behind proxy
[BUG FIXES]
* add missing validate_remote_user default setting to config
* fix for undef HTTP_SERVER and HTTP_PORT err when browsing swagger-ui
2.062002 - 2023-06-06
[BUG FIXES]
* fix mistaken release with device ports partial search default as on
2.062001 - 2023-06-05
[ENHANCEMENTS]
* Add documentation note about SNMPv3 configuration on Cisco IOS
* Update repository and issue tracker links for GitHub
2.034001 - 2016-11-20
[NEW FEATURES]
* Add validate_remote_user setting to check proxied users are known
[ENHANCEMENTS]
* Add Linux SNMP, LLDP setup docs (S. Hobson)
* Add note on SLES 11 SP4 install workaround (C. Ramseyer)
[BUG FIXES]
* Remove some odd behaviour of cached SNMP config hints (L. Ferguson)
lib/App/Netdisco/Web/API/User.pm view on Meta::CPAN
my $provider = Dancer::Plugin::Auth::Extensible::auth_provider('users');
my $want_permanent = $body->{permanent} && setting('allow_permanent_tokens');
my $allowed_ips = (ref $body->{allowed_ips} eq ref []) ? $body->{allowed_ips} : undef;
$user->update({
token_from => time,
token_no_expire => ($want_permanent ? \"true" : \"false"),
(defined $allowed_ips ? (token_allowed_ips => $allowed_ips) : ()),
($provider->validate_api_token($user->token)
? () : (token => \'md5(random()::text)')),
})->discard_changes();
return to_json {
username => $username,
api_key => $user->token,
permanent => ($user->token_no_expire ? \1 : \0),
($user->token_allowed_ips
? (allowed_ips => $user->token_allowed_ips) : ()),
};
lib/App/Netdisco/Web/Auth/Provider/DBIC.pm view on Meta::CPAN
$database->resultset($users_table)->find({
#Â FIXME: ILIKE to get case insensitive match on username, no wildcards
$username_column => { -ilike => quotemeta($username) },
});
};
# each of these settings permits no user in the database
# so create a pseudo user entry instead
if (not $user and
(setting('no_auth') or
(not setting('validate_remote_user')
and (setting('trust_remote_user') or setting('trust_x_remote_user')) ))) {
$user = $database->resultset($users_table)
->new_result({username => $username});
}
return $user;
}
sub validate_api_token {
my ($self, $token) = @_;
return unless defined $token;
my $settings = $self->realm_settings;
my $database = schema($settings->{schema_name})
or die "No database connection";
my $users_table = $settings->{users_resultset} || 'User';
my $token_column = $settings->{users_token_column} || 'token';
lib/App/Netdisco/Web/AuthN.pm view on Meta::CPAN
# this works for API calls, too
elsif (setting('no_auth')) {
$username = 'guest';
}
return unless $username;
# from the internals of Dancer::Plugin::Auth::Extensible
my $provider = Dancer::Plugin::Auth::Extensible::auth_provider('users');
# 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 (
lib/App/Netdisco/Web/AuthN.pm view on Meta::CPAN
(setting('trust_x_remote_user') or setting('trust_remote_user'))) {
session->destroy;
request->path_info('/');
}
# API calls must conform strictly to path and header requirements
elsif (request_is_api and request->header('Authorization')) {
# from the internals of Dancer::Plugin::Auth::Extensible
my $provider = Dancer::Plugin::Auth::Extensible::auth_provider('users');
my $token = request->header('Authorization');
my $user = $provider->validate_api_token($token)
or return send_error('{"error":"invalid or expired token"}', 401);
session(logged_in_user => $user->username);
session(logged_in_user_realm => 'users');
}
elsif ($delegated) {
session(logged_in_user => $delegated->username);
session(logged_in_user_realm => 'users');
}
else {
lib/App/Netdisco/Web/AuthN.pm view on Meta::CPAN
my $provider = Dancer::Plugin::Auth::Extensible::auth_provider('users');
# get authN data from BasicAuth header used by API, put into params
my $authheader = request->header('Authorization');
if (defined $authheader and $authheader =~ /^Basic (.*)$/i) {
my ($u, $p) = split(m/:/, (MIME::Base64::decode($1) || ":"));
params->{username} = $u;
params->{password} = $p;
}
# validate authN
my ($success, $realm) = authenticate_user(param('username'),param('password'));
# or try to get user from somewhere else
my $delegated = _get_delegated_authn_user();
if (($success and not
# protect against delegated authN config but no valid user (then must ignore params)
(not $delegated and (setting('trust_x_remote_user') or setting('trust_remote_user'))))
or $delegated) {
lib/App/Netdisco/Web/AuthN.pm view on Meta::CPAN
my $body = try { from_json(request->body) } catch { {} };
my $want_permanent = $body->{permanent} && setting('allow_permanent_tokens');
my $allowed_ips = (ref $body->{allowed_ips} eq ref [])
? $body->{allowed_ips} : undef;
$user->update({
token_from => time,
token_no_expire => ($want_permanent ? \"true" : \"false"),
($allowed_ips ? (token_allowed_ips => $allowed_ips) : ()),
($provider->validate_api_token($user->token)
? () : (token => \'md5(random()::text)')),
})->discard_changes();
return to_json {
api_key => $user->token,
permanent => ($user->token_no_expire ? \1 : \0),
($user->token_allowed_ips
? (allowed_ips => $user->token_allowed_ips) : ()),
};
}
redirect ((scalar URI::Based->new(param('return_url'))->path_query) || '/');
}
else {
# invalidate session cookie
session->destroy;
schema('netdisco')->resultset('UserLog')->create({
username => param('username'),
userip => request->remote_address,
event => (sprintf 'Login Failure (%s)', ($api ? 'API' : 'WebUI')),
details => param('return_url'),
});
if ($api) {
lib/App/Netdisco/Web/AuthN.pm view on Meta::CPAN
},
get '/logout' => sub {
my $api = ((request->accept and request->accept =~ m/(?:json|javascript)/) ? true : false);
# clear out API token
my $user = schema('netdisco')->resultset('User')
->find({ username => session('logged_in_user')});
$user->update({token => undef, token_from => undef})->discard_changes()
if $user and $user->in_storage;
# invalidate session cookie
session->destroy;
schema('netdisco')->resultset('UserLog')->create({
username => session('logged_in_user'),
userip => request->remote_address,
event => (sprintf 'Logout (%s)', ($api ? 'API' : 'WebUI')),
details => '',
});
if ($api) {
lib/App/Netdisco/Web/Plugin/Device/Neighbors.pm view on Meta::CPAN
my $vlan = param('vlan');
undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/);
my $mapshow = param('mapshow');
return if !defined $mapshow or $mapshow !~ m/^(?:all|cloud|depth)$/;
my $depth = param('depth') || 1;
return if $depth !~ m/^\d+$/;
# list of groups selected by user and passed in param
my $hgroup = (ref [] eq ref param('hgroup') ? param('hgroup') : [param('hgroup')]);
# list of groups validated as real host groups and named host groups
my @hgrplist = List::MoreUtils::uniq
grep { exists setting('host_group_displaynames')->{$_} }
grep { exists setting('host_groups')->{$_} }
grep { defined } @{ $hgroup };
# list of locations selected by user and passed in param
my $lgroup = (ref [] eq ref param('lgroup') ? param('lgroup') : [param('lgroup')]);
my @lgrplist = List::MoreUtils::uniq grep { defined } @{ $lgroup };
my %clean = ();
lib/App/Netdisco/Web/Plugin/Device/Neighbors.pm view on Meta::CPAN
undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/);
my $colorby = (param('colorby') || 'speed');
my $mapshow = (param('mapshow') || 'depth');
my $depth = (param('depth') || 1);
$mapshow = 'depth' if $mapshow !~ m/^(?:all|cloud|depth)$/;
$mapshow = 'all' unless $qdev->in_storage;
# list of groups selected by user and passed in param
my $hgroup = (ref [] eq ref param('hgroup') ? param('hgroup') : [param('hgroup')]);
# list of groups validated as real host groups and named host groups
my @hgrplist = List::MoreUtils::uniq
grep { exists setting('host_group_displaynames')->{$_} }
grep { exists setting('host_groups')->{$_} }
grep { defined } @{ $hgroup };
# list of locations selected by user and passed in param
my $lgroup = (ref [] eq ref param('lgroup') ? param('lgroup') : [param('lgroup')]);
my @lgrplist = List::MoreUtils::uniq grep { defined } @{ $lgroup };
my %ok_dev = ();
lib/App/Netdisco/Worker/Plugin/GetAPIKey.pm view on Meta::CPAN
$user->update({ token => undef, token_from => undef, token_no_expire => \"false" });
return Status->done(sprintf 'Revoked API token for user %s', $username);
}
# from the internals of Dancer::Plugin::Auth::Extensible
my $provider = Dancer::Plugin::Auth::Extensible::auth_provider('users');
my %updates = (
token_from => time,
token_no_expire => ($flag eq 'permanent' ? \"true" : \"false"),
($provider->validate_api_token($user->token)
? () : (token => \'md5(random()::text)')),
);
$user->update(\%updates)->discard_changes();
return Status->done(
sprintf 'Set %s token for user %s: %s',
($flag eq 'permanent' ? 'permanent' : 'session'),
$username, $user->token);
});
share/config.yml view on Meta::CPAN
domain_suffix: []
branding_text: Netdisco
no_auth: false
suggest_guest: false
login_banner_message: null
navbar_autocomplete: true
max_typeahead_rows: 50
trust_remote_user: false
trust_x_remote_user: false
validate_remote_user: false
api_token_lifetime: 3600
allow_permanent_tokens: false
tacacs: {}
radius: {}
ldap: {}
# servers: []
# user_string: 'MYDOMAIN\%USER%'
# base: ""
# proxy_user: ""
# proxy_pass: ""
share/public/css/bootstrap.min.css view on Meta::CPAN
@charset "UTF-8";/*!
* Bootstrap v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff...
/*# sourceMappingURL=bootstrap.min.css.map */
share/public/javascripts/htmx.min.js view on Meta::CPAN
var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=dn(e,t||"post");return n.values},remove:null,addClass:null,removeClass:null,to...
share/public/javascripts/jquery.dataTables.min.js view on Meta::CPAN
/*! DataTables 2.3.8
* © SpryMedia Ltd - datatables.net/license
*/
(n=>{var r;"function"==typeof define&&define.amd?define(["jquery"],function(e){return n(e,window,document)}):"object"==typeof exports?(r=require("jquery"),"undefined"==typeof window?module.exports=function(e,t){return e=e||window,t=t||r(e),n(t,e,e.do...
share/public/javascripts/moment.min.js view on Meta::CPAN
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var H;function _(){return H.apply(null,arguments)}function y(e){return e...
//# sourceMappingURL=moment.min.js.map
share/public/swagger-ui/swagger-ui-bundle.js view on Meta::CPAN
/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */
!function webpackUniversalModuleDefinition(s,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.SwaggerUIBundle=o():s.SwaggerUIBundle=o()}(this,(...
share/public/swagger-ui/swagger-ui-bundle.js.map view on Meta::CPAN
{"version":3,"file":"swagger-ui-bundle.js","mappings":";CAAA,SAAUA,iCAAiCC,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,GAAIH,GACe,iBAAZC,QACdA,QAAyB,gBAAID,IAE7BD,EAAsB,gBAAIC,GAC3B,CATD,CASGK,MAAM,cCRLC,EA...
share/public/swagger-ui/swagger-ui-standalone-preset.js view on Meta::CPAN
/*! For license information please see swagger-ui-standalone-preset.js.LICENSE.txt */
!function webpackUniversalModuleDefinition(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.SwaggerUIStandalonePreset=e():t.SwaggerUIStandalo...
share/public/swagger-ui/swagger-ui-standalone-preset.js.map view on Meta::CPAN
{"version":3,"file":"swagger-ui-standalone-preset.js","mappings":";CAAA,SAAUA,iCAAiCC,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,GAAIH,GACe,iBAAZC,QACdA,QAAmC,0BAAID,IAEvCD,EAAgC,0BAAIC,GACrC,CATD,CASGK,MA...