Skip to content

Commit

Permalink
MDL-61477 admin: sitepolicy handler API
Browse files Browse the repository at this point in the history
- Define sitepolicy handler manager class, base class and the core handler
- Allow to set a plugin as sitepolicyhandler that implements the sitepolicy API
- Modify web services to return information from the 3rd party handler instead of core if needed
  • Loading branch information
marinaglancy committed Mar 15, 2018
1 parent b0b49c9 commit 20884e1
Show file tree
Hide file tree
Showing 23 changed files with 914 additions and 116 deletions.
37 changes: 0 additions & 37 deletions admin/settings/plugins.php
Expand Up @@ -123,43 +123,6 @@
$temp->add($setting);
$ADMIN->add('authsettings', $temp);

$options = array(
0 => get_string('no'),
1 => get_string('yes')
);
$url = new moodle_url('/admin/settings.php?section=supportcontact');
$url = $url->out();
$setting = new admin_setting_configselect('agedigitalconsentverification',
new lang_string('agedigitalconsentverification', 'admin'),
new lang_string('agedigitalconsentverification_desc', 'admin', $url), 0, $options);
$setting->set_force_ltr(true);
$temp->add($setting);

$setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
new lang_string('ageofdigitalconsentmap', 'admin'),
new lang_string('ageofdigitalconsentmap_desc', 'admin'),
// See {@link https://gdpr-info.eu/art-8-gdpr/}.
implode(PHP_EOL, [
'*, 16',
'AT, 14',
'CZ, 13',
'DE, 14',
'DK, 13',
'ES, 13',
'FI, 15',
'GB, 13',
'HU, 14',
'IE, 13',
'LT, 16',
'LU, 16',
'NL, 16',
'PL, 13',
'SE, 13',
]),
PARAM_RAW
);
$temp->add($setting);

$temp = new admin_externalpage('authtestsettings', get_string('testsettings', 'core_auth'), new moodle_url("/auth/test_settings.php"), 'moodle/site:config', true);
$ADMIN->add('authsettings', $temp);

Expand Down
80 changes: 80 additions & 0 deletions admin/settings/privacy.php
@@ -0,0 +1,80 @@
<?php
// 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 <http://www.gnu.org/licenses/>.

