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

(-)a/C4/Auth.pm (+2 lines)
Lines 1068-1073 sub checkauth { Link Here
1068
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1068
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1069
        persona            => C4::Context->preference("Persona"),
1069
        persona            => C4::Context->preference("Persona"),
1070
        opac_css_override => $ENV{'OPAC_CSS_OVERRIDE'},
1070
        opac_css_override => $ENV{'OPAC_CSS_OVERRIDE'},
1071
        OpacResetPassword => C4::Context->preference("OpacResetPassword"),
1072
        OpacPasswordChange => C4::Context->preference("OpacPasswordChange"),
1071
    );
1073
    );
1072
1074
1073
    $template->param( OpacPublic => C4::Context->preference("OpacPublic"));
1075
    $template->param( OpacPublic => C4::Context->preference("OpacPublic"));
(-)a/C4/Members.pm (-1 / +88 lines)
Lines 42-47 use Koha::Borrower::Debarments qw(IsDebarred); Link Here
42
use Text::Unaccent qw( unac_string );
42
use Text::Unaccent qw( unac_string );
43
use Koha::AuthUtils qw(hash_password);
43
use Koha::AuthUtils qw(hash_password);
44
44
45
## Password recovery
46
use CGI;
47
use Encode qw(encode decode);
48
use MIME::QuotedPrint qw(encode_qp);
49
use Mail::Sendmail;
50
45
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
51
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
46
52
47
BEGIN {
53
BEGIN {
Lines 112-118 BEGIN { Link Here
112
    push @EXPORT, qw(
118
    push @EXPORT, qw(
113
        &ModMember
119
        &ModMember
114
        &changepassword
120
        &changepassword
115
         &ModPrivacy
121
        &ModPrivacy
122
    );
123
124
    # Password recovery
125
    push @EXPORT, qw(
126
        &SendPasswordRecoveryEmail
116
    );
127
    );
117
128
118
    #Delete data
129
    #Delete data
Lines 2241-2246 sub ModPrivacy { Link Here
2241
                      privacy        => $privacy );
2252
                      privacy        => $privacy );
2242
}
2253
}
2243
2254
2255
=head2 SendPasswordRecoveryEmail
2256
2257
  SendPasswordRecoveryEmail( $borrowernumber, $email );
2258
2259
Sends email to user using template file opac-send-password-recovery.tt.
2260
The mail contains a link to the script for password reset, with a unique key stored
2261
in the database for validation
2262
2263
=cut
2264
2265
sub SendPasswordRecoveryEmail {
2266
    my $borrowernumber = shift;
2267
    my $email = shift;
2268
    my $dbh = C4::Context->dbh;
2269
    my $username = GetMemberDetails($borrowernumber)->{userid};
2270
2271
    #generate UUID
2272
    my @chars = ("A".."Z", "a".."z", "0".."9");
2273
    my $uuid_str;
2274
    $uuid_str .= $chars[rand @chars] for 1..32;
2275
2276
    #insert into database
2277
    my $sth = $dbh->prepare( 'INSERT INTO borrower_password_recovery VALUES (? ,? , ADDDATE(NOW(), INTERVAL 2 DAY) )' );
2278
    $sth->execute($borrowernumber, $uuid_str);
2279
2280
    my $userEmail = ( $email ) ? $email : GetFirstValidEmailAddress($borrowernumber);
2281
    #define to/from emails
2282
    my $kohaEmail = C4::Context->preference( 'KohaAdminEmailAddress' );
2283
2284
    #create link
2285
    my $uuidLink = "http://" . C4::Context->preference( 'OPACBaseURL' ) . "/cgi-bin/koha/opac-password-recovery.pl?uniqueKey=$uuid_str";
2286
    #warn $uuidLink;
2287
2288
    #build email content
2289
    my $query = new CGI;
2290
    my ( $template2, $borrower_number, $cookie ) = C4::Auth::get_template_and_user(
2291
    {
2292
        template_name   => "opac-send-password-recovery.tmpl",
2293
        query           => $query,
2294
        type            => "opac",
2295
        authnotrequired => 1,
2296
    }
2297
    );
2298
    $template2->param(
2299
        uuidLink         => $uuidLink,
2300
        username         => $username,
2301
    );
2302
2303
    # Getting template result and
2304
    my $template_res = $template2->output();
2305
2306
    #Mail attributes
2307
    my %mail = (
2308
        To  => $userEmail,
2309
        From  => $kohaEmail,
2310
        'Content-Type' => 'text/html; charset=utf-8'
2311
    );
2312
2313
    #getting mail properties
2314
    if ( $template_res =~ /<SUBJECT>(.*)<END_SUBJECT>/s ) { $mail{'subject'} = decode( 'utf-8', $1 ); }
2315
    if ( $template_res =~ /<MESSAGE>\n(.*)\n<END_MESSAGE>/s ) { $mail{'body'} = decode( 'utf-8', $1 ); }
2316
    #send mail
2317
    if ( sendmail %mail )
2318
    {
2319
        # if it works....
2320
        return 1;
2321
    }
2322
    else
2323
    {
2324
        # if it doesnt work....
2325
        warn "Error sending mail: $Mail::Sendmail::error \n";
2326
        return 0;
2327
    }
2328
}
2329
2330
2244
=head2 AddMessage
2331
=head2 AddMessage
2245
2332
2246
  AddMessage( $borrowernumber, $message_type, $message, $branchcode );
