From c26338b241d08841134e8d89d25d916417ac1fa5 Mon Sep 17 00:00:00 2001 From: Alexander Bias Date: Fri, 26 Jan 2024 19:55:26 +0100 Subject: [PATCH] Improvement: Add a side entrance login page for local logins if the local login form is disabled on the standard login page, resolves #539. (#547) --- CHANGES.md | 1 + README.md | 2 + lang/en/theme_boost_union.php | 3 + locallogin.php | 85 +++++++++++++++++++ settings.php | 4 +- templates/localloginform.mustache | 54 ++++++++++++ .../behat_theme_boost_union_base_look.php | 43 ++++++++++ ...boost_union_looksettings_loginpage.feature | 29 +++++++ 8 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 locallogin.php create mode 100644 templates/localloginform.mustache create mode 100755 tests/behat/behat_theme_boost_union_base_look.php diff --git a/CHANGES.md b/CHANGES.md index a6b2539d173..4301ac4c56a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Changes ### Unreleased +* 2024-01-20 - Improvement: Add a side entrance login page for local logins if the local login form is disabled on the standard login page, resolves #539. * 2024-01-20 - Improvement: Make all block regions available for the incourse and coursecategory page layouts, resolves #543. * 2024-01-19 - Bugfix: Get rid of 'Undefined stdClass property' notices for static page settings, resolves #431. diff --git a/README.md b/README.md index d3712fe4fa8..54fdfacbb64 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,8 @@ With this setting, you can make the login form slightly transparent to let the b With this setting, you control if the local login form is shown on the login page or not. By default, the local login form is shown and users an login into the site as normal. If you disable this setting, the local login form is hidden. This allows you to just provide login buttons for external identity providers like OAuth2 or OIDC. +Please note: As soon as you hide the local login form, you risk that admins cannot log in anymore with a local account if there is a problem with the external identity provider. To allow local logins anyway in such cases, a side entrance local login page is provided on /theme/boost_union/locallogin.php. On this side entrance local login page, all of Moodle's login security measures apply as well. + ##### IDP login intro With this setting, you control if the 'Log in using your account on' intro is shown above the IDP login buttons or not. By default, the intro is shown and users will be quickly informed what the IDP buttons are about. If you disable this setting, the IDP intro is hidden. This allows you to provide a clean user login interface if you just use external identity providers like OAuth2 or OIDC. diff --git a/lang/en/theme_boost_union.php b/lang/en/theme_boost_union.php index 07b91801751..980290e2202 100644 --- a/lang/en/theme_boost_union.php +++ b/lang/en/theme_boost_union.php @@ -206,6 +206,9 @@ // ... ... Setting: Local login form. $string['loginlocalloginenablesetting'] = 'Local login'; $string['loginlocalloginenablesetting_desc'] = 'With this setting, you control if the local login form is shown on the login page or not. By default, the local login form is shown and users an login into the site as normal. If you disable this setting, the local login form is hidden. This allows you to just provide login buttons for external identity providers like OAuth2 or OIDC.'; +$string['loginlocalloginenablesetting_note'] = 'Please note: As soon as you hide the local login form, you risk that admins cannot log in anymore with a local account if there is a problem with the external identity provider. To allow local logins anyway in such cases, a side entrance local login page is provided. On this side entrance local login page, all of Moodle\'s login security measures apply as well.'; +$string['loginlocalloginformhead'] = 'Local login'; +$string['loginlocalloginlocalnotdisabled'] = 'The local login is enabled on the standard login form. There is no need to log in on this local login page here. Please use the standard login page for logging in.'; // ... ... Setting: IDP login intro. $string['loginidpshowintrosetting'] = 'IDP login intro'; $string['loginidpshowintrosetting_desc'] = 'With this setting, you control if the \'{$a}\' intro is shown above the IDP login buttons or not. By default, the intro is shown and users will be quickly informed what the IDP buttons are about. If you disable this setting, the IDP intro is hidden. This allows you to provide a clean user login interface if you just use external identity providers like OAuth2 or OIDC.'; diff --git a/locallogin.php b/locallogin.php new file mode 100644 index 00000000000..9bff5a22e8f --- /dev/null +++ b/locallogin.php @@ -0,0 +1,85 @@ +. + +/** + * Theme Boost Union - Local login page + * + * This file is copied, reduced and modified from /login/index.php. + * + * @package theme_boost_union + * @copyright 2023 Alexander Bias + * based on code 1999 onwards Martin Dougiamas + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Include config.php. +// @codingStandardsIgnoreStart +// Let codechecker ignore the next line because otherwise it would complain about a missing login check +// after requiring config.php which is really not needed. +require(__DIR__.'/../../config.php'); +// @codingStandardsIgnoreEnd + +// Require the necessary libraries. +require_once($CFG->dirroot.'/lib/authlib.php'); +require_once($CFG->dirroot.'/theme/boost_union/lib.php'); + +// Set page URL. +$PAGE->set_url('/theme/boost_union/locallogin.php'); + +// Set page layout. +$PAGE->set_pagelayout('login'); + +// Set page context. +$PAGE->set_context(context_system::instance()); + +// Get theme config. +$config = get_config('theme_boost_union'); + +// If the local login is not disabled, we just show a short friendly warning page and are done. +if ($config->loginlocalloginenable != THEME_BOOST_UNION_SETTING_SELECT_NO) { + echo $OUTPUT->header(); + $loginurl = new moodle_url('/login/index.php'); + $notification = new \core\output\notification( + get_string('loginlocalloginlocalnotdisabled', 'theme_boost_union', ['url' => $loginurl]), + \core\output\notification::NOTIFY_INFO); + $notification->set_show_closebutton(false); + echo $OUTPUT->render($notification); + echo $OUTPUT->footer(); + die; +} + +// If the user is already logged in or is a guest user. +if (isloggedin() || isguestuser()) { + // We just redirect him to the standard login page to handle this case. + redirect('/login/index.php'); +} + +// Set page title. +$PAGE->set_title(get_string('loginsite')); + +// Start page output. +echo $OUTPUT->header(); + +// Prepare the local login form. +$templatecontext = []; +$templatecontext['loginurl'] = new moodle_url('/login/index.php'); +$templatecontext['logintoken'] = \core\session\manager::get_login_token(); + +// Output the local login form. +echo $OUTPUT->render_from_template('theme_boost_union/localloginform', $templatecontext); + +// Finish page. +echo $OUTPUT->footer(); diff --git a/settings.php b/settings.php index 85809c11b46..3a71ed1c2e4 100644 --- a/settings.php +++ b/settings.php @@ -665,7 +665,9 @@ // Setting: Local login. $name = 'theme_boost_union/loginlocalloginenable'; $title = get_string('loginlocalloginenablesetting', 'theme_boost_union', null, true); - $description = get_string('loginlocalloginenablesetting_desc', 'theme_boost_union', null, true); + $localloginurl = new moodle_url('/theme/boost_union/locallogin.php'); + $description = get_string('loginlocalloginenablesetting_desc', 'theme_boost_union', null, true).'

