Bug 8753 - Smartmatch substitute, Math::Random::Secure, Perltidy, Passwordrecovery.t
[koha-ffzg.git] / opac / opac-password-recovery.pl
1 #!/usr/bin/perl
2
3 use strict;
4 use Modern::Perl;
5 use CGI;
6
7 use C4::Auth;
8 use C4::Koha;
9 use C4::Members qw(changepassword);
10 use C4::Output;
11 use C4::Context;
12 use C4::Passwordrecovery
13   qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery);
14 use Koha::AuthUtils qw(hash_password);
15 use Koha::Borrowers;
16 my $query = new CGI;
17 use HTML::Entities;
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 $minPassLength  = C4::Context->preference('minPasswordLength');
33 my $id             = $query->param('id');
34 my $uniqueKey      = $query->param('uniqueKey');
35 my $username       = $query->param('username');
36 my $borrower_number;
37
38 #errors
39 my $hasError;
40
41 #email form error
42 my $errNoBorrowerFound;
43 my $errNoBorrowerEmail;
44 my $errAlreadyStartRecovery;
45 my $errTooManyEmailFound;
46 my $errBadEmail;
47
48 #new password form error
49 my $errLinkNotValid;
50 my $errPassNotMatch;
51 my $errPassTooShort;
52
53 if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
54
55     #try with the main email
56     $email ||= '';    # avoid undef
57     my $borrower;
58     my $search_results;
59
60     # Find the borrower by his userid or email
61     if ($username) {
62         $search_results = [ Koha::Borrowers->search( { userid => $username } ) ];
63     }
64     elsif ($email) {
65         $search_results = [ Koha::Borrowers->search( { -or => { email => $email, emailpro => $email, B_email  => $email } } ) ];
66     }
67     if ( not $search_results ) {
68         $hasError           = 1;
69         $errNoBorrowerFound = 1;
70     }
71     elsif ( scalar @$search_results > 1 ) {    # Many matching borrowers
72         $hasError             = 1;
73         $errTooManyEmailFound = 1;
74     }
75     elsif ( $borrower = shift @$search_results ) {    # One matching borrower
76         $username ||= $borrower->userid;
77         my @emails = ( $borrower->email, $borrower->emailpro, $borrower->B_email );
78
79         # Is the given email one of the borrower's ?
80         if ( $email && !( grep { $_ eq $email } @emails ) ) {
81             $hasError    = 1;
82             $errBadEmail = 1;
83         }
84
85 # If we dont have an email yet. Get one of the borrower's email or raise an error.
86 # FIXME: That ugly shift-grep contraption.
87 # $email = shift [ grep { length() } @emails ]
88 # It's supposed to get a non-empty string from the @emails array. There's surely a simpler way
89         elsif ( !$email && !( $email = shift [ grep { length() } @emails ] ) ) {
90             $hasError           = 1;
91             $errNoBorrowerEmail = 1;
92         }
93
94 # Check if a password reset already issued for this borrower AND we are not asking for a new email
95         elsif ( ValidateBorrowernumber( $borrower->borrowernumber )
96             && !$query->param('resendEmail') )
97         {
98             $hasError                = 1;
99             $errAlreadyStartRecovery = 1;
100         }
101     }
102     else {    # 0 matching borrower
103         $hasError           = 1;
104         $errNoBorrowerFound = 1;
105     }
106     if ($hasError) {
107         $template->param(
108             hasError                => 1,
109             errNoBorrowerFound      => $errNoBorrowerFound,
110             errTooManyEmailFound    => $errTooManyEmailFound,
111             errAlreadyStartRecovery => $errAlreadyStartRecovery,
112             errBadEmail             => $errBadEmail,
113             errNoBorrowerEmail      => $errNoBorrowerEmail,
114             password_recovery       => 1,
115             email                   => HTML::Entities::encode($email),
116             username                => $username
117         );
118     }
119     elsif ( SendPasswordRecoveryEmail( $borrower, $email, $query->param('resendEmail') ) ) {    # generate uuid and send recovery email
120         $template->param(
121             mail_sent => 1,
122             email     => $email
123         );
124     }
125     else {    # if it doesn't work....
126         $template->param(
127             password_recovery => 1,
128             sendmailError     => 1
129         );
130     }
131 }
132 elsif ( $query->param('passwordReset') ) {
133     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
134
135     #validate password length & match
136     if (   ($borrower_number)
137         && ( $password eq $repeatPassword )
138         && ( length($password) >= $minPassLength ) )
139     {    #apply changes
140         changepassword( $username, $borrower_number, hash_password($password) );
141         CompletePasswordRecovery($uniqueKey);
142         $template->param(
143             password_reset_done => 1,
144             username            => $username
145         );
146     }
147     else {    #errors
148         if ( !$borrower_number ) {    #parameters not valid
149             $errLinkNotValid = 1;
150         }
151         elsif ( $password ne $repeatPassword ) {    #passwords does not match
152             $errPassNotMatch = 1;
153         }
154         elsif ( length($password) < $minPassLength ) {    #password too short
155             $errPassTooShort = 1;
156         }
157         $template->param(
158             new_password    => 1,
159             minPassLength   => $minPassLength,
160             email           => $email,
161             uniqueKey       => $uniqueKey,
162             errLinkNotValid => $errLinkNotValid,
163             errPassNotMatch => $errPassNotMatch,
164             errPassTooShort => $errPassTooShort,
165             hasError        => 1
166         );
167     }
168 }
169 elsif ($uniqueKey) {    #reset password form
170                         #check if the link is valid
171     ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
172
173     if ( !$borrower_number ) {
174         $errLinkNotValid = 1;
175     }
176
177     $template->param(
178         new_password    => 1,
179         minPassLength   => $minPassLength,
180         email           => $email,
181         uniqueKey       => $uniqueKey,
182         username        => $username,
183         errLinkNotValid => $errLinkNotValid,
184         hasError        => ( $errLinkNotValid ? 1 : 0 ),
185     );
186 }
187 else {    #password recovery form (to send email)
188     $template->param( password_recovery => 1 );
189 }
190
191 output_html_with_http_headers $query, $cookie, $template->output;