/**
* Adds privacy and policies links to admin tree.
*
* @package core_privacy
* @copyright 2018 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

if ($hassiteconfig) {
// Privacy settings.
$temp = new admin_settingpage('privacysettings', new lang_string('privacysettings', 'admin'));

$options = array(
0 => get_string('no'),
1 => get_string('yes')
);
$url = new moodle_url('/admin/settings.php?section=supportcontact');
$url = $url->out();
$setting = new admin_setting_configselect('agedigitalconsentverification',
new lang_string('agedigitalconsentverification', 'admin'),
new lang_string('agedigitalconsentverification_desc', 'admin', $url), 0, $options);
$setting->set_force_ltr(true);
$temp->add($setting);

$setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
new lang_string('ageofdigitalconsentmap', 'admin'),
new lang_string('ageofdigitalconsentmap_desc', 'admin'),
// See {@link https://gdpr-info.eu/art-8-gdpr/}.
implode(PHP_EOL, [
'*, 16',
'AT, 14',
'CZ, 13',
'DE, 14',
'DK, 13',
'ES, 13',
'FI, 15',
'GB, 13',
'HU, 14',
'IE, 13',
'LT, 16',
'LU, 16',
'NL, 16',
'PL, 13',
'SE, 13',
]),
PARAM_RAW
);
$temp->add($setting);

$ADMIN->add('privacy', $temp);

// Policy settings.
$temp = new admin_settingpage('policysettings', new lang_string('policysettings', 'admin'));
$temp->add(new admin_settings_sitepolicy_handler_select('sitepolicyhandler', new lang_string('sitepolicyhandler', 'core_admin'),
new lang_string('sitepolicyhandler_desc', 'core_admin')));
$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));

$ADMIN->add('privacy', $temp);
}
14 changes: 0 additions & 14 deletions admin/settings/security.php
Expand Up @@ -50,20 +50,6 @@

$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));

$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
1 change: 1 addition & 0 deletions admin/settings/top.php
Expand Up @@ -35,6 +35,7 @@
$ADMIN->add('root', new admin_category('location', new lang_string('location','admin')));
$ADMIN->add('root', new admin_category('language', new lang_string('language')));
$ADMIN->add('root', new admin_category('modules', new lang_string('plugins', 'admin')));
$ADMIN->add('root', new admin_category('privacy', new lang_string('privacyandpolicies', 'admin')));
$ADMIN->add('root', new admin_category('security', new lang_string('security','admin')));
$ADMIN->add('root', new admin_category('appearance', new lang_string('appearance','admin')));
$ADMIN->add('root', new admin_category('frontpage', new lang_string('frontpage','admin')));
Expand Down
4 changes: 3 additions & 1 deletion admin/tool/mobile/classes/api.php
Expand Up @@ -211,7 +211,9 @@ public static function get_config($section) {
}

if (empty($section) or $section == 'sitepolicies') {
$settings->sitepolicy = $CFG->sitepolicy;
$manager = new \core_privacy\local\sitepolicy\manager();
$settings->sitepolicy = ($sitepolicy = $manager->get_embed_url()) ? $sitepolicy->out(false) : '';
$settings->sitepolicyhandler = $CFG->sitepolicyhandler;
$settings->disableuserimages = $CFG->disableuserimages;
}

Expand Down
1 change: 1 addition & 0 deletions admin/tool/mobile/tests/externallib_test.php
Expand Up @@ -150,6 +150,7 @@ public function test_get_config() {
array('name' => 'newsitems', 'value' => $SITE->newsitems),
array('name' => 'commentsperpage', 'value' => $CFG->commentsperpage),
array('name' => 'sitepolicy', 'value' => $mysitepolicy),
array('name' => 'sitepolicyhandler', 'value' => ''),
array('name' => 'disableuserimages', 'value' => $CFG->disableuserimages),
array('name' => 'mygradesurl', 'value' => user_mygrades_url()->out(false)),
array('name' => 'tool_mobile_forcelogout', 'value' => 0),
Expand Down
8 changes: 5 additions & 3 deletions auth/email/classes/external.php
Expand Up @@ -88,8 +88,9 @@ public static function get_signup_settings() {
if (!empty($CFG->passwordpolicy)) {
$result['passwordpolicy'] = print_password_policy();
}
if (!empty($CFG->sitepolicy)) {
$result['sitepolicy'] = $CFG->sitepolicy;
$manager = new \core_privacy\local\sitepolicy\manager();
if ($sitepolicy = $manager->get_embed_url()) {
$result['sitepolicy'] = $sitepolicy->out(false);
}
if (!empty($CFG->defaultcity)) {
$result['defaultcity'] = $CFG->defaultcity;
Expand Down Expand Up @@ -287,7 +288,8 @@ public static function signup_user($username, $password, $firstname, $lastname,
$data = $params;
$data['email2'] = $data['email'];
// Force policy agreed if a site policy is set. The client is responsible of implementing the interface check.
if (!empty($CFG->sitepolicy)) {
$manager = new \core_privacy\local\sitepolicy\manager();
if (!$manager->is_defined()) {
$data['policyagreed'] = 1;
}
unset($data['recaptcharesponse']);
Expand Down
2 changes: 1 addition & 1 deletion auth/tests/behat/validateagedigitalconsentmap.feature
Expand Up @@ -6,7 +6,7 @@ Feature: Test validation of 'Age of digital consent' setting.

Background:
Given I log in as "admin"
And I navigate to "Manage authentication" node in "Site administration > Plugins > Authentication"
And I navigate to "Privacy settings" node in "Site administration > Privacy and policies"

Scenario: Admin provides valid value for 'Age of digital consent'.
Given I set the field "s__agedigitalconsentmap" to multiline:
Expand Down
5 changes: 5 additions & 0 deletions auth/upgrade.txt
@@ -1,6 +1,11 @@
This files describes API changes in /auth/* - plugins,
information provided here is intended especially for developers.

=== 3.3.5 ===

* Self registration plugins should use core_privacy\local\sitepolicy\manager instead of directly checking
$CFG->sitepolicy , especially in custom signup forms. See https://docs.moodle.org/dev/Site_policy_handler

=== 3.3 ===

* Authentication plugins have been migrated to use the admin settings API. Plugins should use a settings.php file to
Expand Down
2 changes: 1 addition & 1 deletion file.php
Expand Up @@ -68,7 +68,7 @@
require_login($course, true, null, false);

} else if ($CFG->forcelogin) {
if (!empty($CFG->sitepolicy)
if (empty($CFG->sitepolicyhandler) and !empty($CFG->sitepolicy)
and ($CFG->sitepolicy == $CFG->wwwroot.'/file.php/'.$relativepath
or $CFG->sitepolicy == $CFG->wwwroot.'/file.php?file=/'.$relativepath)) {
//do not require login for policy file
Expand Down
3 changes: 3 additions & 0 deletions lang/en/admin.php
Expand Up @@ -850,6 +850,9 @@
$string['pluginschecktodo'] = 'You must solve all the plugin requirements before proceeding to install this Moodle version!';
$string['pluginsoverview'] = 'Plugins overview';
$string['pluginsoverviewsee'] = 'See <a href="{$a->url}">plugins overview</a> page for more details.';
$string['policysettings'] = 'Policy settings';
$string['privacyandpolicies'] = 'Privacy and policies';
$string['privacysettings'] = 'Privacy settings';
$string['profilecategory'] = 'Category';
$string['profilecategoryname'] = 'Category name (must be unique)';
$string['profilecategorynamenotunique'] = 'This category name is already in use';
Expand Down
43 changes: 43 additions & 0 deletions lib/adminlib.php
Expand Up @@ -10560,3 +10560,46 @@ public function validate($data) {
return true;
}
}

/**
* Selection of plugins that can work as site policy handlers
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright 2018 Marina Glancy
*/
class admin_settings_sitepolicy_handler_select extends admin_setting_configselect {

/**
* Constructor
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
* for ones in config_plugins.
* @param string $visiblename localised
* @param string $description long localised info
* @param string $defaultsetting
*/
public function __construct($name, $visiblename, $description, $defaultsetting = '') {
parent::__construct($name, $visiblename, $description, $defaultsetting, null);
}

/**
* Lazy-load the available choices for the select box
*/
public function load_choices() {
if (during_initial_install()) {
return false;
}
if (is_array($this->choices)) {
return true;
}

$this->choices = ['' => new lang_string('sitepolicyhandlercore', 'core_admin')];
$manager = new \core_privacy\local\sitepolicy\manager();
$plugins = $manager->get_all_handlers();
foreach ($plugins as $pname => $unused) {
$this->choices[$pname] = new lang_string('sitepolicyhandlerplugin', 'core_admin',
['name' => new lang_string('pluginname', $pname), 'component' => $pname]);
}

return true;
}
}
34 changes: 5 additions & 29 deletions lib/moodlelib.php
Expand Up @@ -2738,40 +2738,16 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $

