Navigation Menu

Skip to content

Commit

Permalink
MDL-71239 calendar: disallow manager role users edit user events
Browse files Browse the repository at this point in the history
  • Loading branch information
dcai authored and Jenkins committed Jan 11, 2022
1 parent bd7f72c commit 1b2ec27
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 34 deletions.
6 changes: 3 additions & 3 deletions calendar/externallib.php
Expand Up @@ -803,18 +803,18 @@ public static function get_calendar_event_by_id($eventid) {
$warnings = array();

$eventvault = event_container::get_event_vault();
if ($event = $eventvault->get_event_by_id($eventid)) {
if ($event = $eventvault->get_event_by_id($params['eventid'])) {
$mapper = event_container::get_event_mapper();
if (!calendar_view_event_allowed($mapper->from_event_to_legacy_event($event))) {
$event = null;
throw new moodle_exception('nopermissiontoviewcalendar', 'error');
}
}

if (!$event) {
// We can't return a warning in this case because the event is not optional.
// We don't know the context for the event and it's not worth loading it.
$syscontext = context_system::instance();
throw new \required_capability_exception($syscontext, 'moodle/course:view', 'nopermission', '');
throw new \required_capability_exception($syscontext, 'moodle/course:view', 'nopermissions', 'error');
}

$cache = new events_related_objects_cache([$event]);
Expand Down
77 changes: 55 additions & 22 deletions calendar/lib.php
Expand Up @@ -2171,6 +2171,24 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false, s
return array($courses, $group, $userid);
}

/**
* Can current user manage a non user event in system context.
*
* @param calendar_event|stdClass $event event object
* @return boolean
*/
function calendar_can_manage_non_user_event_in_system($event) {
$sitecontext = \context_system::instance();
$isuserevent = $event->eventtype == 'user';
$canmanageentries = has_capability('moodle/calendar:manageentries', $sitecontext);
// If user has manageentries at site level and it's not user event, return true.
if ($canmanageentries && !$isuserevent) {
return true;
}

return false;
}

/**
* Return the capability for viewing a calendar event.
*
Expand All @@ -2185,10 +2203,7 @@ function calendar_view_event_allowed(calendar_event $event) {
return true;
}

// If a user can manage events at the site level they can see any event.
$sitecontext = \context_system::instance();
// If user has manageentries at site level, return true.
if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
if (calendar_can_manage_non_user_event_in_system($event)) {
return true;
}

Expand Down Expand Up @@ -2244,11 +2259,7 @@ function calendar_view_event_allowed(calendar_event $event) {

return can_access_course(get_course($event->courseid));
} else if ($event->userid) {
if ($event->userid != $USER->id) {
// No-one can ever see another users events.
return false;
}
return true;
return calendar_can_manage_user_event($event);
} else {
throw new moodle_exception('unknown event type');
}
Expand Down Expand Up @@ -2321,10 +2332,7 @@ function calendar_edit_event_allowed($event, $manualedit = false) {
}
}

$sitecontext = \context_system::instance();

// If user has manageentries at site level, return true.
if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
if (calendar_can_manage_non_user_event_in_system($event)) {
return true;
}

Expand All @@ -2348,7 +2356,38 @@ function calendar_edit_event_allowed($event, $manualedit = false) {
// If course is not set, but userid id set, it's a user event.
return (has_capability('moodle/calendar:manageownentries', $event->context));
} else if (!empty($event->userid)) {
return (has_capability('moodle/calendar:manageentries', $event->context));
return calendar_can_manage_user_event($event);
}

return false;
}

/**
* Can current user edit/delete/add an user event?
*
* @param calendar_event|stdClass $event event object
* @return bool
*/
function calendar_can_manage_user_event($event): bool {
global $USER;

if (!($event instanceof \calendar_event)) {
$event = new \calendar_event(clone($event));
}

$canmanage = has_capability('moodle/calendar:manageentries', $event->context);
$canmanageown = has_capability('moodle/calendar:manageownentries', $event->context);
$ismyevent = $event->userid == $USER->id;
$isadminevent = is_siteadmin($event->userid);

if ($canmanageown && $ismyevent) {
return true;
}

// In site context, user must have login and calendar:manageentries permissions
// ... to manage other user's events except admin users.
if ($canmanage && !$isadminevent) {
return true;
}

return false;
Expand Down Expand Up @@ -2660,10 +2699,7 @@ function calendar_add_event_allowed($event) {
return false;
}

$sitecontext = \context_system::instance();

// If user has manageentries at site level, always return true.
if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
if (calendar_can_manage_non_user_event_in_system($event)) {
return true;
}

Expand All @@ -2682,10 +2718,7 @@ function calendar_add_event_allowed($event) {
(has_capability('moodle/calendar:managegroupentries', $event->context)
&& groups_is_member($event->groupid)));
case 'user':
if ($event->userid == $USER->id) {
return (has_capability('moodle/calendar:manageownentries', $event->context));
}
// There is intentionally no 'break'.
return calendar_can_manage_user_event($event);
case 'site':
return has_capability('moodle/calendar:manageentries', $event->context);
default:
Expand Down
8 changes: 4 additions & 4 deletions calendar/tests/events_test.php
Expand Up @@ -223,7 +223,8 @@ public function test_calendar_event_updated() {
* Tests for calendar_event_updated event.
*/
public function test_calendar_event_updated_toggle_visibility() {
global $DB, $SITE;
global $DB;
$siteid = 0;

$this->resetAfterTest();

Expand All @@ -242,10 +243,9 @@ public function test_calendar_event_updated_toggle_visibility() {
$event = $events[0];
$this->assertInstanceOf('\core\event\calendar_event_updated', $event);
$this->assertEquals('event', $event->objecttable);
$this->assertEquals($SITE->id, $event->courseid);
$this->assertEquals($siteid, $event->courseid);
$this->assertEquals($calevent->context, $event->get_context());
$expectedlog = array($SITE->id, 'calendar', 'edit', 'event.php?action=edit&id=' . $calevent->id ,
$calevent->name);
$expectedlog = [$siteid, 'calendar', 'edit', 'event.php?action=edit&id=' . $calevent->id , $calevent->name];
$this->assertEventLegacyLogData($expectedlog, $event);
$other = array('repeatid' => 0, 'timestart' => $time, 'name' => 'Some wickedly awesome event yo!');
$this->assertEquals($other, $event->other);
Expand Down

0 comments on commit 1b2ec27

Please sign in to comment.