From 562fdb3b67d05b4797d06f314b8fbbabec4724e7 Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 18 Dec 2024 01:34:49 +0100 Subject: [PATCH 1/5] feat: added slotmaster capability --- lbplanner/classes/enums/CAPABILITY.php | 5 +++++ lbplanner/classes/enums/CAPABILITY_FLAG.php | 5 +++++ lbplanner/db/access.php | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/lbplanner/classes/enums/CAPABILITY.php b/lbplanner/classes/enums/CAPABILITY.php index ef195f00..cf37d86c 100644 --- a/lbplanner/classes/enums/CAPABILITY.php +++ b/lbplanner/classes/enums/CAPABILITY.php @@ -54,6 +54,11 @@ class CAPABILITY extends Enum { */ const STUDENT = 'local/lb_planner:student'; + /** + * Shortname of the slotmaster CAPABILITY. + */ + const SLOTMASTER = 'local/lb_planner:slotmaster'; + /** * Matches a capability string to its bitmappable flag * @param string $str the capability string diff --git a/lbplanner/classes/enums/CAPABILITY_FLAG.php b/lbplanner/classes/enums/CAPABILITY_FLAG.php index 88d06fe6..5728405d 100644 --- a/lbplanner/classes/enums/CAPABILITY_FLAG.php +++ b/lbplanner/classes/enums/CAPABILITY_FLAG.php @@ -54,6 +54,11 @@ class CAPABILITY_FLAG extends Enum { */ const STUDENT = 8; + /** + * Flag of the slotmaster CAPABILITY. + */ + const SLOTMASTER = 16; + /** * matches a flag to its capability string * @param int $num the bitmappable flag diff --git a/lbplanner/db/access.php b/lbplanner/db/access.php index 921734bc..c0fa9e87 100644 --- a/lbplanner/db/access.php +++ b/lbplanner/db/access.php @@ -46,4 +46,9 @@ 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, ], + 'local/lb_planner:slotmaster' => [ + 'riskbitmask' => RISK_SPAM || RISK_PERSONAL, + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + ], ]; From d916317cae497fc5d01b2353c038befa70842524 Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 18 Dec 2024 01:46:40 +0100 Subject: [PATCH 2/5] feat: slotmaster now has same perms as a slot's supervisor (also admin for good measure) --- lbplanner/classes/helpers/slot_helper.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index f642ad53..205c68db 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -25,10 +25,12 @@ namespace local_lbplanner\helpers; +use context_system; use DateInterval; use DateTime; use DateTimeImmutable; use DateTimeInterface; +use local_lbplanner\enums\CAPABILITY; use local_lbplanner\enums\WEEKDAY; use local_lbplanner\model\{slot, reservation, slot_filter}; @@ -372,15 +374,24 @@ public static function amend_date_with_unit_time(int $unit, DateTimeInterface $d } /** - * Checks whether a user is supervisor for a specific slot. + * Checks whether a user has supervisor-level permissions for a specific slot. + * NOTE: The user in question does not necessarily literally be the slot's supervisor, just have sufficient permissions! * @param int $supervisorid userid of the supervisor in question * @param int $slotid the slot to check * - * @return bool Whether this user is supervisor for this slot + * @return bool Whether this user has perms for this slot */ public static function check_slot_supervisor(int $supervisorid, int $slotid): bool { global $DB; + $context = context_system::instance(); + if ( + has_capability(CAPABILITY::ADMIN, $context, $supervisorid) + || has_capability(CAPABILITY::SLOTMASTER, $context, $supervisorid) + ) { + return true; + } + return $DB->record_exists(self::TABLE_SUPERVISORS, ['userid' => $supervisorid, 'slotid' => $slotid]); } } From a898bf33d8ef5d764bb76f8bb4e9733a586c2dbf Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 18 Dec 2024 02:03:02 +0100 Subject: [PATCH 3/5] feat: added helper function to assert access to slot --- lbplanner/classes/helpers/slot_helper.php | 13 +++++++++++++ lbplanner/services/slots/add_slot_filter.php | 4 +--- lbplanner/services/slots/add_slot_supervisor.php | 4 +--- lbplanner/services/slots/book_reservation.php | 5 +---- lbplanner/services/slots/delete_slot.php | 4 +--- lbplanner/services/slots/get_slot_filters.php | 4 +--- lbplanner/services/slots/get_slot_reservations.php | 4 +--- lbplanner/services/slots/update_slot.php | 4 +--- 8 files changed, 20 insertions(+), 22 deletions(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 205c68db..a8b70001 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -394,4 +394,17 @@ public static function check_slot_supervisor(int $supervisorid, int $slotid): bo return $DB->record_exists(self::TABLE_SUPERVISORS, ['userid' => $supervisorid, 'slotid' => $slotid]); } + + /** + * Same as {@see check_slot_supervisor()}, except it throws an error if permissions are insufficient. + * @param int $supervisorid userid of the supervisor in question + * @param int $slotid the slot to check + * + * @throw \moodle_exception if the user has insufficient permissions + */ + public static function assert_slot_supervisor(int $supervisorid, int $slotid): void { + if (!self::check_slot_supervisor($supervisorid, $slotid)) { + throw new \moodle_exception('Insufficient Permission: you\'re not supervisor of this slot'); + } + } } diff --git a/lbplanner/services/slots/add_slot_filter.php b/lbplanner/services/slots/add_slot_filter.php index 2b87a5c3..fdc7b29b 100644 --- a/lbplanner/services/slots/add_slot_filter.php +++ b/lbplanner/services/slots/add_slot_filter.php @@ -84,9 +84,7 @@ public static function add_slot_filter(int $slotid, ?int $courseid, ?string $vin ); // Check if user is supervisor for this slot, throw error if not. - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Insufficient Permission: you\'re not supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); // Ensure that either $courseid or $vintage are non-null. if (is_null($courseid) && is_null($vintage)) { throw new \moodle_exception('courseid and vintage can\'t both be null'); diff --git a/lbplanner/services/slots/add_slot_supervisor.php b/lbplanner/services/slots/add_slot_supervisor.php index beafa729..ff106a8d 100644 --- a/lbplanner/services/slots/add_slot_supervisor.php +++ b/lbplanner/services/slots/add_slot_supervisor.php @@ -71,9 +71,7 @@ public static function add_slot_supervisor(int $userid, int $slotid): void { ); // Check if current user is supervisor for this slot, throw error if not. - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Insufficient Permission: you\'re not supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); // Add supervisor. $DB->insert_record( diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index de049625..8b118905 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -103,10 +103,7 @@ public static function book_reservation(int $slotid, string $date, int $userid): $student = $USER; } else { // Supervisor reserving slot for student. - - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Forbidden: you\'re not a supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); $maxdays = slot_helper::RESERVATION_RANGE_USER; $student = core_user::get_user($userid, '*', MUST_EXIST); diff --git a/lbplanner/services/slots/delete_slot.php b/lbplanner/services/slots/delete_slot.php index 17caf4d7..9412abd4 100644 --- a/lbplanner/services/slots/delete_slot.php +++ b/lbplanner/services/slots/delete_slot.php @@ -63,9 +63,7 @@ public static function delete_slot(int $slotid): void { ); // Check if user is supervisor for this slot, throw error if not. - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Insufficient Permission: you\'re not supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); // Notify affected users. $reservations = slot_helper::get_reservations_for_slot($slotid); diff --git a/lbplanner/services/slots/get_slot_filters.php b/lbplanner/services/slots/get_slot_filters.php index bcd91046..26e0cbde 100644 --- a/lbplanner/services/slots/get_slot_filters.php +++ b/lbplanner/services/slots/get_slot_filters.php @@ -63,9 +63,7 @@ public static function get_slot_filters(int $slotid): array { ); // Check if user is supervisor for this slot, throw error if not. - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Insufficient Permission: you\'re not supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); // Get all filters for this slot, and return their API representations. $filters = slot_helper::get_filters_for_slot($slotid); $filterdicts = []; diff --git a/lbplanner/services/slots/get_slot_reservations.php b/lbplanner/services/slots/get_slot_reservations.php index 0b390ba9..36f69462 100644 --- a/lbplanner/services/slots/get_slot_reservations.php +++ b/lbplanner/services/slots/get_slot_reservations.php @@ -53,9 +53,7 @@ public static function get_slot_reservations(int $slotid): array { ['slotid' => $slotid] ); - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Insufficient Permissions: not a supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); $reservations = slot_helper::get_reservations_for_slot($slotid); diff --git a/lbplanner/services/slots/update_slot.php b/lbplanner/services/slots/update_slot.php index 7139da66..c5b0bb78 100644 --- a/lbplanner/services/slots/update_slot.php +++ b/lbplanner/services/slots/update_slot.php @@ -109,9 +109,7 @@ public static function update_slot(int $slotid, int $startunit, int $duration, i ); // Check if user is supervisor for this slot, throw error if not. - if (!slot_helper::check_slot_supervisor($USER->id, $slotid)) { - throw new \moodle_exception('Insufficient Permission: you\'re not supervisor of this slot'); - } + slot_helper::assert_slot_supervisor($USER->id, $slotid); // Replace slot's values with new values if not null. $slot = slot_helper::get_slot($slotid); From e32aeb465dce35c35f9dbb2ce2d394114b16452e Mon Sep 17 00:00:00 2001 From: Riedler Date: Wed, 18 Dec 2024 02:34:59 +0100 Subject: [PATCH 4/5] fix: typo --- lbplanner/classes/helpers/slot_helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index a8b70001..a826a0f7 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -400,7 +400,7 @@ public static function check_slot_supervisor(int $supervisorid, int $slotid): bo * @param int $supervisorid userid of the supervisor in question * @param int $slotid the slot to check * - * @throw \moodle_exception if the user has insufficient permissions + * @throws \moodle_exception if the user has insufficient permissions */ public static function assert_slot_supervisor(int $supervisorid, int $slotid): void { if (!self::check_slot_supervisor($supervisorid, $slotid)) { From b1c0c57ec3dc73bbd436cc3cdf7334d1677f30aa Mon Sep 17 00:00:00 2001 From: Riedler Date: Fri, 3 Jan 2025 12:49:52 +0100 Subject: [PATCH 5/5] fix: absolute import for context_system --- lbplanner/classes/helpers/slot_helper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index a826a0f7..980da3e5 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -25,7 +25,8 @@ namespace local_lbplanner\helpers; -use context_system; +use core\context\system as context_system; + use DateInterval; use DateTime; use DateTimeImmutable;