Web UI password is going to expire in n days notification

This patch adds pending password expiration notification support to Web UI. When user's password is going to expire in less or equal than configure days a bold red text 'Your password expires in N days.' and a link 'Reset your password' are shown in Web UI's header (on the left next to 'Logged in as...').

Clicking on 'Reset your password link' opens IPA.user_password_dialog. Successful reset of own password will reload user's information (whoami) and update header (it will most likely hide the warning and link).

https://fedorahosted.org/freeipa/ticket/2625
This commit is contained in:
Petr Vobornik 2012-06-26 16:19:58 +02:00
parent a6ff85f425
commit 5b7084aeb5
8 changed files with 217 additions and 45 deletions

View File

@ -125,7 +125,7 @@ IPA.section_builder = function(spec) {
section_spec.entity = that.container.entity;
section_spec.facet = that.container;
if (!section_spec.label && section_spec.name) {
if (!section_spec.label && section_spec.name && that.container.entity) {
var obj_messages = IPA.messages.objects[that.container.entity.name];
section_spec.label = obj_messages[section_spec.name];
}

View File

@ -70,6 +70,7 @@
<a href="#"><img src="images/ipa-logo.png" /><img src="images/ipa-banner.png" /></a>
</span>
<span class="header-right">
<span class="header-passwordexpires"></span>
<span id="loggedinas" class="header-loggedinas">
<a href="#"><span id="login_header">Logged in as</span>: <strong>user@FREEIPA.ORG</strong></a>
</span>

View File

@ -240,6 +240,18 @@ body {
border: 0;
}
/* ---- Password expiration */
.header-passwordexpires {
margin-right: 30px;
color: red;
font-weight: bold;
}
.header-passwordexpires a {
font-weight: bold;
}
/* ---- Logged-in As ---- */
.header-right {
float: right;

View File

@ -116,18 +116,15 @@ var IPA = function() {
}));
batch.add_command(IPA.command({
entity: 'user',
method: 'find',
options: {
whoami: true,
all: true
},
entity: 'config',
method: 'show',
on_success: function(data, text_status, xhr) {
that.whoami = data.result[0];
that.principal = that.whoami.krbprincipalname[0];
that.server_config = data.result;
}
}));
batch.add_command(that.get_whoami_command(true));
batch.add_command(IPA.command({
method: 'env',
on_success: function(data, text_status, xhr) {
@ -144,9 +141,27 @@ var IPA = function() {
}
}));
batch.execute();
};
that.get_whoami_command = function(batch) {
return IPA.command({
entity: 'user',
method: 'find',
options: {
whoami: true,
all: true
},
on_success: function(data, text_status, xhr) {
that.whoami = batch ? data.result[0] : data.result.result[0];
that.principal = that.whoami.krbprincipalname[0];
that.update_password_expiration();
}
});
};
that.init_metadata = function(params) {
var objects = IPA.command({
@ -459,6 +474,86 @@ IPA.reset_password = function(username, old_password, new_password) {
return result;
};
IPA.update_password_expiration = function() {
var now, expires, notify_days, diff, message, container;
expires = IPA.whoami.krbpasswordexpiration;
expires = expires ? IPA.parse_utc_date(expires[0]) : null;
notify_days = IPA.server_config.ipapwdexpadvnotify;
notify_days = notify_days ? notify_days[0] : 0;
now = new Date();
container = $('.header-passwordexpires');
container.empty();
if (expires) {
diff = expires.getTime() - now.getTime();
diff = Math.floor(diff / 86400000);
if (diff <= notify_days) {
message = IPA.messages.password.expires_in;
message = message.replace('${days}', diff);
container.append(message + ' ');
$('<a/>', {
href: '#reset-password',
click: function() {
IPA.password_selfservice();
return false;
},
text: IPA.messages.password.reset_password_sentence,
title: IPA.messages.password.reset_password
}).appendTo(container);
}
}
};
IPA.password_selfservice = function() {
var reset_dialog = IPA.user_password_dialog({
self_service: true,
on_success: function() {
var command = IPA.get_whoami_command();
command.execute();
alert(IPA.messages.password.password_change_complete);
reset_dialog.close();
}
});
reset_dialog.open();
};
IPA.parse_utc_date = function(value) {
if (!value) return null;
// verify length
if (value.length != 'YYYYmmddHHMMSSZ'.length) {
return null;
}
// We only handle GMT
if (value.charAt(value.length -1) !== 'Z') {
return null;
}
var date = new Date();
date.setUTCFullYear(
value.substring(0, 4), // YYYY
value.substring(4, 6)-1, // mm (0-11)
value.substring(6, 8)); // dd (1-31)
date.setUTCHours(
value.substring(8, 10), // HH (0-23)
value.substring(10, 12), // MM (0-59)
value.substring(12, 14)); // SS (0-59)
return date;
};
/**
* Call an IPA command over JSON-RPC.
*

View File

@ -439,6 +439,7 @@
"password": {
"current_password": "Current Password",
"current_password_required": "Current password is required",
"expires_in": "Your password expires in ${days} days.",
"invalid_password": "The password or username you entered is incorrect.",
"new_password": "New Password",
"new_password_required": "New password is required",
@ -447,6 +448,7 @@
"password_must_match": "Passwords must match",
"reset_failure": "Password reset was not successful.",
"reset_password": "Reset Password",
"reset_password_sentence": "Reset your password.",
"verify_password": "Verify Password"
},
"search": {
@ -499,6 +501,59 @@
}
}
},
{
"error": null,
"result": {
"dn": "cn=ipaconfig,cn=etc,dc=test,dc=example,dc=com",
"ipacertificatesubjectbase": [
"O=EXAMPLE.COM"
],
"ipaconfigstring": [
"AllowNThash"
],
"ipadefaultemaildomain": [
"example.com"
],
"ipadefaultloginshell": [
"/bin/sh"
],
"ipadefaultprimarygroup": [
"ipausers"
],
"ipagroupsearchfields": [
"cn,description"
],
"ipahomesrootdir": [
"/home"
],
"ipamaxusernamelength": [
"32"
],
"ipamigrationenabled": [
"FALSE"
],
"ipapwdexpadvnotify": [
"4"
],
"ipasearchrecordslimit": [
"100"
],
"ipasearchtimelimit": [
"2"
],
"ipaselinuxusermapdefault": [
"guest_u:s0"
],
"ipaselinuxusermaporder": [
"guest_u:s0$xguest_u:s0$user_u:s0-s0:c0.c1023$staff_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023"
],
"ipausersearchfields": [
"uid,givenname,sn,telephonenumber,ou,title"
]
},
"summary": null,
"value": ""
},
{
"count": 1,
"error": null,
@ -534,7 +589,7 @@
"20120110142413Z"
],
"krbpasswordexpiration": [
"20111212052109Z"
"20141212052109Z"
],
"krbprincipalname": [
"admin@DEV.EXAMPLE.COM"

View File

@ -503,9 +503,18 @@ IPA.user_password_dialog = function(spec) {
});
var that = IPA.dialog(spec);
that.success_handler = spec.on_success;
that.error_handler = spec.on_error;
that.self_service = spec.self_service; //option to force self-service
that.get_pkey = function() {
return IPA.nav.get_state('user-pkey');
var pkey;
if (that.self_service) {
pkey = IPA.whoami.uid[0];
} else {
pkey = IPA.nav.get_state('user-pkey');
}
return pkey;
};
that.is_self_service = function() {
@ -575,17 +584,8 @@ IPA.user_password_dialog = function(spec) {
pkey,
current_password,
new_password,
function(data, text_status, xhr) {
alert(IPA.messages.password.password_change_complete);
that.close();
// refresh password expiration field
var facet = IPA.current_entity.get_facet();
facet.refresh();
},
function(xhr, text_status, error_thrown) {
that.close();
}
);
that.on_reset_success,
that.on_reset_error);
};
that.set_password = function(pkey, current_password, password, on_success, on_error) {
@ -604,6 +604,34 @@ IPA.user_password_dialog = function(spec) {
command.execute();
};
that.on_reset_success = function(data, text_status, xhr) {
if (that.success_handler) {
that.success_handler.call(this, data, text_status, xhr);
} else {
alert(IPA.messages.password.password_change_complete);
that.close();
// refresh password expiration field
var facet = IPA.current_entity.get_facet();
facet.refresh();
if (that.is_self_service()) {
var command = IPA.get_whoami_command();
command.execute();
}
}
};
that.on_reset_error = function(xhr, text_status, error_thrown) {
if (that.error_handler) {
that.error_handler.call(this, xhr, text_status, error_thrown);
} else {
that.close();
}
};
that.create_buttons();
return that;

View File

@ -1125,29 +1125,8 @@ IPA.utc_date_formatter = function(spec) {
that.format = function(value) {
if (!value) return '';
// verify length
if (value.length != 'YYYYmmddHHMMSSZ'.length) {
return value;
}
/* We only handle GMT */
if (value.charAt(value.length -1) !== 'Z') {
return value;
}
var date = new Date();
date.setUTCFullYear(
value.substring(0, 4), // YYYY
value.substring(4, 6)-1, // mm (0-11)
value.substring(6, 8)); // dd (1-31)
date.setUTCHours(
value.substring(8, 10), // HH (0-23)
value.substring(10, 12), // MM (0-59)
value.substring(12, 14)); // SS (0-59)
var date = IPA.parse_utc_date(value);
if (!date) return value;
return date.toString();
};

View File

@ -578,6 +578,7 @@ class i18n_messages(Command):
"password": {
"current_password": _("Current Password"),
"current_password_required": _("Current password is required"),
"expires_in": _("Your password expires in ${days} days."),
"invalid_password": _("The password or username you entered is incorrect."),
"new_password": _("New Password"),
"new_password_required": _("New password is required"),
@ -586,6 +587,7 @@ class i18n_messages(Command):
"password_must_match": _("Passwords must match"),
"reset_failure": _("Password reset was not successful."),
"reset_password": _("Reset Password"),
"reset_password_sentence": _("Reset your password."),
"verify_password": _("Verify Password"),
},
"search": {