Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 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 core;
  18  
  19  /**
  20   * Unit tests for sessionlib.php file.
  21   *
  22   * @package   core
  23   * @category  test
  24   * @author    Petr Skoda <petr.skoda@totaralms.com>
  25   * @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  26   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  class sessionlib_test extends \advanced_testcase {
  29      public function test_cron_setup_user() {
  30          global $PAGE, $USER, $SESSION, $SITE, $CFG;
  31          $this->resetAfterTest();
  32  
  33          // NOTE: this function contains some static caches, let's reset first.
  34          cron_setup_user('reset');
  35  
  36          $admin = get_admin();
  37          $user1 = $this->getDataGenerator()->create_user();
  38          $user2 = $this->getDataGenerator()->create_user();
  39          $course = $this->getDataGenerator()->create_course();
  40  
  41          cron_setup_user();
  42          $this->assertSame($admin->id, $USER->id);
  43          $this->assertSame($PAGE->context, \context_course::instance($SITE->id));
  44          $this->assertSame($CFG->timezone, $USER->timezone);
  45          $this->assertSame('', $USER->lang);
  46          $this->assertSame('', $USER->theme);
  47          $SESSION->test1 = true;
  48          $adminsession = $SESSION;
  49          $adminuser = $USER;
  50          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
  51          $this->assertSame($GLOBALS['SESSION'], $SESSION);
  52          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
  53          $this->assertSame($GLOBALS['USER'], $USER);
  54  
  55          cron_setup_user(null, $course);
  56          $this->assertSame($admin->id, $USER->id);
  57          $this->assertSame($PAGE->context, \context_course::instance($course->id));
  58          $this->assertSame($adminsession, $SESSION);
  59          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
  60          $this->assertSame($GLOBALS['SESSION'], $SESSION);
  61          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
  62          $this->assertSame($GLOBALS['USER'], $USER);
  63  
  64          cron_setup_user($user1);
  65          $this->assertSame($user1->id, $USER->id);
  66          $this->assertSame($PAGE->context, \context_course::instance($SITE->id));
  67          $this->assertNotSame($adminsession, $SESSION);
  68          $this->assertObjectNotHasAttribute('test1', $SESSION);
  69          $this->assertEmpty((array)$SESSION);
  70          $usersession1 = $SESSION;
  71          $SESSION->test2 = true;
  72          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
  73          $this->assertSame($GLOBALS['SESSION'], $SESSION);
  74          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
  75          $this->assertSame($GLOBALS['USER'], $USER);
  76  
  77          cron_setup_user($user1);
  78          $this->assertSame($user1->id, $USER->id);
  79          $this->assertSame($PAGE->context, \context_course::instance($SITE->id));
  80          $this->assertNotSame($adminsession, $SESSION);
  81          $this->assertSame($usersession1, $SESSION);
  82          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
  83          $this->assertSame($GLOBALS['SESSION'], $SESSION);
  84          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
  85          $this->assertSame($GLOBALS['USER'], $USER);
  86  
  87          cron_setup_user($user2);
  88          $this->assertSame($user2->id, $USER->id);
  89          $this->assertSame($PAGE->context, \context_course::instance($SITE->id));
  90          $this->assertNotSame($adminsession, $SESSION);
  91          $this->assertNotSame($usersession1, $SESSION);
  92          $this->assertEmpty((array)$SESSION);
  93          $usersession2 = $SESSION;
  94          $usersession2->test3 = true;
  95          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
  96          $this->assertSame($GLOBALS['SESSION'], $SESSION);
  97          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
  98          $this->assertSame($GLOBALS['USER'], $USER);
  99  
 100          cron_setup_user($user2, $course);
 101          $this->assertSame($user2->id, $USER->id);
 102          $this->assertSame($PAGE->context, \context_course::instance($course->id));
 103          $this->assertNotSame($adminsession, $SESSION);
 104          $this->assertNotSame($usersession1, $SESSION);
 105          $this->assertSame($usersession2, $SESSION);
 106          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
 107          $this->assertSame($GLOBALS['SESSION'], $SESSION);
 108          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
 109          $this->assertSame($GLOBALS['USER'], $USER);
 110  
 111          cron_setup_user($user1);
 112          $this->assertSame($user1->id, $USER->id);
 113          $this->assertSame($PAGE->context, \context_course::instance($SITE->id));
 114          $this->assertNotSame($adminsession, $SESSION);
 115          $this->assertNotSame($usersession1, $SESSION);
 116          $this->assertEmpty((array)$SESSION);
 117          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
 118          $this->assertSame($GLOBALS['SESSION'], $SESSION);
 119          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
 120          $this->assertSame($GLOBALS['USER'], $USER);
 121  
 122          cron_setup_user();
 123          $this->assertSame($admin->id, $USER->id);
 124          $this->assertSame($PAGE->context, \context_course::instance($SITE->id));
 125          $this->assertSame($adminsession, $SESSION);
 126          $this->assertSame($adminuser, $USER);
 127          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
 128          $this->assertSame($GLOBALS['SESSION'], $SESSION);
 129          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
 130          $this->assertSame($GLOBALS['USER'], $USER);
 131  
 132          cron_setup_user('reset');
 133          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
 134          $this->assertSame($GLOBALS['SESSION'], $SESSION);
 135          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
 136          $this->assertSame($GLOBALS['USER'], $USER);
 137  
 138          cron_setup_user();
 139          $this->assertNotSame($adminsession, $SESSION);
 140          $this->assertNotSame($adminuser, $USER);
 141          $this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
 142          $this->assertSame($GLOBALS['SESSION'], $SESSION);
 143          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
 144          $this->assertSame($GLOBALS['USER'], $USER);
 145      }
 146  
 147      /**
 148       * Test provided for secure cookie
 149       *
 150       * @return array of config and secure result
 151       */
 152      public function moodle_cookie_secure_provider() {
 153          return array(
 154              array(
 155                  // Non ssl, not set.
 156                  'config' => array(
 157                      'wwwroot'       => 'http://example.com',
 158                      'sslproxy'      => null,
 159                      'cookiesecure'  => null,
 160                  ),
 161                  'secure' => false,
 162              ),
 163              array(
 164                  // Non ssl, off and ignored.
 165                  'config' => array(
 166                      'wwwroot'       => 'http://example.com',
 167                      'sslproxy'      => null,
 168                      'cookiesecure'  => false,
 169                  ),
 170                  'secure' => false,
 171              ),
 172              array(
 173                  // Non ssl, on and ignored.
 174                  'config' => array(
 175                      'wwwroot'       => 'http://example.com',
 176                      'sslproxy'      => null,
 177                      'cookiesecure'  => true,
 178                  ),
 179                  'secure' => false,
 180              ),
 181              array(
 182                  // SSL via proxy, off.
 183                  'config' => array(
 184                      'wwwroot'       => 'http://example.com',
 185                      'sslproxy'      => true,
 186                      'cookiesecure'  => false,
 187                  ),
 188                  'secure' => false,
 189              ),
 190              array(
 191                  // SSL via proxy, on.
 192                  'config' => array(
 193                      'wwwroot'       => 'http://example.com',
 194                      'sslproxy'      => true,
 195                      'cookiesecure'  => true,
 196                  ),
 197                  'secure' => true,
 198              ),
 199              array(
 200                  // SSL and off.
 201                  'config' => array(
 202                      'wwwroot'       => 'https://example.com',
 203                      'sslproxy'      => null,
 204                      'cookiesecure'  => false,
 205                  ),
 206                  'secure' => false,
 207              ),
 208              array(
 209                  // SSL and on.
 210                  'config' => array(
 211                      'wwwroot'       => 'https://example.com',
 212                      'sslproxy'      => null,
 213                      'cookiesecure'  => true,
 214                  ),
 215                  'secure' => true,
 216              ),
 217          );
 218      }
 219  
 220      /**
 221       * Test for secure cookie
 222       *
 223       * @dataProvider moodle_cookie_secure_provider
 224       *
 225       * @param array $config Array of key value config settings
 226       * @param bool $secure Wether cookies should be secure or not
 227       */
 228      public function test_is_moodle_cookie_secure($config, $secure) {
 229          global $CFG;
 230          $this->resetAfterTest();
 231          foreach ($config as $key => $value) {
 232              $CFG->$key = $value;
 233          }
 234          $this->assertEquals($secure, is_moodle_cookie_secure());
 235      }
 236  
 237      public function test_sesskey() {
 238          global $USER;
 239          $this->resetAfterTest();
 240  
 241          $user = $this->getDataGenerator()->create_user();
 242  
 243          \core\session\manager::init_empty_session();
 244          $this->assertObjectNotHasAttribute('sesskey', $USER);
 245  
 246          $sesskey = sesskey();
 247          $this->assertNotEmpty($sesskey);
 248          $this->assertSame($sesskey, $USER->sesskey);
 249          $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
 250          $this->assertSame($GLOBALS['USER'], $USER);
 251  
 252          $this->assertSame($sesskey, sesskey());
 253  
 254          // Test incomplete session init - the sesskeys should return random values.
 255          $_SESSION = array();
 256          unset($GLOBALS['USER']);
 257          unset($GLOBALS['SESSION']);
 258  
 259          $this->assertFalse(sesskey());
 260          $this->assertArrayNotHasKey('USER', $GLOBALS);
 261          $this->assertFalse(sesskey());
 262      }
 263  
 264      public function test_confirm_sesskey() {
 265          $this->resetAfterTest();
 266  
 267          $sesskey = sesskey();
 268  
 269          try {
 270              confirm_sesskey();
 271              $this->fail('Exception expected when sesskey not present');
 272          } catch (\moodle_exception $e) {
 273              $this->assertSame('missingparam', $e->errorcode);
 274          }
 275  
 276          $this->assertTrue(confirm_sesskey($sesskey));
 277          $this->assertFalse(confirm_sesskey('blahblah'));
 278  
 279          $_GET['sesskey'] = $sesskey;
 280          $this->assertTrue(confirm_sesskey());
 281  
 282          $_GET['sesskey'] = 'blah';
 283          $this->assertFalse(confirm_sesskey());
 284      }
 285  
 286      public function test_require_sesskey() {
 287          $this->resetAfterTest();
 288  
 289          $sesskey = sesskey();
 290  
 291          try {
 292              require_sesskey();
 293              $this->fail('Exception expected when sesskey not present');
 294          } catch (\moodle_exception $e) {
 295              $this->assertSame('missingparam', $e->errorcode);
 296          }
 297  
 298          $_GET['sesskey'] = $sesskey;
 299          require_sesskey();
 300  
 301          $_GET['sesskey'] = 'blah';
 302          try {
 303              require_sesskey();
 304              $this->fail('Exception expected when sesskey not incorrect');
 305          } catch (\moodle_exception $e) {
 306              $this->assertSame('invalidsesskey', $e->errorcode);
 307          }
 308      }
 309  }