See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Lists all roles that have the ability to backup user data, as well as users 19 * 20 * @package core 21 * @category check 22 * @copyright 2020 Brendan Heywood <brendan@catalyst-au.net> 23 * @copyright 2008 petr Skoda 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 namespace core\check\access; 28 29 use context; 30 use stdClass; 31 use core\check\result; 32 33 /** 34 * Lists all roles that have the ability to backup user data, as well as users 35 * 36 * @copyright 2020 Brendan Heywood <brendan@catalyst-au.net> 37 * @copyright 2008 petr Skoda 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class riskbackup_result extends \core\check\result { 41 42 /** @var stdClass[] $systemroles */ 43 private $systemroles; 44 45 /** @var stdClass[] $overriddenroles */ 46 private $overriddenroles; 47 48 /** @var string $sqluserinfo */ 49 private $sqluserinfo; 50 51 /** 52 * Constructor 53 */ 54 public function __construct() { 55 global $DB; 56 57 $syscontext = \context_system::instance(); 58 59 $params = array('capability' => 'moodle/backup:userinfo', 'permission' => CAP_ALLOW, 'contextid' => $syscontext->id); 60 $sql = "SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder, r.archetype 61 FROM {role} r 62 JOIN {role_capabilities} rc ON rc.roleid = r.id 63 WHERE rc.capability = :capability 64 AND rc.contextid = :contextid 65 AND rc.permission = :permission"; 66 $this->systemroles = $DB->get_records_sql($sql, $params); 67 68 // Ensure first field is unique (role.id + role_capabilities.contextid). 69 $roleidcontextfield = $DB->sql_concat_join("','", ['r.id', 'rc.contextid']); 70 $params = array('capability' => 'moodle/backup:userinfo', 'permission' => CAP_ALLOW, 'contextid' => $syscontext->id); 71 $sql = "SELECT DISTINCT {$roleidcontextfield} AS rolecontext, r.id, r.name, r.shortname, r.sortorder, r.archetype, 72 rc.contextid 73 FROM {role} r 74 JOIN {role_capabilities} rc ON rc.roleid = r.id 75 WHERE rc.capability = :capability 76 AND rc.contextid <> :contextid 77 AND rc.permission = :permission"; 78 $this->overriddenroles = $DB->get_records_sql($sql, $params); 79 80 // List of users that are able to backup personal info 81 // note: 82 // "sc" is context where is role assigned, 83 // "c" is context where is role overridden or system context if in role definition. 84 $params = [ 85 'capability' => 'moodle/backup:userinfo', 86 'permission' => CAP_ALLOW, 87 'context1' => CONTEXT_COURSE, 88 'context2' => CONTEXT_COURSE, 89 ]; 90 91 $this->sqluserinfo = " 92 FROM (SELECT DISTINCT rcx.contextid, 93 rcx.roleid 94 FROM {role_capabilities} rcx 95 WHERE rcx.permission = :permission 96 AND rcx.capability = :capability) rc 97 JOIN {context} c ON c.id = rc.contextid 98 JOIN {context} sc ON sc.contextlevel <= :context1 99 JOIN {role_assignments} ra ON ra.contextid = sc.id AND ra.roleid = rc.roleid 100 JOIN {user} u ON u.id = ra.userid AND u.deleted = 0 101 WHERE (sc.path = c.path OR 102 sc.path LIKE " . $DB->sql_concat('c.path', "'/%'") . " OR 103 c.path LIKE " . $DB->sql_concat('sc.path', "'/%'") . ") 104 AND c.contextlevel <= :context2"; 105 106 $usercount = $DB->count_records_sql("SELECT COUNT('x') FROM (SELECT DISTINCT u.id $this->sqluserinfo) userinfo", $params); 107 $systemrolecount = empty($this->systemroles) ? 0 : count($this->systemroles); 108 $overriddenrolecount = empty($this->overriddenroles) ? 0 : count($this->overriddenroles); 109 110 if (max($usercount, $systemrolecount, $overriddenrolecount) > 0) { 111 $this->status = result::WARNING; 112 } else { 113 $this->status = result::OK; 114 } 115 116 $a = (object)array( 117 'rolecount' => $systemrolecount, 118 'overridecount' => $overriddenrolecount, 119 'usercount' => $usercount, 120 ); 121 $this->summary = get_string('check_riskbackup_warning', 'report_security', $a); 122 } 123 124 /** 125 * Showing the full list of roles may be slow so defer it 126 * 127 * @return string 128 */ 129 public function get_details(): string { 130 131 global $CFG, $DB; 132 133 $details = ''; 134 135 // Make a list of roles. 136 if ($this->systemroles) { 137 $links = array(); 138 foreach ($this->systemroles as $role) { 139 $role->name = role_get_name($role); 140 $role->url = (new \moodle_url('/admin/roles/manage.php', ['action' => 'edit', 'roleid' => $role->id]))->out(); 141 $links[] = \html_writer::tag('li', get_string('check_riskbackup_editrole', 'report_security', $role)); 142 } 143 $links = \html_writer::tag('ul', implode('', $links)); 144 $details .= get_string('check_riskbackup_details_systemroles', 'report_security', $links); 145 } 146 147 // Make a list of overrides to roles. 148 if ($this->overriddenroles) { 149 $links = array(); 150 foreach ($this->overriddenroles as $role) { 151 $context = context::instance_by_id($role->contextid); 152 $role->name = role_get_name($role, $context, ROLENAME_BOTH); 153 $role->contextname = $context->get_context_name(); 154 $role->url = (new \moodle_url('/admin/roles/override.php', 155 ['contextid' => $role->contextid, 'roleid' => $role->id]))->out(); 156 $links[] = \html_writer::tag('li', get_string('check_riskbackup_editoverride', 'report_security', $role)); 157 } 158 $links = \html_writer::tag('ul', implode('', $links)); 159 $details .= get_string('check_riskbackup_details_overriddenroles', 'report_security', $links); 160 } 161 162 // Get a list of affected users as well. 163 $users = array(); 164 165 list($sort, $sortparams) = users_order_by_sql('u'); 166 $params = [ 167 'capability' => 'moodle/backup:userinfo', 168 'permission' => CAP_ALLOW, 169 'context1' => CONTEXT_COURSE, 170 'context2' => CONTEXT_COURSE, 171 ]; 172 $userfieldsapi = \core_user\fields::for_userpic(); 173 $userfields = $userfieldsapi->get_sql('u', false, '', '', false)->selects; 174 $rs = $DB->get_recordset_sql(" 175 SELECT DISTINCT $userfields, 176 ra.contextid, 177 ra.roleid 178 $this->sqluserinfo 179 ORDER BY $sort", array_merge($params, $sortparams)); 180 181 foreach ($rs as $user) { 182 $context = \context::instance_by_id($user->contextid); 183 $url = new \moodle_url('/admin/roles/assign.php', ['contextid' => $user->contextid, 'roleid' => $user->roleid]); 184 $a = (object)array( 185 'fullname' => fullname($user), 186 'url' => $url->out(), 187 'email' => s($user->email), 188 'contextname' => $context->get_context_name(), 189 ); 190 $users[] = \html_writer::tag('li', get_string('check_riskbackup_unassign', 'report_security', $a)); 191 } 192 $rs->close(); 193 if (!empty($users)) { 194 $users = \html_writer::tag('ul', implode('', $users)); 195 $details .= get_string('check_riskbackup_details_users', 'report_security', $users); 196 } 197 198 return $details; 199 } 200 } 201
title
Description
Body
title
Description
Body
title
Description
Body
title
Body