mirror of
https://github.com/catalyst/moodle-auth_outage.git
synced 2026-09-07 00:06:01 +02:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bc716aeba | ||
|
|
0da0542663 | ||
|
|
a093165caf | ||
|
|
85d0657563 | ||
|
|
88667c51e4 | ||
|
|
5dd73b0909 | ||
|
|
1a94b8e635 | ||
|
|
40fccef237 | ||
|
|
dbc8e75092 |
@@ -53,10 +53,14 @@ class infopage {
|
||||
$CFG->svgicons = true;
|
||||
|
||||
if (is_null($params)) {
|
||||
$id = optional_param('id', null, PARAM_INT);
|
||||
$params = [
|
||||
'id' => optional_param('id', null, PARAM_INT),
|
||||
'id' => $id,
|
||||
'outage' => null,
|
||||
'static' => optional_param('static', false, PARAM_BOOL),
|
||||
'static' => !is_null($id) && hash_equals(
|
||||
self::statickey($id),
|
||||
optional_param('statickey', '', PARAM_ALPHANUM)
|
||||
),
|
||||
];
|
||||
} else {
|
||||
$defaults = [
|
||||
@@ -152,4 +156,21 @@ class infopage {
|
||||
$this->outage = $params['outage'];
|
||||
$this->static = $params['static'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the secret token that proves a request to view an outage's static
|
||||
* rendering came from this plugin's own static-page generator, not an external
|
||||
* client forging the request. Used to gate the 'static' flag (see constructor).
|
||||
*
|
||||
* @param int $outageid
|
||||
* @return string
|
||||
*/
|
||||
public static function statickey($outageid) {
|
||||
$secret = get_config('auth_outage', 'staticsecret');
|
||||
if (empty($secret)) {
|
||||
$secret = random_string(64);
|
||||
set_config('staticsecret', $secret, 'auth_outage');
|
||||
}
|
||||
return hash_hmac('sha256', (string)$outageid, $secret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ class maintenance_static_page {
|
||||
header('X-Outage-EndTime: ' . $outage->stoptime);
|
||||
}
|
||||
$data = maintenance_static_page_io::file_get_data(
|
||||
$CFG->wwwroot . '/auth/outage/info.php?auth_outage_hide_warning=1&static=1&id=' . $outage->id
|
||||
$CFG->wwwroot . '/auth/outage/info.php?auth_outage_hide_warning=1&id=' . $outage->id
|
||||
. '&statickey=' . infopage::statickey($outage->id)
|
||||
);
|
||||
$html = $data['contents'];
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class outagelib {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
$curl = new curl(['ignoresecurity' => true]);
|
||||
$curl = new curl();
|
||||
$contents = $curl->get($file);
|
||||
$info = $curl->get_info();
|
||||
if (!empty($info['content_type'])) {
|
||||
@@ -267,6 +267,10 @@ class outagelib {
|
||||
// single-quotes (and double for the sake of it) are present otherwise it would break the code.
|
||||
$allowedips = addslashes($allowedips);
|
||||
|
||||
// Escape the access key before substitution into the PHP literal to prevent
|
||||
// code injection via a maliciously crafted access key value.
|
||||
$accesskey = addslashes((string)$accesskey);
|
||||
|
||||
$cookiesecure = is_moodle_cookie_secure();
|
||||
|
||||
// Since Moodle 4.3 cookiehttponly is default to true and this CFG is not set.
|
||||
|
||||
@@ -64,6 +64,41 @@ class base_table extends flexible_table {
|
||||
$this->set_attribute('class', 'generaltable admintable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a user by their fullname with a link to a profile.
|
||||
* @param int $userid
|
||||
* @return string HTML link to user profile
|
||||
*/
|
||||
private function format_user(int $userid): string {
|
||||
if ($userid == 0 || !$user = \core_user::get_user($userid)) {
|
||||
return get_string('na', 'auth_outage');
|
||||
}
|
||||
$url = new moodle_url('/user/profile.php', ['id' => $userid]);
|
||||
return html_writer::link($url, fullname($user));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats created by column.
|
||||
* @param outage $outage
|
||||
* @return string The user who created the outage.
|
||||
*/
|
||||
protected function format_created(outage $outage): string {
|
||||
return $this->format_user($outage->createdby);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats modified by column.
|
||||
* @param outage $outage
|
||||
* @return string The user who last modiifed the outage and the last modified time.
|
||||
*/
|
||||
protected function format_modified(outage $outage): string {
|
||||
$timestamp = html_writer::div(
|
||||
userdate($outage->lastmodified, get_string('datetimeformat', 'auth_outage')),
|
||||
'small text-muted'
|
||||
);
|
||||
return $this->format_user($outage->modifiedby) . $timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the action buttons HTML code for a specific outage.
|
||||
* @param outage $outage The outage to generate the buttons.
|
||||
|
||||
@@ -36,7 +36,7 @@ class history_table extends base_table {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->define_columns(['warning', 'starts', 'durationplanned', 'durationactual', 'title', 'actions']);
|
||||
$this->define_columns(['warning', 'starts', 'duration', 'durationactual', 'title', 'created', 'modified', 'actions']);
|
||||
|
||||
$this->define_headers([
|
||||
get_string('tableheaderwarnbefore', 'auth_outage'),
|
||||
@@ -44,6 +44,8 @@ class history_table extends base_table {
|
||||
get_string('tableheaderdurationplanned', 'auth_outage'),
|
||||
get_string('tableheaderdurationactual', 'auth_outage'),
|
||||
get_string('tableheadertitle', 'auth_outage'),
|
||||
get_string('tableheadercreatedby', 'auth_outage'),
|
||||
get_string('tableheadermodifiedby', 'auth_outage'),
|
||||
get_string('actions'),
|
||||
]);
|
||||
|
||||
@@ -64,6 +66,8 @@ class history_table extends base_table {
|
||||
format_time($outage->get_duration_planned()),
|
||||
$finished,
|
||||
$outage->get_title(),
|
||||
$this->format_created($outage),
|
||||
$this->format_modified($outage),
|
||||
$this->create_data_buttons($outage, false),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -38,13 +38,15 @@ class planned_table extends base_table {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->define_columns(['warning', 'starts', 'duration', 'title', 'actions']);
|
||||
$this->define_columns(['warning', 'starts', 'duration', 'title', 'created', 'modified', 'actions']);
|
||||
|
||||
$this->define_headers([
|
||||
get_string('tableheaderwarnbefore', 'auth_outage'),
|
||||
get_string('tableheaderstarttime', 'auth_outage'),
|
||||
get_string('tableheaderduration', 'auth_outage'),
|
||||
get_string('tableheadertitle', 'auth_outage'),
|
||||
get_string('tableheadercreatedby', 'auth_outage'),
|
||||
get_string('tableheadermodifiedby', 'auth_outage'),
|
||||
get_string('actions'),
|
||||
]);
|
||||
|
||||
@@ -68,6 +70,8 @@ class planned_table extends base_table {
|
||||
self::create_starttime_string($outage->starttime),
|
||||
format_time($outage->get_duration_planned()),
|
||||
$title,
|
||||
$this->format_created($outage),
|
||||
$this->format_modified($outage),
|
||||
$this->create_data_buttons($outage, true),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -150,9 +150,11 @@ $string['settingssectionplugin'] = 'Plugin Configuration';
|
||||
$string['settingssectionplugindescription'] = 'General outage management plugin settings.';
|
||||
$string['starttime'] = 'Start date and time';
|
||||
$string['starttime_help'] = 'At which date and time the outage starts, preventing general access to the system.';
|
||||
$string['tableheadercreatedby'] = 'Created by';
|
||||
$string['tableheaderduration'] = 'Duration';
|
||||
$string['tableheaderdurationactual'] = 'Actual duration';
|
||||
$string['tableheaderdurationplanned'] = 'Planned duration';
|
||||
$string['tableheadermodifiedby'] = 'Last modified by';
|
||||
$string['tableheaderstartedtime'] = 'Started on';
|
||||
$string['tableheaderstarttime'] = 'Starts on';
|
||||
$string['tableheadertitle'] = 'Title';
|
||||
|
||||
@@ -30,7 +30,11 @@ use auth_outage\local\controllers\maintenance_static_page;
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
require_once(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
admin_externalpage_setup('auth_outage_manage');
|
||||
|
||||
$id = optional_param('id', null, PARAM_INT);
|
||||
$outage = is_null($id) ? outagedb::get_next_starting() : outagedb::get_by_id($id);
|
||||
if (is_null($outage)) {
|
||||
|
||||
@@ -95,6 +95,9 @@ abstract class base_testcase extends \advanced_testcase {
|
||||
|
||||
parent::setUp();
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// These tests rely on force login being disabled, but Moodle 5.2 enables it by default (MDL-87523).
|
||||
set_config('forcelogin', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -431,39 +431,6 @@ final class maintenance_static_page_test extends \auth_outage\base_testcase {
|
||||
maintenance_static_page_io::file_get_data(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file_get_data with curlsecurityblockedhosts.
|
||||
* We will use an external URL to test passing ignoresecurity inside of file_get_data works,
|
||||
* ideally in real code we should only be calling file_get_data with internal URLs.
|
||||
*/
|
||||
public function test_file_get_data_curlsecurityblockedhosts(): void {
|
||||
global $CFG, $USER;
|
||||
|
||||
$testhtml = $this->getExternalTestFileUrl('/test.html');
|
||||
$url = new \moodle_url($testhtml);
|
||||
$host = $url->get_host();
|
||||
set_config('curlsecurityblockedhosts', $host); // Blocks $host.
|
||||
|
||||
// Test a regular curl with the default security enabled does in fact get blocked.
|
||||
$curl = new \curl();
|
||||
$contents = $curl->get($testhtml);
|
||||
$expected = $curl->get_security()->get_blocked_url_string();
|
||||
self::assertSame($expected, $contents);
|
||||
self::assertSame(0, $curl->get_errno());
|
||||
if ($CFG->branch >= 403) {
|
||||
self::assertDebuggingCalled(
|
||||
"Blocked $testhtml: The URL is blocked. [user {$USER->id}]",
|
||||
DEBUG_NONE
|
||||
);
|
||||
}
|
||||
|
||||
// Test file_get_data does return the page and isn't blocked by security.
|
||||
$found = maintenance_static_page_io::file_get_data($url->out());
|
||||
$expected = '47250a973d1b88d9445f94db4ef2c97a';
|
||||
self::assertSame($expected, md5($found['contents']));
|
||||
self::assertSame('text/html', $found['mime']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test remove css selector.
|
||||
*/
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = "auth_outage";
|
||||
$plugin->version = 2026011302; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->release = 2026011302; // Human-readable release information.
|
||||
$plugin->version = 2026011308; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->release = 2026011308; // Human-readable release information.
|
||||
$plugin->requires = 2025100600; // Moodle 5.1.
|
||||
$plugin->maturity = MATURITY_STABLE; // Suitable for PRODUCTION environments!
|
||||
$plugin->supported = [501, 501]; // A range of branch numbers of supported moodle versions.
|
||||
|
||||
@@ -39,7 +39,15 @@ defined('MOODLE_INTERNAL') || die();
|
||||
<b><?php echo get_string('infountil', 'auth_outage'); ?></b>
|
||||
<?php echo userdate($viewbag['outage']->stoptime, get_string('datetimeformat', 'auth_outage')); ?>
|
||||
</div>
|
||||
<div class="auth_outage_info_description"><?php echo $viewbag['outage']->get_description(); ?></div>
|
||||
<div class="auth_outage_info_description">
|
||||
<?php
|
||||
echo format_text(
|
||||
$viewbag['outage']->get_description(),
|
||||
FORMAT_HTML,
|
||||
['context' => context_system::instance()]
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if ($viewbag['admin']) : ?>
|
||||
<?php
|
||||
|
||||
Reference in New Issue
Block a user