// Check that the user has agreed to a site policy if there is one - do not test in case of admins.
// 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);
}
if ($setwantsurltome) {
$SESSION->wantsurl = qualified_me();
}
redirect($CFG->wwwroot .'/user/policy.php');
} else if (!empty($CFG->sitepolicyguest) and isguestuser()) {
if (!$USER->policyagreed && !is_siteadmin() && !NO_SITEPOLICY_CHECK) {
$manager = new \core_privacy\local\sitepolicy\manager();
if ($policyurl = $manager->get_redirect_url(isguestuser())) {
if ($preventredirect) {
throw new moodle_exception('sitepolicynotagreed', 'error', '', $CFG->sitepolicyguest);
throw new moodle_exception('sitepolicynotagreed', 'error', '', $policyurl->out());
}
if ($setwantsurltome) {
$SESSION->wantsurl = qualified_me();
}
redirect($CFG->wwwroot .'/user/policy.php');
redirect($policyurl);
}
}

Expand Down
6 changes: 3 additions & 3 deletions lib/upgrade.txt
Expand Up @@ -3,9 +3,9 @@ information provided here is intended especially for developers.

=== 3.3.5 ===

* 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.
* Plugins can define class 'PLUGINNAME\privacy\local\sitepolicy\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. See https://docs.moodle.org/dev/Site_policy_handler
* 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.
Expand Down
11 changes: 4 additions & 7 deletions login/signup_form.php
Expand Up @@ -97,13 +97,10 @@ function definition() {
$mform->closeHeaderBefore('recaptcha_element');
}

if (!empty($CFG->sitepolicy)) {
$mform->addElement('header', 'policyagreement', get_string('policyagreement'), '');
$mform->setExpanded('policyagreement');
$mform->addElement('static', 'policylink', '', '<a href="'.$CFG->sitepolicy.'" onclick="this.target=\'_blank\'">'.get_String('policyagreementclick').'</a>');
$mform->addElement('checkbox', 'policyagreed', get_string('policyaccept'));
$mform->addRule('policyagreed', get_string('policyagree'), 'required', null, 'client');
}
// Add "Agree to sitepolicy" controls. By default it is a link to the policy text and a checkbox but
// it can be implemented differently in custom sitepolicy handlers.
$manager = new \core_privacy\local\sitepolicy\manager();
$manager->signup_form($mform);

// buttons
$this->add_action_buttons(true, get_string('createaccount'));
Expand Down
3 changes: 2 additions & 1 deletion message/output/popup/lib.php
Expand Up @@ -36,7 +36,8 @@ function message_popup_render_navbar_output(\renderer_base $renderer) {
// Early bail out conditions.
if (!isloggedin() || isguestuser() || user_not_fully_set_up($USER) ||
get_user_preferences('auth_forcepasswordchange') ||
($CFG->sitepolicy && !$USER->policyagreed && !is_siteadmin())) {
(!$USER->policyagreed && !is_siteadmin() &&
($manager = new \core_privacy\local\sitepolicy\manager()) && $manager->is_defined())) {
return '';
}

Expand Down

0 comments on commit 20884e1

Please sign in to comment.