MDL-69797 core_grades: Implement authorization into fetch method
authorJuan Segarra Montesinos <juan.segarra@uji.es>
Tue, 27 Oct 2020 18:07:46 +0000 (19:07 +0100)
committerJenkins <jenkins@worker07.test.in.moodle.com>
Tue, 12 Jan 2021 09:24:26 +0000 (10:24 +0100)
grade/classes/grades/grader/gradingpanel/scale/external/fetch.php
grade/tests/grades_grader_gradingpanel_scale_external_fetch_test.php

index 8f3bb48..3501e31 100644 (file)
@@ -127,7 +127,12 @@ class fetch extends external_api {
             throw new moodle_exception("The {$itemname} item in {$component}/{$contextid} is not configured for grading with scales");
         }
 
-        $gradeduser = \core_user::get_user($gradeduserid);
+        $gradeduser = \core_user::get_user($gradeduserid, '*', MUST_EXIST);
+
+        // One can access its own grades. Others just if they're graders.
+        if ($gradeduserid != $USER->id) {
+            $gradeitem->require_user_can_grade($gradeduser, $USER);
+        }
 
         // Set up some items we need to return on other interfaces.
         $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->get_grade_item()->id, 'userid' => $gradeduser->id]);
index cd5de19..9a8ec1d 100644 (file)
@@ -189,14 +189,75 @@ class fetch_test extends advanced_testcase {
         $course = $forum->get_course_record();
         $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
         $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
-        $this->setUser($teacher);
+
+        $this->execute_and_assert_fetch($forum, $options, $scale, $teacher, $teacher, $student);
+    }
+
+    /**
+     * Class mates should not get other's grades.
+     */
+    public function test_execute_fetch_does_not_return_data_to_other_students(): void {
+        $this->resetAfterTest();
+
+        $options = [
+            'A',
+            'B',
+            'C'
+        ];
+        $scale = $this->getDataGenerator()->create_scale(['scale' => implode(',', $options)]);
+
+        $forum = $this->get_forum_instance([
+            // Negative numbers mean a scale.
+            'grade_forum' => -1 * $scale->id
+        ]);
+        $course = $forum->get_course_record();
+        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
+        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
+        $evilstudent = $this->getDataGenerator()->create_and_enrol($course, 'student');
+
+        $this->expectException(\required_capability_exception::class);
+        $this->execute_and_assert_fetch($forum, $options, $scale, $evilstudent, $teacher, $student);
+    }
+
+    /**
+     * Grades can be returned to graded user.
+     */
+    public function test_execute_fetch_return_data_to_graded_user(): void {
+        $this->resetAfterTest();
+
+        $options = [
+            'A',
+            'B',
+            'C'
+        ];
+        $scale = $this->getDataGenerator()->create_scale(['scale' => implode(',', $options)]);
+
+        $forum = $this->get_forum_instance([
+            // Negative numbers mean a scale.
+            'grade_forum' => -1 * $scale->id
+        ]);
+        $course = $forum->get_course_record();
+        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
+        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
+
+        $this->execute_and_assert_fetch($forum, $options, $scale, $student, $teacher, $student);
+    }
+
+    /**
+     * Executes the fetch method with the given users and returns the result.
+     */
+    private function execute_and_assert_fetch ($forum, $options, $scale, $fetcheruser, $grader, $gradeduser) {
+
+        $this->setUser($grader);
 
         $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum');
-        $gradeitem->store_grade_from_formdata($student, $teacher, (object) [
+        $gradeitem->store_grade_from_formdata($gradeduser, $grader, (object) [
             'grade' => 2,
         ]);
 
-        $result = fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $student->id);
+        $this->setUser($fetcheruser);
+
+        $result = fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $gradeduser->id);
         $result = external_api::clean_returnvalue(fetch::execute_returns(), $result);
 
         $this->assertIsArray($result);
@@ -204,7 +265,7 @@ class fetch_test extends advanced_testcase {
 
         $this->assertEquals('core_grades/grades/grader/gradingpanel/scale', $result['templatename']);
 
-        $result = fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $student->id);
+        $result = fetch::execute('mod_forum', (int) $forum->get_context()->id, 'forum', (int) $gradeduser->id);
         $result = external_api::clean_returnvalue(fetch::execute_returns(), $result);
 
         $this->assertIsArray($result);
@@ -232,7 +293,7 @@ class fetch_test extends advanced_testcase {
         $this->assertEquals(3, $result['grade']['maxgrade']);
 
         $this->assertArrayHasKey('gradedby', $result['grade']);
-        $this->assertEquals(fullname($teacher), $result['grade']['gradedby']);
+        $this->assertEquals(fullname($grader), $result['grade']['gradedby']);
 
         $this->assertArrayHasKey('options', $result['grade']);
         $this->assertCount(count($options), $result['grade']['options']);