See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 require_once (__DIR__ . '/test_helper_trait.php'); 22 23 /** 24 * PHPUnit tests for the access manager. 25 * 26 * @package quizaccess_seb 27 * @author Andrew Madden <andrewmadden@catalyst-au.net> 28 * @copyright 2020 Catalyst IT 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 * @covers \quizaccess_seb\access_manager 31 */ 32 class access_manager_test extends \advanced_testcase { 33 use \quizaccess_seb_test_helper_trait; 34 35 /** 36 * Called before every test. 37 */ 38 public function setUp(): void { 39 parent::setUp(); 40 41 $this->resetAfterTest(); 42 $this->setAdminUser(); 43 $this->course = $this->getDataGenerator()->create_course(); 44 } 45 46 /** 47 * Test access_manager private property quizsettings is null. 48 */ 49 public function test_access_manager_quizsettings_null() { 50 $this->quiz = $this->create_test_quiz($this->course); 51 52 $accessmanager = $this->get_access_manager(); 53 54 $this->assertFalse($accessmanager->seb_required()); 55 56 $reflection = new \ReflectionClass('\quizaccess_seb\access_manager'); 57 $property = $reflection->getProperty('quizsettings'); 58 $property->setAccessible(true); 59 60 $this->assertFalse($property->getValue($accessmanager)); 61 } 62 63 /** 64 * Test that SEB is not required. 65 */ 66 public function test_seb_required_false() { 67 $this->quiz = $this->create_test_quiz($this->course); 68 69 $accessmanager = $this->get_access_manager(); 70 $this->assertFalse($accessmanager->seb_required()); 71 } 72 73 /** 74 * Test that SEB is required. 75 */ 76 public function test_seb_required_true() { 77 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 78 79 $accessmanager = $this->get_access_manager(); 80 $this->assertTrue($accessmanager->seb_required()); 81 } 82 83 /** 84 * Test that user has capability to bypass SEB check. 85 */ 86 public function test_user_can_bypass_seb_check() { 87 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 88 89 $user = $this->getDataGenerator()->create_user(); 90 $this->setUser($user); 91 92 // Set the bypass SEB check capability to $USER. 93 $this->assign_user_capability('quizaccess/seb:bypassseb', \context_module::instance($this->quiz->cmid)->id); 94 95 $accessmanager = $this->get_access_manager(); 96 $this->assertTrue($accessmanager->can_bypass_seb()); 97 } 98 99 /** 100 * Test that user has capability to bypass SEB check. 101 */ 102 public function test_admin_user_can_bypass_seb_check() { 103 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 104 105 // Test normal user cannot bypass check. 106 $user = $this->getDataGenerator()->create_user(); 107 $this->setUser($user); 108 $accessmanager = $this->get_access_manager(); 109 $this->assertFalse($accessmanager->can_bypass_seb()); 110 111 // Test with admin user. 112 $this->setAdminUser(); 113 $accessmanager = $this->get_access_manager(); 114 $this->assertTrue($accessmanager->can_bypass_seb()); 115 } 116 117 /** 118 * Test user does not have capability to bypass SEB check. 119 */ 120 public function test_user_cannot_bypass_seb_check() { 121 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 122 123 $user = $this->getDataGenerator()->create_user(); 124 $this->setUser($user); 125 126 $accessmanager = $this->get_access_manager(); 127 $this->assertFalse($accessmanager->can_bypass_seb()); 128 } 129 130 /** 131 * Test we can detect SEB usage. 132 */ 133 public function test_is_using_seb() { 134 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 135 136 $accessmanager = $this->get_access_manager(); 137 138 $this->assertFalse($accessmanager->is_using_seb()); 139 140 $_SERVER['HTTP_USER_AGENT'] = 'Test'; 141 $this->assertFalse($accessmanager->is_using_seb()); 142 143 $_SERVER['HTTP_USER_AGENT'] = 'SEB'; 144 $this->assertTrue($accessmanager->is_using_seb()); 145 } 146 147 /** 148 * Test that the quiz Config Key matches the incoming request header. 149 */ 150 public function test_access_keys_validate_with_config_key() { 151 global $FULLME; 152 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 153 154 $accessmanager = $this->get_access_manager(); 155 156 $configkey = quiz_settings::get_record(['quizid' => $this->quiz->id])->get_config_key(); 157 158 // Set up dummy request. 159 $FULLME = 'https://example.com/moodle/mod/quiz/attempt.php?attemptid=123&page=4'; 160 $expectedhash = hash('sha256', $FULLME . $configkey); 161 $_SERVER['HTTP_X_SAFEEXAMBROWSER_CONFIGKEYHASH'] = $expectedhash; 162 163 $this->assertTrue($accessmanager->validate_config_key()); 164 } 165 166 /** 167 * Test that the quiz Config Key matches a provided config key with no incoming request header. 168 */ 169 public function test_access_keys_validate_with_provided_config_key() { 170 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 171 $url = 'https://www.example.com/moodle'; 172 $accessmanager = $this->get_access_manager(); 173 174 $configkey = quiz_settings::get_record(['quizid' => $this->quiz->id])->get_config_key(); 175 $fullconfigkey = hash('sha256', $url . $configkey); 176 177 $this->assertTrue($accessmanager->validate_config_key($fullconfigkey, $url)); 178 } 179 180 /** 181 * Test that the quiz Config Key does not match the incoming request header. 182 */ 183 public function test_access_keys_fail_to_validate_with_config_key() { 184 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 185 $accessmanager = $this->get_access_manager(); 186 187 $this->assertFalse($accessmanager->validate_config_key()); 188 } 189 190 /** 191 * Test that config key is not checked when using client configuration with SEB. 192 */ 193 public function test_config_key_not_checked_if_client_requirement_is_selected() { 194 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 195 $accessmanager = $this->get_access_manager(); 196 $this->assertFalse($accessmanager->should_validate_config_key()); 197 } 198 199 /** 200 * Test that if there are no browser exam keys for quiz, check is skipped. 201 */ 202 public function test_no_browser_exam_keys_cause_check_to_be_successful() { 203 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 204 205 $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 206 $settings->set('allowedbrowserexamkeys', ''); 207 $settings->save(); 208 $accessmanager = $this->get_access_manager(); 209 $this->assertTrue($accessmanager->should_validate_browser_exam_key()); 210 $this->assertTrue($accessmanager->validate_browser_exam_key()); 211 } 212 213 /** 214 * Test that access fails if there is no hash in header. 215 */ 216 public function test_access_keys_fail_if_browser_exam_key_header_does_not_exist() { 217 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 218 219 $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 220 $settings->set('allowedbrowserexamkeys', hash('sha256', 'one') . "\n" . hash('sha256', 'two')); 221 $settings->save(); 222 $accessmanager = $this->get_access_manager(); 223 $this->assertFalse($accessmanager->validate_browser_exam_key()); 224 } 225 226 /** 227 * Test that access fails if browser exam key doesn't match hash in header. 228 */ 229 public function test_access_keys_fail_if_browser_exam_key_header_does_not_match_provided_hash() { 230 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 231 232 $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 233 $settings->set('allowedbrowserexamkeys', hash('sha256', 'one') . "\n" . hash('sha256', 'two')); 234 $settings->save(); 235 $accessmanager = $this->get_access_manager(); 236 $_SERVER['HTTP_X_SAFEEXAMBROWSER_REQUESTHASH'] = hash('sha256', 'notwhatyouwereexpectinghuh'); 237 $this->assertFalse($accessmanager->validate_browser_exam_key()); 238 } 239 240 /** 241 * Test that browser exam key matches hash in header. 242 */ 243 public function test_browser_exam_keys_match_header_hash() { 244 global $FULLME; 245 246 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 247 $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 248 $browserexamkey = hash('sha256', 'browserexamkey'); 249 $settings->set('allowedbrowserexamkeys', $browserexamkey); // Add a hashed BEK. 250 $settings->save(); 251 $accessmanager = $this->get_access_manager(); 252 253 // Set up dummy request. 254 $FULLME = 'https://example.com/moodle/mod/quiz/attempt.php?attemptid=123&page=4'; 255 $expectedhash = hash('sha256', $FULLME . $browserexamkey); 256 $_SERVER['HTTP_X_SAFEEXAMBROWSER_REQUESTHASH'] = $expectedhash; 257 $this->assertTrue($accessmanager->validate_browser_exam_key()); 258 } 259 260 /** 261 * Test that browser exam key matches a provided browser exam key. 262 */ 263 public function test_browser_exam_keys_match_provided_browser_exam_key() { 264 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 265 $url = 'https://www.example.com/moodle'; 266 $settings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 267 $browserexamkey = hash('sha256', 'browserexamkey'); 268 $fullbrowserexamkey = hash('sha256', $url . $browserexamkey); 269 $settings->set('allowedbrowserexamkeys', $browserexamkey); // Add a hashed BEK. 270 $settings->save(); 271 $accessmanager = $this->get_access_manager(); 272 273 $this->assertTrue($accessmanager->validate_browser_exam_key($fullbrowserexamkey, $url)); 274 } 275 276 /** 277 * Test can get received config key. 278 */ 279 public function test_get_received_config_key() { 280 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 281 $accessmanager = $this->get_access_manager(); 282 283 $this->assertNull($accessmanager->get_received_config_key()); 284 285 $_SERVER['HTTP_X_SAFEEXAMBROWSER_CONFIGKEYHASH'] = 'Test key'; 286 $this->assertEquals('Test key', $accessmanager->get_received_config_key()); 287 } 288 289 /** 290 * Test can get received browser key. 291 */ 292 public function get_received_browser_exam_key() { 293 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 294 $accessmanager = $this->get_access_manager(); 295 296 $this->assertNull($accessmanager->get_received_browser_exam_key()); 297 298 $_SERVER['HTTP_X_SAFEEXAMBROWSER_REQUESTHASH'] = 'Test browser key'; 299 $this->assertEquals('Test browser key', $accessmanager->get_received_browser_exam_key()); 300 } 301 302 /** 303 * Test can correctly get type of SEB usage for the quiz. 304 */ 305 public function test_get_seb_use_type() { 306 // No SEB. 307 $this->quiz = $this->create_test_quiz($this->course); 308 $accessmanager = $this->get_access_manager(); 309 $this->assertEquals(settings_provider::USE_SEB_NO, $accessmanager->get_seb_use_type()); 310 311 // Manually. 312 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 313 $accessmanager = $this->get_access_manager(); 314 $this->assertEquals(settings_provider::USE_SEB_CONFIG_MANUALLY, $accessmanager->get_seb_use_type()); 315 316 // Use template. 317 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 318 $quizsettings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 319 $quizsettings->set('requiresafeexambrowser', settings_provider::USE_SEB_TEMPLATE); 320 $quizsettings->set('templateid', $this->create_template()->get('id')); 321 $quizsettings->save(); 322 $accessmanager = $this->get_access_manager(); 323 $this->assertEquals(settings_provider::USE_SEB_TEMPLATE, $accessmanager->get_seb_use_type()); 324 325 // Use uploaded config. 326 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 327 $quizsettings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 328 $quizsettings->set('requiresafeexambrowser', settings_provider::USE_SEB_UPLOAD_CONFIG); // Doesn't check basic header. 329 $xml = file_get_contents(__DIR__ . '/fixtures/unencrypted.seb'); 330 $this->create_module_test_file($xml, $this->quiz->cmid); 331 $quizsettings->save(); 332 $accessmanager = $this->get_access_manager(); 333 $this->assertEquals(settings_provider::USE_SEB_UPLOAD_CONFIG, $accessmanager->get_seb_use_type()); 334 335 // Use client config. 336 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 337 $accessmanager = $this->get_access_manager(); 338 $this->assertEquals(settings_provider::USE_SEB_CLIENT_CONFIG, $accessmanager->get_seb_use_type()); 339 } 340 341 /** 342 * Data provider for self::test_should_validate_basic_header. 343 * 344 * @return array 345 */ 346 public function should_validate_basic_header_data_provider() { 347 return [ 348 [settings_provider::USE_SEB_NO, false], 349 [settings_provider::USE_SEB_CONFIG_MANUALLY, false], 350 [settings_provider::USE_SEB_TEMPLATE, false], 351 [settings_provider::USE_SEB_UPLOAD_CONFIG, false], 352 [settings_provider::USE_SEB_CLIENT_CONFIG, true], 353 ]; 354 } 355 356 /** 357 * Test we know when we should validate basic header. 358 * 359 * @param int $type Type of SEB usage. 360 * @param bool $expected Expected result. 361 * 362 * @dataProvider should_validate_basic_header_data_provider 363 */ 364 public function test_should_validate_basic_header($type, $expected) { 365 $accessmanager = $this->getMockBuilder(access_manager::class) 366 ->disableOriginalConstructor() 367 ->onlyMethods(['get_seb_use_type']) 368 ->getMock(); 369 $accessmanager->method('get_seb_use_type')->willReturn($type); 370 371 $this->assertEquals($expected, $accessmanager->should_validate_basic_header()); 372 373 } 374 375 /** 376 * Data provider for self::test_should_validate_config_key. 377 * 378 * @return array 379 */ 380 public function should_validate_config_key_data_provider() { 381 return [ 382 [settings_provider::USE_SEB_NO, false], 383 [settings_provider::USE_SEB_CONFIG_MANUALLY, true], 384 [settings_provider::USE_SEB_TEMPLATE, true], 385 [settings_provider::USE_SEB_UPLOAD_CONFIG, true], 386 [settings_provider::USE_SEB_CLIENT_CONFIG, false], 387 ]; 388 } 389 390 /** 391 * Test we know when we should validate config key. 392 * 393 * @param int $type Type of SEB usage. 394 * @param bool $expected Expected result. 395 * 396 * @dataProvider should_validate_config_key_data_provider 397 */ 398 public function test_should_validate_config_key($type, $expected) { 399 $accessmanager = $this->getMockBuilder(access_manager::class) 400 ->disableOriginalConstructor() 401 ->onlyMethods(['get_seb_use_type']) 402 ->getMock(); 403 $accessmanager->method('get_seb_use_type')->willReturn($type); 404 405 $this->assertEquals($expected, $accessmanager->should_validate_config_key()); 406 } 407 408 /** 409 * Data provider for self::test_should_validate_browser_exam_key. 410 * 411 * @return array 412 */ 413 public function should_validate_browser_exam_key_data_provider() { 414 return [ 415 [settings_provider::USE_SEB_NO, false], 416 [settings_provider::USE_SEB_CONFIG_MANUALLY, false], 417 [settings_provider::USE_SEB_TEMPLATE, false], 418 [settings_provider::USE_SEB_UPLOAD_CONFIG, true], 419 [settings_provider::USE_SEB_CLIENT_CONFIG, true], 420 ]; 421 } 422 423 /** 424 * Test we know when we should browser exam key. 425 * 426 * @param int $type Type of SEB usage. 427 * @param bool $expected Expected result. 428 * 429 * @dataProvider should_validate_browser_exam_key_data_provider 430 */ 431 public function test_should_validate_browser_exam_key($type, $expected) { 432 $accessmanager = $this->getMockBuilder(access_manager::class) 433 ->disableOriginalConstructor() 434 ->onlyMethods(['get_seb_use_type']) 435 ->getMock(); 436 $accessmanager->method('get_seb_use_type')->willReturn($type); 437 438 $this->assertEquals($expected, $accessmanager->should_validate_browser_exam_key()); 439 } 440 441 /** 442 * Test that access manager uses cached Config Key. 443 */ 444 public function test_access_manager_uses_cached_config_key() { 445 global $FULLME; 446 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 447 448 $accessmanager = $this->get_access_manager(); 449 450 $configkey = $accessmanager->get_valid_config_key(); 451 452 // Set up dummy request. 453 $FULLME = 'https://example.com/moodle/mod/quiz/attempt.php?attemptid=123&page=4'; 454 $expectedhash = hash('sha256', $FULLME . $configkey); 455 $_SERVER['HTTP_X_SAFEEXAMBROWSER_CONFIGKEYHASH'] = $expectedhash; 456 457 $this->assertTrue($accessmanager->validate_config_key()); 458 459 // Change settings (but don't save) and check that still can validate config key. 460 $quizsettings = quiz_settings::get_record(['quizid' => $this->quiz->id]); 461 $quizsettings->set('showsebtaskbar', 0); 462 $this->assertNotEquals($quizsettings->get_config_key(), $configkey); 463 $this->assertTrue($accessmanager->validate_config_key()); 464 465 // Now save settings which should purge caches but access manager still has config key. 466 $quizsettings->save(); 467 $this->assertNotEquals($quizsettings->get_config_key(), $configkey); 468 $this->assertTrue($accessmanager->validate_config_key()); 469 470 // Initialise a new access manager. Now validation should fail. 471 $accessmanager = $this->get_access_manager(); 472 $this->assertFalse($accessmanager->validate_config_key()); 473 } 474 475 /** 476 * Check that valid SEB config key is null if quiz doesn't have SEB settings. 477 */ 478 public function test_valid_config_key_is_null_if_no_settings() { 479 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_NO); 480 $accessmanager = $this->get_access_manager(); 481 482 $this->assertEmpty(quiz_settings::get_record(['quizid' => $this->quiz->id])); 483 $this->assertNull($accessmanager->get_valid_config_key()); 484 485 } 486 487 /** 488 * Test if config key should not be validated. 489 */ 490 public function test_if_config_key_should_not_be_validated() { 491 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_NO); 492 $accessmanager = $this->get_access_manager(); 493 494 $this->assertTrue($accessmanager->validate_config_key()); 495 } 496 497 /** 498 * Test if browser exam key should not be validated. 499 */ 500 public function test_if_browser_exam_key_should_not_be_validated() { 501 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 502 $accessmanager = $this->get_access_manager(); 503 504 $this->assertTrue($accessmanager->validate_browser_exam_key()); 505 } 506 507 /** 508 * Test that access is set correctly in Moodle session. 509 */ 510 public function test_set_session_access() { 511 global $SESSION; 512 513 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 514 $accessmanager = $this->get_access_manager(); 515 516 $this->assertTrue(empty($SESSION->quizaccess_seb_access[$this->quiz->cmid])); 517 518 $accessmanager->set_session_access(true); 519 520 $this->assertTrue($SESSION->quizaccess_seb_access[$this->quiz->cmid]); 521 } 522 523 /** 524 * Test that access is set in Moodle session for only course module associated with access manager. 525 */ 526 public function test_session_access_set_for_specific_course_module() { 527 global $SESSION; 528 529 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 530 $quiz2 = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 531 $accessmanager = $this->get_access_manager(); 532 533 $accessmanager->set_session_access(true); 534 535 $this->assertCount(1, $SESSION->quizaccess_seb_access); 536 $this->assertTrue($SESSION->quizaccess_seb_access[$this->quiz->cmid]); 537 $this->assertTrue(empty($SESSION->quizaccess_seb_access[$quiz2->cmid])); 538 } 539 540 /** 541 * Test that access state can be retrieved from Moodle session. 542 */ 543 public function test_validate_session_access() { 544 global $SESSION; 545 546 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 547 $accessmanager = $this->get_access_manager(); 548 549 $this->assertEmpty($accessmanager->validate_session_access()); 550 551 $SESSION->quizaccess_seb_access[$this->quiz->cmid] = true; 552 553 $this->assertTrue($accessmanager->validate_session_access()); 554 } 555 556 /** 557 * Test that access can be cleared from Moodle session. 558 */ 559 public function test_clear_session_access() { 560 global $SESSION; 561 562 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CLIENT_CONFIG); 563 $accessmanager = $this->get_access_manager(); 564 565 $SESSION->quizaccess_seb_access[$this->quiz->cmid] = true; 566 567 $accessmanager->clear_session_access(); 568 569 $this->assertTrue(empty($SESSION->quizaccess_seb_access[$this->quiz->cmid])); 570 } 571 572 /** 573 * Test we can decide if need to redirect to SEB config link. 574 */ 575 public function test_should_redirect_to_seb_config_link() { 576 $this->quiz = $this->create_test_quiz($this->course, settings_provider::USE_SEB_CONFIG_MANUALLY); 577 $accessmanager = $this->get_access_manager(); 578 579 set_config('autoreconfigureseb', '1', 'quizaccess_seb'); 580 $_SERVER['HTTP_USER_AGENT'] = 'SEB'; 581 $this->assertFalse($accessmanager->should_redirect_to_seb_config_link()); 582 583 set_config('autoreconfigureseb', '1', 'quizaccess_seb'); 584 $_SERVER['HTTP_USER_AGENT'] = 'SEB'; 585 $_SERVER['HTTP_X_SAFEEXAMBROWSER_CONFIGKEYHASH'] = hash('sha256', 'configkey'); 586 $this->assertTrue($accessmanager->should_redirect_to_seb_config_link()); 587 } 588 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body