From 008639172280de28294c6fac1ea7d993d2570afe Mon Sep 17 00:00:00 2001 From: Konzertheld Date: Tue, 12 Feb 2013 00:25:36 +0100 Subject: [PATCH 1/6] Rewrite the login form with FormUI. Add a new admin formcontrol for password fields. Use it. This will break plugins relying on theme_loginform_* hooks. Also, it requires rewriting of the login handler. Handles #461 --- admin/formcontrols/admincontrol_password.php | 12 +++++ admin/login.php | 46 ++++++++------------ 2 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 admin/formcontrols/admincontrol_password.php diff --git a/admin/formcontrols/admincontrol_password.php b/admin/formcontrols/admincontrol_password.php new file mode 100644 index 000000000..c03c75c8e --- /dev/null +++ b/admin/formcontrols/admincontrol_password.php @@ -0,0 +1,12 @@ + + +
+

+ + > +

+ errors_out('
  • %s
  • ', ''); ?> +
    diff --git a/admin/login.php b/admin/login.php index 2d89bfafd..ba1bd9c95 100644 --- a/admin/login.php +++ b/admin/login.php @@ -26,29 +26,18 @@

    - -
    - - - -

    - value="" placeholder="" class="styledformelement"> -

    -

    - -

    - -

    - -

    -

    - -

    - -
    - + set_option( 'form_action', URL::get( 'auth', array( 'page' => 'login' ) ) ); + $form->append( 'static', 'reset_message', '

    ' . _t('Please enter the username you wish to reset the password for. A unique password reset link will be emailed to that user.') . '

    ' ); + $form->append( 'text', 'habari_username', 'null:null', _t('Name') ); + $form->habari_username->template = 'admincontrol_text'; + $form->append( 'password', 'habari_password', 'null:null', _t('Password') ); + $form->habari_password->template = 'admincontrol_password'; + $form->append( 'submit', 'submit_button', _t('Login') ); + $form->append( 'button', 'passwordreset_button', _t('Reset password') ); + $form->out(); + ?>
    @@ -61,6 +50,7 @@ var password_label; $(document).ready( function() { + $("#reset_message").hide(); password_label = $('label[for=habari_password]'); // to fix autofill issues, we need to check the password field on every keyup $('#habari_username').keyup( function() { @@ -73,15 +63,15 @@ // Make the login form a bit more intuitive when requesting a password reset // TODO: Stop this submitting the form when we click the Reset Password the first time when the field is populated. - $("#password_utils input").click(function() { - // Hide password box - $("p:has(input[name=habari_password])").hide(); + $("#passwordreset_button input").click(function() { + // Hide password box (and surrounding container) + $("#habari_password").parent().hide(); // Hide Login button - $("p:has(input[name=submit_button])").first().hide(); + $("#submit_button").hide(); // Show message that explains things a bit better $("p#reset_message").fadeIn(); // Unbind click function - $("#password_utils input").unbind('click'); + $("#passwordreset_button input").unbind('click'); return false; }); }); From da9178bd91379c4fcdf985779bc94fb8a3ad3567 Mon Sep 17 00:00:00 2001 From: Konzertheld Date: Tue, 12 Feb 2013 01:05:19 +0100 Subject: [PATCH 2/6] Turn the old login handler into a new one for FormUI. Use it. --- admin/login.php | 4 ++-- handlers/userhandler.php | 23 +++++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/admin/login.php b/admin/login.php index ba1bd9c95..111ea71b8 100644 --- a/admin/login.php +++ b/admin/login.php @@ -28,14 +28,14 @@
    set_option( 'form_action', URL::get( 'auth', array( 'page' => 'login' ) ) ); + $form->on_success( array( 'Habari\UserHandler', 'login' ) ); $form->append( 'static', 'reset_message', '

    ' . _t('Please enter the username you wish to reset the password for. A unique password reset link will be emailed to that user.') . '

    ' ); $form->append( 'text', 'habari_username', 'null:null', _t('Name') ); $form->habari_username->template = 'admincontrol_text'; $form->append( 'password', 'habari_password', 'null:null', _t('Password') ); $form->habari_password->template = 'admincontrol_password'; $form->append( 'submit', 'submit_button', _t('Login') ); - $form->append( 'button', 'passwordreset_button', _t('Reset password') ); + $form->append( 'submit', 'passwordreset_button', _t('Reset password') ); $form->out(); ?>
    diff --git a/handlers/userhandler.php b/handlers/userhandler.php index 1ed637dd8..88061ddcd 100644 --- a/handlers/userhandler.php +++ b/handlers/userhandler.php @@ -18,12 +18,18 @@ class UserHandler extends ActionHandler * create a session for them; or handle a password reset request. */ public function act_login() + { + // Display the login form. + $this->login_form( $name ); + } + + public function login ( $form ) { // If we're a reset password request, do that. - if ( isset( $_POST['submit_button'] ) && $_POST['submit_button'] === _t( 'Reset password' ) ) { - Utils::check_request_method( array( 'POST' ) ); + if ( isset( $form->passwordreset_button->value ) && !empty( $form->passwordreset_button->value ) ) { + //Utils::check_request_method( array( 'POST' ) ); - $name = $this->handler_vars['habari_username']; + $name = $form->habari_username->value; if ( $name !== null ) { if ( !is_numeric( $name ) && $user = User::get( $name ) ) { $hash = Utils::random_password(); @@ -40,9 +46,9 @@ public function act_login() } // Back to actual login. else { - Utils::check_request_method( array( 'GET', 'HEAD', 'POST' ) ); - $name = $_POST['habari_username']; - $pass = $_POST['habari_password']; + //Utils::check_request_method( array( 'GET', 'HEAD', 'POST' ) ); + $name = $form->habari_username->value; + $pass = $form->habari_password->value; if ( ( null != $name ) || ( null != $pass ) ) { $user = User::authenticate( $name, $pass ); @@ -102,13 +108,10 @@ public function act_login() /* Authentication failed. */ // Remove submitted password, see, we're secure! - $_POST['habari_password'] = ''; + $form->habari_password->value = ''; $this->handler_vars['error'] = _t( 'Bad credentials' ); } } - - // Display the login form. - $this->login_form( $name ); } /** From b53e972bec7db3645cb1ea173c79bba57cf6786e Mon Sep 17 00:00:00 2001 From: Konzertheld Date: Tue, 12 Feb 2013 01:38:47 +0100 Subject: [PATCH 3/6] Move the new login FormUI into UserHandler and get rid of the ancient stuff there. --- admin/login.php | 13 +------------ handlers/userhandler.php | 37 +++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/admin/login.php b/admin/login.php index 111ea71b8..7a9331b53 100644 --- a/admin/login.php +++ b/admin/login.php @@ -26,18 +26,7 @@

    - on_success( array( 'Habari\UserHandler', 'login' ) ); - $form->append( 'static', 'reset_message', '

    ' . _t('Please enter the username you wish to reset the password for. A unique password reset link will be emailed to that user.') . '

    ' ); - $form->append( 'text', 'habari_username', 'null:null', _t('Name') ); - $form->habari_username->template = 'admincontrol_text'; - $form->append( 'password', 'habari_password', 'null:null', _t('Password') ); - $form->habari_password->template = 'admincontrol_password'; - $form->append( 'submit', 'submit_button', _t('Login') ); - $form->append( 'submit', 'passwordreset_button', _t('Reset password') ); - $form->out(); - ?> +
    diff --git a/handlers/userhandler.php b/handlers/userhandler.php index 88061ddcd..5fdb0c223 100644 --- a/handlers/userhandler.php +++ b/handlers/userhandler.php @@ -20,15 +20,13 @@ class UserHandler extends ActionHandler public function act_login() { // Display the login form. - $this->login_form( $name ); + $this->login_form(); } - public function login ( $form ) + public function loginform_success ( $form ) { // If we're a reset password request, do that. if ( isset( $form->passwordreset_button->value ) && !empty( $form->passwordreset_button->value ) ) { - //Utils::check_request_method( array( 'POST' ) ); - $name = $form->habari_username->value; if ( $name !== null ) { if ( !is_numeric( $name ) && $user = User::get( $name ) ) { @@ -46,7 +44,6 @@ public function login ( $form ) } // Back to actual login. else { - //Utils::check_request_method( array( 'GET', 'HEAD', 'POST' ) ); $name = $form->habari_username->value; $pass = $form->habari_password->value; @@ -140,26 +137,30 @@ public function act_logout() * * @param string $name Pre-fill the name field with this name */ - protected function login_form( $name ) + protected function login_form() { - // Display the login form. + // Build theme and login page template $this->theme = Themes::create(); if ( !$this->theme->template_exists( 'login' ) ) { $this->theme = Themes::create( 'admin', 'RawPHPEngine', Site::get_dir( 'admin_theme', true ) ); $this->theme->assign( 'admin_page', 'login' ); } - $request = new \StdClass(); - foreach ( URL::get_active_rules() as $rule ) { - $request->{$rule->name} = ( $rule->name == URL::get_matched_rule()->name ); - } - - if ( isset( $this->handler_vars['error'] ) ) { - $this->theme->assign( 'error', Utils::htmlspecialchars( $this->handler_vars['error'] ) ); - } - - $this->theme->assign( 'request', $request ); - $this->theme->assign( 'habari_username', htmlentities( $name, ENT_QUOTES, 'UTF-8' ) ); + + // Build the login form + $form = new FormUI( 'habari_login' ); + $form->on_success( array( $this, 'loginform_success' ) ); + $form->append( 'static', 'reset_message', '

    ' . _t('Please enter the username you wish to reset the password for. A unique password reset link will be emailed to that user.') . '

    ' ); + $form->append( 'text', 'habari_username', 'null:null', _t('Name') ); + $form->habari_username->template = 'admincontrol_text'; + $form->append( 'password', 'habari_password', 'null:null', _t('Password') ); + $form->habari_password->template = 'admincontrol_password'; + $form->append( 'submit', 'submit_button', _t('Login') ); + $form->append( 'submit', 'passwordreset_button', _t('Reset password') ); + + // Assign login form and display the page + $this->theme->form = $form->get(); $this->display( 'login' ); + return true; } From c3c1c006776258fb71315e9ac798da0f04c4eb97 Mon Sep 17 00:00:00 2001 From: Konzertheld Date: Tue, 12 Feb 2013 01:48:43 +0100 Subject: [PATCH 4/6] Let plugins alter the new login FormUI. Fixes #461 --- handlers/userhandler.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/handlers/userhandler.php b/handlers/userhandler.php index 5fdb0c223..5858a18a9 100644 --- a/handlers/userhandler.php +++ b/handlers/userhandler.php @@ -157,6 +157,9 @@ protected function login_form() $form->append( 'submit', 'submit_button', _t('Login') ); $form->append( 'submit', 'passwordreset_button', _t('Reset password') ); + // Let plugins alter this form + Plugins::act( 'form_login', $form ); + // Assign login form and display the page $this->theme->form = $form->get(); $this->display( 'login' ); From 55e67ae3945ab16f9e46e05377def4f7e07f1d61 Mon Sep 17 00:00:00 2001 From: Konzertheld Date: Tue, 12 Feb 2013 02:07:40 +0100 Subject: [PATCH 5/6] Redirect to the login form instead of displaying it. That stops the 'expired token' message when users log in with their newly reset password. --- handlers/userhandler.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/handlers/userhandler.php b/handlers/userhandler.php index 5858a18a9..eaaa7a325 100644 --- a/handlers/userhandler.php +++ b/handlers/userhandler.php @@ -187,7 +187,6 @@ public function act_password_reset() $id = $this->handler_vars['id']; $hash = $this->handler_vars['hash']; - $name = ''; if ( $user = User::get( $id ) ) { if ( is_string( $hash ) && ( $user->info->password_reset == md5( $hash ) ) ) { @@ -208,15 +207,13 @@ public function act_password_reset() // Clear the request - it should only work once unset( $user->info->password_reset ); $user->info->commit(); - - $name = $user->username; } else { Session::notice( _t( 'The supplied password reset token has expired or is invalid.' ) ); } } // Display the login form. - $this->login_form( $name ); + Utils::redirect( Site::get_url( 'admin' ) ); } } From b18276521c517934f0a230dd5d39b017d2a27bb9 Mon Sep 17 00:00:00 2001 From: Konzertheld Date: Tue, 12 Feb 2013 03:44:44 +0100 Subject: [PATCH 6/6] Redirect to the login page instead of the admin page to avoid a double redirect. --- handlers/userhandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/userhandler.php b/handlers/userhandler.php index eaaa7a325..f28302b11 100644 --- a/handlers/userhandler.php +++ b/handlers/userhandler.php @@ -213,7 +213,7 @@ public function act_password_reset() } } // Display the login form. - Utils::redirect( Site::get_url( 'admin' ) ); + Utils::redirect( URL::get( 'auth', array( 'page' => 'login' ) ) ); } }