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 400 and 401]

   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  declare(strict_types=1);
  18  
  19  namespace core_reportbuilder;
  20  
  21  use advanced_testcase;
  22  use context_system;
  23  use core_reportbuilder_generator;
  24  use Throwable;
  25  use core_user\reportbuilder\datasource\users;
  26  use core_reportbuilder\reportbuilder\audience\manual;
  27  
  28  /**
  29   * Unit tests for the report permission class
  30   *
  31   * @package     core_reportbuilder
  32   * @covers      \core_reportbuilder\permission
  33   * @copyright   2021 Paul Holden <paulh@moodle.com>
  34   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class permission_test extends advanced_testcase {
  37  
  38      /**
  39       * Test whether user can view reports list
  40       */
  41      public function test_require_can_view_reports_list(): void {
  42          global $DB;
  43  
  44          $this->resetAfterTest();
  45  
  46          // User with permission.
  47          $this->setAdminUser();
  48          try {
  49              permission::require_can_view_reports_list();
  50          } catch (Throwable $exception) {
  51              $this->fail($exception->getMessage());
  52          }
  53  
  54          // User without permission.
  55          $user = $this->getDataGenerator()->create_user();
  56          $this->setUser($user);
  57  
  58          $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']);
  59          unassign_capability('moodle/reportbuilder:view', $userrole, context_system::instance());
  60  
  61          $this->expectException(report_access_exception::class);
  62          $this->expectExceptionMessage('You cannot view this report');
  63          permission::require_can_view_reports_list();
  64      }
  65  
  66      /**
  67       * Test whether user can view reports list when custom reports are disabled
  68       */
  69      public function test_require_can_view_reports_list_disabled(): void {
  70          $this->resetAfterTest();
  71          $this->setAdminUser();
  72  
  73          set_config('enablecustomreports', 0);
  74  
  75          $this->expectException(report_access_exception::class);
  76          $this->expectExceptionMessage('You cannot view this report');
  77          permission::require_can_view_reports_list();
  78      }
  79  
  80      /**
  81       * Test whether user can view specific report
  82       */
  83      public function test_require_can_view_report(): void {
  84          global $DB;
  85  
  86          $this->resetAfterTest();
  87  
  88          /** @var core_reportbuilder_generator $generator */
  89          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
  90          $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
  91  
  92          // User with permission.
  93          $this->setAdminUser();
  94          try {
  95              permission::require_can_view_report($report);
  96          } catch (Throwable $exception) {
  97              $this->fail($exception->getMessage());
  98          }
  99  
 100          // User without permission.
 101          $user = $this->getDataGenerator()->create_user();
 102          $this->setUser($user);
 103  
 104          $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']);
 105          unassign_capability('moodle/reportbuilder:view', $userrole, context_system::instance());
 106  
 107          $this->expectException(report_access_exception::class);
 108          $this->expectExceptionMessage('You cannot view this report');
 109          permission::require_can_view_report($report);
 110      }
 111  
 112      /**
 113       * Test whether user can view specific report when it belongs to an audience
 114       */
 115      public function test_require_can_view_report_with_audience(): void {
 116          global $DB;
 117  
 118          $this->resetAfterTest();
 119  
 120          /** @var core_reportbuilder_generator $generator */
 121          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 122          $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
 123  
 124          // User without permission.
 125          $user = $this->getDataGenerator()->create_user();
 126          $this->setUser($user);
 127  
 128          $generator->create_audience([
 129              'reportid' => $report->get('id'),
 130              'classname' => manual::class,
 131              'configdata' => ['users' => [$user->id]],
 132          ]);
 133  
 134          // User has view capability and belongs to an audience.
 135          permission::require_can_view_report($report);
 136  
 137          $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']);
 138          unassign_capability('moodle/reportbuilder:view', $userrole, context_system::instance());
 139  
 140          // User does not have view capability and belongs to an audience.
 141          $this->expectException(report_access_exception::class);
 142          $this->expectExceptionMessage('You cannot view this report');
 143          permission::require_can_view_report($report);
 144      }
 145  
 146      /**
 147       * Test whether user can view report when custom reports are disabled
 148       */
 149      public function test_require_can_view_report_disabled(): void {
 150          $this->resetAfterTest();
 151          $this->setAdminUser();
 152  
 153          set_config('enablecustomreports', 0);
 154  
 155          /** @var core_reportbuilder_generator $generator */
 156          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 157          $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
 158  
 159          $this->expectException(report_access_exception::class);
 160          $this->expectExceptionMessage('You cannot view this report');
 161          permission::require_can_view_report($report);
 162      }
 163  
 164      /**
 165       * Test that user cannot edit system reports
 166       */
 167      public function test_require_can_edit_report_system_report(): void {
 168          global $CFG;
 169          require_once("{$CFG->dirroot}/reportbuilder/tests/fixtures/system_report_available.php");
 170  
 171          $this->resetAfterTest();
 172          $this->setAdminUser();
 173  
 174          $systemreport = system_report_factory::create(system_report_available::class, context_system::instance());
 175  
 176          $this->expectException(report_access_exception::class);
 177          $this->expectExceptionMessage('You cannot edit this report');
 178          permission::require_can_edit_report($systemreport->get_report_persistent());
 179      }
 180  
 181      /**
 182       * Test that user cannot edit any reports without capabilities
 183       */
 184      public function test_require_can_edit_report_none(): void {
 185          $this->resetAfterTest();
 186  
 187          $user = $this->getDataGenerator()->create_user();
 188          $this->setUser($user);
 189  
 190          /** @var core_reportbuilder_generator $generator */
 191          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 192          $report = $generator->create_report(['name' => 'User', 'source' => users::class]);
 193  
 194          $this->expectException(report_access_exception::class);
 195          $this->expectExceptionMessage('You cannot edit this report');
 196          permission::require_can_edit_report($report);
 197      }
 198  
 199      /**
 200       * Test that user can edit their own reports
 201       */
 202      public function test_require_can_edit_report_own(): void {
 203          global $DB;
 204  
 205          $this->resetAfterTest();
 206  
 207          $user = $this->getDataGenerator()->create_user();
 208          $this->setUser($user);
 209  
 210          $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']);
 211          assign_capability('moodle/reportbuilder:edit', CAP_ALLOW, $userrole, context_system::instance());
 212  
 213          /** @var core_reportbuilder_generator $generator */
 214          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 215  
 216          // Confirm user can edit their own report.
 217          $reportuser = $generator->create_report(['name' => 'User', 'source' => users::class]);
 218          permission::require_can_edit_report($reportuser);
 219  
 220          // Create a report by another user, confirm current user cannot edit it.
 221          $reportadmin = $generator->create_report(['name' => 'Admin', 'source' => users::class, 'usercreated' => get_admin()->id]);
 222  
 223          $this->expectException(report_access_exception::class);
 224          $this->expectExceptionMessage('You cannot edit this report');
 225          permission::require_can_edit_report($reportadmin);
 226      }
 227  
 228      /**
 229       * Test that user can edit any reports
 230       */
 231      public function test_require_can_edit_report_all(): void {
 232          global $DB;
 233  
 234          $this->resetAfterTest();
 235  
 236          $user = $this->getDataGenerator()->create_user();
 237          $this->setUser($user);
 238  
 239          $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']);
 240          assign_capability('moodle/reportbuilder:editall', CAP_ALLOW, $userrole, context_system::instance());
 241  
 242          /** @var core_reportbuilder_generator $generator */
 243          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 244  
 245          // Confirm user can edit their own report.
 246          $reportuser = $generator->create_report(['name' => 'User', 'source' => users::class]);
 247          permission::require_can_edit_report($reportuser);
 248  
 249          // Create a report by another user, confirm current user can edit it.
 250          $reportadmin = $generator->create_report(['name' => 'Admin', 'source' => users::class, 'usercreated' => get_admin()->id]);
 251          permission::require_can_edit_report($reportadmin);
 252      }
 253  
 254      /**
 255       * Test whether user can edit report when custom reports are disabled
 256       */
 257      public function test_require_can_edit_report_disabled(): void {
 258          $this->resetAfterTest();
 259          $this->setAdminUser();
 260  
 261          set_config('enablecustomreports', 0);
 262  
 263          /** @var core_reportbuilder_generator $generator */
 264          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 265          $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
 266  
 267          $this->expectException(report_access_exception::class);
 268          $this->expectExceptionMessage('You cannot edit this report');
 269          permission::require_can_edit_report($report);
 270      }
 271  
 272      /**
 273       * Test that user can create a new report
 274       */
 275      public function test_require_can_create_report(): void {
 276          $this->resetAfterTest();
 277  
 278          // User has edit capability.
 279          $user = $this->getDataGenerator()->create_user();
 280          $this->setUser($user);
 281  
 282          $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
 283          assign_capability('moodle/reportbuilder:edit', CAP_ALLOW, $roleid, context_system::instance());
 284          role_assign($roleid, $user->id, context_system::instance()->id);
 285  
 286          try {
 287              permission::require_can_create_report((int)$user->id);
 288          } catch (Throwable $exception) {
 289              $this->fail($exception->getMessage());
 290          }
 291  
 292          // User has editall capability.
 293          $user2 = $this->getDataGenerator()->create_user();
 294          $this->setUser($user2);
 295  
 296          $roleid2 = create_role('Dummy role 2', 'dummyrole2', 'dummy role 2 description');
 297          assign_capability('moodle/reportbuilder:editall', CAP_ALLOW, $roleid2, context_system::instance());
 298          role_assign($roleid2, $user2->id, context_system::instance()->id);
 299  
 300          try {
 301              permission::require_can_create_report((int)$user2->id);
 302          } catch (Throwable $exception) {
 303              $this->fail($exception->getMessage());
 304          }
 305  
 306          // User has no capability.
 307          $user3 = $this->getDataGenerator()->create_user();
 308          $this->setUser($user3);
 309  
 310          $this->expectException(report_access_exception::class);
 311          $this->expectExceptionMessage('You cannot create a new report');
 312          permission::require_can_create_report((int)$user3->id);
 313      }
 314  
 315      /**
 316       * Test whether user can create report when custom reports are disabled
 317       */
 318      public function test_require_can_create_report_disabled(): void {
 319          $this->resetAfterTest();
 320          $this->setAdminUser();
 321  
 322          set_config('enablecustomreports', 0);
 323  
 324          /** @var core_reportbuilder_generator $generator */
 325          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 326          $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
 327  
 328          $this->expectException(report_access_exception::class);
 329          $this->expectExceptionMessage('You cannot create a new report');
 330          permission::require_can_create_report();
 331      }
 332  
 333      /**
 334       * Data provider for {@see test_can_create_report_limit_reached}
 335       *
 336       * @return array
 337       */
 338      public function can_create_report_limit_reached_provider(): array {
 339          return [
 340              [0, 1, true],
 341              [1, 1, false],
 342              [2, 1, true],
 343              [1, 2, false],
 344          ];
 345      }
 346  
 347      /**
 348       * Test whether user can create report when limit report are reache
 349       * @param int $customreportslimit
 350       * @param int $existingreports
 351       * @param bool $expected
 352       * @dataProvider can_create_report_limit_reached_provider
 353       */
 354      public function test_can_create_report_limit_reached(int $customreportslimit, int $existingreports, bool $expected): void {
 355          global $CFG;
 356  
 357          $this->resetAfterTest();
 358          $this->setAdminUser();
 359  
 360          /** @var core_reportbuilder_generator $generator */
 361          $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
 362          for ($i = 1; $i <= $existingreports; $i++) {
 363              $generator->create_report(['name' => 'Report limited '.$i, 'source' => users::class]);
 364          }
 365  
 366          // Set current custom report limit, and check whether user can create reports.
 367          $CFG->customreportslimit = $customreportslimit;
 368          $this->assertEquals($expected, permission::can_create_report());
 369      }
 370  }