View | Details | Raw Unified | Return to bug 8753
Collapse All | Expand All

(-)a/C4/Passwordrecovery.pm (+173 lines)
Line 0 Link Here
1
package C4::Passwordrecovery;
2
3
# Copyright 2014 Solutions InLibro inc.
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use C4::Context;
22
23
use vars qw($VERSION @ISA @EXPORT);
24
25
BEGIN {
26
    # set the version for version checking
27
    $VERSION = 3.07.00.049;
28
    require Exporter;
29
    @ISA    = qw(Exporter);
30
    push @EXPORT, qw(
31
        &ValidateBorrowernumber
32
        &SendPasswordRecoveryEmail
33
        &GetValidLinkInfo
34
        &CompletePasswordRecovery
35
    );
36
}
37
38
=head1 NAME
39
40
C4::Passwordrecovery - Koha password recovery module
41
42
=head1 SYNOPSIS
43
44
use C4::Passwordrecovery;
45
46
=head1 FUNCTIONS
47
48
=head2 ValidateBorrowernumber
49
50
$alread = ValidateBorrowernumber( $borrower_number );
51
52
Check if the system already start recovery
53
54
Returns true false
55
56
=cut
57
58
sub ValidateBorrowernumber {
59
    my ($borrower_number) = @_;
60
    my $schema = Koha::Database->new->schema;
61
62
    my $rs = $schema->resultset('BorrowerPasswordRecovery')->search(
63
    {
64
       borrowernumber => $borrower_number,
65
       valid_until => \'> NOW()'
66
    }, {
67
        columns => 'borrowernumber'
68
    });
69
70
    if ($rs->next){
71
        return 1;
72
    }
73
74
    return 0;
75
}
76
77
=head2 GetValidLinkInfo
78
79
    Check if the link is still valid and return some info.
80
81
=cut
82
83
sub GetValidLinkInfo {
84
    my ($uniqueKey) = @_;
85
    my $dbh = C4::Context->dbh;
86
    my $query = '
87
    SELECT borrower_password_recovery.borrowernumber, userid
88
    FROM borrower_password_recovery, borrowers
89
    WHERE borrowers.borrowernumber = borrower_password_recovery.borrowernumber
90
    AND NOW() < valid_until
91
    AND uuid = ?
92
    ';
93
    my $sth = $dbh->prepare($query);
94
    $sth->execute($uniqueKey);
95
    return $sth->fetchrow;
96
}
97
98
=head2 SendPasswordRecoveryEmail
99
100
 It creates an email using the templates and send it to the user, using the specified email
101
102
=cut
103
104
sub SendPasswordRecoveryEmail {
105
    my $borrower = shift; # from GetMember
106
    my $userEmail = shift; #to_address (the one specified in the request)
107
    my $protocol = shift; #only required to determine if 'http' or 'https'
108
    my $update = shift;
109
110
    my $schema = Koha::Database->new->schema;
111
112
    # generate UUID
113
    my @chars = ("A".."Z", "a".."z", "0".."9");
114
    my $uuid_str;
115
    $uuid_str .= $chars[rand @chars] for 1..32;
116
117
    # insert into database
118
    my $expirydate = DateTime->now(time_zone => C4::Context->tz())->add( days => 2 );
119
    if($update){
120
        my $rs = $schema->resultset('BorrowerPasswordRecovery')->search(
121
        {
122
            borrowernumber => $borrower->{'borrowernumber'},
123
        });
124
        $rs->update({uuid => $uuid_str, valid_until => $expirydate->datetime()});
125
    } else {
126
         my $rs = $schema->resultset('BorrowerPasswordRecovery')->create({
127
            borrowernumber=>$borrower->{'borrowernumber'},
128
            uuid => $uuid_str,
129
            valid_until=> $expirydate->datetime()
130
         });
131
    }
132
133
    # create link
134
    my $uuidLink = $protocol . C4::Context->preference( 'OPACBaseURL' ) . "/cgi-bin/koha/opac-password-recovery.pl?uniqueKey=$uuid_str";
135
136
    # prepare the email
137
    my $letter = C4::Letters::GetPreparedLetter (
138
        module => 'members',
139
        letter_code => 'PASSWORD_RESET',
140
        branchcode => $borrower->{branchcode},
141
        substitute => {passwordreseturl => $uuidLink, user => $borrower->{userid} },
142
    );
143
144
    # define to/from emails
145
    my $kohaEmail = C4::Context->preference( 'KohaAdminEmailAddress' ); # from
146
147
    C4::Letters::EnqueueLetter( {
148
         letter => $letter,
149
         borrowernumber => $borrower->{borrowernumber},
150
         to_address => $userEmail,
151
         from_address => $kohaEmail,
152
         message_transport_type => 'email',
153
    } );
154
155
    return 1;
156
}
157
=head2 CompletePasswordRecovery
158
159
    $bool = CompletePasswordRevovery($uuid);
