Skip to content

Commit

Permalink
MDL-61477 admin: Allow plugins to act as alternate policy handlers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mudrd8mz authored and marinaglancy committed Mar 15, 2018
1 parent a2fc9a4 commit 0bdc578
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 4 deletions.
17 changes: 15 additions & 2 deletions admin/settings/security.php
Expand Up @@ -54,8 +54,21 @@
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'));

Expand Down
4 changes: 4 additions & 0 deletions lang/en/admin.php
Expand Up @@ -1053,6 +1053,10 @@
$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.';
Expand Down
28 changes: 26 additions & 2 deletions lib/moodlelib.php
Expand Up @@ -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);
}
Expand Down
6 changes: 6 additions & 0 deletions lib/upgrade.txt
Expand Up @@ -16,6 +16,12 @@ information provided here is intended especially for developers.
* XMLDB now validates the PATH attribute on every install.xml file. Both the XMLDB editor and installation will fail
when a problem is detected with it. Please ensure your plugins contain correct directory relative paths.
* Add recaptchalib_v2.php for support of reCAPTCHA v2.
* 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 ===

Expand Down
3 changes: 3 additions & 0 deletions user/policy.php
Expand Up @@ -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');
Expand Down

0 comments on commit 0bdc578

Please sign in to comment.