2333
  AddMessage( $borrowernumber, $message_type, $message, $branchcode );
(-)a/installer/data/mysql/kohastructure.sql (+11 lines)
Lines 3393-3398 CREATE TABLE IF NOT EXISTS marc_modification_template_actions ( Link Here
3393
  CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE
3393
  CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE
3394
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3394
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
3395
3395
3396
-- Table structure for table 'borrower_password_recovery'
3397
-- this stores the unique ID sent by email to the patron, for future validation
3398
--
3399
3400
CREATE TABLE IF NOT EXISTS borrower_password_recovery (
3401
  borrowernumber int(11) NOT NULL,
3402
  uuid varchar(128) NOT NULL,
3403
  valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
3404
  KEY borrowernumber (borrowernumber)
3405
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3406
3396
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3407
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
3397
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3408
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
3398
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
3409
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 256-261 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
256
('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'),
256
('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'),
257
('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'),
257
('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'),
258
('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'),
258
('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'),
259
('OpacResetPassword','1','','Shows the \'Forgot your password?\' link in the OPAC','YesNo'),
259
('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','Textarea'),
260
('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','Textarea'),
260
('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'),
261
('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'),
261
('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'),
262
('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'),
(-)a/installer/data/mysql/updatedatabase.pl (+15 lines)
Lines 7931-7936 if(CheckVersion($DBversion)) { Link Here
7931
}
7931
}
7932
7932
7933
7933
7934
$DBversion = "3.15.00.XXX";
7935
if ( CheckVersion($DBversion) ) {
7936
    $dbh->do("INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacResetPassword','1','','Shows the ''Forgot your password?'' link in the OPAC','YesNo')");
7937
    $dbh->do(q{
7938
        CREATE TABLE IF NOT EXISTS borrower_password_recovery (
7939
          borrowernumber int(11) NOT NULL,
7940
          uuid varchar(128) NOT NULL,
7941
          valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
7942
          KEY borrowernumber (borrowernumber)
7943
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
7944
    });
7945
    print "Upgrade to $DBversion done (Bug 8753: Add forgot password link to OPAC)\n";
7946
    SetVersion ($DBversion);
7947
}
7948
7934
=head1 FUNCTIONS
7949
=head1 FUNCTIONS
7935
7950
7936
=head2 TableExists($table)
7951
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+7 lines)
Lines 551-556 OPAC: Link Here
551
                  track: "Track"
551
                  track: "Track"
552
                  no: "Don't track"
552
                  no: "Don't track"
553
            - links that patrons click on
553
            - links that patrons click on
554
        -
555
            - pref: OpacResetPassword
556
              default: 1
557
              choices:
558
                  yes: "On"
559
                  no: "Off"
560
            - ". If On, the user can reset his password on OPAC."
554
561
555
    Shelf Browser:
562
    Shelf Browser:
556
        -
563
        -
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc (-1 / +4 lines)
Lines 278-287 Link Here
278
                        <label for="mpassword">Password:</label><input type="password" id="mpassword" name="password" />
278
                        <label for="mpassword">Password:</label><input type="password" id="mpassword" name="password" />
279
                    [% 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 %]
279
                    [% 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 %]
280
                    </fieldset>
280
                    </fieldset>
281
                    [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
282
                         <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</  a></p>
283
                    [% END %]
281
            </div>
284
            </div>
282
            <div class="modal-footer">
285
            <div class="modal-footer">
283
                <input type="submit" class="btn btn-primary" value="Log in" />
286
                <input type="submit" class="btn btn-primary" value="Log in" />
284
                <a href="#" data-dismiss="modal" aria-hidden="true" class="cancel">Cancel</a>
287
                <a href="#" data-dismiss="modal" aria-hidden="true" class="cancel">Cancel</a>
285
            </div>
288
            </div>
286
        </form> <!-- /#auth -->
289
        </form> <!-- /#auth -->
287
    </div>  <!-- /#modalAuth  -->
290
    </div>  <!-- /#modalAuth  -->
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (+4 lines)
Lines 95-100 Link Here
95
                                    <label for="password">Password</label><input type="password"  size="25" id="password"  name="password" />
95
                                    <label for="password">Password</label><input type="password"  size="25" id="password"  name="password" />
96
                                </fieldset>
96
                                </fieldset>
97
97
98
								[% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
99
								    <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</a></p>
100
								[% END %]
101
98
                                <input type="submit" value="Log in" class="btn" />
102
                                <input type="submit" value="Log in" class="btn" />
99
                                <div id="nologininstructions">
103
                                <div id="nologininstructions">
100
                                    <h5>Don't have a password yet?</h5><p> If you don't have a password yet, stop by the circulation desk the next time you're in the library. We'll happily set one up for you.</p>
104
                                    <h5>Don't have a password yet?</h5><p> If you don't have a password yet, stop by the circulation desk the next time you're in the library. We'll happily set one up for you.</p>
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt (+3 lines)
Lines 78-83 Link Here
78
                                    </fieldset>
78
                                    </fieldset>
79
                                    [% 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 %]
79
                                    [% 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 %]
80
                                    </fieldset>
80
                                    </fieldset>
81
                                    [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
82
                                        <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</a></p>
83
                                    [% END %]
81
                                </form>
84
                                </form>
82
                            </div> <!-- /#login -->
85
                            </div> <!-- /#login -->
83
                        [% END # /casAuthentication %]
86
                        [% END # /casAuthentication %]
(-)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 yo use your alternative email if you have another.
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 recieve the link to reset your password.
53
            <br/>If you didn't recieve 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 authentify you as the account owner.
79
        <br/>Be sure to use the link you recieved 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 from 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 the 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/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-send-password-recovery.tt (+19 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
7
<SUBJECT>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] - Password recovery<END_SUBJECT>
8
9
<MESSAGE>
10
<html>
11
<p>This email has been sent in response to your password recovery request for the account <strong>[% username %]</strong>.</p>
12
<p>
13
You can now create your new password using the following link:
14
<br/><a href="[% uuidLink %]">[% uuidLink %]</a>
15
</p>
16
<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>
17
<p>Thank you.</p>
18
</html>
19
<END_MESSAGE>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt (+3 lines)
Lines 85-90 please choose against which one you would like to authenticate: </p> Link Here
85
</ol></fieldset>
85
</ol></fieldset>
86
86
87
<input type="submit" value="Log In" class="submit" />
87
<input type="submit" value="Log In" class="submit" />
88
[% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
89
    <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</a></p>
90
[% END %]
88
<div id="nologininstructions">
91
<div id="nologininstructions">
89
    <h5>Don't have a password yet?</h5><p> If you don't have a password yet, stop by the circulation desk the next time you're in the library. We'll happily set one up for you.</p>
92
    <h5>Don't have a password yet?</h5><p> If you don't have a password yet, stop by the circulation desk the next time you're in the library. We'll happily set one up for you.</p>
90
    <h5>Don't have a library card?</h5><p> If you don't have a library card, stop by your local library to sign up[% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<span id="registrationinstructions"> or  <a href="/cgi-bin/koha/opac-memberentry.pl">register here</a></span>[% END %].  </p>
93
    <h5>Don't have a library card?</h5><p> If you don't have a library card, stop by your local library to sign up[% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<span id="registrationinstructions"> or  <a href="/cgi-bin/koha/opac-memberentry.pl">register here</a></span>[% END %].  </p>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt (-1 / +5 lines)
Lines 60-66 Link Here
60
60
61
        [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<div id="patronregistration">Don't have an account? <a href="/cgi-bin/koha/opac-memberentry.pl">Register here.</a></div>[% END %]
61
        [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]<div id="patronregistration">Don't have an account? <a href="/cgi-bin/koha/opac-memberentry.pl">Register here.</a></div>[% END %]
62
62
63
	 </fieldset></fieldset>
63
     </fieldset>
64
     [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %]
65
             <p><a href="/cgi-bin/koha/opac-password-recovery.pl">Forgot your password?</a></p>
66
     [% END %]
67
     </fieldset>
64
	</form>
68
	</form>
65
	</div>
69
	</div>
66
    [% END %]
70
    [% END %]
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-password-recovery.tt (+130 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
6
<script type="text/javascript" language="javascript">
7
   $(function() {
8
        $("#CheckAll").click(function(){
9
                $("[name=deleteRequest]").attr('checked', true);
10
                return false;
11
            });
12
13
        $("#CheckNone").click(function(){
14
                $("[name=deleteRequest]").attr('checked', false);
15
                return false;
16
            });
17
18
        $("select#type").change(function() {
19
            $("fieldset#serial, fieldset#book, fieldset#chapter").hide()
20
            $("fieldset#" + $(this).val() ).show();
21
        });
22
   });
23
</script>
24
</head>
25
<body>
26
27
<div id="doc3" class="yui-t1">
28
    <div id="bd">
29
[% INCLUDE 'masthead.inc' %]
30
        <div id="yui-main">
31
            <div class="yui-b">
32
                <div class="yui-g">
33
                    <div class="illrequest">
34
[% IF (!Koha.Preference('OpacResetPassword')) %]
35
    <div class="dialog alert">You can't reset your password.</div>
36
[% ELSIF (password_recovery) %]
37
    [% IF (hasError) %]
38
        <span class="TxtErreur">
39
        [% IF (sendmailError) %]
40
            An error has occured while sending you the password recovery link.
41
            <br/>Please try again later.
42
        [% ELSIF (errNoEmailFound) %]
43
            No account was found with the email address "<strong>[% email %]</strong>"
44
            <br/>Check if you typed it correctly.
45
        [% ELSIF (errTooManyEmailFound) %]
46
            More than one account has been found for the email address: "<strong>[% email %]</strong>"
47
            <br/>Try yo use your alternative email if you have another.
48
        [% ELSIF (errAlreadyStartRecovery) %]
49
            The process of password recovery has already started for this account ("<strong>[% email %]</strong>")
50
            <br/>Check your emails; you should recieve the link to reset your password.
51
            <br/>If you didn't recieve it, <a href="/cgi-bin/koha/opac-password-recovery.pl?resendEmail=true&email=[% email %]">click here to get a new password recovery link</a>
52
        [% END %]
53
        <br/><br/>Please contact the staff if you need further assistance.
54
        </span>
55
    [% END %]
56
        <div id="password-recovery" class="container">
57
            <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
58
                <input type="hidden" name="koha_login_context" value="opac" />
59
                <fieldset class="brief">
60
                    <legend>Password recovery form:</legend>
61
                        <p>To reset your password, enter your email address.
62
                        <br/>A link to reset your password will be sent at this address.</p>
63
                        <ol>
64
                            <li><label for="email">Email:</label><input type="text" id="email" size="40" name="email" value="[% email %]" /></li>
65
                        </ol>
66
                    <fieldset class="action">
67
                 <input type="submit" value="Submit" class="submit" name="sendEmail" />
68
                    </fieldset>
69
                 </fieldset>
70
            </form>
71
        </div>
72
73
[% ELSIF (new_password) %]
74
    [% IF (errLinkNotValid) %]
75
        <span class="TxtErreur"><h6>
76
        We could not authentify you as the account owner.
77
        <br/>Be sure to use the link you recieved in your email.
78
        </h6></span>
79
    [% ELSE %]
80
        [% IF (hasError) %]
81
            <span class="TxtErreur">
82
            [% IF (errPassNotMatch) %]
83
                The passwords entered does not match.
84
                <br/>Please try again.
85
            [% ELSIF (errPassTooShort) %]
86
                The password is too short.
87
                <br/>The password must contain at least [% minPassLength %] characters.
88
            [% END %]
89
            </span>
90
        [% END %]
91
            <div id="password-recovery" class="container">
92
                <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
93
                    <input type="hidden" name="koha_login_context" value="opac" />
94
                    <fieldset class="brief">
95
                        <legend>Password recovery form:</legend>
96
                            <p class="light">The password must contain at least [% minPassLength %] characters.</p>
97
                            <ol>
98
                                <li><label for="password">New password:</label><input type="password" id="password" size="40" name="password" /></li>
99
                                <li><label for="repeatPassword">Confirm new password:</label><input type="password" id="repeatPassword" size="40" name="repeatPassword" /></li>
100
                            </ol>
101
                        <fieldset class="action">
102
                        <input type="hidden" name="username" value="[% username %]" />
103
                        <input type="hidden" name="uniqueKey" value="[% uniqueKey %]" />
104
                        <input type="submit" value="Submit" class="submit" name="passwordReset" />
105
                        </fieldset>
106
                     </fieldset>
107
                </form>
108
            </div>
109
    [% END %]
110
[% ELSIF (mail_sent) %]
111
    <p>A mail has been sent to "[% email %]".
112
    <br/>It contains a link to create a new password.
113
    <br/>This link will be valid for 2 days from now.</p>
114
    <br/><a href="/cgi-bin/koha/opac-main.pl"">Click here to return to the main page.</a>
115
[% ELSIF (password_reset_done) %]
116
    <p>The password has been changed for the user "[% username %]".
117
    <br/>You can now login using <a href="/cgi-bin/koha/opac-user.pl">this form</a>.</p>
118
[% END %]
119
                    </div>
120
                </div>
121
            </div>
122
        </div>
123
        <div class="yui-b">
124
            <div class="container">
125
                [% INCLUDE 'usermenu.inc' %]
126
            </div>
127
        </div>
128
    </div>
129
[% INCLUDE 'opac-bottom.inc' %]
130
</div>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-send-password-recovery.tt (+17 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
<SUBJECT>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] - Password recovery<END_SUBJECT>
6
7
<MESSAGE>
8
<html>
9
<p>This email has been sent in response to your password recovery request for the account <strong>[% username %]</strong>.</p>
10
<p>
11
You can now create your new password using the following link:
12
<br/><a href="[% uuidLink %]">[% uuidLink %]</a>
13
</p>
14
<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>
15
<p>Thank you.</p>
16
</html>
17
<END_MESSAGE>
(-)a/opac/opac-main.pl (+1 lines)
Lines 58-63 $template->param( Link Here
58
    koha_news_count     => $koha_news_count,
58
    koha_news_count     => $koha_news_count,
59
    display_daily_quote => C4::Context->preference('QuoteOfTheDay'),
59
    display_daily_quote => C4::Context->preference('QuoteOfTheDay'),
60
    daily_quote         => $quote,
60
    daily_quote         => $quote,
61
    OpacResetPassword   => C4::Context->preference('OpacResetPassword'),
61
);
62
);
62
63
63
# If GoogleIndicTransliteration system preference is On Set paramter to load Google's javascript in OPAC search screens
64
# If GoogleIndicTransliteration system preference is On Set paramter to load Google's javascript in OPAC search screens
(-)a/opac/opac-password-recovery.pl (-1 / +205 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
use strict;
4
use Modern::Perl;
5
6
use CGI;
7
use Mail::Sendmail;
8
use Digest::MD5 qw(md5_base64);
9
use HTML::Entities;
10
11
use C4::Auth;
12
use C4::Koha;
13
use C4::Members qw(changepassword GetMember GetMemberDetails SendPasswordRecoveryEmail);
14
use C4::Output;
15
use C4::Context;
16
17
my $query = new CGI;
18
19
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
20
    {
21
        template_name   => "opac-password-recovery.tmpl",
22
        query           => $query,
23
        type            => "opac",
24
        authnotrequired => 1,
25
        debug           => 1,
26
    }
27
);
28
29
my $email          = $query->param('email');
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 $errNoEmailFound;
43
my $errAlreadyStartRecovery;
44
45
#new password form error
46
my $errLinkNotValid;
47
my $errPassNotMatch;
48
my $errPassTooShort;
49
50
my $dbh = C4::Context->dbh;
51
52
$template->param( OpacResetPassword => C4::Context->preference("OpacResetPassword") );
53
54
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
55
    #send mail + confirmation
56
57
    #try with the main email
58
    my $borrower_number;
59
    my %borrower_infos = GetMember( email => $email );
60
    if (%borrower_infos) {
61
        $borrower_number = GetMember( email => $email )->{'borrowernumber'};
62
        $username = GetMemberDetails($borrower_number)->{'userid'};
63
    }
64
    else {
65
        #try with the secondary email
66
        %borrower_infos = GetMember( emailpro => $email );
67
        if (%borrower_infos) {
68
            $borrower_number = GetMember( emailpro => $email )->{'borrowernumber'};
69
            $username = GetMemberDetails($borrower_number)->{'userid'};
70
        }
71
        else {
72
            #try when the other contact email
73
            %borrower_infos = GetMember( B_email => $email );
74
            if (%borrower_infos) {
75
                $borrower_number = GetMember( B_email => $email )->{'borrowernumber'};
76
                $username = GetMemberDetails($borrower_number)->{'userid'};
77
            }
78
        }
79
    }
80
81
    if ( !$email || !$username || !$borrower_number ) {
82
        $hasError        = 1;
83
        $errNoEmailFound = 1;
84
    }
85
    elsif ( !$query->param('resendEmail') ) {
86
        my $sth = $dbh->prepare(
87
"SELECT borrowernumber FROM borrower_password_recovery WHERE NOW() < valid_until AND borrowernumber = ?"
88
        );
89
        $sth->execute($borrower_number);
90
        if ( my $already = $sth->fetchrow ) {
91
            $hasError                = 1;
92
            $errAlreadyStartRecovery = 1;
93
        }
94
    }
95
96
    if ($hasError) {
97
        $template->param(
98
            hasError                => 1,
99
            errNoEmailFound         => $errNoEmailFound,
100
            errAlreadyStartRecovery => $errAlreadyStartRecovery,
101
            password_recovery       => 1,
102
            email                   => HTML::Entities::encode($email),
103
        );
104
    }
105
    else {
106
        #generate uuid and send recovery email
107
        if ( SendPasswordRecoveryEmail( $borrower_number, $email ) ) {
108
            # if it works....
109
            $template->param(
110
                mail_sent => 1,
111
                email     => $email
112
            );
113
        }
114
        else {
115
            # if it doesnt work....
116
            $template->param(
117
                password_recovery => 1,
118
                sendmailError     => 1
119
            );
120
        }
121
    }
122
}
123
elsif ( $query->param('passwordReset') ) {
124
    #new password form
125
    #check if the link is still valid
126
    my $sth = $dbh->prepare(
127
        "SELECT borrower_password_recovery.borrowernumber, userid
128
                              FROM borrower_password_recovery, borrowers
129
                              WHERE borrowers.borrowernumber = borrower_password_recovery.borrowernumber
130
                              AND NOW() < valid_until
131
                              AND uuid = ?"
132
    );
133
    $sth->execute($uniqueKey);
134
    ( $borrower_number, $username ) = $sth->fetchrow;
135
136
    #validate password length & match
137
    if (   ($borrower_number)
138
        && ( $password eq $repeatPassword )
139
        && ( length($password) >= $minPassLength ) )
140
    {  #apply changes
141
        changepassword( $username, $borrower_number, md5_base64($password) );
142
143
        #remove entry
144
        my $sth = $dbh->prepare(
145
            "DELETE FROM borrower_password_recovery
146
                                  WHERE uuid = ?
147
                                  ORDER BY valid_until DESC LIMIT 1"
148
        );
149
        $sth->execute($uniqueKey);
150
151
        $template->param(
152
            password_reset_done => 1,
153
            username            => $username
154
        );
155
    }
156
    else { #errors
157
        if ( !$borrower_number ) { #parameters not valid
158
            $errLinkNotValid = 1;
159
        }
160
        elsif ( $password ne $repeatPassword ) { #passwords does not match
161
            $errPassNotMatch = 1;
162
        }
163
        elsif ( length($password) < $minPassLength ) { #password too short
164
            $errPassTooShort = 1;
165
        }
166
        $template->param(
167
            new_password    => 1,
168
            minPassLength   => $minPassLength,
169
            email           => $email,
170
            uniqueKey       => $uniqueKey,
171
            errLinkNotValid => $errLinkNotValid,
172
            errPassNotMatch => $errPassNotMatch,
173
            errPassTooShort => $errPassTooShort,
174
            hasError        => 1
175
        );
176
    }
177
}
178
elsif ($uniqueKey) {  #reset password form
179
    #check if the link is valid
180
    my $sth = $dbh->prepare(
181
        "SELECT borrower_password_recovery.borrowernumber, userid
182
                              FROM borrower_password_recovery, borrowers
183
                              WHERE borrowers.borrowernumber = borrower_password_recovery.borrowernumber
184
                              AND NOW() < valid_until
185
                              AND uuid = ?"
186
    );
187
    $sth->execute($uniqueKey);
188
    ( $borrower_number, $username ) = $sth->fetchrow;
189
    if ( !$borrower_number ) {
190
        $errLinkNotValid = 1;
191
    }
192
    $template->param(
193
        new_password    => 1,
194
        minPassLength   => $minPassLength,
195
        email           => $email,
196
        uniqueKey       => $uniqueKey,
197
        username        => $username,
198
        errLinkNotValid => $errLinkNotValid
199
    );
200
}
201
else { #password recovery form (to send email)
202
    $template->param( password_recovery => 1 );
203
}
204
205
output_html_with_http_headers $query, $cookie, $template->output;

Return to bug 8753