MDL-61477 admin: Allow plugins to act as alternate policy handlers

The patch introduces a new site setting 'sitepolicyhandler' that can be
either empty or contain a plugin component name. If it is empty, the
site policy feature keeps working as before and the core keeps the
control over it.

If a plugin is specified, it is expected to implement the callback
'site_policy_handler' in its lib.php file. The callback should return a
URL to a script where the user can accept the site policies. The plugin
itself is responsible for setting the 'policyagreed' flag in the users
table. The callback may return an empty value, in which case the user
can continue using the site without being redirected.

The patch adds support for a new pre-config flag NO_SITEPOLICY_CHECK.
This constant should be defined and set to true if we should not check
the user's policyagreed status during the require_login().

This is for pages where the user actually accepts the site policies and
helps to avoid the redirect loop.
This commit is contained in:
David Mudrák
2018-03-15 09:30:59 +08:00
committed by Marina Glancy
parent 98e4385879
commit 94e7b022c7
5 changed files with 57 additions and 4 deletions
+15 -2
View File
@@ -54,8 +54,21 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
3600 => new lang_string('numminutes', '', 60))));
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'admin'), new lang_string('sitepolicy_help', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'admin'), new lang_string('sitepolicyguest_help', 'admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
$sitepolicyhandlers = ['' => new lang_string('sitepolicyhandlercore', 'core_admin')];
foreach (get_plugins_with_function('site_policy_handler') as $ptype => $pnames) {
foreach ($pnames as $pname => $fname) {
$sitepolicyhandlers[$ptype.'_'.$pname] = new lang_string('sitepolicyhandlerplugin', 'core_admin',
['name' => new lang_string('pluginname', $ptype.'_'.$pname), 'component' => $ptype.'_'.$pname]);
}
}
$temp->add(new admin_setting_configselect('sitepolicyhandler', new lang_string('sitepolicyhandler', 'core_admin'),
new lang_string('sitepolicyhandler_desc', 'core_admin'), '', $sitepolicyhandlers));
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'core_admin'),
new lang_string('sitepolicy_help', 'core_admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'core_admin'),
new lang_string('sitepolicyguest_help', 'core_admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('keeptagnamecase', new lang_string('keeptagnamecase','admin'),new lang_string('configkeeptagnamecase', 'admin'),'1'));
+4
View File
@@ -1050,6 +1050,10 @@ $string['sitemaintenancewarning2'] = 'Your site is currently in maintenance mode
$string['sitepolicies'] = 'Site policies';
$string['sitepolicy'] = 'Site policy URL';
$string['sitepolicy_help'] = 'If you have a site policy that all registered users must see and agree to before using this site, then specify the URL to it here, otherwise leave this field blank. This setting can contain any public URL.';
$string['sitepolicyhandler'] = 'Site policy handler';
$string['sitepolicyhandler_desc'] = 'Select the component to handle user agreements to site policies. The default core handler provides a simple functionality controlled by the two other settings `sitepolicy` and `sitepolicyguest`. Alternative handlers may be provided by additional plugins and offer more advanced control of site policies.';
$string['sitepolicyhandlercore'] = 'Default (core)';
$string['sitepolicyhandlerplugin'] = '{$a->name} ({$a->component})';
$string['sitepolicyguest'] = 'Site policy URL for guests';
$string['sitepolicyguest_help'] = 'If you have a site policy that all guests must see and agree to before using this site, then specify the URL to it here, otherwise leave this field blank. This setting can contain any public URL. Note: access of not-logged-in users may be prevented with forcelogin setting.';
$string['sitesectionhelp'] = 'If selected, a topic section will be displayed on the site\'s front page.';
+26 -2
View File
@@ -2715,9 +2715,33 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $
return;
}
// Scripts have a chance to declare that $USER->policyagreed should not be checked.
// This is mostly for places where users are actually accepting the policies, to avoid the redirect loop.
if (!defined('NO_SITEPOLICY_CHECK')) {
define('NO_SITEPOLICY_CHECK', false);
}
// Check that the user has agreed to a site policy if there is one - do not test in case of admins.
if (!$USER->policyagreed and !is_siteadmin()) {
if (!empty($CFG->sitepolicy) and !isguestuser()) {
// Do not test if the script explicitly asked for skipping the site policies check.
// Also do not check during AJAX requests as they may be actually performed on pages where policies are accepted.
if (!$USER->policyagreed && !is_siteadmin() && !NO_SITEPOLICY_CHECK && !AJAX_SCRIPT) {
if (!empty($CFG->sitepolicyhandler)) {
try {
$handler = component_callback($CFG->sitepolicyhandler, 'site_policy_handler');
} catch (Exception $e) {
debugging('Error while trying to execute the site_policy_handler callback!');
$handler = false;
}
if (!empty($handler) && (empty($PAGE->url) || !$PAGE->url->compare(new moodle_url($handler), URL_MATCH_BASE))) {
if ($preventredirect) {
throw new moodle_exception('sitepolicynotagreed', 'error', '', $handler);
}
if ($setwantsurltome) {
$SESSION->wantsurl = qualified_me();
}
redirect($handler);
}
} else if (!empty($CFG->sitepolicy) and !isguestuser()) {
if ($preventredirect) {
throw new moodle_exception('sitepolicynotagreed', 'error', '', $CFG->sitepolicy);
}
+9
View File
@@ -1,6 +1,15 @@
This files describes API changes in core libraries and APIs,
information provided here is intended especially for developers.
=== 3.4.2 ===
* Plugins can provide a new callback 'site_policy_handler' if they implement an alternative mechanisms for site policies
managements and agreements. Administrators can define which component is to be used for handling site policies and
agreements.
* Scripts can define a constant NO_SITEPOLICY_CHECK and set it to true before requiring the main config.php file. It
will make the require_login() skipping the test for the user's policyagreed status. This is useful for plugins that
act as a site policy handler.
=== 3.4 ===
* oauth2_client::request method has an extra parameter to specify the accept header for the response (MDL-60733)
* The following functions, previously used (exclusively) by upgrade steps are not available
+3
View File
@@ -22,6 +22,9 @@
* @package core_user
*/
// Do not check for the site policies in require_login() to avoid the redirect loop.
define('NO_SITEPOLICY_CHECK', true);
require_once('../config.php');
require_once($CFG->libdir.'/filelib.php');
require_once($CFG->libdir.'/resourcelib.php');