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

(-)a/C4/Passwordrecovery.pm (+159 lines)
Line 0 Link Here
1
package C4::Passwordrecovery;
2
3
# Copyright 2014 PTFS Europe
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
    );
35
}
36
37
=head1 NAME
38
39
C4::Passwordrecovery - Koha password recovery module
40
41
=head1 SYNOPSIS
42
43
use C4::Passwordrecovery;
44
45
=head1 FUNCTIONS
46
47
=head2 ValidateBorrowernumber
48
49
$alread = ValidateBorrowernumber( $borrower_number );
50
51
Check if the system already start recovery
52
53
Returns true false
54
55
=cut
56
57
sub ValidateBorrowernumber {
58
    my ($borrower_number) = @_;
59
    my $schema = Koha::Database->new->schema;
60
61
    my $rs = $schema->resultset('BorrowerPasswordRecovery')->search(
62
    {
63
       borrowernumber => $borrower_number,
64
       valid_until => \'> NOW()'
65
    }, {
66
        columns => 'borrowernumber'
67
    });
68
69
    if ($rs->next){
70
        return 1;
71
    }
72
73
    return 0;
74
}
75
76
=head2 GetValidLinkInfo
77
78
    Check if the link is still valid and return some info.
79
80
=cut
81
82
sub GetValidLinkInfo {
83
    my ($uniqueKey) = @_;
84
    my $dbh = C4::Context->dbh;
85
    my $query = '
86
    SELECT borrower_password_recovery.borrowernumber, userid
87
    FROM borrower_password_recovery, borrowers
88
    WHERE borrowers.borrowernumber = borrower_password_recovery.borrowernumber
89
    AND NOW() < valid_until
90
    AND uuid = ?
91
    ';
92
    my $sth = $dbh->prepare($query);
93
    $sth->execute($uniqueKey);
94
    return $sth->fetchrow;
95
}
96
97
=head2 SendPasswordRecoveryEmail
98
99
 It creates an email using the templates and send it to the user, using the specified email
