Differences Between: [Versions 400 and 402] [Versions 401 and 402]
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 namespace quizaccess_seb\external; 18 19 use quizaccess_seb\seb_quiz_settings; 20 21 defined('MOODLE_INTERNAL') || die(); 22 23 require_once (__DIR__ . '/../test_helper_trait.php'); 24 25 /** 26 * PHPUnit tests for external function. 27 * 28 * @package quizaccess_seb 29 * @author Andrew Madden <andrewmadden@catalyst-au.net> 30 * @copyright 2021 Catalyst IT 31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 * @covers \quizaccess_seb\external\validate_quiz_access 33 */ 34 class validate_quiz_access_test extends \advanced_testcase { 35 use \quizaccess_seb_test_helper_trait; 36 37 /** 38 * This method runs before every test. 39 */ 40 public function setUp(): void { 41 parent::setUp(); 42 $this->resetAfterTest(); 43 44 // Generate data objects. 45 $this->course = $this->getDataGenerator()->create_course(); 46 $this->quiz = $this->create_test_quiz($this->course); 47 $this->user = $this->getDataGenerator()->create_user(); 48 $this->getDataGenerator()->enrol_user($this->user->id, $this->course->id, 'student'); 49 $this->setUser($this->user); 50 } 51 52 /** 53 * Bad parameter provider. 54 * 55 * @return array 56 */ 57 public function bad_parameters_provider(): array { 58 return [ 59 'no params' => [ 60 'cmid' => null, 61 'url' => null, 62 'configkey' => null, 63 '/Invalid parameter value detected \(Missing required key in single structure: cmid\)/' 64 ], 65 'no course module id' => [ 66 'cmid' => null, 67 'url' => 'https://www.example.com/moodle', 68 'configkey' => hash('sha256', 'configkey'), 69 '/Invalid parameter value detected \(Missing required key in single structure: cmid\)/' 70 ], 71 'no url' => [ 72 'cmid' => 123, 73 'url' => null, 74 'configkey' => hash('sha256', 'configkey'), 75 '/Invalid parameter value detected \(Missing required key in single structure: url\)/' 76 ], 77 'cmid is not an int' => [ 78 'cmid' => 'test', 79 'url' => 'https://www.example.com/moodle', 80 'configkey' => null, 81 '/Invalid external api parameter: the value is "test", the server was expecting "int" type/' 82 ], 83 'url is not a url' => [ 84 'cmid' => 123, 85 'url' => 123, 86 'configkey' => hash('sha256', 'configkey'), 87 '/Invalid external api parameter: the value is "123", the server was expecting "url" type/' 88 ], 89 ]; 90 } 91 92 /** 93 * Test exception thrown for bad parameters. 94 * 95 * @param mixed $cmid Course module id. 96 * @param mixed $url Page URL. 97 * @param mixed $configkey SEB config key. 98 * @param mixed $messageregex Error message regex to check. 99 * 100 * @dataProvider bad_parameters_provider 101 */ 102 public function test_invalid_parameters($cmid, $url, $configkey, $messageregex) { 103 $params = []; 104 if (!empty($cmid)) { 105 $params['cmid'] = $cmid; 106 } 107 if (!empty($url)) { 108 $params['url'] = $url; 109 } 110 if (!empty($configkey)) { 111 $params['configkey'] = $configkey; 112 } 113 114 $this->expectException(\invalid_parameter_exception::class); 115 $this->expectExceptionMessageMatches($messageregex); 116 \core_external\external_api::validate_parameters(validate_quiz_keys::execute_parameters(), $params); 117 } 118 119 /** 120 * Test that the user has permissions to access context. 121 */ 122 public function test_context_is_not_valid_for_user() { 123 // Set user as user not enrolled in course and quiz. 124 $this->user = $this->getDataGenerator()->create_user(); 125 $this->setUser($this->user); 126 127 $this->expectException(\require_login_exception::class); 128 $this->expectExceptionMessage('Course or activity not accessible. (Not enrolled)'); 129 validate_quiz_keys::execute($this->quiz->cmid, 'https://www.example.com/moodle', 'configkey'); 130 } 131 132 /** 133 * Test exception thrown when no key provided. 134 */ 135 public function test_no_keys_provided() { 136 $this->expectException(\invalid_parameter_exception::class); 137 $this->expectExceptionMessage('At least one Safe Exam Browser key must be provided.'); 138 validate_quiz_keys::execute($this->quiz->cmid, 'https://www.example.com/moodle'); 139 } 140 141 /** 142 * Test exception thrown if cmid doesn't match a quiz. 143 */ 144 public function test_quiz_does_not_exist() { 145 $this->setAdminUser(); 146 $forum = $this->getDataGenerator()->create_module('forum', ['course' => $this->course->id]); 147 $this->expectException(\invalid_parameter_exception::class); 148 $this->expectExceptionMessage('Quiz not found matching course module ID: ' . $forum->cmid); 149 validate_quiz_keys::execute($forum->cmid, 'https://www.example.com/moodle', 'configkey'); 150 } 151 152 /** 153 * Test config key is valid. 154 */ 155 public function test_config_key_valid() { 156 $sink = $this->redirectEvents(); 157 // Test settings to populate the quiz. 158 $settings = $this->get_test_settings([ 159 'quizid' => $this->quiz->id, 160 'cmid' => $this->quiz->cmid, 161 ]); 162 $url = 'https://www.example.com/moodle'; 163 164 // Create the quiz settings. 165 $quizsettings = new seb_quiz_settings(0, $settings); 166 $quizsettings->save(); 167 168 $fullconfigkey = hash('sha256', $url . $quizsettings->get_config_key()); 169 $result = validate_quiz_keys::execute($this->quiz->cmid, $url, $fullconfigkey); 170 $this->assertTrue($result['configkey']); 171 $this->assertTrue($result['browserexamkey']); 172 173 $events = $sink->get_events(); 174 $this->assertCount(0, $events); 175 } 176 177 /** 178 * Test config key is not valid. 179 */ 180 public function test_config_key_not_valid() { 181 $sink = $this->redirectEvents(); 182 // Test settings to populate the quiz. 183 $settings = $this->get_test_settings([ 184 'quizid' => $this->quiz->id, 185 'cmid' => $this->quiz->cmid, 186 ]); 187 188 // Create the quiz settings. 189 $quizsettings = new seb_quiz_settings(0, $settings); 190 $quizsettings->save(); 191 192 $result = validate_quiz_keys::execute($this->quiz->cmid, 'https://www.example.com/moodle', 'badconfigkey'); 193 $this->assertFalse($result['configkey']); 194 $this->assertTrue($result['browserexamkey']); 195 $events = $sink->get_events(); 196 $this->assertCount(1, $events); 197 $event = reset($events); 198 $this->assertInstanceOf('\quizaccess_seb\event\access_prevented', $event); 199 $this->assertStringContainsString('Invalid SEB config key', $event->get_description()); 200 } 201 202 /** 203 * Test browser exam key is valid. 204 */ 205 public function test_browser_exam_key_valid() { 206 $sink = $this->redirectEvents(); 207 // Test settings to populate the quiz. 208 $url = 'https://www.example.com/moodle'; 209 $validbrowserexamkey = hash('sha256', 'validbrowserexamkey'); 210 $settings = $this->get_test_settings([ 211 'quizid' => $this->quiz->id, 212 'cmid' => $this->quiz->cmid, 213 'requiresafeexambrowser' => \quizaccess_seb\settings_provider::USE_SEB_CLIENT_CONFIG, 214 'allowedbrowserexamkeys' => $validbrowserexamkey, 215 ]); 216 217 // Create the quiz settings. 218 $quizsettings = new seb_quiz_settings(0, $settings); 219 $quizsettings->save(); 220 221 $fullbrowserexamkey = hash('sha256', $url . $validbrowserexamkey); 222 $result = validate_quiz_keys::execute($this->quiz->cmid, $url, null, $fullbrowserexamkey); 223 $this->assertTrue($result['configkey']); 224 $this->assertTrue($result['browserexamkey']); 225 $events = $sink->get_events(); 226 $this->assertCount(0, $events); 227 } 228 229 /** 230 * Test browser exam key is not valid. 231 */ 232 public function test_browser_exam_key_not_valid() { 233 $sink = $this->redirectEvents(); 234 // Test settings to populate the quiz. 235 $validbrowserexamkey = hash('sha256', 'validbrowserexamkey'); 236 $settings = $this->get_test_settings([ 237 'quizid' => $this->quiz->id, 238 'cmid' => $this->quiz->cmid, 239 'requiresafeexambrowser' => \quizaccess_seb\settings_provider::USE_SEB_CLIENT_CONFIG, 240 'allowedbrowserexamkeys' => $validbrowserexamkey, 241 ]); 242 243 // Create the quiz settings. 244 $quizsettings = new seb_quiz_settings(0, $settings); 245 $quizsettings->save(); 246 247 $result = validate_quiz_keys::execute($this->quiz->cmid, 'https://www.example.com/moodle', null, 248 hash('sha256', 'badbrowserexamkey')); 249 $this->assertTrue($result['configkey']); 250 $this->assertFalse($result['browserexamkey']); 251 $events = $sink->get_events(); 252 $this->assertCount(1, $events); 253 $event = reset($events); 254 $this->assertInstanceOf('\quizaccess_seb\event\access_prevented', $event); 255 $this->assertStringContainsString('Invalid SEB browser key', $event->get_description()); 256 } 257 258 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body