</actions>
</permacrud>
</class>
- <class id="aupsd" controller="open-ils.cstore" oils_obj:fieldmapper="action::usr_password_set_date" reporter:label="User Password Set Date" oils_persist:readonly="true">
+ <class id="aupsd" controller="open-ils.cstore" oils_obj:fieldmapper="actor::usr_password_set_date" reporter:label="User Password Set Date" oils_persist:readonly="true">
<oils_persist:source_definition><![CDATA[
SELECT usr,create_date,edit_date FROM actor.passwd
]]></oils_persist:source_definition>
__PACKAGE__->register_method(
method => "get_password_last_edit_age",
- api_name => "open-ils.actor.get_password_age"
+ api_name => "open-ils.actor.get_password_age",
+ signature => {
+ desc => "Finds the number of days since a user's password was last updated.",
+ params => [
+ {desc => 'Authentication token', type => 'string'},
+ {desc => 'Patron ID', type => 'number'},
+ {desc => 'Reference Time', type => 'string'},
+ ],
+ return => {desc => 'Number of days since password update'}
+ }
);
sub get_password_last_edit_age {
- my( $self, $client, $auth, $patron_id ) = @_;
+ my( $self, $client, $auth, $patron_id, $ref_time ) = @_;
my $e = new_editor(authtoken => $auth);
return $e->event unless $e->checkauth;
my $patron = $e->retrieve_actor_user($patron_id);
});
if(defined $aupsds){
- my $pwd = $aupsds->[0];
- #convert the dates with the DateTime module
+ my $pwd = $aupsds->[0];
if($pwd){
+ #convert the dates with the DateTime module
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();
+ #get the time we are subtracting from, use ref_time if it's defined or the current datetime otherwise
+ my $now = defined($ref_time) ? DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($ref_time)) : DateTime->now();
my $duration = $now->subtract_datetime_absolute($edit_datetime)->delta_seconds / (24*60*60);
return int($duration);
--- /dev/null
+#!perl
+use constant FUTURE_DAYS => 150;
+use strict; use warnings;
+use Test::More tests => 4;
+use OpenILS::Utils::TestUtils;
+use OpenILS::Const qw(:const);
+use OpenILS::Utils::CStoreEditor qw/:funcs/;
+use OpenILS::Utils::Fieldmapper;
+use DateTime;
+use DateTime::Format::ISO8601;
+
+diag("test password age");
+
+my $U = 'OpenILS::Application::AppUtils';
+
+my $script = OpenILS::Utils::TestUtils->new();
+$script->bootstrap;
+
+$script->authenticate({
+ username => 'admin',
+ password => 'demo123',
+ type => 'staff'
+});
+
+my $authtoken = $script->authtoken;
+ok($authtoken, 'was able to authenticate');
+
+my $new_user = Fieldmapper::actor::user->new();
+my $new_card = Fieldmapper::actor::card->new();
+
+$new_card->barcode("lew_$$");
+$new_card->id(-1); # virtual ID
+$new_card->usr(undef);
+$new_card->isnew(1);
+
+$new_user->cards([ $new_card ]);
+$new_user->card($new_card);
+$new_user->usrname("lew_$$");
+$new_user->passwd('lew_$$');
+$new_user->family_name('Marshall');
+$new_user->first_given_name('Llewellyn');
+$new_user->profile(2);
+$new_user->home_ou(4);
+$new_user->ident_type(1);
+$new_user->isnew(1);
+
+my $resp = $U->simplereq(
+ 'open-ils.actor',
+ 'open-ils.actor.patron.update',
+ $authtoken,
+ $new_user
+);
+
+isa_ok($resp, 'Fieldmapper::actor::user', 'new patron');
+
+my $new_id = $resp->id();
+
+$resp = $U->simplereq(
+ 'open-ils.actor',
+ 'open-ils.actor.get_password_age',
+ $authtoken,
+ $new_id
+);
+
+cmp_ok($resp, '==', 0, 'Password age on new user is 0 days');
+
+my $dt = DateTime->now();
+
+$dt->add( days => FUTURE_DAYS );
+
+$resp = $U->simplereq(
+ 'open-ils.actor',
+ 'open-ils.actor.get_password_age',
+ $authtoken,
+ $new_id,
+ $dt->iso8601()
+);
+
+cmp_ok($resp, '==', FUTURE_DAYS, FUTURE_DAYS." days from now, Password age on new user is ".FUTURE_DAYS." days");
+
+# clean up
+$U->simplereq(
+ 'open-ils.actor',
+ 'open-ils.actor.user.delete',
+ $authtoken,
+ $new_id
+);
\ No newline at end of file
aout.name = 'Consortium' AND
(perm.code = 'ADMIN_GEOLOCATION_SERVICES' OR perm.code = 'VIEW_GEOLOCATION_SERVICES');
+-- Password age reset
+
+INSERT INTO config.org_unit_setting_type
+ (name, grp, label, description, datatype)
+ VALUES (
+ 'global.password_reset_age',
+ 'glob',
+ oils_i18n_gettext(
+ 'global.password_reset_age',
+ 'Password Reset Age',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'global.password_reset_age',
+ 'The number of days after a password has been changed before ' ||
+ 'users will be alerted that they should update it.',
+ 'coust',
+ 'description'
+ ),
+ 'integer'
+ );
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+ 'au.passwd_changed',
+ 'au',
+ 'A user\'s password was updated',
+ false
+);
+
+INSERT INTO action_trigger.validator (module, description) VALUES (
+ 'PatronOldPassword', 'Confirm that the patron has not updated their password since this event was created.'
+);
+
------------------- Disabled example A/T defintions ------------------------------
-- Create a "dummy" slot when applicable, and trigger the "offer curbside" events
--- /dev/null
+BEGIN;
+
+--SELECT evergreen.upgrade_deps_block_check('xxxx', :eg_version);
+
+-- password age display setting
+
+INSERT INTO config.org_unit_setting_type
+ (name, grp, label, description, datatype)
+ VALUES (
+ 'global.password_reset_age',
+ 'glob',
+ oils_i18n_gettext(
+ 'global.password_reset_age',
+ 'Password Reset Age',
+ 'coust',
+ 'label'
+ ),
+ oils_i18n_gettext(
+ 'global.password_reset_age',
+ 'The number of days after a password has been changed before ' ||
+ 'users will be alerted that they should update it.',
+ 'coust',
+ 'description'
+ ),
+ 'integer'
+ );
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+ 'au.passwd_changed',
+ 'au',
+ 'A user\'s password was updated',
+ false
+);
+
+INSERT INTO action_trigger.validator (module, description) VALUES (
+ 'PatronOldPassword', 'Confirm that the patron has not updated their password since this event was created.'
+);
+
+--ROLLBACK;
+COMMIT;
\ No newline at end of file
[% need_password_change = ctx.password_age == -1 || ctx.password_age >= ctx.password_age_reminder %]
<div class="col-12">
[% IF ctx.password_age == -1 %]
- You have never changed your password. Please consider updating your password.
+ [% l('You have never changed your password. Please consider updating your password.') %]
[% ELSIF ctx.password_age >= (ctx.password_age_reminder - 7) %]
- Your password is <b>[% ctx.password_age %]</b> days old[%- IF !need_password_change %], you will be asked to change it soon.[%- ELSE %]. We recommend passwords be updated every <b>[% ctx.password_age_reminder %]</b> days. Please consider updating your password.[% END %]
+ [% l('Your password is <b>[_1]</b> days old.',ctx.password_age) %][%- IF !need_password_change %] [% l('You will be asked to change your password soon.') %][%- ELSE %] [% l('It is recommended to update your password every <b>[_1]</b> days. Please consider updating your password.',ctx.password_age_reminder) %][% END %]
[% END %]
[% IF need_password_change %]
<br>
<div class="col-md-3">
</div>
<div class="col-md-9">
- <div ng-show="password_age !== undefined && password_age !== '' && password_age !== '-1'"><i>Password last changed <b>{{password_age}}</b> day(s) ago</i></div>
- <div ng-show="password_age === '-1'"><i>User has never changed their password</i></div>
+ <div ng-show="password_age !== undefined && password_age !== '' && password_age !== '-1'"><i>[% l('Password last changed <b>[_1]</b> day(s) ago', '{{password_age}}') %]</i></div>
+ <div ng-show="password_age === '-1'"><i>[% l('User has never changed their password') %]</i></div>
</div>
</div>
<div class="row reg-field-row">
<h1 class="sr-only" i18n>Evergreen Staff Client Home Page</h1>
</div>
</div>
- <div ng-if="password_reset_age && password_age >= password_reset_age" class="alert alert-danger row">Your password is <b>{{password_age}} days</b> old. It is recommended that passwords be updated every <b>{{password_reset_age}} days</b>.
+ <div ng-if="password_reset_age && password_age >= (password_reset_age - 7)" class="alert alert-danger row">[% l('Your password is <b>[_1] days</b> old. It is recommended that passwords be updated every <b>[_2] days</b>.','{{password_age}}','{{password_reset_age}}') %]
<p ng-if="!can_self_update">
- Please contact an adminstrator to have your password changed.
+ [% l('Please contact an administrator to have your password changed.') %]
</p>
<div ng-if="can_self_update">
<br>
<a class="btn btn-warning btn-block" target="_top" href="{{self_update_link}}">
- Update Password
+ [% l('Update Password') %]
</a>
</div>
</div>
service.org_settings = settings;
if (egCore && egCore.env && !egCore.env.aous) {
egCore.env.aous = settings;
- console.log('setting egCore.env.aous');
}
return service.process_org_settings(settings);
});