Koha/opac/opac-password-recovery.pl
Marcel de Rooy d35cc83379 Bug 21533: Do not allow password recovery for administrative locked patrons
Depends on bug 21336 for the ADMINISTRATIVE_LOCKOUT constant.

This is a bit lazy solution (but good enough): The account will not be found
when recovering the password. The user should contact the library. Since
the library chose to lock the account, that seems appropriate.

Test plan:
Select a borrower and set login_attempts to -1. Via mysql command line or
with Koha::Patrons->find(borrowernumber)->lock.
Enable password recovery.
Try to recover password from OPAC. You should fail with 'Not found, contact
the library'.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>

Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Bouzid Fergani <bouzid.fergani@inlibro.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
2019-05-10 12:19:13 +00:00

214 lines
6.9 KiB
Perl
Executable file

#!/usr/bin/perl
use Modern::Perl;
use CGI;
use C4::Auth;
use C4::Koha;
use C4::Output;
use C4::Context;
use Koha::Patron::Password::Recovery
qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery DeleteExpiredPasswordRecovery);
use Koha::Patrons;
use Koha::Patrons;
my $query = new CGI;
use HTML::Entities;
use Try::Tiny;
use List::Util qw/any/;
my ( $template, $dummy, $cookie ) = get_template_and_user(
{
template_name => "opac-password-recovery.tt",
query => $query,
type => "opac",
authnotrequired => 1,
debug => 1,
}
);
my $email = $query->param('email') // q{};
my $password = $query->param('password');
my $repeatPassword = $query->param('repeatPassword');
my $id = $query->param('id');
my $uniqueKey = $query->param('uniqueKey');
my $username = $query->param('username') // q{};
my $borrower_number;
#errors
my $hasError;
#email form error
my $errNoBorrowerFound;
my $errNoBorrowerEmail;
my $errMultipleAccountsForEmail;
my $errAlreadyStartRecovery;
my $errTooManyEmailFound;
my $errBadEmail;
my $errResetForbidden;
#new password form error
my $errLinkNotValid;
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
#try with the main email
my $borrower;
my $search_results;
# Find the borrower by userid, card number, or email
if ($username) {
$search_results = Koha::Patrons->search( { -or => { userid => $username, cardnumber => $username }, login_attempts => { '!=', Koha::Patron::ADMINISTRATIVE_LOCKOUT } } );
}
elsif ($email) {
$search_results = Koha::Patrons->search( { -or => { email => $email, emailpro => $email, B_email => $email }, login_attempts => { '!=', Koha::Patron::ADMINISTRATIVE_LOCKOUT } } );
}
if ( !defined $search_results || $search_results->count < 1) {
$hasError = 1;
$errNoBorrowerFound = 1;
}
elsif ( $username && $search_results->count > 1) { # Multiple accounts for username
$hasError = 1;
$errNoBorrowerFound = 1;
}
elsif ( $email && $search_results->count > 1) { # Muliple accounts for E-Mail
$hasError = 1;
$errMultipleAccountsForEmail = 1;
}
elsif ( $borrower = $search_results->next() ) { # One matching borrower
if ( $borrower->category->effective_reset_password ) {
my @emails = grep { $_ } ( $borrower->email, $borrower->emailpro, $borrower->B_email );
my $firstNonEmptyEmail;
$firstNonEmptyEmail = $emails[0] if @emails;
# Is the given email one of the borrower's ?
if ( $email && !( any { /^$email$/i } @emails ) ) {
$hasError = 1;
$errNoBorrowerFound = 1;
}
# If there is no given email, and there is no email on record
elsif ( !$email && !$firstNonEmptyEmail ) {
$hasError = 1;
$errNoBorrowerEmail = 1;
}
# Check if a password reset already issued for this
# borrower AND we are not asking for a new email
elsif ( not $query->param('resendEmail') ) {
if ( ValidateBorrowernumber( $borrower->borrowernumber ) ) {
$hasError = 1;
$errAlreadyStartRecovery = 1;
}
else {
DeleteExpiredPasswordRecovery( $borrower->borrowernumber );
}
}
# Set the $email, if we don't have one.
if ( !$hasError && !$email ) {
$email = $firstNonEmptyEmail;
}
}
else {
$hasError = 1;
$errResetForbidden = 1;
}
}
else { # 0 matching borrower
$hasError = 1;
$errNoBorrowerFound = 1;
}
if ($hasError) {
$template->param(
hasError => 1,
errNoBorrowerFound => $errNoBorrowerFound,
errTooManyEmailFound => $errTooManyEmailFound,
errAlreadyStartRecovery => $errAlreadyStartRecovery,
errBadEmail => $errBadEmail,
errNoBorrowerEmail => $errNoBorrowerEmail,
errMultipleAccountsForEmail => $errMultipleAccountsForEmail,
errResetForbidden => $errResetForbidden,
password_recovery => 1,
email => HTML::Entities::encode($email),
username => $username
);
}
elsif ( SendPasswordRecoveryEmail( $borrower, $email, scalar $query->param('resendEmail') ) ) { # generate uuid and send recovery email
$template->param(
mail_sent => 1,
email => $email
);
}
else { # if it doesn't work....
$template->param(
hasError => 1,
password_recovery => 1,
sendmailError => 1
);
}
}
elsif ( $query->param('passwordReset') ) {
( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
my $error;
if ( not $borrower_number ) {
$error = 'errLinkNotValid';
} elsif ( $password ne $repeatPassword ) {
$error = 'errPassNotMatch';
} else {
try {
Koha::Patrons->find($borrower_number)->set_password({ password => $password });
CompletePasswordRecovery($uniqueKey);
$template->param(
password_reset_done => 1,
username => $username
);
}
catch {
if ( $_->isa('Koha::Exceptions::Password::TooShort') ) {
$error = 'password_too_short';
}
elsif ( $_->isa('Koha::Exceptions::Password::WhitespaceCharacters') ) {
$error = 'password_has_whitespaces';
}
elsif ( $_->isa('Koha::Exceptions::Password::TooWeak') ) {
$error = 'password_too_weak';
}
};
}
if ( $error ) {
$template->param(
new_password => 1,
email => $email,
uniqueKey => $uniqueKey,
hasError => 1,
$error => 1,
);
}
}
elsif ($uniqueKey) { #reset password form
#check if the link is valid
( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
if ( !$borrower_number ) {
$errLinkNotValid = 1;
}
$template->param(
new_password => 1,
email => $email,
uniqueKey => $uniqueKey,
username => $username,
errLinkNotValid => $errLinkNotValid,
hasError => ( $errLinkNotValid ? 1 : 0 ),
);
}
else { #password recovery form (to send email)
$template->param( password_recovery => 1 );
}
output_html_with_http_headers $query, $cookie, $template->output;