Bug 20023: Password recovery using email should be case insensitive
[koha.git] / opac / opac-password-recovery.pl
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4 use CGI;
5
6 use C4::Auth;
7 use C4::Koha;
8 use C4::Output;
9 use C4::Context;
10 use Koha::Patron::Password::Recovery
11   qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery DeleteExpiredPasswordRecovery);
12 use Koha::Patrons;
13 use Koha::Patrons;
14 my $query = new CGI;
15 use HTML::Entities;
16
17 my ( $template, $dummy, $cookie ) = get_template_and_user(
18     {
19         template_name   => "opac-password-recovery.tt",
20         query           => $query,
21         type            => "opac",
22         authnotrequired => 1,
23         debug           => 1,
24     }
25 );
26
27 my $email          = $query->param('email') // q{};
28 my $password       = $query->param('password');
29 my $repeatPassword = $query->param('repeatPassword');
30 my $id             = $query->param('id');
31 my $uniqueKey      = $query->param('uniqueKey');
32 my $username       = $query->param('username') // q{};
33 my $borrower_number;
34
35 #errors
36 my $hasError;
37
38 #email form error
39 my $errNoBorrowerFound;
40 my $errNoBorrowerEmail;
41 my $errMultipleAccountsForEmail;
42 my $errAlreadyStartRecovery;
43 my $errTooManyEmailFound;
44 my $errBadEmail;
45
46 #new password form error
47 my $errLinkNotValid;
48
49 if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
50
51     #try with the main email
52     my $borrower;
53     my $search_results;
54
55     # Find the borrower by userid, card number, or email
56     if ($username) {
57         $search_results = Koha::Patrons->search( { -or => { userid => $username, cardnumber => $username } } );
58     }
59     elsif ($email) {
60         $search_results = Koha::Patrons->search( { -or => { email => $email, emailpro => $email, B_email  => $email } } );
61     }
62
63     if ( !defined $search_results || $search_results->count < 1) {
64         $hasError           = 1;
65         $errNoBorrowerFound = 1;
66     }
67     elsif ( $username && $search_results->count > 1) { # Multiple accounts for username
68         $hasError           = 1;
69         $errNoBorrowerFound = 1;
70     }
71     elsif ( $email && $search_results->count > 1) { # Muliple accounts for E-Mail
72         $hasError           = 1;
73         $errMultipleAccountsForEmail = 1;
74     }
75     elsif ( $borrower = $search_results->next() ) {    # One matching borrower
76         my @emails = ( $borrower->email || '', $borrower->emailpro || '', $borrower->B_email || '');
77
78         my $firstNonEmptyEmail = '';
79         foreach my $address ( @emails ) {
80             $firstNonEmptyEmail = $address if length $address;
81             last if $firstNonEmptyEmail;
82         }
83
84         # Is the given email one of the borrower's ?
85         if ( $email && !( grep /^$email$/i, @emails ) ) {
86             $hasError    = 1;
87             $errNoBorrowerFound = 1;
88         }
89
90         # If there is no given email, and there is no email on record
91         elsif ( !$email && !$firstNonEmptyEmail ) {
92             $hasError           = 1;
93             $errNoBorrowerEmail = 1;
94         }
95
96 # Check if a password reset already issued for this borrower AND we are not asking for a new email
97         elsif ( not $query->param('resendEmail') ) {
98             if ( ValidateBorrowernumber( $borrower->borrowernumber ) ) {
99                 $hasError                = 1;
100                 $errAlreadyStartRecovery = 1;
101             }
102             else {
103                 DeleteExpiredPasswordRecovery( $borrower->borrowernumber );
104             }
105         }
106         # Set the $email, if we don't have one.
107         if ( !$hasError && !$email ) {
108             $email = $firstNonEmptyEmail;
109         }
110     }
111     else {    # 0 matching borrower
112         $hasError           = 1;
113         $errNoBorrowerFound = 1;
114     }
115     if ($hasError) {
116         $template->param(
117             hasError                => 1,
118             errNoBorrowerFound      => $errNoBorrowerFound,
119             errTooManyEmailFound    => $errTooManyEmailFound,
120             errAlreadyStartRecovery => $errAlreadyStartRecovery,
121             errBadEmail             => $errBadEmail,
122             errNoBorrowerEmail      => $errNoBorrowerEmail,
123             errMultipleAccountsForEmail => $errMultipleAccountsForEmail,
124             password_recovery       => 1,
125             email                   => HTML::Entities::encode($email),
126             username                => $username
127         );
128     }
129     elsif ( SendPasswordRecoveryEmail( $borrower, $email, scalar $query->param('resendEmail') ) ) {    # generate uuid and send recovery email
130         $template->param(
131             mail_sent => 1,
132             email     => $email
133         );
134     }
135     else {    # if it doesn't work....
136         $template->param(
137             hasError          => 1,
138             password_recovery => 1,
139             sendmailError     => 1
140         );
141     }
142 }
143 elsif ( $query->param('passwordReset') ) {
144     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
145
146     my $error;
147     if ( not $borrower_number ) {
148         $error = 'errLinkNotValid';
149     } elsif ( $password ne $repeatPassword ) {
150         $error = 'errPassNotMatch';
151     } else {
152         my ( $is_valid, $err) = Koha::AuthUtils::is_password_valid( $password );
153         unless ( $is_valid ) {
154             $error = 'password_too_short' if $err eq 'too_short';
155             $error = 'password_too_weak' if $err eq 'too_weak';
156             $error = 'password_has_whitespaces' if $err eq 'has_whitespaces';
157         } else {
158             Koha::Patrons->find($borrower_number)->update_password( $username, $password );
159             CompletePasswordRecovery($uniqueKey);
160             $template->param(
161                 password_reset_done => 1,
162                 username            => $username
163             );
164         }
165     }
166     if ( $error ) {
167         $template->param(
168             new_password => 1,
169             email        => $email,
170             uniqueKey    => $uniqueKey,
171             hasError     => 1,
172             $error       => 1,
173         );
174     }
175 }
176 elsif ($uniqueKey) {    #reset password form
177                         #check if the link is valid
178     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
179
180     if ( !$borrower_number ) {
181         $errLinkNotValid = 1;
182     }
183
184     $template->param(
185         new_password    => 1,
186         email           => $email,
187         uniqueKey       => $uniqueKey,
188         username        => $username,
189         errLinkNotValid => $errLinkNotValid,
190         hasError        => ( $errLinkNotValid ? 1 : 0 ),
191     );
192 }
193 else {    #password recovery form (to send email)
194     $template->param( password_recovery => 1 );
195 }
196
197 output_html_with_http_headers $query, $cookie, $template->output;