From e3d56597cd8aba4eee17a19f326f36bfcb3b90e2 Mon Sep 17 00:00:00 2001 From: Petr Vobornik Date: Tue, 29 Oct 2013 16:01:25 +0100 Subject: Fix password expiration notification - was broken by navigation and application controller refactoring https://fedorahosted.org/freeipa/ticket/4003 --- install/ui/src/freeipa/Application_controller.js | 6 +- install/ui/src/freeipa/ipa.js | 4 +- install/ui/src/freeipa/user.js | 1 - ipatests/test_webui/test_user.py | 113 +++++++++++++++++++++-- ipatests/test_webui/ui_driver.py | 32 ++++++- 5 files changed, 137 insertions(+), 19 deletions(-) diff --git a/install/ui/src/freeipa/Application_controller.js b/install/ui/src/freeipa/Application_controller.js index 4bde1238c..13c270fca 100644 --- a/install/ui/src/freeipa/Application_controller.js +++ b/install/ui/src/freeipa/Application_controller.js @@ -116,8 +116,10 @@ define([ start_runtime: function() { this.run_time = new Deferred(); - // now we are ready for displaying a facet - // cat match a facet if hash is set + IPA.update_password_expiration(); + + // now we are ready for displaying a facet, + // it can match a facet if hash is set this.router.startup(); // choose default facet if not defined by route diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js index b3017650d..51b4e1d24 100644 --- a/install/ui/src/freeipa/ipa.js +++ b/install/ui/src/freeipa/ipa.js @@ -610,7 +610,7 @@ IPA.update_password_expiration = function() { */ IPA.password_selfservice = function() { var reset_dialog = IPA.user_password_dialog({ - self_service: true, + pkey: IPA.whoami.uid[0], on_success: function() { var command = IPA.get_whoami_command(); var orig_on_success = command.on_success; @@ -620,7 +620,7 @@ IPA.password_selfservice = function() { }; command.execute(); - alert(text.get('@i18n:password.password_change_complete')); + IPA.notify_success(text.get('@i18n:password.password_change_complete')); reset_dialog.close(); } }); diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js index 34c3a7adf..61bdb43b4 100644 --- a/install/ui/src/freeipa/user.js +++ b/install/ui/src/freeipa/user.js @@ -536,7 +536,6 @@ IPA.user_password_dialog = function(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.pkey = spec.pkey; that.is_self_service = function() { diff --git a/ipatests/test_webui/test_user.py b/ipatests/test_webui/test_user.py index a17ac27a6..eb5134188 100644 --- a/ipatests/test_webui/test_user.py +++ b/ipatests/test_webui/test_user.py @@ -29,6 +29,11 @@ import ipatests.test_webui.data_hbac as hbac import ipatests.test_webui.test_rbac as rbac import ipatests.test_webui.data_sudo as sudo +try: + from selenium.webdriver.common.by import By +except ImportError: + pass + class test_user(UI_driver): @@ -143,17 +148,107 @@ class test_user(UI_driver): # reset password pwd = self.config.get('ipa_password') - fields = [ - ('password', 'password1', pwd), - ('password', 'password2', pwd), - ] + self.reset_password_action(pwd) + self.assert_text_field('has_password', '******') + + # delete + self.delete_action(user.ENTITY, user.PKEY) + + def test_password_expiration_notification(self): + """ + Test password expiration notification + """ + + pwd = self.config.get('ipa_password') + + self.init_app() + + self.set_ipapwdexpadvnotify('15') + + # create user and group and add user to that group + self.add_record(user.ENTITY, user.DATA) + self.add_record(group.ENTITY, group.DATA) + self.navigate_to_entity(group.ENTITY) + self.navigate_to_record(group.PKEY) + self.add_associations([user.PKEY]) + + # password policy for group + self.add_record('pwpolicy', { + 'pkey': group.PKEY, + 'add': [ + ('combobox', 'cn', group.PKEY), + ('textbox', 'cospriority', '12345'), + ]}) + self.navigate_to_record(group.PKEY) + self.mod_record('pwpolicy', { + 'pkey': group.PKEY, + 'mod': [ + ('textbox', 'krbmaxpwdlife', '7'), + ('textbox', 'krbminpwdlife', '0'), + ]}) + + # reset password + self.navigate_to_record(user.PKEY, entity=user.ENTITY) + self.reset_password_action(pwd) + + #re-login as new user + self.logout() + self.init_app(user.PKEY, pwd) + + header = self.find('.header', By.CSS_SELECTOR) + self.assert_text( + '.header-passwordexpires', + 'Your password expires in 6 days. Reset your password.', + header) + + # test password reset + link = self.find('.header-passwordexpires a', By.CSS_SELECTOR, strict=True) + link.click() + self.fill_password_dialog(pwd, pwd) + + # cleanup + self.logout() + self.init_app() + self.set_ipapwdexpadvnotify('4') + self.delete(user.ENTITY, [user.DATA]) + self.delete(group.ENTITY, [group.DATA]) + + def set_ipapwdexpadvnotify(self, days): + """ + Set ipa config "Password Expiration Notification (days)" field + """ + + self.navigate_to_entity('config') + self.mod_record('config', { + 'mod': [ + ('textbox', 'ipapwdexpadvnotify', days), + ] + }) + + def reset_password_action(self, password): + """ + Execute reset password action + """ + self.action_panel_action('account_actions', 'reset_password') + self.fill_password_dialog(password) + + def fill_password_dialog(self, password, current=None): + """ + Fill password dialog + """ + self.assert_dialog() + + fields = [ + ('password', 'password1', password), + ('password', 'password2', password), + ] + + if current: + fields.append(('password', 'current_password', current)) + self.fill_fields(fields) self.dialog_button_click('reset_password') - self.wait_for_request(n=2) + self.wait_for_request(n=3) self.assert_no_error_dialog() - self.assert_text_field('has_password', '******') - - # delete - self.delete_action(user.ENTITY, user.PKEY) diff --git a/ipatests/test_webui/ui_driver.py b/ipatests/test_webui/ui_driver.py index 46d7d6794..8603aa705 100644 --- a/ipatests/test_webui/ui_driver.py +++ b/ipatests/test_webui/ui_driver.py @@ -288,13 +288,13 @@ class UI_driver(object): """ return "contains(concat(' ',normalize-space(@%s), ' '),' %s ')" % (attr, val) - def init_app(self): + def init_app(self, login=None, password=None): """ Load and login """ self.load() self.wait(0.5) - self.login() + self.login(login, password) # metadata + default page self.wait_for_request(n=5) @@ -306,21 +306,39 @@ class UI_driver(object): runner = self WebDriverWait(self.driver, 10).until(lambda d: runner.files_loaded()) - def login(self): + def login(self, login=None, password=None, new_password=None): """ Log in if user is not logged in. """ self.wait_for_request(n=2) if not self.logged_in(): + + if not login: + login = self.config['ipa_admin'] + if not password: + password = self.config['ipa_password'] + if not new_password: + new_password = password + auth = self.get_auth_dialog() login_tb = self.find("//input[@type='text'][@name='username']", 'xpath', auth, strict=True) psw_tb = self.find("//input[@type='password'][@name='password']", 'xpath', auth, strict=True) - login_tb.send_keys(self.config['ipa_admin']) - psw_tb.send_keys(self.config['ipa_password']) + login_tb.send_keys(login) + psw_tb.send_keys(password) psw_tb.send_keys(Keys.RETURN) self.wait(0.5) self.wait_for_request() + # reset password if needed + if self.get_auth_dialog(): + newpw_tb = self.find("//input[@type='password'][@name='new_password']", 'xpath', auth, strict=True) + verify_tb = self.find("//input[@type='password'][@name='verify_password']", 'xpath', auth, strict=True) + newpw_tb.send_keys(new_password) + verify_tb.send_keys(new_password) + verify_tb.send_keys(Keys.RETURN) + self.wait(0.5) + self.wait_for_request(n=2) + def logged_in(self): """ Check if user is logged in @@ -330,6 +348,10 @@ class UI_driver(object): logged_in = not self.auth_dialog_opened() and visible_name return logged_in + def logout(self): + btn = self.find('logout', 'class name') + btn.click() + def get_auth_dialog(self): """ Get reference to authentication dialog -- cgit