From 8c875ed525558df1e6f26df20bd90b484eb08112 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Fri, 9 Aug 2024 16:32:43 +0100 Subject: [PATCH] MDL-82567 core: Add has_capability method Co-authored-by: David Woloszyn Co-authored-by: Jun Pataleta --- admin/classes/table/plugin_management_table.php | 11 +++++++++++ lib/table/classes/dynamic.php | 3 +++ lib/table/classes/external/dynamic/get.php | 7 +++++++ lib/tablelib.php | 15 +++++++++++++++ .../classes/table/custom_report_table.php | 9 +++++++++ .../classes/table/custom_report_table_view.php | 9 +++++++++ .../classes/table/system_report_table.php | 14 ++++++++++++++ user/classes/table/participants.php | 13 +++++++++++++ 8 files changed, 81 insertions(+) diff --git a/admin/classes/table/plugin_management_table.php b/admin/classes/table/plugin_management_table.php index 314fe8a1e15..b9c60d35db7 100644 --- a/admin/classes/table/plugin_management_table.php +++ b/admin/classes/table/plugin_management_table.php @@ -500,4 +500,15 @@ abstract class plugin_management_table extends flexible_table implements dynamic protected function supports_ordering(): bool { return $this->plugininfoclass::plugintype_supports_ordering(); } + + /** + * Check if the user has the capability to access this table. + * + * Default implementation for plugin management tables is to require 'moodle/site:config' capability + * + * @return bool Return true if capability check passed. + */ + public function has_capability(): bool { + return has_capability('moodle/site:config', $this->get_context()); + } } diff --git a/lib/table/classes/dynamic.php b/lib/table/classes/dynamic.php index 4288756b822..e2c4e699f75 100644 --- a/lib/table/classes/dynamic.php +++ b/lib/table/classes/dynamic.php @@ -41,4 +41,7 @@ namespace core_table; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ interface dynamic { + // Classes implementing this interface must define function `public has_capability(): bool` + // If it is not defined, the web service `core_table_get_dynamic_table_content` will check capability + // 'moodle/site:config' in the system context, allowing only admins to access the table data. } diff --git a/lib/table/classes/external/dynamic/get.php b/lib/table/classes/external/dynamic/get.php index 32fbce7e5e0..815bcfe7606 100644 --- a/lib/table/classes/external/dynamic/get.php +++ b/lib/table/classes/external/dynamic/get.php @@ -227,6 +227,13 @@ class get extends external_api { $instance = new $tableclass($uniqueid); $instance->set_filterset($filterset); self::validate_context($instance->get_context()); + if (!method_exists($instance, 'has_capability')) { + // Method \core_table\dynamic::has_capability() will be added in Moodle 4.5. Until then if it is not + // implemented, we will require the admin capability. + require_capability('moodle/site:config', \context_system::instance()); + } else if (!$instance->has_capability()) { + throw new \moodle_exception('nopermissiontoaccesspage'); + } $instance->set_sortdata($sortdata); $alphabet = get_string('alphabet', 'langconfig'); diff --git a/lib/tablelib.php b/lib/tablelib.php index b1d70463a44..0ed7f137b98 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -211,6 +211,21 @@ class flexible_table { TABLE_VAR_RESET => 'treset', TABLE_VAR_DIR => 'tdir', ); + + static $notified = []; + if (!(defined('AJAX_SCRIPT') && AJAX_SCRIPT) && + $this instanceof \core_table\dynamic && + !method_exists($this, 'has_capability') && + empty($notified[get_class($this)])) { + // Classes implementing \core_table\dynamic must have a method has_capability():bool . + // This will be enforced in Moodle 4.5. + \core\notification::add( + get_string('codingerror', 'debug', + 'Error in class '.get_class($this).'. Some functionality may be available to admins only.'), + \core\notification::WARNING + ); + $notified[get_class($this)] = true; + } } /** diff --git a/reportbuilder/classes/table/custom_report_table.php b/reportbuilder/classes/table/custom_report_table.php index f0541389d4c..1ed1a30d6c3 100644 --- a/reportbuilder/classes/table/custom_report_table.php +++ b/reportbuilder/classes/table/custom_report_table.php @@ -389,4 +389,13 @@ class custom_report_table extends base_report_table { return !empty($CFG->customreportsliveediting); } + + /** + * Check if the user has the capability to access this table. + * + * @return bool Return true if capability check passed. + */ + public function has_capability(): bool { + return \core_reportbuilder\permission::can_edit_report($this->persistent); + } } diff --git a/reportbuilder/classes/table/custom_report_table_view.php b/reportbuilder/classes/table/custom_report_table_view.php index 2ed750d51c8..0533aa4b006 100644 --- a/reportbuilder/classes/table/custom_report_table_view.php +++ b/reportbuilder/classes/table/custom_report_table_view.php @@ -74,4 +74,13 @@ class custom_report_table_view extends custom_report_table { return ''; } + + /** + * Check if the user has the capability to access this table. + * + * @return bool Return true if capability check passed. + */ + public function has_capability(): bool { + return \core_reportbuilder\permission::can_view_report($this->persistent); + } } diff --git a/reportbuilder/classes/table/system_report_table.php b/reportbuilder/classes/table/system_report_table.php index d3878068410..e46424f7113 100644 --- a/reportbuilder/classes/table/system_report_table.php +++ b/reportbuilder/classes/table/system_report_table.php @@ -299,4 +299,18 @@ class system_report_table extends base_report_table { return ''; } + + /** + * Check if the user has the capability to access this table. + * + * @return bool Return true if capability check passed. + */ + public function has_capability(): bool { + try { + $this->report->require_can_view(); + return true; + } catch (\core_reportbuilder\report_access_exception $e) { + return false; + } + } } diff --git a/user/classes/table/participants.php b/user/classes/table/participants.php index d8264c70212..9c3d35995c1 100644 --- a/user/classes/table/participants.php +++ b/user/classes/table/participants.php @@ -483,4 +483,17 @@ class participants extends \table_sql implements dynamic_table { public function get_context(): context { return $this->context; } + + /** + * Check if the user has the capability to access this table. + * + * @return bool Return true if capability check passed. + */ + public function has_capability(): bool { + global $CFG; + require_once($CFG->dirroot . '/course/lib.php'); + + $context = $this->course->id == SITEID ? \context_system::instance() : $this->get_context(); + return course_can_view_participants($context); + } }