From b37ca8be14139248c2fcb553dfcecdc82388af18 Mon Sep 17 00:00:00 2001 From: Llewellyn Marshall Date: Thu, 9 Dec 2021 17:00:44 -0500 Subject: [PATCH] API call to get the age of a patron's password, this is displayed in the user editor and my opac home page. Added a configurable variable in config to set when the password reminder should show up. note for patron with expired pword get password age in staff splash check user perms for user self edit, provide button to update password if they do default config tt2 uses org unit setting for password age password changed hook fixed issues with the templates. --- Open-ILS/examples/fm_IDL.xml | 13 +++++ .../src/perlmods/lib/OpenILS/Application/Actor.pm | 56 ++++++++++++++++++++-- .../src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm | 4 ++ .../src/templates-bootstrap/opac/myopac/main.tt2 | 20 +++++++- .../src/templates-bootstrap/opac/parts/config.tt2 | 7 +++ Open-ILS/src/templates/opac/parts/config.tt2 | 8 ++++ .../src/templates/staff/circ/patron/t_edit.tt2 | 9 +++- Open-ILS/src/templates/staff/t_splash.tt2 | 11 +++++ Open-ILS/web/js/ui/default/staff/app.js | 20 +++++++- .../web/js/ui/default/staff/circ/patron/regctl.js | 14 ++++++ 10 files changed, 155 insertions(+), 7 deletions(-) diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 674ace4fc6..013ee908ee 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -2409,6 +2409,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + + + + + + + + + + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index 4298f2837d..46dda80ccf 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -525,6 +525,7 @@ sub update_patron { my $old_patron; my $barred_hook = ''; my $renew_hook = ''; + my $password_hook = ''; if($patron->isnew()) { ( $new_patron, $evt ) = _add_patron($e, _clone_patron($patron)); @@ -555,6 +556,8 @@ sub update_patron { modify_migrated_user_password($e, $patron->id, $patron->passwd); $new_patron->passwd(''); # subsequent update will set # actor.usr.passwd to MD5('') + #$U->create_events_for_hook('au.passwd_changed', $db_user, $e->requestor->ws_ou); + $password_hook = 'au.passwd_changed'; } } @@ -603,6 +606,9 @@ sub update_patron { $tses->request('open-ils.trigger.event.autocreate', $barred_hook, $new_patron, $new_patron->home_ou) if $barred_hook; + + $tses->request('open-ils.trigger.event.autocreate', $password_hook, + $new_patron, $new_patron->home_ou) if $password_hook; } $e->xact_begin; # $e->rollback is called in new_flesh_user @@ -1650,9 +1656,9 @@ sub update_passwd { # NOTE: with access to the plain text password we could crypt # the password without the extra MD5 pre-hashing. Other changes # would be required. Noting here for future reference. - modify_migrated_user_password($e, $db_user->id, $new_val); + modify_migrated_user_password($e, $db_user->id, $new_val); $db_user->passwd(''); - + $U->create_events_for_hook('au.passwd_changed', $db_user, $e->requestor->ws_ou); } else { # if we don't clear the password, the user will be updated with @@ -4427,7 +4433,8 @@ sub commit_password_reset { # All is well; update the password modify_migrated_user_password($e, $user->id, $password); - + $U->create_events_for_hook('au.passwd_changed', $user, $user->home_ou); + # And flag that this password reset request has been honoured $aupr->[0]->has_been_reset('t'); $e->update_actor_usr_password_reset($aupr->[0]); @@ -4987,6 +4994,49 @@ sub get_barcodes { return $db_result; } } + +__PACKAGE__->register_method( + method => "get_password_last_edit_age", + api_name => "open-ils.actor.get_password_age" +); + +sub get_password_last_edit_age { + my( $self, $client, $auth, $patron_id ) = @_; + my $e = new_editor(authtoken => $auth); + return $e->event unless $e->checkauth; + my $patron = $e->retrieve_actor_user($patron_id); + + #return unless the requestor is either the patron in question, or can view users at that patron's home ou + unless($patron && ($patron_id == $e->requestor->id || $e->allowed('VIEW_USER', $patron->home_ou))) { + return $e->event; + } + + #get the password dates from the virtual table + my $aupsds = $e->json_query({ + select => {aupsd => ['create_date','edit_date']}, + from => 'aupsd', + where => { + usr => $patron_id + } + }); + + if(defined $aupsds){ + my $pwd = $aupsds->[0]; + #convert the dates with the DateTime module + if($pwd){ + my $edit_datetime = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($pwd->{'edit_date'})); + #get time in days since last password update + #my $now = DateTime->today()->iso8601(); + my $now = DateTime->now(); + + my $duration = $now->subtract_datetime_absolute($edit_datetime)->delta_seconds / (24*60*60); + return int($duration); + } + } + #no password entry, return -1 days + return -1; +} + __PACKAGE__->register_method( method => 'address_alert_test', api_name => 'open-ils.actor.address_alert.test', diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm index 5763cb8e03..5b9b3205dd 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm @@ -15,6 +15,7 @@ use OpenILS::Utils::Fieldmapper; use OpenSRF::Utils::Cache; use OpenILS::Event; use DateTime::Format::ISO8601; +use Data::Dumper; use CGI qw(:all -utf8); use Time::HiRes; @@ -381,6 +382,9 @@ sub load_common { $ctx->{authtoken} = $e->authtoken; $ctx->{authtime} = $e->authtime; $ctx->{user} = $e->requestor; + $ctx->{password_age} = int($U->simplereq( + 'open-ils.actor', + 'open-ils.actor.get_password_age', $e->authtoken, $ctx->{user}->id)); my $card = $self->editor->retrieve_actor_card($ctx->{user}->card); $ctx->{active_card} = (ref $card) ? $card->barcode : undef; $ctx->{place_unfillable} = 1 if $e->requestor->wsid && $e->allowed('PLACE_UNFILLABLE_HOLD', $e->requestor->ws_ou); diff --git a/Open-ILS/src/templates-bootstrap/opac/myopac/main.tt2 b/Open-ILS/src/templates-bootstrap/opac/myopac/main.tt2 index 29b8198538..1454b4d5eb 100755 --- a/Open-ILS/src/templates-bootstrap/opac/myopac/main.tt2 +++ b/Open-ILS/src/templates-bootstrap/opac/myopac/main.tt2 @@ -14,6 +14,24 @@

[% l('My Account Summary') %]

+
+ [% IF ctx.password_age && ctx.password_age_reminder && ctx.disable_password_change != 'true' %] + [% need_password_change = ctx.password_age == -1 || ctx.password_age >= ctx.password_age_reminder %] +
+ [% IF ctx.password_age == -1 %] + You have never changed your password. Please consider updating your password. + [% ELSIF ctx.password_age >= (ctx.password_age_reminder - 7) %] + Your password is [% ctx.password_age %] days old[%- IF !need_password_change %], you will be asked to change it soon.[%- ELSE %]. We recommend passwords be updated every [% ctx.password_age_reminder %] days. Please consider updating your password.[% END %] + [% END %] + [% IF need_password_change %] +
+ [% l("Change Password") %] +
+ [% END %] +
+
+ [% END %]
[% l("Account Expiration Date - ") %] @@ -29,7 +47,7 @@ [% END %]
-
+
diff --git a/Open-ILS/src/templates-bootstrap/opac/parts/config.tt2 b/Open-ILS/src/templates-bootstrap/opac/parts/config.tt2 index 7409a4b4ec..698f2a18e4 100755 --- a/Open-ILS/src/templates-bootstrap/opac/parts/config.tt2 +++ b/Open-ILS/src/templates-bootstrap/opac/parts/config.tt2 @@ -280,4 +280,11 @@ ctx.max_cart_size = 500; ############################################################################## ctx.show_reservations_tab = 'false'; +############################################################################## +# Password Reminder Settings +############################################################################## + +# days since last password change to start reminding a patron to change their password +# commenting out this line will disable the reminder +ctx.password_age_reminder = 15; %] diff --git a/Open-ILS/src/templates/opac/parts/config.tt2 b/Open-ILS/src/templates/opac/parts/config.tt2 index eda51ad814..9de990e4e9 100644 --- a/Open-ILS/src/templates/opac/parts/config.tt2 +++ b/Open-ILS/src/templates/opac/parts/config.tt2 @@ -285,4 +285,12 @@ contents_truncate_length = 50; # Edit parts/record/contents.tt2 to designate character length on a field-by- # field basis for notes. + +############################################################################## +# Password Reminder Settings +############################################################################## + +# days since last password change to start reminding a patron to change their password +# commenting out this line will disable the reminder +ctx.password_age_reminder = ctx.get_org_setting(ctx.physical_loc || 1, 'global.password_reset_age'); %] diff --git a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 index 820e346ac3..d56e7c800f 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 @@ -222,7 +222,14 @@ within the "form" by name for validation. [% l('Generate Password') %]
- +
+
+
+
+
Password last changed {{password_age}} day(s) ago
+
User has never changed their password
+
+
+

diff --git a/Open-ILS/web/js/ui/default/staff/app.js b/Open-ILS/web/js/ui/default/staff/app.js index 58afd0664d..aa3ba9be5f 100644 --- a/Open-ILS/web/js/ui/default/staff/app.js +++ b/Open-ILS/web/js/ui/default/staff/app.js @@ -157,10 +157,26 @@ function($routeProvider , $locationProvider) { function($scope, $window,egCore) { $scope.focus_search = true; - + $scope.can_self_update = false; + egCore.strings.setPageTitle( egCore.strings['PAGE_TITLE_SPLASH']); - + egCore.org.settingsFromServer(['global.password_reset_age','global.password_regex']).then(function(settings) { + $scope.password_reset_age = parseInt(settings['global.password_reset_age']); + }); + egCore.net.request( + 'open-ils.actor', + 'open-ils.actor.get_password_age', + egCore.auth.token(), + egCore.auth.user().id() + ).then(function(age) { + $scope.password_age = parseInt(age); + }); + egCore.perm.hasPermHere('EDIT_SELF_IN_CLIENT') + .then(function(bool){ + $scope.can_self_update = bool; + $scope.self_update_link = './circ/patron/' + egCore.auth.user().id() + '/edit' + }); $scope.catalog_search = function($event) { $scope.focus_search = true; if (!$scope.cat_query) return; diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js b/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js index ac1894ce45..de023c3f98 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js @@ -30,6 +30,7 @@ angular.module('egCoreMod') // These are fetched with every instance of the page. var page_data = [ service.get_user_settings(), + service.get_user_password_age(), service.get_clone_user(), service.get_stage_user() ]; @@ -638,6 +639,18 @@ angular.module('egCoreMod') }); } + service.get_user_password_age = function() { + return egCore.net.request( + 'open-ils.actor', + 'open-ils.actor.get_password_age', + egCore.auth.token(), + service.patron_id + ).then(function(age) { + console.log("retrieved from AUSPD: "+age) + service.password_age = age; + }); + } + service.invalidate_field = function(patron, field) { console.log('Invalidating patron field ' + field); @@ -1394,6 +1407,7 @@ function($scope , $routeParams , $q , $uibModal , $window , egCore , $scope.stat_cat_entry_maps = prs.stat_cat_entry_maps; $scope.stage_user = prs.stage_user; $scope.stage_user_requestor = prs.stage_user_requestor; + $scope.password_age = prs.password_age; $scope.user_settings = prs.user_settings; prs.user_settings = {}; -- 2.11.0