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 0bdc578 commit 1727c93
Show file tree
Hide file tree
Showing 24 changed files with 913 additions and 117 deletions.
37 changes: 0 additions & 37 deletions admin/settings/plugins.php
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,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
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,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
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,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
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
2 changes: 2 additions & 0 deletions auth/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ information provided here is intended especially for developers.

* The auth_db and auth_ldap plugins' implementations of update_user_record() have been removed and both now
call the new implementation added in the base class.
* 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 ===

Expand Down
2 changes: 1 addition & 1 deletion file.php
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,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
Original file line number Diff line number Diff line change
Expand Up @@ -10626,3 +10626,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
Original file line number Diff line number Diff line change
Expand Up @@ -2723,40 +2723,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
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ 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.
* 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit 1727c93

Please sign in to comment.