mirror of
https://github.com/catalyst/moodle-auth_outage.git
synced 2026-09-07 08:11:07 +02:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ccefa9eda | ||
|
|
2f5bb06e3c | ||
|
|
f785693d06 | ||
|
|
4976c5c3b6 | ||
|
|
789a1c1163 | ||
|
|
a6e465b7a3 | ||
|
|
1b2979f8e6 | ||
|
|
6aad6d37ba | ||
|
|
675ec899f4 | ||
|
|
40fccef237 | ||
|
|
dbc8e75092 |
@@ -69,6 +69,7 @@ if (is_callable('auth_outage_bootstrap_callback')) {
|
||||
}
|
||||
|
||||
// 3) Check for allowed scripts or IPs during outages.
|
||||
$outageinfo = false;
|
||||
if (!empty($_SERVER['REQUEST_URI'])) {
|
||||
$rooturl = parse_url($CFG->wwwroot);
|
||||
$path = '';
|
||||
|
||||
@@ -40,16 +40,18 @@ class calendar {
|
||||
/**
|
||||
* Create an event on the calendar for this outage.
|
||||
* @param outage $outage Outage to be added to the calendar.
|
||||
* @return void
|
||||
*/
|
||||
public static function create(outage $outage) {
|
||||
public static function create(outage $outage): void {
|
||||
calendar_event::create(self::create_data($outage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an event on the calendar based on this outage.
|
||||
* @param outage $outage Outage to be updated in the calendar.
|
||||
* @return void
|
||||
*/
|
||||
public static function update(outage $outage) {
|
||||
public static function update(outage $outage): void {
|
||||
$event = self::load($outage->id);
|
||||
|
||||
if (is_null($event)) {
|
||||
@@ -63,8 +65,9 @@ class calendar {
|
||||
/**
|
||||
* Removes an event from the calendar related to this outage.
|
||||
* @param int $outageid Id of outage to be deleted from the calendar.
|
||||
* @return void
|
||||
*/
|
||||
public static function delete($outageid) {
|
||||
public static function delete(int $outageid): void {
|
||||
$event = self::load($outageid);
|
||||
|
||||
// If not found (was not created before) ignore it.
|
||||
|
||||
@@ -48,6 +48,7 @@ class outagedb {
|
||||
|
||||
/**
|
||||
* Gets all outage entries.
|
||||
* @return outage[]
|
||||
*/
|
||||
public static function get_all() {
|
||||
global $DB;
|
||||
@@ -84,82 +85,6 @@ class outagedb {
|
||||
return new outage($outage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Also sends all admins the event as a message
|
||||
*
|
||||
* @param $outage
|
||||
* @param $event
|
||||
*/
|
||||
private static function notify($outage, $event) {
|
||||
|
||||
$admins = get_admins();
|
||||
|
||||
foreach ($admins as $admin) {
|
||||
self::notify_user($outage, $event, $admin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send outage info to one user
|
||||
*
|
||||
* @param $outage outage
|
||||
* @param $event event
|
||||
* @param $to user object
|
||||
*/
|
||||
private static function notify_user($outage, $event, $to) {
|
||||
|
||||
global $SITE, $CFG;
|
||||
|
||||
$from = \core_user::get_user($event->userid);
|
||||
if (!$from) {
|
||||
return;
|
||||
}
|
||||
$fields = [
|
||||
'site_shortname' => $SITE->shortname,
|
||||
'site_fullname' => $SITE->fullname,
|
||||
'site_wwwroot' => $CFG->wwwroot,
|
||||
|
||||
'outage_id' => $outage->id,
|
||||
'outage_title' => $outage->get_title(),
|
||||
'outage_desc' => clean_text($outage->get_description(), FORMAT_HTML),
|
||||
'outage_start' => userdate($outage->starttime, get_string('datetimeformat', 'auth_outage')),
|
||||
'outage_stop' => userdate($outage->stoptime, get_string('datetimeformat', 'auth_outage')),
|
||||
'outage_duration' => format_time($outage->get_duration_planned()),
|
||||
|
||||
'event_name' => $event->get_name(),
|
||||
'event_desc' => $event->get_description(),
|
||||
'event_link' => $event->get_url()->out(),
|
||||
|
||||
'from_name' => fullname($from),
|
||||
'to_name' => fullname($to),
|
||||
'prefs_link' => (new \moodle_url('/message/notificationpreferences.php'))->out(),
|
||||
|
||||
];
|
||||
|
||||
$message = new \core\message\message();
|
||||
$message->component = 'auth_outage';
|
||||
$message->name = 'updatenotify';
|
||||
$message->userto = $to;
|
||||
$message->subject = get_string('messagesubject', 'auth_outage', $fields);
|
||||
$message->fullmessage = get_string('messagetext', 'auth_outage', $fields);
|
||||
$message->fullmessagehtml = get_string('messagehtml', 'auth_outage', $fields);
|
||||
$message->fullmessageformat = FORMAT_HTML;
|
||||
|
||||
$threadid = generate_email_messageid('outage' . $outage->id);
|
||||
$message->userfrom = $from;
|
||||
$message->userfrom->customheaders = [
|
||||
"In-Reply-To: $threadid",
|
||||
"References: $threadid",
|
||||
"Thread-Topic: " . $message->subject,
|
||||
"Thread-Index: $threadid",
|
||||
];
|
||||
|
||||
$message->notification = 1;
|
||||
message_send($message);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an outage to the database.
|
||||
*
|
||||
@@ -190,7 +115,6 @@ class outagedb {
|
||||
]);
|
||||
$event->add_record_snapshot('auth_outage', (object)(array) $outage);
|
||||
$event->trigger();
|
||||
self::notify($outage, $event);
|
||||
|
||||
// Create calendar entry.
|
||||
calendar::create($outage);
|
||||
@@ -204,7 +128,6 @@ class outagedb {
|
||||
|
||||
$event->add_record_snapshot('auth_outage', (object)(array) $outage);
|
||||
$event->trigger();
|
||||
self::notify($outage, $event);
|
||||
|
||||
// Remove the createdby field so it does not get updated.
|
||||
unset($outage->createdby);
|
||||
@@ -248,7 +171,6 @@ class outagedb {
|
||||
|
||||
$event->add_record_snapshot('auth_outage', $previous);
|
||||
$event->trigger();
|
||||
self::notify($outage, $event);
|
||||
|
||||
// Delete it and remove from calendar.
|
||||
$DB->delete_records('auth_outage', ['id' => $id]);
|
||||
@@ -440,7 +362,7 @@ class outagedb {
|
||||
$data = $DB->get_records_select(
|
||||
'auth_outage',
|
||||
'starttime <= :datetime1 AND :datetime2 <= stoptime AND finished IS NULL',
|
||||
['datetime1' => $time, 'datetime2' => $time, 'datetime3' => $time],
|
||||
['datetime1' => $time, 'datetime2' => $time],
|
||||
'starttime ASC, stoptime DESC, title ASC',
|
||||
'*',
|
||||
0,
|
||||
|
||||
@@ -28,23 +28,13 @@ use moodle_url;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outage_created extends base {
|
||||
|
||||
/**
|
||||
* Return localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('eventoutagecreated', 'auth_outage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with the id '{$this->userid}' scheduled outage {$this->other['id']} '{$this->other['title']}'";
|
||||
return "The user with the id '{$this->userid}' created outage {$this->other['id']} '{$this->other['title']}'";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,16 +28,6 @@ use moodle_url;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outage_deleted extends base {
|
||||
|
||||
/**
|
||||
* Return localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('eventoutagedeleted', 'auth_outage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
|
||||
@@ -28,16 +28,6 @@ use moodle_url;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class outage_updated extends base {
|
||||
|
||||
/**
|
||||
* Return localised event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('eventoutageupdated', 'auth_outage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
|
||||
@@ -67,6 +67,7 @@ class edit extends moodleform {
|
||||
$mform->addHelpButton('title', 'title', 'auth_outage');
|
||||
|
||||
$mform->addElement('editor', 'description', get_string('description', 'auth_outage'));
|
||||
$mform->setType('description[text]', PARAM_RAW);
|
||||
$mform->addHelpButton('description', 'description', 'auth_outage');
|
||||
|
||||
$mform->addElement('static', 'usagehints', '', get_string('textplaceholdershint', 'auth_outage'));
|
||||
@@ -79,6 +80,7 @@ class edit extends moodleform {
|
||||
get_string('useaccesskey:desc', 'auth_outage'),
|
||||
0
|
||||
);
|
||||
$mform->setType('useaccesskey', PARAM_BOOL);
|
||||
|
||||
$mform->addElement('text', 'accesskey', get_string('accesskey', 'auth_outage'));
|
||||
$mform->setType('accesskey', PARAM_TEXT);
|
||||
|
||||
@@ -79,6 +79,6 @@ class cli_exception extends Exception {
|
||||
* @param Exception|null $previous Another exception as reference or null.
|
||||
*/
|
||||
public function __construct($message, $code = 1, ?Exception $previous = null) {
|
||||
parent::__construct('*ERROR* ' . $message, $code, $previous = null);
|
||||
parent::__construct('*ERROR* ' . $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,6 @@ abstract class clibase {
|
||||
* Change session to admin user.
|
||||
*/
|
||||
protected function become_admin_user() {
|
||||
global $DB;
|
||||
$user = get_admin();
|
||||
unset($user->description);
|
||||
unset($user->access);
|
||||
|
||||
@@ -28,8 +28,7 @@ use coding_exception;
|
||||
* @copyright 2016 Catalyst IT
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class create extends clibase
|
||||
{
|
||||
class create extends clibase {
|
||||
/**
|
||||
* @var mixed[] Defaults to use if given option is null.
|
||||
*/
|
||||
@@ -99,6 +98,7 @@ class create extends clibase
|
||||
|
||||
/**
|
||||
* Executes the CLI.
|
||||
* @throws cli_exception
|
||||
*/
|
||||
public function execute() {
|
||||
// Help always overrides any other parameter.
|
||||
@@ -269,32 +269,4 @@ class create extends clibase
|
||||
}
|
||||
return $option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the given option is or can be converted to a bool.
|
||||
* @param mixed $option The parameter to check.
|
||||
* @param string $param Name of that parameter.
|
||||
* @return bool The converted parameter.
|
||||
* @throws cli_exception
|
||||
*/
|
||||
private function merge_options_check_parameters_bool($option, $param) {
|
||||
if (is_bool($option)) {
|
||||
return $option;
|
||||
}
|
||||
|
||||
if (is_string($option)) {
|
||||
$option = strtoupper($option);
|
||||
if (in_array($option, ['0', 'FALSE', 'NO', 'N'])) {
|
||||
return false;
|
||||
}
|
||||
if (in_array($option, ['1', 'TRUE', 'YES', 'Y'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
throw new cli_exception(
|
||||
get_string('clierrorinvalidvaluenotbool', 'auth_outage', ['param' => $param]),
|
||||
cli_exception::ERROR_PARAMETER_INVALID
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ class finish extends clibase {
|
||||
|
||||
/**
|
||||
* Executes the CLI.
|
||||
* @throws cli_exception
|
||||
*/
|
||||
public function execute() {
|
||||
// Help always overrides any other parameter.
|
||||
|
||||
@@ -101,6 +101,7 @@ class waitforit extends clibase {
|
||||
$outage = $this->get_outage();
|
||||
|
||||
while ($sleep = $this->wait_for_outage_to_start($outage)) {
|
||||
$sleep = max(1, $sleep);
|
||||
if (is_null($this->sleepcallback)) {
|
||||
$this->verbose('Sleeping for ' . $sleep . ' second(s).');
|
||||
sleep($sleep);
|
||||
|
||||
@@ -47,11 +47,6 @@ class infopage {
|
||||
* @param array|null $params Parameters to use or null to get from Moodle API (request).
|
||||
*/
|
||||
public function __construct(?array $params = null) {
|
||||
global $CFG;
|
||||
// Enable SVG support here to make sure all SVG files
|
||||
// used in the current theme are served properly.
|
||||
$CFG->svgicons = true;
|
||||
|
||||
if (is_null($params)) {
|
||||
$params = [
|
||||
'id' => optional_param('id', null, PARAM_INT),
|
||||
@@ -101,21 +96,29 @@ class infopage {
|
||||
if (!$this->static && !has_capability('auth/outage:viewinfo', context_system::instance())) {
|
||||
redirect(new moodle_url('/'));
|
||||
}
|
||||
|
||||
// Enable SVG support here to make sure all SVG files
|
||||
// used in the current theme are served properly.
|
||||
$previoussvg = $CFG->svgicons ?? null;
|
||||
$CFG->svgicons = true;
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_title($this->outage->get_title());
|
||||
$PAGE->set_heading($this->outage->get_title());
|
||||
$PAGE->set_url(new moodle_url('/auth/outage/info.php'));
|
||||
|
||||
// No hooks injecting into this page, do it manually.
|
||||
echo outagelib::get_inject_code();
|
||||
|
||||
// Inject metadata into the header before output.
|
||||
// Inject metadata into the header before any output starts, otherwise header() will
|
||||
// fail once outagelib::get_inject_code() below has echoed anything.
|
||||
if (!empty($this->outage->metadata)) {
|
||||
header('X-Outage-Metadata: ' . $this->outage->metadata);
|
||||
$safemeta = str_replace(["\r", "\n"], '', $this->outage->metadata);
|
||||
header('X-Outage-Metadata: ' . $safemeta);
|
||||
header('X-Outage-StartTime: ' . $this->outage->starttime);
|
||||
header('X-Outage-EndTime: ' . $this->outage->stoptime);
|
||||
}
|
||||
|
||||
// No hooks injecting into this page, do it manually.
|
||||
echo outagelib::get_inject_code();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
$viewbag = [
|
||||
'admin' => is_siteadmin(),
|
||||
@@ -123,10 +126,8 @@ class infopage {
|
||||
];
|
||||
require($CFG->dirroot . '/auth/outage/views/info/content.php');
|
||||
|
||||
// Moodle 2.7 did not check for CLI mode, which was fixed later.
|
||||
if (!($CFG->branch == '27' && CLI_SCRIPT)) {
|
||||
echo $OUTPUT->footer();
|
||||
}
|
||||
echo $OUTPUT->footer();
|
||||
$CFG->svgicons = $previoussvg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,7 +51,8 @@ class maintenance_static_page {
|
||||
} else {
|
||||
// Inject metadata into the header before output.
|
||||
if (!empty($outage->metadata)) {
|
||||
header('X-Outage-Metadata: ' . $outage->metadata);
|
||||
$safemeta = str_replace(["\r", "\n"], '', $outage->metadata);
|
||||
header('X-Outage-Metadata: ' . $safemeta);
|
||||
header('X-Outage-StartTime: ' . $outage->starttime);
|
||||
header('X-Outage-EndTime: ' . $outage->stoptime);
|
||||
}
|
||||
|
||||
@@ -51,12 +51,13 @@ class outagelib {
|
||||
/**
|
||||
* Fetches page.
|
||||
* @param string $file file to be fetched
|
||||
* @return array{contents: string|false, mime: string}
|
||||
*/
|
||||
public static function fetch_page($file) {
|
||||
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'])) {
|
||||
@@ -69,6 +70,7 @@ class outagelib {
|
||||
|
||||
/**
|
||||
* Resets inject called to allow the code to be regenerated.
|
||||
* @return void
|
||||
*/
|
||||
public static function reset_injectcalled() {
|
||||
self::$injectcalled = false;
|
||||
@@ -77,6 +79,7 @@ class outagelib {
|
||||
/**
|
||||
* Given a time, usually now, when is the next outage window?
|
||||
* @param int $time time for next window
|
||||
* @return int
|
||||
*/
|
||||
public static function get_next_window($time = null) {
|
||||
|
||||
@@ -177,6 +180,7 @@ class outagelib {
|
||||
'default_warning_duration' => (string)(60 * 60),
|
||||
'default_title' => get_string('defaulttitlevalue', 'auth_outage'),
|
||||
'default_description' => get_string('defaultdescriptionvalue', 'auth_outage'),
|
||||
'default_metadata' => '',
|
||||
'remove_selectors' => ".usermenu\n.logininfo\n.homelink",
|
||||
];
|
||||
}
|
||||
@@ -284,7 +288,7 @@ if ((time() >= {{STARTTIME}}) && (time() < {{STOPTIME}})) {
|
||||
require_once($CFG->dirroot.'/lib/classes/ip_utils.php');
|
||||
}
|
||||
// Put access key as a cookie if given. This stops the need to put it as a url param on every request.
|
||||
$urlaccesskey = optional_param('accesskey', null, PARAM_TEXT);
|
||||
$urlaccesskey = optional_param('accesskey', null, PARAM_ALPHANUM);
|
||||
$isphpunit = defined('PHPUNIT_TEST');
|
||||
|
||||
if (!empty($urlaccesskey) && !$isphpunit) {
|
||||
@@ -328,7 +332,8 @@ if ((time() >= {{STARTTIME}}) && (time() < {{STOPTIME}})) {
|
||||
}
|
||||
|
||||
if ({{USEACCESSKEY}} && $accesskeyblocked) {
|
||||
echo '<!-- auth_outage blocked by missing or incorrect access key, access key given: '. $useraccesskey .' -->';
|
||||
$safeaccesskey = htmlspecialchars($useraccesskey ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
echo '<!-- auth_outage blocked by missing or incorrect access key, access key given: ' . $safeaccesskey . ' -->';
|
||||
}
|
||||
|
||||
if (!$isphpunit) {
|
||||
|
||||
@@ -64,41 +64,6 @@ 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', 'duration', 'durationactual', 'title', 'created', 'modified', 'actions']);
|
||||
$this->define_columns(['warning', 'starts', 'durationplanned', 'durationactual', 'title', 'actions']);
|
||||
|
||||
$this->define_headers([
|
||||
get_string('tableheaderwarnbefore', 'auth_outage'),
|
||||
@@ -44,8 +44,6 @@ 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'),
|
||||
]);
|
||||
|
||||
@@ -66,8 +64,6 @@ 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,15 +38,13 @@ class planned_table extends base_table {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->define_columns(['warning', 'starts', 'duration', 'title', 'created', 'modified', 'actions']);
|
||||
$this->define_columns(['warning', 'starts', 'duration', 'title', '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'),
|
||||
]);
|
||||
|
||||
@@ -70,8 +68,6 @@ 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),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -187,8 +187,8 @@ class renderer extends plugin_renderer_base {
|
||||
$outagehtml = html_writer::div(
|
||||
html_writer::tag(
|
||||
'blockquote',
|
||||
html_writer::div(html_writer::tag('b', $outage->get_title(), ['data-id' => $outage->id])) .
|
||||
html_writer::div(html_writer::tag('i', $outage->get_description())) .
|
||||
html_writer::div(html_writer::tag('b', format_string($outage->get_title()), ['data-id' => $outage->id])) .
|
||||
html_writer::div(html_writer::tag('i', format_text($outage->get_description(), FORMAT_HTML))) .
|
||||
html_writer::div(
|
||||
html_writer::tag('b', get_string('tableheaderwarnbefore', 'auth_outage') . ': ') .
|
||||
format_time($outage->get_warning_duration())
|
||||
|
||||
@@ -37,7 +37,10 @@ class update_static_page extends scheduled_task {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the event.
|
||||
* Executes the task: regenerates the maintenance static page for the next scheduled outage.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @throws \file_exception
|
||||
*/
|
||||
public function execute() {
|
||||
outagelib::prepare_next_outage();
|
||||
|
||||
@@ -34,13 +34,4 @@ $capabilities = [
|
||||
'user' => CAP_ALLOW,
|
||||
],
|
||||
],
|
||||
'auth/outage:updatenotify' => [
|
||||
'captype' => 'write',
|
||||
'riskbitmask' => RISK_XSS,
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'manager' => CAP_ALLOW,
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
@@ -21,9 +21,14 @@
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="fk_createdby" TYPE="foreign" FIELDS="createdby" REFTABLE="user" REFFIELDS="id"/>
|
||||
<KEY NAME="fk_modifiedby" TYPE="foreign" FIELDS="modifiedby" REFTABLE="user" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="start_stop_title" UNIQUE="false" FIELDS="starttime, stoptime, title"/>
|
||||
<INDEX NAME="ix_stoptime_finished" UNIQUE="false" FIELDS="stoptime, finished"/>
|
||||
<INDEX NAME="ix_createdby" UNIQUE="false" FIELDS="createdby"/>
|
||||
<INDEX NAME="ix_modifiedby" UNIQUE="false" FIELDS="modifiedby"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Defines message providers for outage
|
||||
*
|
||||
* @package auth_outage
|
||||
* @copyright 2020 Brendan Heywood <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$messageproviders = [
|
||||
'updatenotify' => [
|
||||
'capability' => 'auth/outage:updatenotify',
|
||||
]
|
||||
];
|
||||
|
||||
@@ -37,14 +37,31 @@ if (!isset($_GET['file'])) {
|
||||
die('Missing file parameter.');
|
||||
}
|
||||
|
||||
$parts = explode('.', $_GET['file']);
|
||||
$rawfile = $_GET['file'];
|
||||
if (!preg_match('/^[a-zA-Z0-9_\-\.\/]+$/', $rawfile)) {
|
||||
http_response_code(400);
|
||||
die('Invalid file parameter.');
|
||||
}
|
||||
|
||||
$parts = explode('.', $rawfile);
|
||||
if (count($parts) != 2) {
|
||||
http_response_code(400);
|
||||
die('Invalid file requested.');
|
||||
}
|
||||
$mime = base64_decode($parts[1]);
|
||||
$extension = strtolower(pathinfo($parts[0], PATHINFO_EXTENSION));
|
||||
$allowedmimes = [
|
||||
'css' => 'text/css',
|
||||
'png' => 'image/png',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'gif' => 'image/gif',
|
||||
];
|
||||
if (!array_key_exists($extension, $allowedmimes)) {
|
||||
http_response_code(400);
|
||||
die('Unsupported file type.');
|
||||
}
|
||||
$mime = $allowedmimes[$extension];
|
||||
|
||||
// Detect type, we only support css or PNG images.
|
||||
header('Content-Type: ' . $mime);
|
||||
|
||||
// Use cache.
|
||||
|
||||
+1
-45
@@ -100,9 +100,6 @@ $string['defaultwarningduration'] = 'Warning duration';
|
||||
$string['defaultwarningdurationdescription'] = 'Default warning time (in minutes) for outages.';
|
||||
$string['description'] = 'Public Description';
|
||||
$string['description_help'] = 'A full description of the outage, publicly visible by all users.';
|
||||
$string['eventoutagecreated'] = 'Outage scheduled';
|
||||
$string['eventoutagedeleted'] = 'Outage cancelled';
|
||||
$string['eventoutageupdated'] = 'Outage updated';
|
||||
$string['finish'] = 'Finish';
|
||||
$string['info15secondsbefore'] = '15 seconds before';
|
||||
$string['infoendofoutage'] = 'end of outage';
|
||||
@@ -124,48 +121,9 @@ $string['messageoutageongoing'] = 'Back online at {$a->stop}.';
|
||||
$string['messageoutagewarning'] = 'Shutting down in {{countdown}}';
|
||||
$string['metadata'] = 'Outage metadata';
|
||||
$string['metadata_help'] = 'Data here will be output in the outage page as a meta tag in the header of the outage page.';
|
||||
$string['messageprovider:updatenotify'] = 'Changes to planned outages';
|
||||
$string['messagesubject'] = '[{$a->site_shortname}] {$a->event_name} #{$a->outage_id}: {$a->outage_start}';
|
||||
$string['messagetext'] = '{$a->event_name}
|
||||
|
||||
{$a->site_fullname} ({$a->site_wwwroot})
|
||||
|
||||
{$a->event_link}
|
||||
|
||||
ID: {$a->outage_id}
|
||||
NAME: {$a->outage_title}
|
||||
START: {$a->outage_start}
|
||||
DURATION: {$a->outage_duration}
|
||||
DESCRIPTION:
|
||||
{$a->outage_desc}
|
||||
|
||||
--
|
||||
|
||||
To unsubscribe visit:
|
||||
{$a->prefs_link}';
|
||||
$string['messagehtml'] = '
|
||||
<h3>{$a->event_name}</h3>
|
||||
|
||||
<p>{$a->site_fullname} (<a href="{$a->site_wwwroot}">{$a->site_wwwroot}</a>)</p>
|
||||
|
||||
<p><a href="{$a->event_link}">{$a->event_link}</a></p>
|
||||
|
||||
<h4>Name:</h4>
|
||||
<p>{$a->outage_title}</p>
|
||||
<h4>Start:</h4>
|
||||
<p>{$a->outage_start}</p>
|
||||
<h4>Duration:</h4>
|
||||
<p>{$a->outage_duration}</p>
|
||||
<h4>Description:</h4>
|
||||
<p>{$a->outage_desc}</p>
|
||||
|
||||
<hr>
|
||||
<p>To unsubscribe visit:<br>
|
||||
<a href="{$a->prefs_link}">{$a->prefs_link}</a></p>
|
||||
';
|
||||
$string['na'] = 'n/a';
|
||||
$string['notfound'] = 'No outages found.';
|
||||
$string['outage:updatenotify'] = 'Receive outage update notifications';
|
||||
$string['outage:updatenotify'] = '';
|
||||
$string['outage:viewinfo'] = 'View outage info';
|
||||
$string['outageclone'] = 'Clone outage';
|
||||
$string['outageclonecrumb'] = 'Clone';
|
||||
@@ -192,11 +150,9 @@ $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';
|
||||
|
||||
@@ -31,6 +31,8 @@ use auth_outage\local\controllers\maintenance_static_page;
|
||||
// @codingStandardsIgnoreStart
|
||||
require_once(__DIR__.'/../../config.php');
|
||||
// @codingStandardsIgnoreEnd
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
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)) {
|
||||
|
||||
@@ -154,15 +154,23 @@ final class infopage_test extends \auth_outage\base_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor enables SVG support.
|
||||
* Tests that rendering the page enables SVG support and restores the previous value afterwards.
|
||||
*/
|
||||
public function test_svgicons_is_true(): void {
|
||||
public function test_svgicons_is_restored_after_output(): void {
|
||||
global $CFG;
|
||||
|
||||
$this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance()));
|
||||
|
||||
$outage = $this->get_dummy_outage();
|
||||
$CFG->svgicons = false;
|
||||
new infopage();
|
||||
self::assertTrue($CFG->svgicons);
|
||||
|
||||
$info = new infopage(['outage' => $outage, 'static' => false]);
|
||||
// Constructing the page should not touch $CFG->svgicons.
|
||||
self::assertFalse($CFG->svgicons);
|
||||
|
||||
$info->get_output();
|
||||
|
||||
// Svgicons should be restored to its original value once rendering has finished.
|
||||
self::assertFalse($CFG->svgicons);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -272,7 +272,7 @@ if ((time() >= 123) && (time() < 456)) {
|
||||
require_once($CFG->dirroot.'/lib/classes/ip_utils.php');
|
||||
}
|
||||
// Put access key as a cookie if given. This stops the need to put it as a url param on every request.
|
||||
$urlaccesskey = optional_param('accesskey', null, PARAM_TEXT);
|
||||
$urlaccesskey = optional_param('accesskey', null, PARAM_ALPHANUM);
|
||||
$isphpunit = defined('PHPUNIT_TEST');
|
||||
|
||||
if (!empty($urlaccesskey) && !$isphpunit) {
|
||||
@@ -318,7 +318,8 @@ e.e.e.e/20');
|
||||
}
|
||||
|
||||
if (true && $accesskeyblocked) {
|
||||
echo '<!-- auth_outage blocked by missing or incorrect access key, access key given: '. $useraccesskey .' -->';
|
||||
$safeaccesskey = htmlspecialchars($useraccesskey ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
echo '<!-- auth_outage blocked by missing or incorrect access key, access key given: ' . $safeaccesskey . ' -->';
|
||||
}
|
||||
|
||||
if (!$isphpunit) {
|
||||
@@ -358,7 +359,7 @@ if ((time() >= 123) && (time() < 456)) {
|
||||
require_once($CFG->dirroot.'/lib/classes/ip_utils.php');
|
||||
}
|
||||
// Put access key as a cookie if given. This stops the need to put it as a url param on every request.
|
||||
$urlaccesskey = optional_param('accesskey', null, PARAM_TEXT);
|
||||
$urlaccesskey = optional_param('accesskey', null, PARAM_ALPHANUM);
|
||||
$isphpunit = defined('PHPUNIT_TEST');
|
||||
|
||||
if (!empty($urlaccesskey) && !$isphpunit) {
|
||||
@@ -402,7 +403,8 @@ if ((time() >= 123) && (time() < 456)) {
|
||||
}
|
||||
|
||||
if (true && $accesskeyblocked) {
|
||||
echo '<!-- auth_outage blocked by missing or incorrect access key, access key given: '. $useraccesskey .' -->';
|
||||
$safeaccesskey = htmlspecialchars($useraccesskey ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
echo '<!-- auth_outage blocked by missing or incorrect access key, access key given: ' . $safeaccesskey . ' -->';
|
||||
}
|
||||
|
||||
if (!$isphpunit) {
|
||||
|
||||
+3
-2
@@ -28,7 +28,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = "auth_outage";
|
||||
$plugin->version = 2026011304; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->release = 2026011304; // Human-readable release information.
|
||||
$plugin->version = 2026011305; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->release = 2026011305; // 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,7 @@ 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); ?></div>
|
||||
|
||||
<?php if ($viewbag['admin']) : ?>
|
||||
<?php
|
||||
|
||||
@@ -68,7 +68,7 @@ if (!$viewbag['static']) {
|
||||
<style>
|
||||
<?php
|
||||
readfile($CFG->dirroot . '/auth/outage/views/warningbar/warningbar.css');
|
||||
echo outagelib::get_config()->css;
|
||||
echo preg_replace('/<\s*\/\s*style\s*>/i', '', outagelib::get_config()->css);
|
||||
?>
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user