use Modern::Perl;
use CGI;
-use C4::Auth;
-use C4::Koha;
-use C4::Output;
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
use C4::Context;
-use Koha::Patron::Password::Recovery
- qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery DeleteExpiredPasswordRecovery);
-use Koha::Patrons;
-use Koha::AuthUtils qw(hash_password);
+use Koha::Patron::Password::Recovery qw(
+ CompletePasswordRecovery
+ DeleteExpiredPasswordRecovery
+ GetValidLinkInfo
+ SendPasswordRecoveryEmail
+ ValidateBorrowernumber
+);
use Koha::Patrons;
-my $query = new CGI;
+my $query = CGI->new;
use HTML::Entities;
+use Try::Tiny qw( catch try );
+use List::Util qw( any );
my ( $template, $dummy, $cookie ) = get_template_and_user(
{
query => $query,
type => "opac",
authnotrequired => 1,
- debug => 1,
}
);
my $email = $query->param('email') // q{};
-my $password = $query->param('password');
+my $password = $query->param('newPassword');
my $repeatPassword = $query->param('repeatPassword');
-my $minPassLength = C4::Context->preference('minPasswordLength');
my $id = $query->param('id');
my $uniqueKey = $query->param('uniqueKey');
-my $username = $query->param('username');
+my $username = $query->param('username') // q{};
my $borrower_number;
#errors
my $errNoBorrowerEmail;
my $errMultipleAccountsForEmail;
my $errAlreadyStartRecovery;
-my $errTooManyEmailFound;
-my $errBadEmail;
+my $errResetForbidden;
#new password form error
my $errLinkNotValid;
-my $errPassNotMatch;
-my $errPassTooShort;
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
#try with the main email
- $email ||= ''; # avoid undef
my $borrower;
my $search_results;
-
- # Find the borrower by his userid or email
+ # Find the borrower by userid, card number, or email
if ($username) {
- $search_results = Koha::Patrons->search( { userid => $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 } } );
+ $search_results = Koha::Patrons->search( { -or => { email => $email, emailpro => $email, B_email => $email }, login_attempts => { '!=', Koha::Patron::ADMINISTRATIVE_LOCKOUT } } );
}
- if ( not $search_results || $search_results->count < 1) {
+ if ( !defined $search_results || $search_results->count < 1) {
$hasError = 1;
$errNoBorrowerFound = 1;
}
$errMultipleAccountsForEmail = 1;
}
elsif ( $borrower = $search_results->next() ) { # One matching borrower
- $username ||= $borrower->userid;
- my @emails = ( $borrower->email, $borrower->emailpro, $borrower->B_email );
- my $firstNonEmptyEmail = '';
- foreach my $address ( @emails ) {
- $firstNonEmptyEmail = $address if length $address;
- last if $firstNonEmptyEmail;
- }
+ if ( $borrower->category->effective_reset_password ) {
- # Is the given email one of the borrower's ?
- if ( $email && !( grep { $_ eq $email } @emails ) ) {
- $hasError = 1;
- $errNoBorrowerFound = 1;
- }
+ my @emails = grep { $_ } ( $borrower->email, $borrower->emailpro, $borrower->B_email );
-# If we dont have an email yet. Get one of the borrower's email or raise an error.
- elsif ( !$email && !( $email = $firstNonEmptyEmail ) ) {
- $hasError = 1;
- $errNoBorrowerEmail = 1;
- }
+ my $firstNonEmptyEmail;
+ $firstNonEmptyEmail = $emails[0] if @emails;
-# 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;
+ # Is the given email one of the borrower's ?
+ if ( $email && !( any { lc($_) eq lc($email) } @emails ) ) {
+ $hasError = 1;
+ $errNoBorrowerFound = 1;
}
- else {
- DeleteExpiredPasswordRecovery( $borrower->borrowernumber );
+
+ # 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
$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, $query->param('resendEmail') ) ) { # generate uuid and send recovery email
+ 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);
- #validate password length & match
- if ( ($borrower_number)
- && ( $password eq $repeatPassword )
- && ( length($password) >= $minPassLength ) )
- { #apply changes
- Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
- CompletePasswordRecovery($uniqueKey);
- $template->param(
- password_reset_done => 1,
- username => $username
- );
- }
- else { #errors
- if ( !$borrower_number ) { #parameters not valid
- $errLinkNotValid = 1;
- }
- elsif ( $password ne $repeatPassword ) { #passwords does not match
- $errPassNotMatch = 1;
- }
- elsif ( length($password) < $minPassLength ) { #password too short
- $errPassTooShort = 1;
+ my $error;
+ my $min_password_length = C4::Context->preference('minPasswordPreference');
+ my $require_strong_password = C4::Context->preference('RequireStrongPassword');
+ if ( not $borrower_number ) {
+ $error = 'errLinkNotValid';
+ } elsif ( $password ne $repeatPassword ) {
+ $error = 'errPassNotMatch';
+ } else {
+ my $borrower = Koha::Patrons->find($borrower_number);
+ $min_password_length = $borrower->category->effective_min_password_length;
+ $require_strong_password = $borrower->category->effective_require_strong_password;
+ try {
+ $borrower->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,
- minPassLength => $minPassLength,
- email => $email,
- uniqueKey => $uniqueKey,
- errLinkNotValid => $errLinkNotValid,
- errPassNotMatch => $errPassNotMatch,
- errPassTooShort => $errPassTooShort,
- hasError => 1
+ new_password => 1,
+ email => $email,
+ uniqueKey => $uniqueKey,
+ hasError => 1,
+ $error => 1,
+ minPasswordLength => $min_password_length,
+ RequireStrongPassword => $require_strong_password
);
}
}
$errLinkNotValid = 1;
}
+ my $borrower = Koha::Patrons->find($borrower_number);
+
$template->param(
new_password => 1,
- minPassLength => $minPassLength,
email => $email,
uniqueKey => $uniqueKey,
username => $username,
errLinkNotValid => $errLinkNotValid,
hasError => ( $errLinkNotValid ? 1 : 0 ),
+ minPasswordLength => $borrower->category->effective_min_password_length,
+ RequireStrongPassword => $borrower->category->effective_require_strong_password
);
}
else { #password recovery form (to send email)