160
161
    Deletes a password recovery entry.
162
163
=cut
164
sub CompletePasswordRecovery{
165
    my $uniqueKey = shift;
166
    my $model = Koha::Database->new->schema->resultset('BorrowerPasswordRecovery');
167
    my $entry = $model->search({-or => [uuid => $uniqueKey, valid_until => \'< NOW()']});
168
    return $entry->delete();
169
}
170
171
END { }    # module clean-up code here (global destructor)
172
173
1;
(-)a/Koha/Schema/Result/BorrowerPasswordRecovery.pm (+66 lines)
Line 0 Link Here
1
use utf8;
2
package Koha::Schema::Result::BorrowerPasswordRecovery;
3
4
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
7
=head1 NAME
8
9
Koha::Schema::Result::BorrowerPasswordRecovery
10
11
=cut
12
13
use strict;
14
use warnings;
15
16
use base 'DBIx::Class::Core';
17
18
=head1 TABLE: C<borrower_password_recovery>
19
20
=cut
21
22
__PACKAGE__->table("borrower_password_recovery");
23
24
=head1 ACCESSORS
25
26
=head2 borrowernumber
27
28
  data_type: 'integer'
29
  is_nullable: 0
30
31
=head2 uuid
32
33
  data_type: 'varchar'
34
  is_nullable: 0
35
  size: 128
36
37
=head2 valid_until
38
39
  data_type: 'timestamp'
40
  datetime_undef_if_invalid: 1
41
  default_value: current_timestamp
42
  is_nullable: 0
43
44
=cut
45
46
__PACKAGE__->add_columns(
47
  "borrowernumber",
48
  { data_type => "integer", is_nullable => 0 },
49
  "uuid",
50
  { data_type => "varchar", is_nullable => 0, size => 128 },
51
  "valid_until",
52
  {
53
    data_type => "timestamp",
54
    datetime_undef_if_invalid => 1,
55
    default_value => \"current_timestamp",
56
    is_nullable => 0,
57
  },
58
);
59
60
61
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-11-03 12:08:20
62
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ORAWxUHIkefSfPSqrcfeXA
63
64
65
# You can replace this text with custom code or comments, and it will be preserved on regeneration
66
1;
(-)a/installer/data/mysql/atomicupdate/bug_8753-Add_forgot_password_link_to_OPAC.sql (+12 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type)
2
VALUES ('OpacResetPassword',  '0','','Shows the ''Forgot your password?'' link in the OPAC','YesNo');
3
4
CREATE TABLE IF NOT EXISTS borrower_password_recovery (
5
  borrowernumber int(11) NOT NULL,
6
  uuid varchar(128) NOT NULL,
7
  valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
8
  KEY borrowernumber (borrowernumber)
9
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
10
11
INSERT IGNORE INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type)
12
VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','<html>\r\n<p>This email has been sent in response to your password recovery request for the account <strong><<user>></strong>.\r\n</p>\r\n<p>\r\nYou can now create your new password using the following link:\r\n<br/><a href=\"<<passwordreseturl>>\"><<passwordreseturl>></a>\r\n</p>\r\n<p>This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.</p>\r\n<p>Thank you.</p>\r\n</html>\r\n','email');
(-)a/installer/data/mysql/en/mandatory/sample_notices.sql (+4 lines)
Lines 162-164 VALUES ( 'circulation', 'OVERDUES_SLIP', '', 'Overdues Slip', '0', 'OVERDUES_SLI Link Here
162
162
163
<item>"<<biblio.title>>" by <<biblio.author>>, <<items.itemcallnumber>>, Barcode: <<items.barcode>> Fine: <<items.fine>></item>
163
<item>"<<biblio.title>>" by <<biblio.author>>, <<items.itemcallnumber>>, Barcode: <<items.barcode>> Fine: <<items.fine>></item>
164
', 'print' );
164
', 'print' );
165
166
INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type)
167
VALUES ('members','PASSWORD_RESET','','Online password reset',1,'Koha password recovery','<html>\r\n<p>This email has been sent in response to your password recovery request for the account <strong><<user>></strong>.\r\n</p>\r\n<p>\r\nYou can now create your new password using the following link:\r\n<br/><a href=\"<<passwordreseturl>>\"><<passwordreseturl>></a>\r\n</p>\r\n<p>This link will be valid for 2 days from this email\'s reception, then you must reapply if you do not change your password.</p>\r\n<p>Thank you.</p>\r\n</html>\r\n','email'
168
);
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+8 lines)
Lines 346-351 OPAC: Link Here
346
                  no: "Don't allow"
