diff --git a/classes/local/controllers/infopage.php b/classes/local/controllers/infopage.php index 0fdb6b6..760943f 100644 --- a/classes/local/controllers/infopage.php +++ b/classes/local/controllers/infopage.php @@ -48,6 +48,11 @@ class infopage { */ private $outage; + /** + * @var bool|null Defines if the page is generated for a static outage page. + */ + private $static; + /** * infopage_controller constructor. * @param array $params Parameters to use or null to get from Moodle API (request). @@ -62,11 +67,13 @@ class infopage { $params = [ 'id' => optional_param('id', null, PARAM_INT), 'outage' => null, + 'static' => optional_param('static', false, PARAM_BOOL), ]; } else { $defaults = [ 'id' => null, 'outage' => null, + 'static' => false, ]; $params = array_merge($defaults, $params); } @@ -97,10 +104,14 @@ class infopage { public function output() { global $PAGE, $CFG, $OUTPUT; - if (is_null($this->outage) || !has_capability('auth/outage:viewinfo', context_system::instance())) { + if (is_null($this->outage)) { redirect(new moodle_url('/')); } + // If it's not static outage page, then check access, then redirect if not allowed. + if (!$this->static && !has_capability('auth/outage:viewinfo', context_system::instance())) { + redirect(new moodle_url('/')); + } $PAGE->set_context(context_system::instance()); $PAGE->set_title($this->outage->get_title()); $PAGE->set_heading($this->outage->get_title()); @@ -143,5 +154,6 @@ class infopage { } $this->outage = $params['outage']; + $this->static = $params['static']; } } diff --git a/classes/local/controllers/maintenance_static_page.php b/classes/local/controllers/maintenance_static_page.php index 41def14..73a4a3d 100644 --- a/classes/local/controllers/maintenance_static_page.php +++ b/classes/local/controllers/maintenance_static_page.php @@ -61,7 +61,7 @@ class maintenance_static_page { $html = ''; } else { $data = maintenance_static_page_io::file_get_data( - $CFG->wwwroot.'/auth/outage/info.php?auth_outage_hide_warning=1&id='.$outage->id); + $CFG->wwwroot.'/auth/outage/info.php?auth_outage_hide_warning=1&static=1&id='.$outage->id); $html = $data['contents']; } diff --git a/tests/phpunit/base_testcase.php b/tests/phpunit/base_testcase.php index 910148f..9a33623 100644 --- a/tests/phpunit/base_testcase.php +++ b/tests/phpunit/base_testcase.php @@ -32,6 +32,7 @@ */ use auth_outage\dml\outagedb; +use auth_outage\local\outage; defined('MOODLE_INTERNAL') || die(); @@ -65,6 +66,37 @@ abstract class auth_outage_base_testcase extends advanced_testcase { } } + /** + * Revoke permission to see info page. + */ + protected function revoke_info_page_permissions() { + global $DB; + + $guestrole = $DB->get_record('role', array('shortname' => 'guest')); + role_change_permission($guestrole->id, context_system::instance(), 'auth/outage:viewinfo', CAP_PREVENT); + + $this->setGuestUser(); + } + + /** + * Get an outage object. + * + * @return \auth_outage\local\outage + */ + protected function get_dummy_outage() { + $now = time(); + + return new outage([ + 'id' => 1, + 'autostart' => false, + 'warntime' => $now - 100, + 'starttime' => $now + 100, + 'stoptime' => $now + 200, + 'title' => 'Title', + 'description' => 'Description', + ]); + } + /** * Setup testcase. */ diff --git a/tests/phpunit/local/controllers/infopage_test.php b/tests/phpunit/local/controllers/infopage_test.php index e7a8334..e9a844c 100644 --- a/tests/phpunit/local/controllers/infopage_test.php +++ b/tests/phpunit/local/controllers/infopage_test.php @@ -42,6 +42,8 @@ class auth_outage_infopagecontroller_test extends auth_outage_base_testcase { * Tests the constructor. */ public function test_constructor() { + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + new infopage(); } @@ -49,6 +51,8 @@ class auth_outage_infopagecontroller_test extends auth_outage_base_testcase { * Tests the constructor with given parameters. */ public function test_constructor_withparams() { + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + $_GET = ['id' => 1, 'static' => 'true']; new infopage(); } @@ -57,16 +61,10 @@ class auth_outage_infopagecontroller_test extends auth_outage_base_testcase { * Tests the constructor with different id and outage id. */ public function test_constructor_idmismatch() { - $outage = new outage([ - 'id' => 1, - 'autostart' => false, - 'warntime' => time() - 60, - 'starttime' => time(), - 'stoptime' => time() + 60, - 'title' => 'Title', - 'description' => 'Description', - ]); - $this->set_expected_exception('coding_exception'); + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + + $outage = $this->get_dummy_outage(); + $this->set_expected_exception('coding_exception', 'Provided id and outage->id do not match. (2/1)'); new infopage(['id' => 2, 'outage' => $outage]); } @@ -74,43 +72,92 @@ class auth_outage_infopagecontroller_test extends auth_outage_base_testcase { * Tests the constructor with an invalid outage. */ public function test_constructor_invalidoutage() { - $this->set_expected_exception('coding_exception'); - new infopage(['outage' => 'My outage']); - } + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); - /** - * We should have an exception because CLI cannot redirect. - */ - public function test_output_nonstatic_nooutage() { - $info = new infopage(['static' => false]); - $this->set_expected_exception('moodle_exception'); - $info->output(); + $this->set_expected_exception('coding_exception', 'Provided outage is not a valid outage object. (My outage)'); + new infopage(['outage' => 'My outage']); } /** * Checks the output of the info page. */ public function test_output() { - $now = time(); - $outage = new outage([ - 'id' => 1, - 'autostart' => false, - 'warntime' => $now - 100, - 'starttime' => $now + 100, - 'stoptime' => $now + 200, - 'title' => 'Title', - 'description' => 'Description', - ]); + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + + $outage = $this->get_dummy_outage(); + $info = new infopage(['outage' => $outage]); $output = $info->get_output(); self::assertStringContainsString('auth_outage_info', $output); } + /** + * Checks the output of the info page. + */ + public function test_output_without_permission() { + $this->revoke_info_page_permissions(); + $this->assertFalse(has_capability('auth/outage:viewinfo', context_system::instance())); + + $outage = $this->get_dummy_outage(); + $info = new infopage(['outage' => $outage]); + + $this->set_expected_exception('moodle_exception', 'Unsupported redirect detected, script execution terminated'); + $output = $info->get_output(); + } + + /** + * Checks the output of the info page. + */ + public function test_output_without_permission_but_static() { + $this->revoke_info_page_permissions(); + $this->assertFalse(has_capability('auth/outage:viewinfo', context_system::instance())); + + $outage = $this->get_dummy_outage(); + $info = new infopage(['outage' => $outage, 'static' => true]); + + $output = $info->get_output(); + self::assertStringContainsString('auth_outage_info', $output); + } + + /** + * Checks the output of the info page. + */ + public function test_output_with_forcelogin() { + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + + set_config('forcelogin', true); + + $outage = $this->get_dummy_outage(); + $info = new infopage(['outage' => $outage]); + + $this->set_expected_exception('moodle_exception', 'Unsupported redirect detected, script execution terminated'); + $info->get_output(); + } + + /** + * Checks the output of the info page. + */ + public function test_output_with_forcelogin_if_static() { + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + + set_config('forcelogin', true); + + $outage = $this->get_dummy_outage(); + + $info = new infopage(['outage' => $outage, 'static' => true]); + + $output = $info->get_output(); + self::assertStringContainsString('auth_outage_info', $output); + } + /** * Tests the constructor enables SVG support. */ public function test_svgicons_is_true() { global $CFG; + + $this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance())); + $CFG->svgicons = false; new infopage(); self::assertTrue($CFG->svgicons);