Koha-clms/Koha/Auth/Client.pm

224 lines
5.8 KiB
Perl

package Koha::Auth::Client;
# Copyright Theke Solutions 2022
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <https://www.gnu.org/licenses>.
use Modern::Perl;
use C4::Context;
use Koha::Exceptions::Auth;
use Koha::Auth::Identity::Providers;
=head1 NAME
Koha::Auth::Client - Base Koha auth client
=head1 API
=head2 Methods
=head3 new
my $auth_client = Koha::Auth::Client->new();
=cut
sub new {
my ($class) = @_;
my $self = {};
bless( $self, $class );
}
=head3 get_user
$auth_client->get_user($provider, $data)
Get user data according to provider's mapping configuration
=cut
sub get_user {
my ( $self, $params ) = @_;
my $provider_code = $params->{provider};
my $data = $params->{data};
my $interface = $params->{interface};
my $config = $params->{config};
my $provider = Koha::Auth::Identity::Providers->search( { code => $provider_code } )->next;
my ( $mapped_data, $patron ) =
$self->_get_data_and_patron( { provider => $provider, data => $data, config => $config } );
$mapped_data //= {};
my $domain = $self->has_valid_domain_config(
{ provider => $provider, email => $mapped_data->{email}, interface => $interface } );
my $args = {
provider => $provider,
data => $data,
config => $config,
mapped_data => $mapped_data,
patron => $patron,
domain => $domain,
};
# Call the plugin hook "auth_client_get_user" of all plugins.
Koha::Plugins->call( 'auth_client_get_user', $args );
$mapped_data = $args->{'mapped_data'};
$patron = $args->{'patron'};
$domain = $args->{'domain'};
$patron->set($mapped_data)->store if $patron && $domain->update_on_auth;
$mapped_data->{categorycode} = $domain->default_category_id;
$mapped_data->{branchcode} = $domain->default_library_id;
return ( $patron, $mapped_data, $domain );
}
=head3 get_valid_domain_config
my $domain = Koha::Auth::Client->get_valid_domain_config(
{ provider => $provider,
email => $user_email,
interface => $interface
}
);
Gets the best suited valid domain configuration for the given provider.
=cut
sub get_valid_domain_config {
# FIXME: Should be a hashref param
my ( $self, $params ) = @_;
my $provider = $params->{provider};
my $user_email = $params->{email};
my $interface = $params->{interface};
my $domains = $provider->domains;
my $allow = "allow_$interface";
my @subdomain_matches;
my $perfect_match;
my $response;
while ( my $domain = $domains->next ) {
my $pattern = '@';
my $domain_text = $domain->domain;
unless ( defined $domain_text && $domain_text ne '' ) {
$response = $domain;
next;
}
my ( $asterisk, $domain_name ) = ( $domain_text =~ /^(\*)?(.+)$/ );
if ( defined $asterisk && $asterisk eq '*' ) {
$pattern .= '.*';
}
$domain_name =~ s/\./\\\./g;
$pattern .= $domain_name . '$';
if ( $user_email =~ /$pattern/ ) {
if ( defined $asterisk && $asterisk eq '*' ) {
push @subdomain_matches, { domain => $domain, match_length => length $domain_name };
} else {
$perfect_match = $domain;
}
}
}
if ( !$perfect_match && @subdomain_matches ) {
@subdomain_matches = sort { $b->{match_length} <=> $a->{match_length} } @subdomain_matches
unless scalar @subdomain_matches == 1;
$response = $subdomain_matches[0]->{domain};
} elsif ($perfect_match) {
$response = $perfect_match;
}
return unless $response && $response->$allow;
return $response;
}
=head3 has_valid_domain_config
my $has_valid_domain = Koha::Auth::Client->has_valid_domain_config(
{ provider => $provider,
email => $user_email,
interface => $interface
}
);
Checks if provider has a valid domain for user email. If has, returns that domain.
=cut
sub has_valid_domain_config {
# FIXME: Should be a hashref param
my ( $self, $params ) = @_;
my $domain = $self->get_valid_domain_config($params);
Koha::Exceptions::Auth::NoValidDomain->throw( code => 401 )
unless $domain;
return $domain;
}
=head3 _get_data_and_patron
my $mapping = $auth_client->_get_data_and_patron(
{ provider => $provider,
data => $data,
config => $config
}
);
Generic method that maps raw data to patron schema, and returns a patron if it can.
Note: this only returns an empty I<hashref>. Each class should have its
own mapping returned.
=cut
sub _get_data_and_patron {
return {};
}
=head3 _traverse_hash
my $value = $auth_client->_traverse_hash( { base => $base_hash, keys => $key_string } );
Get deep nested value in a hash.
=cut
sub _traverse_hash {
my ( $self, $params ) = @_;
my $base = $params->{base};
my $keys = $params->{keys};
my ( $key, $rest ) = ( $keys =~ /^([^.]+)(?:\.(.*))?/ );
return unless defined $key;
my $value = ref $base eq 'HASH' ? $base->{$key} : $base->[$key];
return $value unless $rest;
return $self->_traverse_hash( { base => $value, keys => $rest } );
}
1;