346
                  no: "Don't allow"
347
            - patrons to change their own password on the OPAC. Note that this must be off to use LDAP authentication.
347
            - patrons to change their own password on the OPAC. Note that this must be off to use LDAP authentication.
348
        -
348
        -
349
            - "The user "
350
            - pref: OpacResetPassword
351
              default: 1
352
              choices:
353
                  yes: "can reset"
354
                  no: "can not reset"
355
            - " their password on OPAC."
356
        -
349
            - pref: OPACPatronDetails
357
            - pref: OPACPatronDetails
350
              choices:
358
              choices:
351
                  yes: Allow
359
                  yes: Allow
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc (+6 lines)
Lines 316-321 Link Here
316
                    <fieldset class="brief">
316
                    <fieldset class="brief">
317
                        <label for="muserid">Login:</label><input type="text" id="muserid" name="userid" />
317
                        <label for="muserid">Login:</label><input type="text" id="muserid" name="userid" />
318
                        <label for="mpassword">Password:</label><input type="password" id="mpassword" name="password" />
318
                        <label for="mpassword">Password:</label><input type="password" id="mpassword" name="password" />
319
                    [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
320
                        <div id="forgotpassword-modal">
321
                            <h5>Forgot your password?</h5>
322
                            <p>If you do not remember your password, click <a href="/cgi-bin/koha/opac-password-recovery.pl">here</a> to create a new one.</p>
323
                        </div>
324
                    [% END %]
319
                    [% IF Koha.Preference( 'NoLoginInstructions' ) %]
325
                    [% IF Koha.Preference( 'NoLoginInstructions' ) %]
320
                        <div id="nologininstructions-modal">
326
                        <div id="nologininstructions-modal">
321
                            [% Koha.Preference( 'NoLoginInstructions' ) %]
327
                            [% Koha.Preference( 'NoLoginInstructions' ) %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (+6 lines)
Lines 150-155 Link Here
150
                                </fieldset>
150
                                </fieldset>
151
151
152
                                <input type="submit" value="Log in" class="btn" />
152
                                <input type="submit" value="Log in" class="btn" />
153
                                [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
154
                                    <div id="forgotpassword">
155
                                        <h5>Forgot your password?</h5>
156
                                        <p>If you do not remember your password, click <a href="/cgi-bin/koha/opac-password-recovery.pl">here</a> to create a new one.</p>
157
                                    </div>
158
                                [% END %]
153
                                <div id="nologininstructions">
159
                                <div id="nologininstructions">
154
                                    [% IF Koha.Preference('NoLoginInstructions') %]
160
                                    [% IF Koha.Preference('NoLoginInstructions') %]
155
                                        [% Koha.Preference('NoLoginInstructions') %]
161
                                        [% Koha.Preference('NoLoginInstructions') %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt (+6 lines)
Lines 85-90 Link Here
85
                                    </fieldset>
85
                                    </fieldset>
86
                                    [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<div id="patronregistration"><p>Don't have an account? <a href="/cgi-bin/koha/opac-memberentry.pl">Register here.</a></p></div>[% END %]
86
                                    [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<div id="patronregistration"><p>Don't have an account? <a href="/cgi-bin/koha/opac-memberentry.pl">Register here.</a></p></div>[% END %]
87
                                    </fieldset>
87
                                    </fieldset>
88
                                [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
89
                                    <div id="forgotpassword">
90
                                        <h5>Forgot your password?</h5>
91
                                        <p>If you do not remember your password, click <a href="/cgi-bin/koha/opac-password-recovery.pl">here</a> to create a new one.</p>
92
                                    </div>
93
                                [% END %]
88
                                [% IF Koha.Preference( 'NoLoginInstructions' ) %]
94
                                [% IF Koha.Preference( 'NoLoginInstructions' ) %]
89
                                    <div id="nologininstructions-main">
95
                                    <div id="nologininstructions-main">
90
                                        [% Koha.Preference( 'NoLoginInstructions' ) %]
96
                                        [% Koha.Preference( 'NoLoginInstructions' ) %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt (+134 lines)
Line 0 Link Here
1
[% USE Koha %]
2
[% INCLUDE 'doc-head-open.inc' %]
3
[% IF (LibraryNameTitle) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo;
4
[% INCLUDE 'doc-head-close.inc' %]
5
[% BLOCK cssinclude %][% END %]
6
[% BLOCK jsinclude %]
7
<script type="text/javascript" language="javascript">
8
   $(function() {
9
        $("#CheckAll").click(function(){
10
                $("[name=deleteRequest]").attr('checked', true);
11
                return false;
12
            });
13
14
        $("#CheckNone").click(function(){
15
                $("[name=deleteRequest]").attr('checked', false);
16
                return false;
17
            });
18
19
        $("select#type").change(function() {
20
            $("fieldset#serial, fieldset#book, fieldset#chapter").hide()
21
            $("fieldset#" + $(this).val() ).show();
22
        });
23
   });
24
</script>
25
[% END %]
26
</head>
27
[% INCLUDE 'bodytag.inc' bodyid='opac-password-recovery' %]
28
[% INCLUDE 'masthead.inc' %]
29
30
<div class="main">
31
    <ul class="breadcrumb">
32
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
33
        <li><a href="#">Change your password</a></li>
34
    </ul>
35
36
    <div class="container-fluid">
37
        <div class="row-fluid">
38
            <div class="span2">
39
                <div id="navigation">
40
                    [% INCLUDE 'navigation.inc' IsPatronPage=0 %]
41
                </div>
42
            </div>
43
            <div class="span10">
44
                    <h3>Password recovery</h3>
45
            [% IF (hasError) %]
46
                <div class="alert alert-warning">
47
                    <h3>An error occured</h3>
48
                    <p>
49
                    [% IF (sendmailError) %]
50
                        An error has occured while sending you the password recovery link.
51
                        <br/>Please try again later.
52
                    [% ELSIF (errNoBorrowerFound) %]
53
                        No account was found with the provided information.
54
                        <br/>Check if you typed it correctly.
55
                    [% ELSIF (errBadEmail) %]
56
                        The provided email address is not tied to this account.
57
                    [% ELSIF (errTooManyEmailFound) %]
58
                        More than one account has been found for the email address: "<strong>[% email %]</strong>"
59
                        <br/>Try to use your username or an alternative email if you have one.
60
                    [% ELSIF (errNoBorrowerEmail) %]
61
                        This account has no email address we can send the email to.
62
                    [% ELSIF (errAlreadyStartRecovery) %]
63
                        The process of password recovery has already started for this account ("<strong>[% username %]</strong>")
64
                        <br/>Check your emails; you should receive the link to reset your password.
65
                        <br/>If you did not receive it, click <a href="/cgi-bin/koha/opac-password-recovery.pl?resendEmail=true&email=[% email %]&username=[% username %]">here</a> to get a new password recovery link.
66
                    [% ELSIF (errPassNotMatch) %]
67
                        The passwords entered does not match.
68
                        <br/>Please try again.
69
                    [% ELSIF (errPassTooShort) %]
70
                        The password is too short.
71
                        <br/>The password must contain at least [% minPassLength %] characters.
72
                    [% ELSIF (errLinkNotValid) %]
73
                        We could not authenticate you as the account owner.
74
                        <br/>Be sure to use the link you received in your email.
75
                    [% END %]
76
                    </p>
77
                    <p>Please contact the staff if you need further assistance.</p>
78
                </div>
79
            [% END %]
80
                <div id="password-recovery">
81
[% IF (!Koha.Preference('OpacResetPassword')) %]
82
                    <div class="alert alert-info">You can't reset your password.</div>
83
[% ELSIF (password_recovery) %]
84
                    <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
85
                        <input type="hidden" name="koha_login_context" value="opac" />
86
                        <fieldset>
87
                            <p>To reset your password, enter your username or email address.
88
                            <br/>A link to reset your password will be sent at this address.</p>
89
                            <label for="username">Login:</label>
90
                            <input type="text" id="username" size="40" name="username" value="[% username %]" />
91
                            <label for="email">Email:</label>
92
                            <input type="text" id="email" size="40" name="email" value="[% email %]" />
93
                            <fieldset class="action">
94
                                <input type="submit" value="Submit" class="btn" name="sendEmail" />
95
                            </fieldset>
96
                         </fieldset>
97
                    </form>
98
[% ELSIF (new_password) %]
99
                    <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
100
                        <input type="hidden" name="koha_login_context" value="opac" />
101
                        <fieldset>
102
                            <div class="alert alert-info">The password must contain at least [% minPassLength %] characters.</div>
103
                            <label for="password">New password:</label>
104
                            <input type="password" id="password" size="40" name="password" />
105
                            <label for="repeatPassword">Confirm new password:</label>
106
                            <input type="password" id="repeatPassword" size="40" name="repeatPassword" />
107
                            <fieldset class="action">
108
                                <input type="hidden" name="username" value="[% username %]" />
109
                                <input type="hidden" name="uniqueKey" value="[% uniqueKey %]" />
110
                                <input type="submit" value="Submit" class="btn" name="passwordReset" />
111
                            </fieldset>
112
                         </fieldset>
113
                    </form>
114
[% ELSIF (mail_sent) %]
115
                    <div class="alert alert-info">
116
                        <p>
117
                            An email has been sent to "[% email %]".
118
                            <br/>It contains a link to create a new password.
119
                            <br/>This link will be valid for 2 days starting now.
120
                        </p>
121
                        Click <a href="/cgi-bin/koha/opac-main.pl"">here</a> to return to the main page.
122
                    </div>
123
[% ELSIF (password_reset_done) %]
124
                    <div class="alert alert-success">
125
                        <p>The password has been changed for user "[% username %]".</p>
126
                        Click <a href="/cgi-bin/koha/opac-user.pl">here</a> to login.
127
                    </div>
128
[% END %]
129
                </div><!-- / #password-recovery -->
130
            </div><!-- / .span10 -->
131
        </div><!-- / .row-fluid -->
132
    </div><!-- / .container-fluid -->
133
</div><!-- / .main -->
134
[% INCLUDE 'opac-bottom.inc' %]
(-)a/opac/opac-password-recovery.pl (-1 / +179 lines)
Line 0 Link Here
0
- 
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 Search);
10
use C4::Output;
11
use C4::Context;
12
use C4::Passwordrecovery qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo CompletePasswordRecovery);
13
use Koha::AuthUtils qw(hash_password);
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 $minPassLength  = C4::Context->preference('minPasswordLength');
31
my $id             = $query->param('id');
32
my $uniqueKey      = $query->param('uniqueKey');
33
my $username       = $query->param('username');
34
my $borrower_number;
35
36
#errors
37
my $hasError;
38
39
#email form error
40
my $errNoBorrowerFound;
41
my $errNoBorrowerEmail;
42
my $errAlreadyStartRecovery;
43
my $errTooManyEmailFound;
44
my $errBadEmail;
45
46
#new password form error
47
my $errLinkNotValid;
48
my $errPassNotMatch;
49
my $errPassTooShort;
50
51
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
52
    my $protocol = $query->https() ? "https://" : "http://";
53
    #try with the main email
54
    $email ||= ''; # avoid undef
55
    my $borrower;
56
    my $search_results;
57
58
    # Find the borrower by his userid or email
59
    if( $username ){
60
        $search_results = Search({ userid => $username });
61
    }
62
    elsif ( $email ){
63
        $search_results = Search({ '' => $email }, undef, undef, undef, ['emailpro', 'email', 'B_email']);
64
    }
65
66
    if(scalar @$search_results > 1){ # Many matching borrowers
67
       $hasError             = 1;
68
       $errTooManyEmailFound = 1;
69
    }
70
    elsif( $borrower = shift @$search_results ){ # One matching borrower
71
        $username ||= $borrower->{'userid'};
72
        my @emails = ( $borrower->{'email'}, $borrower->{'emailpro'}, $borrower->{'B_email'} );
73
        # Is the given email one of the borrower's ?
74
        if( $email && !($email ~~ @emails) ){
75
             $hasError    = 1;
76
             $errBadEmail = 1;
77
        }
78
        # If we dont have an email yet. Get one of the borrower's email or raise an error.
79
        # FIXME: That ugly shift-grep contraption.
80
        # $email = shift [ grep { length() } @emails ]
81
        # It's supposed to get a non-empty string from the @emails array. There's surely a simpler way
82
        elsif( !$email && !($email = shift [ grep { length() } @emails ]) ){
83
             $hasError           = 1;
84
             $errNoBorrowerEmail = 1;
85
        }
86
        # Check if a password reset already issued for this borrower AND we are not asking for a new email
87
        elsif( ValidateBorrowernumber( $borrower->{'borrowernumber'} ) && !$query->param('resendEmail') ){
88
            $hasError                = 1;
89
            $errAlreadyStartRecovery = 1;
90
        }
91
    }
92
    else{ # 0 matching borrower
93
        $hasError           = 1;
94
        $errNoBorrowerFound = 1;
95
    }
96
    if ($hasError) {
97
        $template->param(
98
            hasError                => 1,
99
            errNoBorrowerFound      => $errNoBorrowerFound,
100
            errTooManyEmailFound    => $errTooManyEmailFound,
101
            errAlreadyStartRecovery => $errAlreadyStartRecovery,
102
            errBadEmail             => $errBadEmail,
103
            errNoBorrowerEmail      => $errNoBorrowerEmail,
104
            password_recovery       => 1,
105
            email                   => HTML::Entities::encode($email),
106
            username                => $username
107
        );
108
    }
109
    elsif ( SendPasswordRecoveryEmail( $borrower, $email, $protocol, $query->param('resendEmail') ) ) {#generate uuid and send recovery email
110
        $template->param(
111
            mail_sent => 1,
112
            email     => $email
113
        );
114
    }
115
    else {# if it doesnt work....
116
        $template->param(
117
            password_recovery => 1,
118
            sendmailError     => 1
119
        );
120
    }
121
}
122
elsif ( $query->param('passwordReset') ) {
123
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
124
    #validate password length & match
125
    if (   ($borrower_number)
126
        && ( $password eq $repeatPassword )
127
        && ( length($password) >= $minPassLength ) )
128
    {  #apply changes
129
        changepassword( $username, $borrower_number, hash_password($password) );
130
        CompletePasswordRecovery($uniqueKey);
131
        $template->param(
132
            password_reset_done => 1,
133
            username            => $username
134
        );
135
    }
136
    else { #errors
137
        if ( !$borrower_number ) { #parameters not valid
138
            $errLinkNotValid = 1;
139
        }
140
        elsif ( $password ne $repeatPassword ) { #passwords does not match
141
            $errPassNotMatch = 1;
142
        }
143
        elsif ( length($password) < $minPassLength ) { #password too short
144
            $errPassTooShort = 1;
145
        }
146
        $template->param(
147
            new_password    => 1,
148
            minPassLength   => $minPassLength,
149
            email           => $email,
150
            uniqueKey       => $uniqueKey,
151
            errLinkNotValid => $errLinkNotValid,
152
            errPassNotMatch => $errPassNotMatch,
153
            errPassTooShort => $errPassTooShort,
154
            hasError        => 1
155
        );
156
    }
157
}
158
elsif ($uniqueKey) {  #reset password form
159
    #check if the link is valid
160
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
161
162
    if ( !$borrower_number ) {
163
        $errLinkNotValid = 1;
164
    }
165
166
    $template->param(
167
        new_password    => 1,
168
        minPassLength   => $minPassLength,
169
        email           => $email,
170
        uniqueKey       => $uniqueKey,
171
        username        => $username,
172
        errLinkNotValid => $errLinkNotValid
173
    );
174
}
175
else { #password recovery form (to send email)
176
    $template->param( password_recovery => 1 );
177
}
178
179
output_html_with_http_headers $query, $cookie, $template->output;

Return to bug 8753