From c3b02dff9bf090e874016726a8d55d7256ee2bde Mon Sep 17 00:00:00 2001 From: Blou Date: Mon, 27 Jan 2014 15:53:09 -0500 Subject: [PATCH] Fixes all comments specified by mtompsett. Same testing procedure. Rebased. http://bugs.koha-community.org/show_bug.cgi?id=8753 --- C4/Auth.pm | 2 + C4/Members.pm | 94 ++++++++- installer/data/mysql/kohastructure.sql | 11 ++ installer/data/mysql/sysprefs.sql | 1 + installer/data/mysql/updatedatabase.pl | 15 ++ .../prog/en/modules/admin/preferences/opac.pref | 8 + .../opac-tmpl/bootstrap/en/includes/masthead.inc | 5 +- .../opac-tmpl/bootstrap/en/modules/opac-auth.tt | 4 + .../opac-tmpl/bootstrap/en/modules/opac-main.tt | 3 + .../bootstrap/en/modules/opac-password-recovery.tt | 132 +++++++++++++ .../en/modules/opac-send-password-recovery.tt | 19 ++ koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt | 3 + koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt | 6 +- .../prog/en/modules/opac-password-recovery.tt | 130 +++++++++++++ .../prog/en/modules/opac-send-password-recovery.tt | 17 ++ opac/opac-main.pl | 1 + opac/opac-password-recovery.pl | 203 ++++++++++++++++++++ 17 files changed, 651 insertions(+), 3 deletions(-) create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-send-password-recovery.tt create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-password-recovery.tt create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-send-password-recovery.tt create mode 100755 opac/opac-password-recovery.pl diff --git a/C4/Auth.pm b/C4/Auth.pm index 44edf67..7b1194e 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -1068,6 +1068,8 @@ sub checkauth { PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"), persona => C4::Context->preference("Persona"), opac_css_override => $ENV{'OPAC_CSS_OVERRIDE'}, + OpacResetPassword => C4::Context->preference("OpacResetPassword"), + OpacPasswordChange => C4::Context->preference("OpacPasswordChange"), ); $template->param( OpacPublic => C4::Context->preference("OpacPublic")); diff --git a/C4/Members.pm b/C4/Members.pm index 29eda68..c6fe793 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -42,6 +42,12 @@ use Koha::Borrower::Debarments qw(IsDebarred); use Text::Unaccent qw( unac_string ); use Koha::AuthUtils qw(hash_password); +## Password recovery +use CGI; +use Encode qw(encode decode); +use MIME::QuotedPrint qw(encode_qp); +use Mail::Sendmail; + our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug); BEGIN { @@ -112,7 +118,12 @@ BEGIN { push @EXPORT, qw( &ModMember &changepassword - &ModPrivacy + &ModPrivacy + ); + + # Password recovery + push @EXPORT, qw( + &SendPasswordRecoveryEmail ); #Delete data @@ -2241,6 +2252,87 @@ sub ModPrivacy { privacy => $privacy ); } +=head2 SendPasswordRecoveryEmail + + SendPasswordRecoveryEmail( $borrowernumber, $email, $query ); + +Sends email to user using template file opac-send-password-recovery.tt. +The mail contains a link to the script for password reset, with a unique key stored +in the database for validation + +$query is the CGI object, required to determine if http or https must be used + +=cut + +sub SendPasswordRecoveryEmail { + my $borrowernumber = shift; + my $email = shift; + my $query = shift; + my $dbh = C4::Context->dbh; + my $username = GetMemberDetails($borrowernumber)->{userid}; + + #generate UUID + my @chars = ("A".."Z", "a".."z", "0".."9"); + my $uuid_str; + $uuid_str .= $chars[rand @chars] for 1..32; + + #insert into database + my $expirydate = DateTime->now(time_zone => C4::Context->tz())->add( days => 2 ); + my $sth = $dbh->prepare( 'INSERT INTO borrower_password_recovery VALUES (?, ?, ?)'); + $sth->execute($borrowernumber, $uuid_str, $expirydate->ymd()); + + my $userEmail = ( $email ) ? $email : GetFirstValidEmailAddress($borrowernumber); + #define to/from emails + my $kohaEmail = C4::Context->preference( 'KohaAdminEmailAddress' ); + + #create link + my $https = $query->https() ? "https://" : "http://"; + my $uuidLink = $https . C4::Context->preference( 'OPACBaseURL' ) . "/cgi-bin/koha/opac-password-recovery.pl?uniqueKey=$uuid_str"; + #warn $uuidLink; + + #build email content + my $query = new CGI; + my ( $template2, $borrower_number, $cookie ) = C4::Auth::get_template_and_user( + { + template_name => "opac-send-password-recovery.tmpl", + query => $query, + type => "opac", + authnotrequired => 1, + } + ); + $template2->param( + uuidLink => $uuidLink, + username => $username, + ); + + # Getting template result and + my $template_res = $template2->output(); + + #Mail attributes + my %mail = ( + To => $userEmail, + From => $kohaEmail, + 'Content-Type' => 'text/html; charset=utf-8' + ); + + #getting mail properties + if ( $template_res =~ /(.*)/s ) { $mail{'subject'} = decode( 'utf-8', $1 ); } + if ( $template_res =~ /\n(.*)\n/s ) { $mail{'body'} = decode( 'utf-8', $1 ); } + #send mail + if ( sendmail %mail ) + { + # if it works.... + return 1; + } + else + { + # if it doesnt work.... + warn "Error sending mail: $Mail::Sendmail::error \n"; + return 0; + } +} + + =head2 AddMessage AddMessage( $borrowernumber, $message_type, $message, $branchcode ); diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 136104f..881db92 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -3393,6 +3393,17 @@ CREATE TABLE IF NOT EXISTS marc_modification_template_actions ( CONSTRAINT `mmta_ibfk_1` FOREIGN KEY (`template_id`) REFERENCES `marc_modification_templates` (`template_id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- Table structure for table 'borrower_password_recovery' +-- this stores the unique ID sent by email to the patron, for future validation +-- + +CREATE TABLE IF NOT EXISTS borrower_password_recovery ( + borrowernumber int(11) NOT NULL, + uuid varchar(128) NOT NULL, + valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + KEY borrowernumber (borrowernumber) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 1668d37..1ac0ad4 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -256,6 +256,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('opacreadinghistory','1','','If ON, enables display of Patron Circulation History in OPAC','YesNo'), ('OpacRenewalAllowed','0',NULL,'If ON, users can renew their issues directly from their OPAC account','YesNo'), ('OpacRenewalBranch','checkoutbranch','itemhomebranch|patronhomebranch|checkoutbranch|null','Choose how the branch for an OPAC renewal is recorded in statistics','Choice'), +('OpacResetPassword','1','','Shows the \'Forgot your password?\' link in the OPAC','YesNo'), ('OPACResultsSidebar','','70|10','Define HTML to be included on the search results page, underneath the facets sidebar','Textarea'), ('OPACSearchForTitleIn','
  • Other Libraries (WorldCat)
  • \n
  • Other Databases (Google Scholar)
  • \n
  • Online Stores (Bookfinder.com)
  • \n
  • Open Library (openlibrary.org)
  • ','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'), ('OpacSeparateHoldings','0',NULL,'Separate current branch holdings from other holdings (OPAC)','YesNo'), diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index f98daa7..5c6fdad 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -7945,6 +7945,21 @@ if (CheckVersion($DBversion)) { SetVersion($DBversion); } +$DBversion = "3.15.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do("INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OpacResetPassword','1','','Shows the ''Forgot your password?'' link in the OPAC','YesNo')"); + $dbh->do(q{ + CREATE TABLE IF NOT EXISTS borrower_password_recovery ( + borrowernumber int(11) NOT NULL, + uuid varchar(128) NOT NULL, + valid_until timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + KEY borrowernumber (borrowernumber) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + }); + print "Upgrade to $DBversion done (Bug 8753: Add forgot password link to OPAC)\n"; + SetVersion ($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index 1364ff1..66eeb56 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -557,6 +557,14 @@ OPAC: track: "Track" no: "Don't track" - links that patrons click on + - + - "The user " + - pref: OpacResetPassword + default: 1 + choices: + yes: "can reset" + no: "can not reset" + - " their password on OPAC." Shelf Browser: - diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc index 1edc244..a786069 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc +++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc @@ -278,10 +278,13 @@ [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]

    Don't have an account? Register here.

    [% END %] + [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %] +

    Forgot your password?

    + [% END %] - \ No newline at end of file + diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt index 5b5e90f..194d471 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt @@ -95,6 +95,10 @@ + [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %] +

    Forgot your password?

    + [% END %] +
    Don't have a password yet?

    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.

    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt index 5b68c19..200e1bf 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt @@ -78,6 +78,9 @@ [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]

    Don't have an account? Register here.

    [% END %] + [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %] +

    Forgot your password?

    + [% END %]
    [% END # /casAuthentication %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt new file mode 100644 index 0000000..8dd44aa --- /dev/null +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt @@ -0,0 +1,132 @@ +[% USE Koha %] +[% INCLUDE 'doc-head-open.inc' %] +[% IF (LibraryNameTitle) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › +[% INCLUDE 'doc-head-close.inc' %] +[% BLOCK cssinclude %][% END %] +[% BLOCK jsinclude %] + +[% END %] + + + +
    +
    +[% INCLUDE 'masthead.inc' %] +
    +
    +
    +
    +[% IF (!Koha.Preference('OpacResetPassword')) %] +
    You can't reset your password.
    +[% ELSIF (password_recovery) %] + [% IF (hasError) %] + + [% IF (sendmailError) %] + An error has occured while sending you the password recovery link. +
    Please try again later. + [% ELSIF (errNoEmailFound) %] + No account was found with the email address "[% email %]" +
    Check if you typed it correctly. + [% ELSIF (errTooManyEmailFound) %] + More than one account has been found for the email address: "[% email %]" +
    Try to use an alternative email if you have one. + [% ELSIF (errAlreadyStartRecovery) %] + The process of password recovery has already started for this account ("[% email %]") +
    Check your emails; you should receive the link to reset your password. +
    If you did not receive it, click here to get a new password recovery link + [% END %] +

    Please contact the staff if you need further assistance. +
    + [% END %] +
    +
    + +
    + Password recovery form: +

    To reset your password, enter your email address. +
    A link to reset your password will be sent at this address.

    +
      +
    1. +
    +
    + +
    +
    +
    +
    + +[% ELSIF (new_password) %] + [% IF (errLinkNotValid) %] +
    + We could not authenticate you as the account owner. +
    Be sure to use the link you received in your email. +
    + [% ELSE %] + [% IF (hasError) %] + + [% IF (errPassNotMatch) %] + The passwords entered does not match. +
    Please try again. + [% ELSIF (errPassTooShort) %] + The password is too short. +
    The password must contain at least [% minPassLength %] characters. + [% END %] +
    + [% END %] +
    +
    + +
    + Password recovery form: +

    The password must contain at least [% minPassLength %] characters.

    +
      +
    1. +
    2. +
    +
    + + + +
    +
    +
    +
    + [% END %] +[% ELSIF (mail_sent) %] +

    A mail has been sent to "[% email %]". +
    It contains a link to create a new password. +
    This link will be valid for 2 days starting now.

    +
    Click here to return to the main page. +[% ELSIF (password_reset_done) %] +

    The password has been changed for user "[% username %]". +
    You can now login using this form.

    +[% END %] +
    +
    +
    +
    +
    +
    + [% INCLUDE 'usermenu.inc' %] +
    +
    +
    +[% INCLUDE 'opac-bottom.inc' %] +
    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-send-password-recovery.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-send-password-recovery.tt new file mode 100644 index 0000000..85c6b7e --- /dev/null +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-send-password-recovery.tt @@ -0,0 +1,19 @@ +[% USE Koha %] +[% INCLUDE 'doc-head-open.inc' %] +[% IF (LibraryNameTitle) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › +[% INCLUDE 'doc-head-close.inc' %] +[% BLOCK cssinclude %][% END %] + +[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] - Password recovery + + + +

    This email has been sent in response to your password recovery request for the account [% username %].

    +

    +You can now create your new password using the following link: +
    [% uuidLink %] +

    +

    This link will be valid for 2 days from this email's reception, then you must reapply if you do not change your password.

    +

    Thank you.

    + + diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt index 7b8b8f9..9580668 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt @@ -85,6 +85,9 @@ please choose against which one you would like to authenticate:

    +[% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %] +

    Forgot your password?

    +[% END %]
    Don't have a password yet?

    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.

    Don't have a library card?

    If you don't have a library card, stop by your local library to sign up[% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %] or register here[% END %].

    diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt index eb1e600..5d66aa2 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt @@ -60,7 +60,11 @@ [% IF PatronSelfRegistration && PatronSelfRegistrationDefaultCategory %]
    Don't have an account? Register here.
    [% END %] - + + [% IF Koha.Preference('OpacPasswordChange') && Koha.Preference('OpacResetPassword') %] +

    Forgot your password?

    + [% END %] +
    [% END %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-password-recovery.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-password-recovery.tt new file mode 100644 index 0000000..1c650c6 --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-password-recovery.tt @@ -0,0 +1,130 @@ +[% USE Koha %] +[% INCLUDE 'doc-head-open.inc' %] +[% IF (LibraryNameTitle) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › +[% INCLUDE 'doc-head-close.inc' %] + + + + + +
    +
    +[% INCLUDE 'masthead.inc' %] +
    +
    +
    +
    +[% IF (!Koha.Preference('OpacResetPassword')) %] +
    You can't reset your password.
    +[% ELSIF (password_recovery) %] + [% IF (hasError) %] + + [% IF (sendmailError) %] + An error has occured while sending you the password recovery link. +
    Please try again later. + [% ELSIF (errNoEmailFound) %] + No account was found with the email address "[% email %]" +
    Check if you typed it correctly. + [% ELSIF (errTooManyEmailFound) %] + More than one account has been found for the email address: "[% email %]" +
    Try to use your alternative email if you have one. + [% ELSIF (errAlreadyStartRecovery) %] + The process of password recovery has already started for this account ("[% email %]") +
    Check your emails; you should receive the link to reset your password. +
    If you didn't receive it, click here to get a new password recovery link + [% END %] +

    Please contact the staff if you need further assistance. +
    + [% END %] +
    +
    + +
    + Password recovery form: +

    To reset your password, enter your email address. +
    A link to reset your password will be sent at this address.

    +
      +
    1. +
    +
    + +
    +
    +
    +
    + +[% ELSIF (new_password) %] + [% IF (errLinkNotValid) %] +
    + We could not authenticate you as the account owner. +
    Be sure to use the link you received in your email. +
    + [% ELSE %] + [% IF (hasError) %] + + [% IF (errPassNotMatch) %] + The passwords entered does not match. +
    Please try again. + [% ELSIF (errPassTooShort) %] + The password is too short. +
    The password must contain at least [% minPassLength %] characters. + [% END %] +
    + [% END %] +
    +
    + +
    + Password recovery form: +

    The password must contain at least [% minPassLength %] characters.

    +
      +
    1. +
    2. +
    +
    + + + +
    +
    +
    +
    + [% END %] +[% ELSIF (mail_sent) %] +

    A mail has been sent to "[% email %]". +
    It contains a link to create a new password. +
    This link will be valid for 2 days starting now.

    +
    Click here to return to the main page. +[% ELSIF (password_reset_done) %] +

    The password has been changed for user "[% username %]". +
    You can now login using this form.

    +[% END %] +
    +
    +
    +
    +
    +
    + [% INCLUDE 'usermenu.inc' %] +
    +
    +
    +[% INCLUDE 'opac-bottom.inc' %] +
    diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-send-password-recovery.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-send-password-recovery.tt new file mode 100644 index 0000000..8b1cd73 --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-send-password-recovery.tt @@ -0,0 +1,17 @@ +[% USE Koha %] +[% INCLUDE 'doc-head-open.inc' %] +[% IF (LibraryNameTitle) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › +[% INCLUDE 'doc-head-close.inc' %] +[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] - Password recovery + + + +

    This email has been sent in response to your password recovery request for the account [% username %].

    +

    +You can now create your new password using the following link: +
    [% uuidLink %] +

    +

    This link will be valid for 2 days from this email's reception, then you must reapply if you do not change your password.

    +

    Thank you.

    + + diff --git a/opac/opac-main.pl b/opac/opac-main.pl index 7c6ee36..15dc8cd 100755 --- a/opac/opac-main.pl +++ b/opac/opac-main.pl @@ -58,6 +58,7 @@ $template->param( koha_news_count => $koha_news_count, display_daily_quote => C4::Context->preference('QuoteOfTheDay'), daily_quote => $quote, + OpacResetPassword => C4::Context->preference('OpacResetPassword'), ); # If GoogleIndicTransliteration system preference is On Set paramter to load Google's javascript in OPAC search screens diff --git a/opac/opac-password-recovery.pl b/opac/opac-password-recovery.pl new file mode 100755 index 0000000..197234e --- /dev/null +++ b/opac/opac-password-recovery.pl @@ -0,0 +1,203 @@ +#!/usr/bin/perl + +use strict; +use Modern::Perl; + +use CGI; +use Mail::Sendmail; +use Digest::MD5 qw(md5_base64); +use HTML::Entities; + +use C4::Auth; +use C4::Koha; +use C4::Members qw(changepassword GetMember GetMemberDetails SendPasswordRecoveryEmail); +use C4::Output; +use C4::Context; + +my $query = new CGI; + +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( + { + template_name => "opac-password-recovery.tmpl", + query => $query, + type => "opac", + authnotrequired => 1, + debug => 1, + } +); + +my $email = $query->param('email'); +my $password = $query->param('password'); +my $repeatPassword = $query->param('repeatPassword'); +my $minPassLength = C4::Context->preference('minPasswordLength'); +my $id = $query->param('id'); +my $uniqueKey = $query->param('uniqueKey'); +my $username = $query->param('username'); +my $borrower_number; + +#errors +my $hasError; + +#email form error +my $errNoEmailFound; +my $errAlreadyStartRecovery; + +#new password form error +my $errLinkNotValid; +my $errPassNotMatch; +my $errPassTooShort; + +my $dbh = C4::Context->dbh; + +if ( $query->param('sendEmail') || $query->param('resendEmail') ) { + #send mail + confirmation + + #try with the main email + my $borrower_number; + my %borrower_infos = GetMember( email => $email ); + if (%borrower_infos) { + $borrower_number = GetMember( email => $email )->{'borrowernumber'}; + $username = GetMemberDetails($borrower_number)->{'userid'}; + } + else { + #try with the secondary email + %borrower_infos = GetMember( emailpro => $email ); + if (%borrower_infos) { + $borrower_number = GetMember( emailpro => $email )->{'borrowernumber'}; + $username = GetMemberDetails($borrower_number)->{'userid'}; + } + else { + #try when the other contact email + %borrower_infos = GetMember( B_email => $email ); + if (%borrower_infos) { + $borrower_number = GetMember( B_email => $email )->{'borrowernumber'}; + $username = GetMemberDetails($borrower_number)->{'userid'}; + } + } + } + + if ( !$email || !$username || !$borrower_number ) { + $hasError = 1; + $errNoEmailFound = 1; + } + elsif ( !$query->param('resendEmail') ) { + my $sth = $dbh->prepare( +"SELECT borrowernumber FROM borrower_password_recovery WHERE NOW() < valid_until AND borrowernumber = ?" + ); + $sth->execute($borrower_number); + if ( my $already = $sth->fetchrow ) { + $hasError = 1; + $errAlreadyStartRecovery = 1; + } + } + + if ($hasError) { + $template->param( + hasError => 1, + errNoEmailFound => $errNoEmailFound, + errAlreadyStartRecovery => $errAlreadyStartRecovery, + password_recovery => 1, + email => HTML::Entities::encode($email), + ); + } + else { + #generate uuid and send recovery email + if ( SendPasswordRecoveryEmail( $borrower_number, $email, $query ) ) { + # if it works.... + $template->param( + mail_sent => 1, + email => $email + ); + } + else { + # if it doesnt work.... + $template->param( + password_recovery => 1, + sendmailError => 1 + ); + } + } +} +elsif ( $query->param('passwordReset') ) { + #new password form + #check if the link is still valid + my $sth = $dbh->prepare( + "SELECT borrower_password_recovery.borrowernumber, userid + FROM borrower_password_recovery, borrowers + WHERE borrowers.borrowernumber = borrower_password_recovery.borrowernumber + AND NOW() < valid_until + AND uuid = ?" + ); + $sth->execute($uniqueKey); + ( $borrower_number, $username ) = $sth->fetchrow; + + #validate password length & match + if ( ($borrower_number) + && ( $password eq $repeatPassword ) + && ( length($password) >= $minPassLength ) ) + { #apply changes + changepassword( $username, $borrower_number, md5_base64($password) ); + + #remove entry + my $sth = $dbh->prepare( + "DELETE FROM borrower_password_recovery + WHERE uuid = ? + ORDER BY valid_until DESC LIMIT 1" + ); + $sth->execute($uniqueKey); + + $template->param( + password_reset_done => 1, + username => $username + ); + } + else { #errors + if ( !$borrower_number ) { #parameters not valid + $errLinkNotValid = 1; + } + elsif ( $password ne $repeatPassword ) { #passwords does not match + $errPassNotMatch = 1; + } + elsif ( length($password) < $minPassLength ) { #password too short + $errPassTooShort = 1; + } + $template->param( + new_password => 1, + minPassLength => $minPassLength, + email => $email, + uniqueKey => $uniqueKey, + errLinkNotValid => $errLinkNotValid, + errPassNotMatch => $errPassNotMatch, + errPassTooShort => $errPassTooShort, + hasError => 1 + ); + } +} +elsif ($uniqueKey) { #reset password form + #check if the link is valid + my $sth = $dbh->prepare( + "SELECT borrower_password_recovery.borrowernumber, userid + FROM borrower_password_recovery, borrowers + WHERE borrowers.borrowernumber = borrower_password_recovery.borrowernumber + AND NOW() < valid_until + AND uuid = ?" + ); + $sth->execute($uniqueKey); + ( $borrower_number, $username ) = $sth->fetchrow; + if ( !$borrower_number ) { + $errLinkNotValid = 1; + } + $template->param( + new_password => 1, + minPassLength => $minPassLength, + email => $email, + uniqueKey => $uniqueKey, + username => $username, + errLinkNotValid => $errLinkNotValid + ); +} +else { #password recovery form (to send email) + $template->param( password_recovery => 1 ); +} + +output_html_with_http_headers $query, $cookie, $template->output; -- 1.7.10.4