App-Netdisco
view release on metacpan or search on metacpan
lib/App/Netdisco/Web/Auth/Provider/DBIC.pm view on Meta::CPAN
package App::Netdisco::Web::Auth::Provider::DBIC;
use strict;
use warnings;
use base 'Dancer::Plugin::Auth::Extensible::Provider::Base';
# with thanks to yanick's patch at
# https://github.com/bigpresh/Dancer-Plugin-Auth-Extensible/pull/24
use Dancer ':syntax';
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Passphrase;
use Digest::MD5;
use Net::LDAP;
use Authen::Radius;
use Authen::TacacsPlus;
use Path::Class;
use File::ShareDir 'dist_dir';
use Try::Tiny;
sub authenticate_user {
my ($self, $username, $password) = @_;
return unless defined $username;
my $user = $self->get_user_details($username) or return;
return unless $user->in_storage;
return $self->match_password($password, $user);
}
sub get_user_details {
my ($self, $username) = @_;
my $settings = $self->realm_settings;
my $database = schema($settings->{schema_name})
or die "No database connection";
my $users_table = $settings->{users_resultset} || 'User';
my $username_column = $settings->{users_username_column} || 'username';
my $user = try {
$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';
$token =~ s/^Apikey //i; # should be there but swagger-ui doesn't add it
my $user = try {
$database->resultset($users_table)->find({ $token_column => $token });
};
return $user
if $user and $user->in_storage and $user->token_from
and $user->token_from > (time - setting('api_token_lifetime'));
return undef;
}
sub get_user_roles {
my ($self, $username) = @_;
return unless defined $username;
my $settings = $self->realm_settings;
my $database = schema($settings->{schema_name})
or die "No database connection";
# Get details of the user first; both to check they exist, and so we have
# their ID to use.
my $user = $self->get_user_details($username)
or return;
my $roles = $settings->{roles_relationship} || 'roles';
my $role_column = $settings->{role_column} || 'role';
# this method returns a list of current user roles
#Â but for API with trust_remote_user, trust_x_remote_user, and no_auth
# we need to fake that there is a valid API key
my $api_requires_key =
(setting('trust_remote_user') or setting('trust_x_remote_user') or setting('no_auth'))
eq '1' ? 'false' : 'true';
return [ try {
$user->$roles->search({}, { bind => [
$api_requires_key, setting('api_token_lifetime'),
$api_requires_key, setting('api_token_lifetime'),
] })->get_column( $role_column )->all;
} ];
}
sub match_password {
my($self, $password, $user) = @_;
return unless $user;
my $settings = $self->realm_settings;
my $username_column = $settings->{users_username_column} || 'username';
( run in 2.327 seconds using v1.01-cache-2.11-cpan-56fb94df46f )