'. + get_string('loginlocalloginenablesetting_note', 'theme_boost_union', ['url' => $localloginurl], true); $setting = new admin_setting_configselect($name, $title, $description, THEME_BOOST_UNION_SETTING_SELECT_YES, $yesnooption); $tab->add($setting); diff --git a/templates/localloginform.mustache b/templates/localloginform.mustache new file mode 100644 index 00000000000..fb73b7d3e18 --- /dev/null +++ b/templates/localloginform.mustache @@ -0,0 +1,54 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template theme_boost_union/localloginform + + Boost Union template for outputting the local login form on the local login page. + This is a limited and modified version of core/loginform. + + Context variables required for this template: + * loginurl - Login url, + * logintoken - Random token to protect login request., + + Example context (json): + { + "loginurl": "http://localhost/stable_master/login/index.php", + "logintoken": "randomstring", + } +}} + +
+

{{#str}}loginlocalloginformhead, theme_boost_union{{/str}}

+ +
diff --git a/tests/behat/behat_theme_boost_union_base_look.php b/tests/behat/behat_theme_boost_union_base_look.php new file mode 100755 index 00000000000..414ad558664 --- /dev/null +++ b/tests/behat/behat_theme_boost_union_base_look.php @@ -0,0 +1,43 @@ +. + +/** + * Theme Boost Union - Custom Behat rules for the 'Look' settings + * + * @package theme_boost_union + * @copyright 2023 Alexander Bias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../../lib/behat/behat_base.php'); + +/** + * Class behat_theme_boost_union_base_look + * + * @package theme_boost_union + * @copyright 2023 Alexander Bias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_theme_boost_union_base_look extends behat_base { + /** + * Open the local login page. + * + * @Given /^I am on local login page$/ + */ + public function i_am_on_local_login_page() { + $this->execute('behat_general::i_visit', ['/theme/boost_union/locallogin.php']); + } +} diff --git a/tests/behat/theme_boost_union_looksettings_loginpage.feature b/tests/behat/theme_boost_union_looksettings_loginpage.feature index 39011a37350..53efafc4cdf 100644 --- a/tests/behat/theme_boost_union_looksettings_loginpage.feature +++ b/tests/behat/theme_boost_union_looksettings_loginpage.feature @@ -151,6 +151,35 @@ Feature: Configuring the theme_boost_union plugin for the "Login page" tab on th | yes | should | | no | should not | + Scenario Outline: Setting: Local login - View the side entrance login page + Given the following config values are set as admin: + | config | value | plugin | + | loginlocalloginenable | | theme_boost_union | + When I am on local login page + Then I see "Local login" + And ".login-heading" "css_element" exist + And "#username" "css_element" exist + And "#password" "css_element" exist + And "#loginbtn" "css_element" exist + And I see "The local login is enabled on the standard login form" + + Examples: + | setting | shouldornot1 | shouldornot2 | + | yes | should not | should | + | no | should | should not | + + Scenario: Setting: Local login - Use the side entrance login page + Given the following config values are set as admin: + | config | value | plugin | + | loginlocalloginenable | no | theme_boost_union | + When I am on local login page + And I set the following fields to these values: + # With behat, the password is always the same as the username. + | Username | admin | + | Password | admin | + And I press "Log in" + Then I should see "Welcome, Admin" in the "page-header" "region" + Scenario Outline: Setting: IDP login intro Given the following config values are set as admin: | config | value | plugin |