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