. declare(strict_types=1); namespace core_reportbuilder; use advanced_testcase; use context_system; use core_reportbuilder_generator; use Throwable; use core_user\reportbuilder\datasource\users; use core_reportbuilder\reportbuilder\audience\manual; /** * Unit tests for the report permission class * * @package core_reportbuilder * @covers \core_reportbuilder\permission * @copyright 2021 Paul Holden * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class permission_test extends advanced_testcase { /** * Test whether user can view reports list */ public function test_require_can_view_reports_list(): void { global $DB; $this->resetAfterTest(); // User with permission. $this->setAdminUser(); try { permission::require_can_view_reports_list(); } catch (Throwable $exception) { $this->fail($exception->getMessage()); } // User without permission. $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']); unassign_capability('moodle/reportbuilder:view', $userrole, context_system::instance()); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot view this report'); permission::require_can_view_reports_list(); } /** * Test whether user can view reports list when custom reports are disabled */ public function test_require_can_view_reports_list_disabled(): void { $this->resetAfterTest(); $this->setAdminUser(); set_config('enablecustomreports', 0); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot view this report'); permission::require_can_view_reports_list(); } /** * Test whether user can view specific report */ public function test_require_can_view_report(): void { global $DB; $this->resetAfterTest(); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); // User with permission. $this->setAdminUser(); try { permission::require_can_view_report($report); } catch (Throwable $exception) { $this->fail($exception->getMessage()); } // User without permission. $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']); unassign_capability('moodle/reportbuilder:view', $userrole, context_system::instance()); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot view this report'); permission::require_can_view_report($report); } /** * Test whether user can view specific report when it belongs to an audience */ public function test_require_can_view_report_with_audience(): void { global $DB; $this->resetAfterTest(); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); // User without permission. $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $generator->create_audience([ 'reportid' => $report->get('id'), 'classname' => manual::class, 'configdata' => ['users' => [$user->id]], ]); // User has view capability and belongs to an audience. permission::require_can_view_report($report); $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']); unassign_capability('moodle/reportbuilder:view', $userrole, context_system::instance()); // User does not have view capability and belongs to an audience. $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot view this report'); permission::require_can_view_report($report); } /** * Test whether user can view report when custom reports are disabled */ public function test_require_can_view_report_disabled(): void { $this->resetAfterTest(); $this->setAdminUser(); set_config('enablecustomreports', 0); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot view this report'); permission::require_can_view_report($report); } /** * Test that user cannot edit system reports */ public function test_require_can_edit_report_system_report(): void { global $CFG; require_once("{$CFG->dirroot}/reportbuilder/tests/fixtures/system_report_available.php"); $this->resetAfterTest(); $this->setAdminUser(); $systemreport = system_report_factory::create(system_report_available::class, context_system::instance()); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot edit this report'); permission::require_can_edit_report($systemreport->get_report_persistent()); } /** * Test that user cannot edit any reports without capabilities */ public function test_require_can_edit_report_none(): void { $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'User', 'source' => users::class]); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot edit this report'); permission::require_can_edit_report($report); } /** * Test that user can edit their own reports */ public function test_require_can_edit_report_own(): void { global $DB; $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']); assign_capability('moodle/reportbuilder:edit', CAP_ALLOW, $userrole, context_system::instance()); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); // Confirm user can edit their own report. $reportuser = $generator->create_report(['name' => 'User', 'source' => users::class]); permission::require_can_edit_report($reportuser); // Create a report by another user, confirm current user cannot edit it. $reportadmin = $generator->create_report(['name' => 'Admin', 'source' => users::class, 'usercreated' => get_admin()->id]); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot edit this report'); permission::require_can_edit_report($reportadmin); } /** * Test that user can edit any reports */ public function test_require_can_edit_report_all(): void { global $DB; $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']); assign_capability('moodle/reportbuilder:editall', CAP_ALLOW, $userrole, context_system::instance()); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); // Confirm user can edit their own report. $reportuser = $generator->create_report(['name' => 'User', 'source' => users::class]); permission::require_can_edit_report($reportuser); // Create a report by another user, confirm current user can edit it. $reportadmin = $generator->create_report(['name' => 'Admin', 'source' => users::class, 'usercreated' => get_admin()->id]); permission::require_can_edit_report($reportadmin); } /** * Test whether user can edit report when custom reports are disabled */ public function test_require_can_edit_report_disabled(): void { $this->resetAfterTest(); $this->setAdminUser(); set_config('enablecustomreports', 0); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot edit this report'); permission::require_can_edit_report($report); } /** * Test that user can create a new report */ public function test_require_can_create_report(): void { $this->resetAfterTest(); // User has edit capability. $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description'); assign_capability('moodle/reportbuilder:edit', CAP_ALLOW, $roleid, context_system::instance()); role_assign($roleid, $user->id, context_system::instance()->id); try { permission::require_can_create_report((int)$user->id); } catch (Throwable $exception) { $this->fail($exception->getMessage()); } // User has editall capability. $user2 = $this->getDataGenerator()->create_user(); $this->setUser($user2); $roleid2 = create_role('Dummy role 2', 'dummyrole2', 'dummy role 2 description'); assign_capability('moodle/reportbuilder:editall', CAP_ALLOW, $roleid2, context_system::instance()); role_assign($roleid2, $user2->id, context_system::instance()->id); try { permission::require_can_create_report((int)$user2->id); } catch (Throwable $exception) { $this->fail($exception->getMessage()); } // User has no capability. $user3 = $this->getDataGenerator()->create_user(); $this->setUser($user3); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot create a new report'); permission::require_can_create_report((int)$user3->id); } /** * Test whether user can create report when custom reports are disabled */ public function test_require_can_create_report_disabled(): void { $this->resetAfterTest(); $this->setAdminUser(); set_config('enablecustomreports', 0); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); $report = $generator->create_report(['name' => 'My report', 'source' => users::class]); $this->expectException(report_access_exception::class); $this->expectExceptionMessage('You cannot create a new report'); permission::require_can_create_report(); } /** * Data provider for {@see test_can_create_report_limit_reached} * * @return array */ public function can_create_report_limit_reached_provider(): array { return [ [0, 1, true], [1, 1, false], [2, 1, true], [1, 2, false], ]; } /** * Test whether user can create report when limit report are reache * @param int $customreportslimit * @param int $existingreports * @param bool $expected * @dataProvider can_create_report_limit_reached_provider */ public function test_can_create_report_limit_reached(int $customreportslimit, int $existingreports, bool $expected): void { global $CFG; $this->resetAfterTest(); $this->setAdminUser(); /** @var core_reportbuilder_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); for ($i = 1; $i <= $existingreports; $i++) { $generator->create_report(['name' => 'Report limited '.$i, 'source' => users::class]); } // Set current custom report limit, and check whether user can create reports. $CFG->customreportslimit = $customreportslimit; $this->assertEquals($expected, permission::can_create_report()); } }