On 06/27/2012 04:33 PM, Petr Vobornik wrote:
On 06/27/2012 03:54 AM, Endi Sukma Dewata wrote:
On 6/26/2012 9:46 AM, Petr Vobornik wrote:
This is patch is more like a draft.

I'm not sure where to display the 'password is going to expire'
notification.

I was deciding between:
1) red bold text in Web UI header
2) popup dialog after Web UI initialization

I don't like unwanted pop-up dialogs so I used first option.

If we only support 1 short message I'd prefer option #1. Some users
might not want to reset the password immediately, so they need to be
constantly reminded about the password expiration.

If the message is too long, or we want to support multiple messages (not
just for password expiration), we can show a message icon like in the
upper right corner of Fedora desktop. When you click it it will open a
dialog box listing all messages. In this dialog you can delete each
message. The icon will disappear only if there's no message left.

I didn't make a 'password reset link' because it is done in user's
detail page and a link there is right next to this notification.

I'd say the message should include a link, something like this:

Your password will expire in n days. [Reset your password].

The link is important because:

* Without the link the message doesn't tell you what to do or how
to reset the password.
* Users might not realize that the [Logged In As: <user>] is a link
that can bring them to their profile page.
* Even if they're in the right page, they might not know there's a
reset password link in the action panel.

The [Reset your password] link can open the Password Reset dialog for
the current user, regardless of the current page. To avoid confusion the
dialog probably should be changed to show the username of the user being
updated.

What do you think?


I like it.

I'll add the reset link next to the message. If we encounter more cases
we can moved it to the notification icon functionality.

I found more non-existing options used and also #2876. I'll return to
this ticket when I fix these regression.

Here's an updated version.

It displays the warning with reset link next to it. I slightly modified user_password_dialog to be usable alone.

--
Petr Vobornik
From d85cb42d30b27904cc1afa1ae416c78c1ca6985a Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Tue, 26 Jun 2012 16:19:58 +0200
Subject: [PATCH] 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
---
 install/ui/details.js              |    2 +-
 install/ui/index.html              |    1 +
 install/ui/ipa.css                 |   12 ++++
 install/ui/ipa.js                  |  111 +++++++++++++++++++++++++++++++++---
 install/ui/test/data/ipa_init.json |   57 ++++++++++++++++++-
 install/ui/user.js                 |   52 +++++++++++++----
 install/ui/widget.js               |   25 +--------
 ipalib/plugins/internal.py         |    2 +
 8 files changed, 217 insertions(+), 45 deletions(-)

diff --git a/install/ui/details.js b/install/ui/details.js
index 65de284423698bd6f8288fe5f84759d56a47d1b0..618d02f573e38f2573b532440265ff934e91f8c3 100644
--- a/install/ui/details.js
+++ b/install/ui/details.js
@@ -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];
         }
diff --git a/install/ui/index.html b/install/ui/index.html
index 653704b7bca323febb7c5874e24b47034f9c898e..33c0923c197d53824d79591488b18dda2ea90ad2 100644
--- a/install/ui/index.html
+++ b/install/ui/index.html
@@ -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>u...@freeipa.org</strong></a>
                 </span>
diff --git a/install/ui/ipa.css b/install/ui/ipa.css
index c0cec89a44532e22103474910ae18110597d76ac..dac345ac39c92c30aa6b8c9754eb325c41152c28 100644
--- a/install/ui/ipa.css
+++ b/install/ui/ipa.css
@@ -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;
diff --git a/install/ui/ipa.js b/install/ui/ipa.js
index f0ad01c3215291fe308d8729e66c9202d3a1c248..aadea8d2af07c1d0c7f5ae1b8168a36966c546c5 100644
--- a/install/ui/ipa.js
+++ b/install/ui/ipa.js
@@ -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.
  *
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 6621fe56f1d43f9ac0e2caba30375dbe8416bdea..85ff9366ce4ad293b95829d864653561a55d6429 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -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": {
@@ -500,6 +502,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,
                 "result": [
@@ -534,7 +589,7 @@
                             "20120110142413Z"
                         ],
                         "krbpasswordexpiration": [
-                            "20111212052109Z"
+                            "20141212052109Z"
                         ],
                         "krbprincipalname": [
                             "ad...@dev.example.com"
diff --git a/install/ui/user.js b/install/ui/user.js
index c9835c9c0219320a1504431abcbef8d85595cca0..02f6f73e45e50b8c5501ccad57209a681100082d 100644
--- a/install/ui/user.js
+++ b/install/ui/user.js
@@ -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;
diff --git a/install/ui/widget.js b/install/ui/widget.js
index 503897554421ac71b6a6bad5a7074ff32d34ec55..a55cc347f49cc2e61f00422f12c47ab4c1c70449 100644
--- a/install/ui/widget.js
+++ b/install/ui/widget.js
@@ -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();
     };
 
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 0ba2aa8597549ff351a4a5b085aa310ece890ab1..a4d87b1d744afe38b5e4ca1b6789724b33d6aa57 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -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": {
-- 
1.7.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to