a695165b56eb775f97f9f9c809b128f9ef9ab6fb
[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 use Try::Tiny;
17 use List::Util qw/any/;
18
19 my ( $template, $dummy, $cookie ) = get_template_and_user(
20     {
21         template_name   => "opac-password-recovery.tt",
22         query           => $query,
23         type            => "opac",
24         authnotrequired => 1,
25         debug           => 1,
26     }
27 );
28
29 my $email          = $query->param('email') // q{};
30 my $password       = $query->param('password');
31 my $repeatPassword = $query->param('repeatPassword');
32 my $id             = $query->param('id');
33 my $uniqueKey      = $query->param('uniqueKey');
34 my $username       = $query->param('username') // q{};
35 my $borrower_number;
36
37 #errors
38 my $hasError;
39
40 #email form error
41 my $errNoBorrowerFound;
42 my $errNoBorrowerEmail;
43 my $errMultipleAccountsForEmail;
44 my $errAlreadyStartRecovery;
45 my $errTooManyEmailFound;
46 my $errBadEmail;
47 my $errResetForbidden;
48
49 #new password form error
50 my $errLinkNotValid;
51
52 if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
53
54     #try with the main email
55     my $borrower;
56     my $search_results;
57
58     # Find the borrower by userid, card number, or email
59     if ($username) {
60         $search_results = Koha::Patrons->search( { -or => { userid => $username, cardnumber => $username }, login_attempts => { '!=', Koha::Patron::ADMINISTRATIVE_LOCKOUT } } );
61     }
62     elsif ($email) {
63         $search_results = Koha::Patrons->search( { -or => { email => $email, emailpro => $email, B_email  => $email }, login_attempts => { '!=', Koha::Patron::ADMINISTRATIVE_LOCKOUT } } );
64     }
65
66     if ( !defined $search_results || $search_results->count < 1) {
67         $hasError           = 1;
68         $errNoBorrowerFound = 1;
69     }
70     elsif ( $username && $search_results->count > 1) { # Multiple accounts for username
71         $hasError           = 1;
72         $errNoBorrowerFound = 1;
73     }
74     elsif ( $email && $search_results->count > 1) { # Muliple accounts for E-Mail
75         $hasError           = 1;
76         $errMultipleAccountsForEmail = 1;
77     }
78     elsif ( $borrower = $search_results->next() ) {    # One matching borrower
79
80         if ( $borrower->category->effective_reset_password ) {
81
82             my @emails = grep { $_ } ( $borrower->email, $borrower->emailpro, $borrower->B_email );
83
84             my $firstNonEmptyEmail;
85             $firstNonEmptyEmail = $emails[0] if @emails;
86
87             # Is the given email one of the borrower's ?
88             if ( $email && !( any { /^$email$/i } @emails ) ) {
89                 $hasError    = 1;
90                 $errNoBorrowerFound = 1;
91             }
92
93             # If there is no given email, and there is no email on record
94             elsif ( !$email && !$firstNonEmptyEmail ) {
95                 $hasError           = 1;
96                 $errNoBorrowerEmail = 1;
97             }
98
99             # Check if a password reset already issued for this
100             # borrower AND we are not asking for a new email
101             elsif ( not $query->param('resendEmail') ) {
102                 if ( ValidateBorrowernumber( $borrower->borrowernumber ) ) {
103                     $hasError                = 1;
104                     $errAlreadyStartRecovery = 1;
105                 }
106                 else {
107                     DeleteExpiredPasswordRecovery( $borrower->borrowernumber );
108                 }
109             }
110             # Set the $email, if we don't have one.
111             if ( !$hasError && !$email ) {
112                 $email = $firstNonEmptyEmail;
113             }
114         }
115         else {
116             $hasError          = 1;
117             $errResetForbidden = 1;
118         }
119     }
120     else {    # 0 matching borrower
121         $hasError           = 1;
122         $errNoBorrowerFound = 1;
123     }
124     if ($hasError) {
125         $template->param(
126             hasError                => 1,
127             errNoBorrowerFound      => $errNoBorrowerFound,
128             errTooManyEmailFound    => $errTooManyEmailFound,
129             errAlreadyStartRecovery => $errAlreadyStartRecovery,
130             errBadEmail             => $errBadEmail,
131             errNoBorrowerEmail      => $errNoBorrowerEmail,
132             errMultipleAccountsForEmail => $errMultipleAccountsForEmail,
133             errResetForbidden       => $errResetForbidden,
134             password_recovery       => 1,
135             email                   => HTML::Entities::encode($email),
136             username                => $username
137         );
138     }
139     elsif ( SendPasswordRecoveryEmail( $borrower, $email, scalar $query->param('resendEmail') ) ) {    # generate uuid and send recovery email
140         $template->param(
141             mail_sent => 1,
142             email     => $email
143         );
144     }
145     else {    # if it doesn't work....
146         $template->param(
147             hasError          => 1,
148             password_recovery => 1,
149             sendmailError     => 1
150         );
151     }
152 }
153 elsif ( $query->param('passwordReset') ) {
154     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
155
156     my $error;
157     if ( not $borrower_number ) {
158         $error = 'errLinkNotValid';
159     } elsif ( $password ne $repeatPassword ) {
160         $error = 'errPassNotMatch';
161     } else {
162         try {
163             Koha::Patrons->find($borrower_number)->set_password({ password => $password });
164
165             CompletePasswordRecovery($uniqueKey);
166             $template->param(
167                 password_reset_done => 1,
168                 username            => $username
169             );
170         }
171         catch {
172             if ( $_->isa('Koha::Exceptions::Password::TooShort') ) {
173                 $error = 'password_too_short';
174             }
175             elsif ( $_->isa('Koha::Exceptions::Password::WhitespaceCharacters') ) {
176                 $error = 'password_has_whitespaces';
177             }
178             elsif ( $_->isa('Koha::Exceptions::Password::TooWeak') ) {
179                 $error = 'password_too_weak';
180             }
181         };
182     }
183     if ( $error ) {
184         $template->param(
185             new_password => 1,
186             email        => $email,
187             uniqueKey    => $uniqueKey,
188             hasError     => 1,
189             $error       => 1,
190         );
191     }
192 }
193 elsif ($uniqueKey) {    #reset password form
194                         #check if the link is valid
195     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
196
197     if ( !$borrower_number ) {
198         $errLinkNotValid = 1;
199     }
200
201     $template->param(
202         new_password    => 1,
203         email           => $email,
204         uniqueKey       => $uniqueKey,
205         username        => $username,
206         errLinkNotValid => $errLinkNotValid,
207         hasError        => ( $errLinkNotValid ? 1 : 0 ),
208     );
209 }
210 else {    #password recovery form (to send email)
211     $template->param( password_recovery => 1 );
212 }
213
214 output_html_with_http_headers $query, $cookie, $template->output;