100
101
=cut
102
103
sub SendPasswordRecoveryEmail {
104
    my $borrower = shift; # from GetMember
105
    my $userEmail = shift; #to_address (the one specified in the request)
106
    my $protocol = shift; #only required to determine if 'http' or 'https'
107
    my $update = shift;
108
109
    my $schema = Koha::Database->new->schema;
110
111
    # generate UUID
112
    my @chars = ("A".."Z", "a".."z", "0".."9");
113
    my $uuid_str;
114
    $uuid_str .= $chars[rand @chars] for 1..32;
115
116
    # insert into database
117
    my $expirydate = DateTime->now(time_zone => C4::Context->tz())->add( days => 2 );
118
    if($update){
119
        my $rs = $schema->resultset('BorrowerPasswordRecovery')->search(
120
        {
121
            borrowernumber => $borrower->{'borrowernumber'},
122
        });
123
        $rs->update({uuid => $uuid_str, valid_until => $expirydate->datetime()});
124
    } else {
125
         my $rs = $schema->resultset('BorrowerPasswordRecovery')->create({
126
            borrowernumber=>$borrower->{'borrowernumber'},
127
            uuid => $uuid_str,
128
            valid_until=> $expirydate->datetime()
129
         });
130
    }
131
132
    # create link
133
    my $uuidLink = $protocol . C4::Context->preference( 'OPACBaseURL' ) . "/cgi-bin/koha/opac-password-recovery.pl?uniqueKey=$uuid_str";
134
135
    # prepare the email
136
    my $letter = C4::Letters::GetPreparedLetter (
137
        module => 'members',
138
        letter_code => 'PASSWORD_RESET',
139
        branchcode => $borrower->{branchcode},
140
        substitute => {passwordreseturl => $uuidLink, user => $borrower->{userid} },
141
    );
142
143
    # define to/from emails
144
    my $kohaEmail = C4::Context->preference( 'KohaAdminEmailAddress' ); # from
145
146
    C4::Letters::EnqueueLetter( {
147
         letter => $letter,
148
         borrowernumber => $borrower->{borrowernumber},
149
         to_address => $userEmail,
150
         from_address => $kohaEmail,
151
         message_transport_type => 'email',
152
    } );
153
154
    return 1;
155
}
156
157
END { }    # module clean-up code here (global destructor)
158
159
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/en/mandatory/sample_notices.sql (+4 lines)
Lines 142-144 Thank you. Link Here
142
142
143
Your library.'
143
Your library.'
144
);
144
);
145
146
INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type)
147
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'
148
);
(-)a/installer/data/mysql/kohastructure.sql (+11 lines)
Lines 3504-3509 CREATE TABLE items_search_fields ( Link Here
3504
    ON DELETE SET NULL ON UPDATE CASCADE
3504
    ON DELETE SET NULL ON UPDATE CASCADE
3505
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3505
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3506
3506
3507
-- Table structure for table 'borrower_password_recovery'
3508
-- this stores the unique ID sent by email to the patron, for future validation
3509
--
3510
3511
CREATE TABLE IF NOT EXISTS borrower_password_recovery (
3512
  borrowernumber int(11) NOT NULL,
3513
  uuid varchar(128) NOT NULL,
3514
  valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
3515
  KEY borrowernumber (borrowernumber)
3516
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3517
3507
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3518
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3508
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3519
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3509
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
3520
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 291-296 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
291
('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'),
291
('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'),
292
('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'),
292
('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'),
293
('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'),
293
('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'),
294
('OpacResetPassword','1','','Shows the \'Forgot your password?\' link in the OPAC','YesNo'),
294
('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','Textarea'),
295
('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','Textarea'),
295
('OPACSearchForTitleIn','<li><a  href=\"http://worldcat.org/search?q={TITLE}\" target=\"_blank\">Other Libraries (WorldCat)</a></li>\n<li><a href=\"http://www.scholar.google.com/scholar?q={TITLE}\" target=\"_blank\">Other Databases (Google Scholar)</a></li>\n<li><a href=\"http://www.bookfinder.com/search/?author={AUTHOR}&amp;title={TITLE}&amp;st=xl&amp;ac=qr\" target=\"_blank\">Online Stores (Bookfinder.com)</a></li>\n<li><a href=\"http://openlibrary.org/search/?author=({AUTHOR})&title=({TITLE})\" target=\"_blank\">Open Library (openlibrary.org)</a></li>','70|10','Enter the HTML that will appear in the \'Search for this title in\' box on the detail page in the OPAC.  Enter {TITLE}, {AUTHOR}, or {ISBN} in place of their respective variables in the URL. Leave blank to disable \'More Searches\' menu.','Textarea'),
296
('OPACSearchForTitleIn','<li><a  href=\"http://worldcat.org/search?q={TITLE}\" target=\"_blank\">Other Libraries (WorldCat)</a></li>\n<li><a href=\"http://www.scholar.google.com/scholar?q={TITLE}\" target=\"_blank\">Other Databases (Google Scholar)</a></li>\n<li><a href=\"http://www.bookfinder.com/search/?author={AUTHOR}&amp;title={TITLE}&amp;st=xl&amp;ac=qr\" target=\"_blank\">Online Stores (Bookfinder.com)</a></li>\n<li><a href=\"http://openlibrary.org/search/?author=({AUTHOR})&title=({TITLE})\" target=\"_blank\">Open Library (openlibrary.org)</a></li>','70|10','Enter the HTML that will appear in the \'Search for this title in\' box on the detail page in the OPAC.  Enter {TITLE}, {AUTHOR}, or {ISBN} in place of their respective variables in the URL. Leave blank to disable \'More Searches\' menu.','Textarea'),
296
('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'),
297
('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'),
(-)a/installer/data/mysql/updatedatabase.pl (+18 lines)
Lines 9804-9809 if ( CheckVersion($DBversion) ) { Link Here
9804
    SetVersion($DBversion);
9804
    SetVersion($DBversion);
9805
}
9805
}
9806
9806
9807
$DBversion = "XXX";
9808
if ( CheckVersion($DBversion) ) {
9809
    $dbh->do("INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacResetPassword',  '1','','Shows the ''Forgot your password?'' link in the OPAC','YesNo')");
9810
    $dbh->do(q{
9811
        CREATE TABLE IF NOT EXISTS borrower_password_recovery (
9812
          borrowernumber int(11) NOT NULL,
9813
          uuid varchar(128) NOT NULL,
9814
          valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
9815
          KEY borrowernumber (borrowernumber)
9816
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
9817
    });
9818
    $dbh->do(q{
9819
        INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type) 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><< borrowers.userid>></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')
9820
        });
9821
    print "Upgrade to $DBversion done (Bug 8753: Add forgot password link to OPAC)\n";
9822
    SetVersion ($DBversion);
9823
}
9824
9807
=head1 FUNCTIONS
9825
=head1 FUNCTIONS
9808
9826
9809
=head2 TableExists($table)
9827
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+8 lines)
Lines 338-343 OPAC: Link Here
338
                  no: "Don't allow"
