View | Details | Raw Unified | Return to bug 13068
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 (-1 / +5 lines)
Lines 144-147 Your library.' Link Here
144
);
144
);
145
145
146
INSERT INTO letter(module, code, branchcode, name, title, content, message_transport_type)
146
INSERT INTO letter(module, code, branchcode, name, title, content, message_transport_type)
147
VALUES ('acquisition', 'ACQ_NOTIF_ON_RECEIV', '', 'Notification on receiving', 'Order received', 'Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\n The order <<aqorders.ordernumber>> (<<biblio.title>>) has been received.\n\nYour library.', 'email')
147
VALUES ('acquisition', 'ACQ_NOTIF_ON_RECEIV', '', 'Notification on receiving', 'Order received', 'Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\n The order <<aqorders.ordernumber>> (<<biblio.title>>) has been received.\n\nYour library.', 'email');
148
149
INSERT INTO `letter` (module, code, branchcode, name, is_html, title, content, message_transport_type)
150
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'
151
);
(-)a/installer/data/mysql/kohastructure.sql (+11 lines)
Lines 3520-3525 CREATE TABLE items_search_fields ( Link Here
3520
    ON DELETE SET NULL ON UPDATE CASCADE
3520
    ON DELETE SET NULL ON UPDATE CASCADE
3521
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3521
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3522
3522
3523
-- Table structure for table 'borrower_password_recovery'
3524
-- this stores the unique ID sent by email to the patron, for future validation
3525
--
3526
3527
CREATE TABLE IF NOT EXISTS borrower_password_recovery (
3528
  borrowernumber int(11) NOT NULL,
3529
  uuid varchar(128) NOT NULL,
3530
  valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
3531
  KEY borrowernumber (borrowernumber)
3532
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3533
3523
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3534
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3524
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3535
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3525
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
3536
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 292-297 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
292
('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'),
292
('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'),
293
('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'),
293
('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'),
294
('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'),
294
('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'),
295
('OpacResetPassword','1','','Shows the \'Forgot your password?\' link in the OPAC','YesNo'),
295
('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','Textarea'),
296
('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','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'),
297
('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'),
297
('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'),
298
('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'),
(-)a/installer/data/mysql/updatedatabase.pl (+17 lines)
Lines 9971-9976 if ( CheckVersion($DBversion) ) { Link Here
9971
    SetVersion($DBversion);
9971
    SetVersion($DBversion);
9972
}
9972
}
9973
9973
9974
$DBversion = "XXX";
9975
if ( CheckVersion($DBversion) ) {
9976
    $dbh->do("INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacResetPassword',  '1','','Shows the ''Forgot your password?'' link in the OPAC','YesNo')");
9977
    $dbh->do(q{
9978
        CREATE TABLE IF NOT EXISTS borrower_password_recovery (
9979
          borrowernumber int(11) NOT NULL,
9980
          uuid varchar(128) NOT NULL,
9981
          valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
9982
          KEY borrowernumber (borrowernumber)
9983
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
9984
    });
9985
    $dbh->do(q{
9986
        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')
9987
        });
9988
    print "Upgrade to $DBversion done (Bug 8753: Add forgot password link to OPAC)\n";
9989
    SetVersion ($DBversion);
9990
}
9974
9991
9975
# DEVELOPER PROCESS, search for anything to execute in the db_update directory
9992
# DEVELOPER PROCESS, search for anything to execute in the db_update directory
9976
# SEE bug 13068
9993
# SEE bug 13068
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+8 lines)
Lines 339-344 OPAC: Link Here
339
                  no: "Don't allow"
339
                  no: "Don't allow"
340
            - patrons to change their own password on the OPAC. Note that this must be off to use LDAP authentication.
340
            - patrons to change their own password on the OPAC. Note that this must be off to use LDAP authentication.
341
        -
341
        -
342
            - "The user "
343
            - pref: OpacResetPassword
344
              default: 1
345
              choices:
346
                  yes: "can reset"
347
                  no: "can not reset"
348
            - " their password on OPAC."
349
        -
342
            - pref: OPACPatronDetails
350
            - pref: OPACPatronDetails
343
              choices:
351
              choices:
344
                  yes: Allow
352
                  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 13068