Bugzilla – Attachment 129707 Details for
Bug 29924
Introduce password expiration to patron categories
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 29924: Add password expiration feature
Bug-29924-Add-password-expiration-feature.patch (text/plain), 13.69 KB, created by
Nick Clemens (kidclamp)
on 2022-01-21 17:16:24 UTC
(
hide
)
Description:
Bug 29924: Add password expiration feature
Filename:
MIME Type:
Creator:
Nick Clemens (kidclamp)
Created:
2022-01-21 17:16:24 UTC
Size:
13.69 KB
patch
obsolete
>From 461056895eeded8e1e2c9edb1bf4764fcdcd6d67 Mon Sep 17 00:00:00 2001 >From: Nick Clemens <nick@bywatersolutions.com> >Date: Fri, 21 Jan 2022 17:01:10 +0000 >Subject: [PATCH] Bug 29924: Add password expiration feature > >This patch adds the ability to define password_expiry_days for a patron category. > >When defined a patron's password will expire after X days and they will be required to >reset their password. If OPAC resets are enabled for the catgeory they may do so on their >own, otherwise they will need to contact the library > >To test: > 1 - Apply patch, updatedatabase > 2 - Set 'Password expiration' for a patron category > Home->Administration->Patron categories->Edit > 3 - Create a new patron in this category with a userid/password set, and an email > 4 - Confirm their password_expiration field is set > SELECT password_expiration FROM borrowers WHERE borrowernumber=51; > 5 - Create a new patron, do not set a password > 6 - Confirm their password_expiration field is NULL > 7 - Update the patron with an expiration to be expired > UPDATE borrowers SET password_expiration='2022-01-01' WHERE borrowernumber=51; > 8 - Give the borrower catalogue permission > 9 - Attempt to log in to Straff interface >10 - Confirm you are signed out and notified that password must be reset >11 - Attempt to sign in to OPAC >12 - Confirm you are signed out and notified password must be reset >13 - Enable password reset for the patron's category and perform a password reset > Note: you will have to find the link in the message_queue unless you have emails > setup on your test environment > SELECT * FROM message_queue WHERE borrowernumber=51; >14 - Confirm that you cna now sign in and password_expiration field is set 10 days in the future >15 - Expire the patron's password again >16 - Chaneg the patron's password via the staff interface >17 - Confirm they can sign in and the expiration is updated >--- > C4/Auth.pm | 31 +++++++++++++++++++ > Koha/Patron.pm | 20 ++++++++++++ > Koha/Patron/Category.pm | 20 ++++++++++++ > Koha/REST/V1/Auth.pm | 7 ++++- > admin/categories.pl | 3 ++ > .../prog/en/modules/admin/categories.tt | 11 +++++++ > .../intranet-tmpl/prog/en/modules/auth.tt | 7 +++++ > .../bootstrap/en/modules/opac-auth.tt | 13 ++++++-- > 8 files changed, 109 insertions(+), 3 deletions(-) > >diff --git a/C4/Auth.pm b/C4/Auth.pm >index 1cfeed48cc..29ef133d47 100644 >--- a/C4/Auth.pm >+++ b/C4/Auth.pm >@@ -278,6 +278,37 @@ sub get_template_and_user { > # FIXME What to do if $patron does not exist? > } > >+ if ($patron->password_expired) { >+ my $reset_template_name = ( $in->{type} eq 'opac' ) ? 'opac-auth.tt' : 'auth.tt'; >+ $template = C4::Templates::gettemplate( $reset_template_name, $in->{type}, >+ $in->{query} ); >+ $cookie = $in->{query}->cookie( >+ -name => 'CGISESSID', >+ -value => '', >+ -expires => '', >+ -HttpOnly => 1, >+ -secure => ( C4::Context->https_enabled() ? 1 : 0 ), >+ ); >+ >+ $template->param( >+ loginprompt => 1, >+ login => 1, >+ password_has_expired => 1, >+ script_name => get_script_name(), >+ ); >+ >+ print $in->{query}->header( >+ { >+ type => 'text/html', >+ charset => 'utf-8', >+ cookie => $cookie, >+ 'X-Frame-Options' => 'SAMEORIGIN' >+ } >+ ), >+ $template->output; >+ safe_exit; >+ } >+ > # user info > $template->param( loggedinusername => $user ); # OBSOLETE - Do not reuse this in template, use logged_in_user.userid instead > $template->param( loggedinusernumber => $borrowernumber ); # FIXME Should be replaced with logged_in_user.borrowernumber >diff --git a/Koha/Patron.pm b/Koha/Patron.pm >index 3414546ca2..4400c9946e 100644 >--- a/Koha/Patron.pm >+++ b/Koha/Patron.pm >@@ -264,6 +264,9 @@ sub store { > # Make a copy of the plain text password for later use > $self->plain_text_password( $self->password ); > >+ $self->password_expiration_date( $self->password >+ ? $self->category->get_password_expiry_date >+ : undef ); > # Create a disabled account if no password provided > $self->password( $self->password > ? Koha::AuthUtils::hash_password( $self->password ) >@@ -777,6 +780,21 @@ sub is_expired { > return 0; > } > >+=head3 password_expired >+ >+my $password_expired = $patron->password_expired; >+ >+Returns 1 if the patron's password is expired or 0; >+ >+=cut >+ >+sub password_expired { >+ my ($self) = @_; >+ return 0 unless $self->password_expiration_date; >+ return 1 if dt_from_string( $self->password_expiration_date ) < dt_from_string->truncate( to => 'day' ); >+ return 0; >+} >+ > =head3 is_going_to_expire > > my $is_going_to_expire = $patron->is_going_to_expire; >@@ -876,6 +894,8 @@ sub set_password { > > my $digest = Koha::AuthUtils::hash_password($password); > >+ $self->password_expiration_date( $self->category->get_password_expiry_date ); >+ > # We do not want to call $self->store and retrieve password from DB > $self->password($digest); > $self->login_attempts(0); >diff --git a/Koha/Patron/Category.pm b/Koha/Patron/Category.pm >index 892d00c2ae..c6837ca00f 100644 >--- a/Koha/Patron/Category.pm >+++ b/Koha/Patron/Category.pm >@@ -113,6 +113,26 @@ sub get_expiry_date { > } > } > >+=head3 get_password_expiry_date >+ >+Returns date based on password expiry days set for the category. If the value is not set >+we return undef, password does not expire >+ >+my $expiry_date = $category->get_password_expiry_date(); >+ >+=cut >+ >+sub get_password_expiry_date { >+ my ($self, $date ) = @_; >+ if ( $self->password_expiry_days ) { >+ $date ||= dt_from_string; >+ $date = dt_from_string( $date ) unless ref $date; >+ return $date->add( days => $self->password_expiry_days )->ymd; >+ } else { >+ return; >+ } >+} >+ > =head3 effective_reset_password > > Returns if patrons in this category can reset their password. If set in $self->reset_password >diff --git a/Koha/REST/V1/Auth.pm b/Koha/REST/V1/Auth.pm >index 01eef3375e..0bc12bca7c 100644 >--- a/Koha/REST/V1/Auth.pm >+++ b/Koha/REST/V1/Auth.pm >@@ -490,7 +490,12 @@ sub _basic_auth { > Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Invalid password' ); > } > >- return Koha::Patrons->find({ userid => $user_id }); >+ my $patron = Koha::Patrons->find({ userid => $user_id }); >+ if ( $patron->password_expired ) { >+ Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Password has expired' ); >+ } >+ >+ return $patron; > } > > =head3 _set_userenv >diff --git a/admin/categories.pl b/admin/categories.pl >index 368960f9cd..e41a28904d 100755 >--- a/admin/categories.pl >+++ b/admin/categories.pl >@@ -63,6 +63,7 @@ elsif ( $op eq 'add_validate' ) { > my $description = $input->param('description'); > my $enrolmentperiod = $input->param('enrolmentperiod'); > my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef; >+ my $password_expiry_days = $input->param('password_expiry_days') || undef; > my $upperagelimit = $input->param('upperagelimit'); > my $dateofbirthrequired = $input->param('dateofbirthrequired'); > my $enrolmentfee = $input->param('enrolmentfee'); >@@ -103,6 +104,7 @@ elsif ( $op eq 'add_validate' ) { > $category->description($description); > $category->enrolmentperiod($enrolmentperiod); > $category->enrolmentperioddate($enrolmentperioddate); >+ $category->password_expiry_days($password_expiry_days); > $category->upperagelimit($upperagelimit); > $category->dateofbirthrequired($dateofbirthrequired); > $category->enrolmentfee($enrolmentfee); >@@ -134,6 +136,7 @@ elsif ( $op eq 'add_validate' ) { > description => $description, > enrolmentperiod => $enrolmentperiod, > enrolmentperioddate => $enrolmentperioddate, >+ password_expiry_days => $password_expiry_days, > upperagelimit => $upperagelimit, > dateofbirthrequired => $dateofbirthrequired, > enrolmentfee => $enrolmentfee, >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt >index a5e5b8e85f..153a65941b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt >@@ -162,6 +162,10 @@ > </ol> > </fieldset> > </li> >+ <li> >+ <label for="password_expiry_days">Password expiration: </label> >+ <input type="text" name="password_expiry_days" id="password_expiry_days" value="[% category.password_expiry_days | html %]" size="3" maxlength="5" /> days >+ </li> > <li> > <label for="dateofbirthrequired">Age required: </label> > <input type="text" name="dateofbirthrequired" id="dateofbirthrequired" value="[% category.dateofbirthrequired | html %]" size="3" maxlength="3" /> years >@@ -449,6 +453,7 @@ > [% END %] > </td> > </tr> >+ <tr><th scope="row">Password expiration: </th><td>[% category.password_expiry_days | html %] days</td></tr> > <tr><th scope="row">Age required: </th><td>[% category.dateofbirthrequired | html %] years</td></tr> > <tr><th scope="row">Upperage limit: </th><td>[% category.upperagelimit | html %] years</td></tr> > <tr><th scope="row">Enrollment fee: </th><td>[% category.enrolmentfee | $Price %]</td></tr> >@@ -517,6 +522,7 @@ > <th scope="col">Category name</th> > <th scope="col">Type</th> > <th scope="col">Enrollment period</th> >+ <th scope="col">Password expiration</th> > <th scope="col">Age required</th> > <th scope="col">Upper age limit</th> > <th scope="col">Enrollment fee</th> >@@ -559,6 +565,11 @@ > until [% category.enrolmentperioddate | $KohaDates %] > [% END %] > </td> >+ [% IF (category.password_expiry_days) %] >+ <td>[% category.password_expiry_days | html %] days</td> >+ [% ELSE %] >+ <td>-</td> >+ [% END %] > [% IF (category.dateofbirthrequired) %] > <td>[% category.dateofbirthrequired | html %] years</td> > [% ELSE %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt >index 73b3761764..f750b7cd75 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt >@@ -51,6 +51,13 @@ > [% END %] > [% ELSIF invalid_username_or_password %] > <div id="login_error"><strong>Error: </strong>Invalid username or password</div> >+[% ELSIF password_has_expired %] >+ <div id="login_error"><strong>Error: </strong>Your password has expired!</div> >+ [% IF Categories.can_any_reset_password && Koha.Preference('OpacBaseURL') %] >+ <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-password-recovery.pl">You must reset your password</a>. >+ [% ELSE %] >+ <p>You must contact the library to have your password reset</p> >+ [% END %] > [% END %] > > [% IF (shibbolethAuthentication) %] >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 68b2cdad78..2b090a42a5 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt >@@ -167,7 +167,16 @@ > [% END # /IF GoogleOpenIDConnect %] > [% END # /UNLESS OPACShibOnly %] > >- [% IF !Koha.Preference('OPACShibOnly') or SCO_login or SCI_login %] >+ [% IF password_has_expired %] >+ <p class="error"><strong>Error: </strong>Your password has expired!</p> >+ [% IF Koha.Preference('OpacPasswordChange') && Categories.can_any_reset_password %] >+ <div id="resetpassword"> >+ <a href="/cgi-bin/koha/opac-password-recovery.pl">Reset your password?</a> >+ </div> >+ [% ELSE %] >+ <p>You must contact the library to reset your password</p> >+ [% END %] >+ [% ELSIF !Koha.Preference('OPACShibOnly') or SCO_login or SCI_login %] > [% IF SCO_login %] > <form action="/cgi-bin/koha/sco/sco-main.pl" name="auth" id="auth" method="post" autocomplete="off"> > [% ELSIF SCI_login %] >@@ -217,7 +226,7 @@ > [% END %] > </div> > </form> >- [% END # / IF !OPACShibOnly or SCO_login or SCI_login %] >+ [% END # / IF password_has_expired / ELSIF !OPACShibOnly or SCO_login or SCI_login %] > [% END # / IF loginprompt %] > > [% ELSE %] >-- >2.30.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 29924
:
129705
|
129706
|
129707
|
129708
|
129762
|
129763
|
129764
|
129765
|
129766
|
129823
|
129953
|
129954
|
129955
|
129956
|
129957
|
130116
|
130117
|
130118
|
130119
|
130120
|
130495
|
130500
|
130501
|
130502
|
130503
|
130504
|
130505
|
130557
|
130558
|
130559
|
130560
|
130561
|
130562
|
130563
|
130677
|
130678
|
130679
|
130680
|
130681
|
130682
|
130683
|
131128
|
132059
|
132060
|
132061
|
132062
|
132063
|
132064
|
132065
|
132066
|
132084
|
132085
|
132086
|
132087
|
132088
|
132089
|
132090
|
132091
|
132092
|
133741
|
133742
|
133743
|
133744
|
133745
|
133746
|
133747
|
133748
|
133801
|
133802
|
133803
|
133804
|
133805
|
133806
|
133807
|
133808
|
133809
|
133810
|
133989
|
134758