Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [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\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\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 = seb_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 = seb_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 = seb_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 = seb_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 = seb_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 = seb_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 = seb_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 = seb_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 = seb_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(seb_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(seb_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(seb_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 = seb_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(seb_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  }