Bug 22048: Use set_password opac/opac-password-recovery.pl
[koha.git] / opac / opac-password-recovery.pl
index 257ca92..6429f7b 100755 (executable)
@@ -5,12 +5,11 @@ use CGI;
 
 use C4::Auth;
 use C4::Koha;
-use C4::Members qw(changepassword);
 use C4::Output;
 use C4::Context;
 use Koha::Patron::Password::Recovery
-  qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery);
-use Koha::AuthUtils qw(hash_password);
+  qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery DeleteExpiredPasswordRecovery);
+use Koha::Patrons;
 use Koha::Patrons;
 my $query = new CGI;
 use HTML::Entities;
@@ -28,10 +27,9 @@ my ( $template, $dummy, $cookie ) = get_template_and_user(
 my $email          = $query->param('email') // q{};
 my $password       = $query->param('password');
 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
@@ -40,61 +38,71 @@ my $hasError;
 #email form error
 my $errNoBorrowerFound;
 my $errNoBorrowerEmail;
+my $errMultipleAccountsForEmail;
 my $errAlreadyStartRecovery;
 my $errTooManyEmailFound;
 my $errBadEmail;
 
 #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 = [];
+    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 } } );
     }
     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 } } );
     }
-    if ( not $search_results || scalar @$search_results > 1 ) {
+
+    if ( !defined $search_results || $search_results->count < 1) {
         $hasError           = 1;
         $errNoBorrowerFound = 1;
     }
-    elsif ( $borrower = shift @$search_results ) {    # 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;
-        }
+    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
+        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 && !( grep { $_ eq $email } @emails ) ) {
+        if ( $email && !( grep /^$email$/i, @emails ) ) {
             $hasError    = 1;
             $errNoBorrowerFound = 1;
         }
 
-# If we dont have an email yet. Get one of the borrower's email or raise an error.
-        elsif ( !$email && !( $email = $firstNonEmptyEmail ) ) {
+        # 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 ( ValidateBorrowernumber( $borrower->borrowernumber )
-            && !$query->param('resendEmail') )
-        {
-            $hasError                = 1;
-            $errAlreadyStartRecovery = 1;
+        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 {    # 0 matching borrower
@@ -109,12 +117,13 @@ if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
             errAlreadyStartRecovery => $errAlreadyStartRecovery,
             errBadEmail             => $errBadEmail,
             errNoBorrowerEmail      => $errNoBorrowerEmail,
+            errMultipleAccountsForEmail => $errMultipleAccountsForEmail,
             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
@@ -122,6 +131,7 @@ if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
     }
     else {    # if it doesn't work....
         $template->param(
+            hasError          => 1,
             password_recovery => 1,
             sendmailError     => 1
         );
@@ -130,37 +140,40 @@ if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
 elsif ( $query->param('passwordReset') ) {
     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
 
-    #validate password length & match
-    if (   ($borrower_number)
-        && ( $password eq $repeatPassword )
-        && ( length($password) >= $minPassLength ) )
-    {    #apply changes
-        changepassword( $username, $borrower_number, 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;
+    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,
-            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,
         );
     }
 }
@@ -174,7 +187,6 @@ elsif ($uniqueKey) {    #reset password form
 
     $template->param(
         new_password    => 1,
-        minPassLength   => $minPassLength,
         email           => $email,
         uniqueKey       => $uniqueKey,
         username        => $username,