use List::MoreUtils qw/ any /;
use Encode qw( encode is_utf8);
use C4::Auth_with_shibboleth;
+use Net::CIDR;
# use utf8;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout);
@ISA = qw(Exporter);
@EXPORT = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions);
@EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &checkpw_internal &checkpw_hash
- &get_all_subpermissions &get_user_subpermissions track_login_daily
+ &get_all_subpermissions &get_user_subpermissions track_login_daily &in_ipset
);
%EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
$ldap = C4::Context->config('useldapserver') || 0;
}
# If we enforce GDPR and the user did not consent, redirect
+ # Exceptions for consent page itself and SCI/SCO system
if( $in->{type} eq 'opac' && $user &&
- $in->{'template_name'} !~ /opac-patron-consent/ &&
+ $in->{'template_name'} !~ /^(opac-patron-consent|sc[io]\/)/ &&
C4::Context->preference('GDPR_Policy') eq 'Enforced' )
{
my $consent = Koha::Patron::Consents->search({
if (
# If the user logged in is the SCO user and they try to go out of the SCO module,
# log the user out removing the CGISESSID cookie
- $in->{template_name} !~ m|sco/|
+ $in->{template_name} !~ m|sco/| && $in->{template_name} !~ m|errors/errorpage.tt|
&& C4::Context->preference('AutoSelfCheckID')
&& $user eq C4::Context->preference('AutoSelfCheckID')
)
AmazonCoverImages => C4::Context->preference("AmazonCoverImages"),
AutoLocation => C4::Context->preference("AutoLocation"),
"BiblioDefaultView" . C4::Context->preference("IntranetBiblioDefaultView") => 1,
- CircAutocompl => C4::Context->preference("CircAutocompl"),
+ PatronAutocompletion => C4::Context->preference("PatronAutocompletion"),
FRBRizeEditions => C4::Context->preference("FRBRizeEditions"),
IndependentBranches => C4::Context->preference("IndependentBranches"),
IntranetNav => C4::Context->preference("IntranetNav"),
my @search_groups = Koha::Library::Groups->get_search_groups({ interface => 'opac' });
$template->param(
- OpacAdditionalStylesheet => C4::Context->preference("OpacAdditionalStylesheet"),
AnonSuggestions => "" . C4::Context->preference("AnonSuggestions"),
LibrarySearchGroups => \@search_groups,
opac_name => $opac_name,
OpacKohaUrl => C4::Context->preference("OpacKohaUrl"),
OpacMainUserBlock => "" . C4::Context->preference("OpacMainUserBlock"),
OpacNav => "" . C4::Context->preference("OpacNav"),
- OpacNavRight => "" . C4::Context->preference("OpacNavRight"),
OpacNavBottom => "" . C4::Context->preference("OpacNavBottom"),
OpacPasswordChange => C4::Context->preference("OpacPasswordChange"),
OPACPatronDetails => C4::Context->preference("OPACPatronDetails"),
'Version' => C4::Context->preference('Version'),
hidelostitems => C4::Context->preference("hidelostitems"),
mylibraryfirst => ( C4::Context->preference("SearchMyLibraryFirst") && C4::Context->userenv ) ? C4::Context->userenv->{'branch'} : '',
- opaclayoutstylesheet => "" . C4::Context->preference("opaclayoutstylesheet"),
opacbookbag => "" . C4::Context->preference("opacbookbag"),
opaccredits => "" . C4::Context->preference("opaccredits"),
OpacFavicon => C4::Context->preference("OpacFavicon"),
$session->param( 'emailaddress', $emailaddress );
$session->param( 'ip', $session->remote_addr() );
$session->param( 'lasttime', time() );
+ $session->param( 'interface', $type);
$session->param( 'shibboleth', $shibSuccess );
$debug and printf STDERR "AUTH_4: (%s)\t%s %s - %s\n", map { $session->param($_) } qw(cardnumber firstname surname branch);
}
$session->param( 'lasttime', time() );
$session->param( 'ip', $session->remote_addr() );
$session->param( 'sessiontype', 'anon' );
+ $session->param( 'interface', $type);
}
} # END if ( $q_userid
elsif ( $type eq "opac" ) {
$session->param( 'ip', $session->remote_addr() );
$session->param( 'lasttime', time() );
$session->param( 'sessiontype', 'anon' );
+ $session->param( 'interface', $type);
}
} # END unless ($userid)
my $template_name = ( $type eq 'opac' ) ? 'opac-auth.tt' : 'auth.tt';
my $template = C4::Templates::gettemplate( $template_name, $type, $query );
$template->param(
- OpacAdditionalStylesheet => C4::Context->preference("OpacAdditionalStylesheet"),
- opaclayoutstylesheet => C4::Context->preference("opaclayoutstylesheet"),
login => 1,
INPUTS => \@inputs,
script_name => get_script_name(),
LibraryNameTitle => "" . $LibraryNameTitle,
opacuserlogin => C4::Context->preference("opacuserlogin"),
OpacNav => C4::Context->preference("OpacNav"),
- OpacNavRight => C4::Context->preference("OpacNavRight"),
OpacNavBottom => C4::Context->preference("OpacNavBottom"),
opaccredits => C4::Context->preference("opaccredits"),
OpacFavicon => C4::Context->preference("OpacFavicon"),
my $session = get_session($sessionID);
C4::Context->_new_userenv($sessionID);
if ($session) {
+ C4::Context->interface($session->param('interface'));
C4::Context->set_userenv(
$session->param('number'), $session->param('id'),
$session->param('cardnumber'), $session->param('firstname'),
$session->param( 'emailaddress', $emailaddress );
$session->param( 'ip', $session->remote_addr() );
$session->param( 'lasttime', time() );
+ $session->param( 'interface', 'api' );
}
$session->param( 'cas_ticket', $cas_ticket);
C4::Context->set_userenv(
($status, $sessionId) = check_api_auth($cookie, $userflags);
Given a CGISESSID cookie set during a previous login to Koha, determine
-if the user has the privileges specified by C<$userflags>.
+if the user has the privileges specified by C<$userflags>. C<$userflags>
+is passed unaltered into C<haspermission> and as such accepts all options
+avaiable to that routine with the one caveat that C<check_api_auth> will
+also allow 'undef' to be passed and in such a case the permissions check
+will be skipped altogether.
C<check_cookie_auth> is meant for authenticating special services
such as tools/upload-file.pl that are invoked by other pages that
my $session = get_session($sessionID);
C4::Context->_new_userenv($sessionID);
if ($session) {
+ C4::Context->interface($session->param('interface'));
C4::Context->set_userenv(
$session->param('number'), $session->param('id'),
$session->param('cardnumber'), $session->param('firstname'),
return ( "expired", undef );
} else {
$session->param( 'lasttime', time() );
- my $flags = haspermission( $userid, $flagsrequired );
+ my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
if ($flags) {
return ( "ok", $sessionID );
} else {
my @return;
my $patron = Koha::Patrons->find({ userid => $userid });
+ $patron = Koha::Patrons->find({ cardnumber => $userid }) unless $patron;
my $check_internal_as_fallback = 0;
my $passwd_ok = 0;
# Note: checkpw_* routines returns:
if( $patron ) {
if ( $passwd_ok ) {
$patron->update({ login_attempts => 0 });
- } else {
+ } elsif( !$patron->account_locked ) {
$patron->update({ login_attempts => $patron->login_attempts + 1 });
}
}
=head2 haspermission
+ $flagsrequired = '*'; # Any permission at all
+ $flagsrequired = 'a_flag'; # a_flag must be satisfied (all subpermissions)
+ $flagsrequired = [ 'a_flag', 'b_flag' ]; # a_flag OR b_flag must be satisfied
+ $flagsrequired = { 'a_flag => 1, 'b_flag' => 1 }; # a_flag AND b_flag must be satisfied
+ $flagsrequired = { 'a_flag' => 'sub_a' }; # sub_a of a_flag must be satisfied
+ $flagsrequired = { 'a_flag' => [ 'sub_a, 'sub_b' ] }; # sub_a OR sub_b of a_flag must be satisfied
+
$flags = ($userid, $flagsrequired);
C<$userid> the userid of the member
C<$flags> is a query structure similar to that used by SQL::Abstract that
-denotes the combination of flags required.
+denotes the combination of flags required. It is a required parameter.
The main logic of this method is that things in arrays are OR'ed, and things
-in hashes are AND'ed.
+in hashes are AND'ed. The `*` character can be used, at any depth, to denote `ANY`
Returns member's flags or 0 if a permission is not met.
}
} elsif ($ref eq 'HASH') {
foreach my $key (keys %{$required}) {
+ next if $flags == 1;
my $require = $required->{$key};
my $rflags = $flags->{$key};
return 0 unless _dispatch($require, $rflags);
sub haspermission {
my ( $userid, $flagsrequired ) = @_;
+
+ #Koha::Exceptions::WrongParameter->throw('$flagsrequired should not be undef')
+ # unless defined($flagsrequired);
+
my $sth = C4::Context->dbh->prepare("SELECT flags FROM borrowers WHERE userid=?");
$sth->execute($userid);
my $row = $sth->fetchrow();
my $flags = getuserflags( $row, $userid );
+ return $flags unless defined($flagsrequired);
return $flags if $flags->{superlibrarian};
return _dispatch($flagsrequired, $flags);
#FIXME - This fcn should return the failed permission so a suitable error msg can be delivered.
}
+=head2 in_ipset
+
+ $flags = ($ipset);
+
+C<$ipset> A space separated string describing an IP set. Can include single IPs or ranges
+
+Returns 1 if the remote address is in the provided ipset, or 0 otherwise.
+
+=cut
+
+sub in_ipset {
+ my ($ipset) = @_;
+ my $result = 1;
+ my @allowedipranges = $ipset ? split(' ', $ipset) : ();
+ if (scalar @allowedipranges > 0) {
+ my @rangelist;
+ eval { @rangelist = Net::CIDR::range2cidr(@allowedipranges); }; return 0 if $@;
+ eval { $result = Net::CIDR::cidrlookup($ENV{'REMOTE_ADDR'}, @rangelist) } || ( $ENV{DEBUG} && warn 'cidrlookup failed for ' . join(' ',@rangelist) );
+ }
+ return $result ? 1 : 0;
+}
+
sub getborrowernumber {
my ($userid) = @_;
my $userenv = C4::Context->userenv;