338
                  no: "Don't allow"
339
            - patrons to change their own password on the OPAC. Note that this must be off to use LDAP authentication.
339
            - patrons to change their own password on the OPAC. Note that this must be off to use LDAP authentication.
340
        -
340
        -
341
            - "The user "
342
            - pref: OpacResetPassword
343
              default: 1
344
              choices:
345
                  yes: "can reset"
346
                  no: "can not reset"
347
            - " their password on OPAC."
348
        -
341
            - pref: OPACPatronDetails
349
            - pref: OPACPatronDetails
342
              choices:
350
              choices:
343
                  yes: Allow
351
                  yes: Allow
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc (+3 lines)
Lines 309-314 Link Here
309
                    [% END %]
309
                    [% END %]
310
                        [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<div id="mpatronregistration"><p>Don't have an account? <a href="/cgi-bin/koha/opac-memberentry.pl">Register here.</a></p></div>[% END %]
310
                        [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<div id="mpatronregistration"><p>Don't have an account? <a href="/cgi-bin/koha/opac-memberentry.pl">Register here.</a></p></div>[% END %]
311
                    </fieldset>
311
                    </fieldset>
312
                    [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
313
                         <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</  a></p>
314
                    [% END %]
312
            </div>
315
            </div>
313
            <div class="modal-footer">
316
            <div class="modal-footer">
314
                <input type="submit" class="btn btn-primary" value="Log in" />
317
                <input type="submit" class="btn btn-primary" value="Log in" />
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (+3 lines)
Lines 148-153 Link Here
148
                                    <input type="text"  size="25" id="userid"  name="userid" />
148
                                    <input type="text"  size="25" id="userid"  name="userid" />
149
                                    <label for="password">Password</label><input type="password"  size="25" id="password"  name="password" />
149
                                    <label for="password">Password</label><input type="password"  size="25" id="password"  name="password" />
150
                                </fieldset>
150
                                </fieldset>
151
                                [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
152
                                    <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</a></p>
153
                                [% END %]
151
154
152
                                <input type="submit" value="Log in" class="btn" />
155
                                <input type="submit" value="Log in" class="btn" />
153
                                <div id="nologininstructions">
156
                                <div id="nologininstructions">
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt (+132 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
<body>
28
29
<div id="doc3" class="yui-t1">
30
    <div id="bd">
31
[% INCLUDE 'masthead.inc' %]
32
        <div id="yui-main">
33
            <div class="yui-b">
34
                <div class="yui-g">
35
                    <div class="illrequest">
36
[% IF (!Koha.Preference('OpacResetPassword')) %]
37
    <div class="dialog alert">You can't reset your password.</div>
38
[% ELSIF (password_recovery) %]
39
    [% IF (hasError) %]
40
        <span class="TxtErreur">
41
        [% IF (sendmailError) %]
42
            An error has occured while sending you the password recovery link.
43
            <br/>Please try again later.
44
        [% ELSIF (errNoEmailFound) %]
45
            No account was found with the email address "<strong>[% email %]</strong>"
46
            <br/>Check if you typed it correctly.
47
        [% ELSIF (errTooManyEmailFound) %]
48
            More than one account has been found for the email address: "<strong>[% email %]</strong>"
49
            <br/>Try to use an alternative email if you have one.
50
        [% ELSIF (errAlreadyStartRecovery) %]
51
            The process of password recovery has already started for this account ("<strong>[% email %]</strong>")
52
            <br/>Check your emails; you should receive the link to reset your password.
53
            <br/>If you did not receive it, <a href="/cgi-bin/koha/opac-password-recovery.pl?resendEmail=true&email=[% email %]">click here to get a new password recovery link</a>
54
        [% END %]
55
        <br/><br/>Please contact the staff if you need further assistance.
56
        </span>
57
    [% END %]
58
        <div id="password-recovery" class="container">
59
            <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
60
                <input type="hidden" name="koha_login_context" value="opac" />
61
                <fieldset class="brief">
62
                    <legend>Password recovery form:</legend>
63
                        <p>To reset your password, enter your email address.
64
                        <br/>A link to reset your password will be sent at this address.</p>
65
                        <ol>
66
                            <li><label for="email">Email:</label><input type="text" id="email" size="40" name="email" value="[% email %]" /></li>
67
                        </ol>
68
                    <fieldset class="action">
69
                 <input type="submit" value="Submit" class="submit" name="sendEmail" />
70
                    </fieldset>
71
                 </fieldset>
72
            </form>
73
        </div>
74
75
[% ELSIF (new_password) %]
76
    [% IF (errLinkNotValid) %]
77
        <span class="TxtErreur"><h6>
78
        We could not authenticate you as the account owner.
79
        <br/>Be sure to use the link you received in your email.
80
        </h6></span>
81
    [% ELSE %]
82
        [% IF (hasError) %]
83
            <span class="TxtErreur">
84
            [% IF (errPassNotMatch) %]
85
                The passwords entered does not match.
86
                <br/>Please try again.
87
            [% ELSIF (errPassTooShort) %]
88
                The password is too short.
89
                <br/>The password must contain at least [% minPassLength %] characters.
90
            [% END %]
91
            </span>
92
        [% END %]
93
            <div id="password-recovery" class="container">
94
                <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
95
                    <input type="hidden" name="koha_login_context" value="opac" />
96
                    <fieldset class="brief">
97
                        <legend>Password recovery form:</legend>
98
                            <p class="light">The password must contain at least [% minPassLength %] characters.</p>
99
                            <ol>
100
                                <li><label for="password">New password:</label><input type="password" id="password" size="40" name="password" /></li>
101
                                <li><label for="repeatPassword">Confirm new password:</label><input type="password" id="repeatPassword" size="40" name="repeatPassword" /></li>
102
                            </ol>
103
                        <fieldset class="action">
104
                        <input type="hidden" name="username" value="[% username %]" />
105
                        <input type="hidden" name="uniqueKey" value="[% uniqueKey %]" />
106
                        <input type="submit" value="Submit" class="submit" name="passwordReset" />
107
                        </fieldset>
108
                     </fieldset>
109
                </form>
110
            </div>
111
    [% END %]
112
[% ELSIF (mail_sent) %]
113
    <p>A mail has been sent to "[% email %]".
114
    <br/>It contains a link to create a new password.
115
    <br/>This link will be valid for 2 days starting now.</p>
116
    <br/><a href="/cgi-bin/koha/opac-main.pl"">Click here to return to the main page.</a>
117
[% ELSIF (password_reset_done) %]
118
    <p>The password has been changed for user "[% username %]".
119
    <br/>You can now login using <a href="/cgi-bin/koha/opac-user.pl">this form</a>.</p>
120
[% END %]
121
                    </div>
122
                </div>
123
            </div>
124
        </div>
125
        <div class="yui-b">
126
            <div class="container">
127
                [% INCLUDE 'usermenu.inc' %]
128
            </div>
129
        </div>
130
    </div>
131
[% INCLUDE 'opac-bottom.inc' %]
132
</div>
(-)a/opac/opac-password-recovery.pl (-1 / +156 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 GetMember GetMemberDetails );
10
use C4::Output;
11
use C4::Context;
12
use C4::Passwordrecovery qw(SendPasswordRecoveryEmail ValidateBorrowernumber GetValidLinkInfo);
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 $errNoEmailFound;
41
my $errAlreadyStartRecovery;
42
43
#new password form error
44
my $errLinkNotValid;
45
my $errPassNotMatch;
46
my $errPassTooShort;
47
48
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
49
    my $protocol = $query->https() ? "https://" : "http://";
50
    #try with the main email
51
    $email ||= ''; # avoid undef
52
    my $borrower_infos = GetMember( email => $email );
53
    $borrower_infos = GetMember( emailpro => $email ) unless $borrower_infos;
54
    $borrower_infos = GetMember( B_email => $email ) unless $borrower_infos;
55
    if($borrower_infos) {
56
        $borrower_number = $borrower_infos->{'borrowernumber'};
57
    }
58
59
    if ( !$email || !$borrower_number ) {
60
        $hasError        = 1;
61
        $errNoEmailFound = 1;
62
    }
63
    elsif ( !$query->param('resendEmail') ) {
64
        my $already = ValidateBorrowernumber( $borrower_number );
65
66
        if ( $already ) {
67
            $hasError                = 1;
68
            $errAlreadyStartRecovery = 1;
69
        }
70
    }
71
72
    if ($hasError) {
73
        $template->param(
74
            hasError                => 1,
75
            errNoEmailFound         => $errNoEmailFound,
76
            errAlreadyStartRecovery => $errAlreadyStartRecovery,
77
            password_recovery       => 1,
78
            email                   => HTML::Entities::encode($email),
79
        );
80
    }
81
    elsif ( SendPasswordRecoveryEmail( $borrower_infos, $email, $protocol, $query->param('resendEmail') ) ) {#generate uuid and send recovery email
82
        $template->param(
83
            mail_sent => 1,
84
            email     => $email
85
        );
86
    }
87
    else {# if it doesnt work....
88
        $template->param(
89
            password_recovery => 1,
90
            sendmailError     => 1
91
        );
92
    }
93
}
94
elsif ( $query->param('passwordReset') ) {
95
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
96
    #validate password length & match
97
    if (   ($borrower_number)
98
        && ( $password eq $repeatPassword )
99
        && ( length($password) >= $minPassLength ) )
100
    {  #apply changes
101
        changepassword( $username, $borrower_number, hash_password($password) );
102
103
        #remove entry
104
        my $schema = Koha::Database->new->schema;
105
        my $rs = $schema->resultset('BorrowerPasswordRecovery')->search({-or => [uuid => $uniqueKey, valid_until => \'< NOW()']});
106
        $rs->delete;
107
108
        $template->param(
109
            password_reset_done => 1,
110
            username            => $username
111
        );
112
    }
113
    else { #errors
114
        if ( !$borrower_number ) { #parameters not valid
115
            $errLinkNotValid = 1;
116
        }
117
        elsif ( $password ne $repeatPassword ) { #passwords does not match
118
            $errPassNotMatch = 1;
119
        }
120
        elsif ( length($password) < $minPassLength ) { #password too short
121
            $errPassTooShort = 1;
122
        }
123
        $template->param(
124
            new_password    => 1,
125
            minPassLength   => $minPassLength,
126
            email           => $email,
127
            uniqueKey       => $uniqueKey,
128
            errLinkNotValid => $errLinkNotValid,
129
            errPassNotMatch => $errPassNotMatch,
130
            errPassTooShort => $errPassTooShort,
131
            hasError        => 1
132
        );
133
    }
134
}
135
elsif ($uniqueKey) {  #reset password form
136
    #check if the link is valid
137
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
138
139
    if ( !$borrower_number ) {
140
        $errLinkNotValid = 1;
141
    }
142
143
    $template->param(
144
        new_password    => 1,
145
        minPassLength   => $minPassLength,
146
        email           => $email,
147
        uniqueKey       => $uniqueKey,
148
        username        => $username,
149
        errLinkNotValid => $errLinkNotValid
150
    );
151
}
152
else { #password recovery form (to send email)
153
    $template->param( password_recovery => 1 );
154
}
155
156
output_html_with_http_headers $query, $cookie, $template->output;

Return to bug 8753