5 Commits

Author SHA1 Message Date
Jerome Charaoui
c4fc4b4396 Include filelib.php to fix class not found exception 2021-05-06 10:29:33 +12:00
Dan Marsden
e632b1c2f9 We haven't been testing postgres on 3.5 - it needs pg12
disable pg test for now, but we should think about adding it back.
2021-05-06 10:04:50 +12:00
Dan Marsden
b4d996125d Update Readme with new branch naming. 2021-05-06 10:04:24 +12:00
Dan Marsden
f8d0d658fa tidy up github action config. 2021-05-05 20:23:22 +12:00
Dan Marsden
a38deb7abf Test 3.5 and 3.8 on this branch. 2021-05-05 14:53:07 +12:00
72 changed files with 953 additions and 1390 deletions

View File

@@ -1,12 +1,126 @@
# .github/workflows/ci.yml
name: ci
name: Moodle plugin CI for master
# Controls when the action will run.
on: [push, pull_request]
jobs:
ci:
uses: catalyst/catalyst-moodle-workflows/.github/workflows/ci.yml@main
secrets:
moodle_org_token: ${{ secrets.MOODLE_ORG_TOKEN }}
with:
disable_behat: true
citest:
name: CI test
runs-on: 'ubuntu-latest'
services:
postgres:
image: postgres
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 3
ports:
- 5432:5432
mariadb:
image: mariadb
env:
MYSQL_USER: 'root'
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval 10s
--health-timeout 5s
--health-retries 3
strategy:
fail-fast: false
matrix:
database: ['mariadb']
moodle-branch: ['MOODLE_35_STABLE']
node: ['14.15.1']
php: ['7.1']
include:
- {moodle-branch: 'MOODLE_38_STABLE', php: '7.1', node: '14.15.1', database: 'mariadb'}
- {moodle-branch: 'MOODLE_38_STABLE', php: '7.4', node: '14.15.1', database: 'pgsql'}
steps:
- name: Check out repository code
uses: actions/checkout@v2
with:
path: plugin
- name: Install node ${{ matrix.node }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pgsql, zip, gd, xmlrpc, soap
coverage: none
- name: Initialise moodle-plugin-ci
run: |
composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
# Add dirs to $PATH
echo $(cd ci/bin; pwd) >> $GITHUB_PATH
echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
# PHPUnit depends on en_AU.UTF-8 locale
sudo locale-gen en_AU.UTF-8
- name: Install Moodle
run: |
mkdir ~/.npm-global
export PATH=~/.npm-global/bin:$PATH
source ~/.profile
moodle-plugin-ci install -vvv --plugin ./plugin --db-host=127.0.0.1
env:
DB: ${{ matrix.database }}
MOODLE_BRANCH: ${{ matrix.moodle-branch }}
- name: Run phplint
if: ${{ always() }}
run: moodle-plugin-ci phplint
- name: Run phpcpd
if: ${{ always() }}
run: moodle-plugin-ci phpcpd || true
- name: Run phpmd
if: ${{ always() }}
run: moodle-plugin-ci phpmd
- name: Run codechecker
if: ${{ always() }}
run: moodle-plugin-ci codechecker
- name: Run validate
if: ${{ always() }}
run: moodle-plugin-ci validate
- name: Run savepoints
if: ${{ always() }}
run: moodle-plugin-ci savepoints
- name: Run mustache
if: ${{ always() }}
run: moodle-plugin-ci phpcpd
- name: Run grunt
if: ${{ always() }}
run: moodle-plugin-ci grunt
- name: Run phpdoc
if: ${{ always() }}
run: moodle-plugin-ci phpdoc
- name: Run phpunit
if: ${{ always() }}
run: moodle-plugin-ci phpunit
# - name: Run behat
# if: ${{ always() }}
# run: moodle-plugin-ci behat --profile chrome

View File

@@ -59,9 +59,6 @@ Basic Usage
_Anyone who tries to use Moodle now will receive a maintenance message._
**Note:** If the outage starts with the option `Auto start maintenance mode` checked, the maint mode won't exit automatically.
It will need to be disabled through command line.
1) Perform the maintenance activities.
At this point it is safe to perform the required maintenance as no one can use the system, not even admins.

102
README.md
View File

@@ -1,21 +1,18 @@
[![ci](https://github.com/catalyst/moodle-auth_outage/actions/workflows/ci.yml/badge.svg?branch=MOODLE_39_STABLE)](https://github.com/catalyst/moodle-auth_outage/actions/workflows/ci.yml?branch=MOODLE_39_STABLE)
<a href="https://travis-ci.org/catalyst/moodle-auth_outage">
<img src="https://travis-ci.org/catalyst/moodle-auth_outage.svg?branch=master">
</a>
# Moodle Outage manager plugin
- [Moodle Outage manager plugin](#moodle-outage-manager-plugin)
- [What is this?](#what-is-this)
- [Moodle Requirements](#moodle-requirements)
- [Branches](#branches)
- [Screenshots](#screenshots)
- [Installation](#installation)
- [Theme configuration](#theme-configuration)
- [Custom Theme Additional SCSS](#custom-theme-additional-scss)
- [How to use](#how-to-use)
- [Quick Guide](#quick-guide)
- [Why it is an auth plugin?](#why-it-is-an-auth-plugin)
- [Tester restriction options](#tester-restriction-options)
- [IP restriction](#ip-restriction)
- [Access key](#access-key)
- [Feedback and issues](#feedback-and-issues)
* [Version Support](#version-support)
* [What is this?](#what-is-this)
* [Moodle Requirements](#moodle-requirements)
* [Screenshots](#screenshots)
* [Installation](#installation)
* [Theme configuration](#theme-configuration)
* [How to use](#how-to-use)
* [Quick Guide](#quick-guide)
* [Why is it an auth plugin?](#why-it-is-an-auth-plugin)
* [Feedback and issues](#feedback-and-issues)
What is this?
-------------
@@ -29,7 +26,10 @@ this plugin creates the concept of graduated outages where at predefined times b
an outage and after, different levels of warning and access can be provided to students
and testers letting them know what is about to happen and why.
![image](https://user-images.githubusercontent.com/187449/149717343-1d2c5237-dbc6-4d2a-a08c-2bdb343e87d2.png)
<img alt="Default" src="https://cdn.rawgit.com/catalyst/moodle-auth_outage/master/docs/default.svg" width="520">
<img alt="Manager" src="https://cdn.rawgit.com/catalyst/moodle-auth_outage/master/docs/outage.svg" width="520">
Moodle Requirements
-------------------
@@ -42,12 +42,14 @@ need to manually add one extra plugin, please check:
Branches
--------
| Moodle version | Totara | Branch | PHP |
| ------------------ | --------------- | ---------------- | ---- |
| Moodle 3.9+ | Totara 13+ | MOODLE_39_STABLE | 7.2+ |
| Moodle 3.3 to 3.8 | Totara 11 to 12 | MOODLE_38_STABLE | 7.1+ |
| Moodle 2.7 to 3.2 | | MOODLE_32_STABLE | 5.5+ |
| | Totara up to 10 | TOTARA_10 | 5.5+ |
| Moodle version | Branch | PHP |
| ----------------- | ----------- | ---- |
| Moodle 2.7 to 3.2 | MOODLE_32_STABLE | 5.5+ |
| Totara up to 10 | TOTARA_10 | 5.5+ |
| Moodle 3.3 to 3.8 | MOODLE_38_STABLE | 7.1+ |
| Totara 11 to 12 | MOODLE_38_STABLE | 7.1+ |
| Moodle 3.9+ | MOODLE_39_STABLE | 7.2+ |
| Totara 13+ | MOODLE_39_STABLE | 7.2+ |
Screenshots
-----------
@@ -105,48 +107,6 @@ This can be found at:
Custom Theme Additional SCSS
-------------------
Custom themes generally do not have the same `$navbar-height` variable set to 80px (MOODLE), therefore custom themes will not calculate the change in navbar height with page elements that calculate the navbar total height.
Add the following SCSS For Moodle 3.11+
```
body.auth_outage {
#page-wrapper {
#nav-drawer {
top: $navbar-height + 100px;
height: calc(100% - (#{$navbar-height} + 100px));
}
#page {
margin-top: $navbar-height + 100px;
}
}
[data-region=right-hand-drawer].drawer {
top: $navbar-height + 100px;
height: calc(100% - (#{$navbar-height} + 100px));
}
}
```
Totara is a little different with version 13+ and no variables are used to set the `totaraNav` height
Add the following CSS For Totara 13+
```
.totaraNav {
margin-top: 100px;
}
.local_envbar .totaraNav {
margin-top: 50px;
}
body.auth_outage #page {
margin-top: 0;
}
```
How to use
----------
@@ -183,18 +143,6 @@ Why it is an auth plugin?
One of the graduated stages this plugin introduces is a 'tester only' mode which disables login for most normal users. This is conceptually similar to the maintenance mode but enables testers to login and confirm the state after an upgrade without needing full admin privileges.
Tester restriction options
------------
Two options are available to restrict the site to only let testers in during the tester phase.
Note: these restrictions build on each other; If both are enabled, users must meet both criteria to be allowed in.
## IP restriction
Only allow users from a certain IP or range of ips to enter.
## Access key
Users provide an access key in the URL params on first page load, which is then stored as a cookie for 24 hours. If the access key matches the one setup for the outage, they are allowed in.
## Using IP restriction with access key
Users will be allowed if they are from the configured allowed ips OR if they provide the correct access key.
Feedback and issues
-------------------

View File

@@ -13,7 +13,6 @@
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file should run before config.php requires '/lib/setup.php'.
*
@@ -30,16 +29,18 @@
* @var stdClass $CFG
*/
define('MOODLE_INTERNAL', true);
defined('MOODLE_INTERNAL') || die(); // Make sniffer happy.
//
// This call is required by Moodle, but this script should have been called by config.php anyway.
// @codingStandardsIgnoreStart
require_once(__DIR__.'/../../config.php');
// @codingStandardsIgnoreEnd
// We need the CFG->dataroot, if not set yet this script is called too early in config.php file.
if (!isset($CFG->dataroot)) {
return;
}
// 1) Make sure we replace the configurations for behat as we have not ran 'lib/setup.php' yet.
if (!empty($CFG->behat_wwwroot) || !empty($CFG->behat_dataroot) || !empty($CFG->behat_prefix)) {
if (!empty($CFG->behat_wwwroot) or !empty($CFG->behat_dataroot) or !empty($CFG->behat_prefix)) {
require_once(__DIR__.'/../../lib/behat/lib.php');
behat_update_vars_for_process();
if (behat_is_test_site()) {
@@ -77,15 +78,13 @@ if (!empty($_SERVER['REQUEST_URI'])) {
$url = $path.'/auth/outage/info.php';
$outageinfo = strpos($_SERVER['REQUEST_URI'], $url) === 0 ? true : false;
}
$allowed = !file_exists($CFG->dataroot.'/climaintenance.php') // Not in maintenance mode.
|| (defined('ABORT_AFTER_CONFIG') && ABORT_AFTER_CONFIG) // Only config requested.
|| (defined('CLI_SCRIPT') && CLI_SCRIPT) // Allow CLI scripts.
|| $outageinfo // Allow outage info requests.
|| (defined('NO_AUTH_OUTAGE') && NO_AUTH_OUTAGE); // Allow any page should not be blocked by maintenance mode.
if (!$allowed) {
// Call the climaintenance.php which will check for the conditions
// that have been baked into it from the frontend (ip, accesskey, etc...).
// Call the climaintenance.php which will check for allowed IPs.
$CFG->dirroot = dirname(dirname(dirname(__FILE__))); // It is not defined yet but the script below needs it.
require($CFG->dataroot.'/climaintenance.php'); // This call may terminate the script here or not.
}

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* calendar class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\calendar;
use auth_outage\local\outage;
@@ -89,7 +98,6 @@ class calendar {
'userid' => 0,
'modulename' => '',
'instance' => $outage->id,
'component' => 'auth_outage',
'eventtype' => 'auth_outage',
'timestart' => $outage->starttime,
'visible' => true,

View File

@@ -14,6 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outagedb class.
*
* The DB Context to manipulate Outages.
* It will also commit changes to the calendar as you change outages.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\dml;
use auth_outage\calendar\calendar;
@@ -199,20 +211,21 @@ class outagedb {
throw new coding_exception('$time must be null or a positive int.', $time);
}
// Get cached outage, or null.
$outageinfo = get_config('moodle', 'auth_outage_active_outage');
$select = ':datetime2 <= stoptime AND (finished IS NULL OR :datetime3 <= finished)'; // End condition.
$select = "(warntime <= :datetime1 AND (${select}))"; // Full select part.
$data = $DB->get_records_select(
'auth_outage',
$select,
['datetime1' => $time, 'datetime2' => $time, 'datetime3' => $time],
'starttime ASC, stoptime DESC, title ASC',
'*',
0,
1
);
if (!$outageinfo) {
return null;
} else {
$outagecache = new outage(json_decode($outageinfo));
}
if ($outagecache && $outagecache->warntime <= $time && $outagecache->stoptime >= $time
&& (!$outagecache->finished || $outagecache->finished >= $time)) {
return $outagecache;
}
return null;
// Not using $DB->get_record_select instead because there is no 'limit' parameter.
// Allowing multiple records still raises an internal error.
return (count($data) == 0) ? null : new outage(array_shift($data));
}
/**

View File

@@ -14,11 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Toutage_created class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\event;
use core\event\base;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
/**
* outage_created class.
*

View File

@@ -14,11 +14,21 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outage_deleted class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\event;
use core\event\base;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
/**
* outage_deleted class.
*

View File

@@ -14,11 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outage_updated class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\event;
use core\event\base;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
/**
* outage_updated class.
*

View File

@@ -14,11 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* delete class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\form\outage;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/formslib.php');
defined('MOODLE_INTERNAL') || die();
/**
* delete class.
*

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* edit class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\form\outage;
use auth_outage\local\outage;
@@ -75,14 +84,6 @@ class edit extends moodleform {
$mform->addElement('static', 'usagehints', '', get_string('textplaceholdershint', 'auth_outage'));
$mform->addElement('static', 'warningreenablemaintenancemode', '');
$mform->addElement('advcheckbox', 'useaccesskey', get_string('useaccesskey', 'auth_outage'),
get_string('useaccesskey:desc', 'auth_outage'), 0);
$mform->addElement('text', 'accesskey', get_string('accesskey', 'auth_outage'));
$mform->setType('accesskey', PARAM_TEXT);
$mform->disabledIf('accesskey', 'useaccesskey');
$mform->addHelpButton('accesskey', 'accesskey', 'auth_outage');
$this->add_action_buttons();
}
@@ -136,7 +137,6 @@ class edit extends moodleform {
'warntime' => $data->starttime - $data->warningduration,
'title' => $data->title,
'description' => $data->description['text'],
'accesskey' => $data->useaccesskey ? $data->accesskey : null,
];
return new outage($outagedata);
}
@@ -147,7 +147,7 @@ class edit extends moodleform {
* @throws coding_exception
*/
public function set_data($outage) {
global $OUTPUT, $CFG;
global $OUTPUT;
$mform = $this->_form;
// Cannot change method signature, check type.
@@ -160,19 +160,8 @@ class edit extends moodleform {
'warningduration' => $outage->get_warning_duration(),
'title' => $outage->title,
'description' => ['text' => $outage->description, 'format' => '1'],
'accesskey' => $outage->accesskey,
'useaccesskey' => !empty($outage->accesskey),
]);
// If the default_autostart is configured in config, then force autostart to be the default value.
if (array_key_exists('auth_outage', $CFG->forced_plugin_settings)
&& array_key_exists('default_autostart', $CFG->forced_plugin_settings['auth_outage'])) {
$this->_form->setDefaults([
'autostart' => $CFG->forced_plugin_settings['auth_outage']['default_autostart'],
]);
$mform->freeze('autostart');
}
if (!empty($outage->id) && $outage->autostart && $outage->starttime < time() && $outage->stoptime > time()) {
$warning = $mform->getElement('warningreenablemaintenancemode');
$warning->setValue($OUTPUT->notification(get_string('warningreenablemaintenancemode', 'auth_outage'),

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* finish class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\form\outage;
use moodleform;

View File

@@ -1,41 +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/>.
namespace auth_outage;
use auth_outage\local\outagelib;
use core\hook\output\before_standard_top_of_body_html_generation;
/**
* Hook callbacks for auth_outage.
*
* @package auth_outage
* @author Benjamin Walker (benjaminwalker@catalyst-au.net)
* @copyright 2024 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class hook_callbacks {
/**
* Inject the warning bar into the page if there is currently an outage.
*
* @param before_standard_top_of_body_html_generation $hook
*/
public static function before_standard_top_of_body_html_generation(before_standard_top_of_body_html_generation $hook): void {
// Get code to inject.
$hook->add_html(outagelib::get_inject_code());
}
}

View File

@@ -14,10 +14,21 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* cli_exception class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\cli;
use Exception;
defined('MOODLE_INTERNAL') || die();
/**
* cli_exception class.
*
@@ -76,9 +87,9 @@ class cli_exception extends Exception {
* cliexception constructor.
* @param string $message An explanation of the exception.
* @param int $code Exit code to be used.
* @param Exception|null $previous Another exception as reference or null.
* @param Exception $previous Another exception as reference or null.
*/
public function __construct($message, $code = 1, ?Exception $previous = null) {
public function __construct($message, $code = 1, Exception $previous = null) {
parent::__construct('*ERROR* '.$message, $code, $previous = null);
}
}

View File

@@ -14,12 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* clibase class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\cli;
use auth_outage\local\outagelib;
use coding_exception;
use core\session\manager;
defined('MOODLE_INTERNAL') || die();
/**
* clibase class.
*
@@ -41,10 +52,10 @@ abstract class clibase {
/**
* clibase constructor.
* @param array|null $options The parameters to use.
* @param array $options The parameters to use.
* @throws cli_exception
*/
public function __construct(?array $options = null) {
public function __construct(array $options = null) {
global $CFG;
require_once($CFG->libdir.'/clilib.php');
@@ -113,7 +124,7 @@ abstract class clibase {
*/
protected function become_admin_user() {
global $DB;
$user = get_admin();
$user = $DB->get_record('user', ['id' => 2]);
unset($user->description);
unset($user->access);
unset($user->preference);

View File

@@ -14,12 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* create class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\cli;
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
use coding_exception;
defined('MOODLE_INTERNAL') || die();
/**
* create class.
*

View File

@@ -14,11 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* finish class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\cli;
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
/**
* finish class.
*

View File

@@ -14,11 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* waitforit class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\cli;
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
/**
* waitforit class.
*
@@ -120,7 +131,7 @@ class waitforit extends clibase {
return;
}
$time = date('Y-m-d H:i:s T', time());
$time = strftime('%F %T %Z');
printf("[%s] %s\n", $time, $message);
}

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* infopage class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\controllers;
use auth_outage\dml\outagedb;
@@ -23,6 +32,8 @@ use coding_exception;
use context_system;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
/**
* infopage class.
*
@@ -37,16 +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|null $params Parameters to use or null to get from Moodle API (request).
* @param array $params Parameters to use or null to get from Moodle API (request).
*/
public function __construct(?array $params = null) {
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.
@@ -56,13 +62,11 @@ 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 +101,6 @@ class infopage {
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,6 +143,5 @@ class infopage {
}
$this->outage = $params['outage'];
$this->static = $params['static'];
}
}

View File

@@ -14,12 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* maintenance_static_page class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\controllers;
use auth_outage\local\outage;
use coding_exception;
use DOMDocument;
defined('MOODLE_INTERNAL') || die();
/**
* maintenance_static_page class.
*
@@ -50,7 +61,7 @@ class maintenance_static_page {
$html = '<html></html>';
} else {
$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);
$html = $data['contents'];
}

View File

@@ -14,16 +14,26 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* maintenance_static_page_generator class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\controllers;
use auth_outage\local\outagelib;
use coding_exception;
use core_php_time_limit;
use DOMDocument;
use DOMElement;
use invalid_state_exception;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
/**
* maintenance_static_page_generator class.
*
@@ -33,15 +43,6 @@ use moodle_url;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class maintenance_static_page_generator {
/** PATTERN
* The pattern should match the attribute values that
* go as 'url(xxxxx)', but make sure 'url(data:xxxxx)' is not
* rewritten. Must be case insensitive to match 'URL(xxxxx)'.
* It should be possible to specify other background attributes as
* 'background: color url(xxxxx) no-repeat'.
*/
protected const PATTERN = '/url\s*\(\s*[\'"]?(?![\'"]?data:)([^\s\'"]+)[\'"]?\s*\)/i';
/** @var DOMDocument */
protected $dom;
@@ -74,10 +75,6 @@ class maintenance_static_page_generator {
$this->io->cleanup();
if (!is_null($this->dom)) {
// This can take a while to process using repeated curls.
core_php_time_limit::raise();
$this->io->create_resources_path();
$this->remove_script_tags();
@@ -86,7 +83,6 @@ class maintenance_static_page_generator {
$this->update_link_favicon();
$this->update_images();
$this->remove_configured_css_selectors();
$this->update_inline_background_images();
$html = $this->dom->saveHTML();
if (trim($html) == '') {
@@ -154,18 +150,6 @@ class maintenance_static_page_generator {
return $matches;
}
/**
* Retrieves a URL from inline style using regular expressions.
*
* @param string $style Content of the style attribute
* @return array Array containing match
*/
public function get_url_from_inline_style($style) {
preg_match(self::PATTERN, $style, $match);
return $match;
}
/**
* Checks for urls inside filename.
*
@@ -234,31 +218,6 @@ class maintenance_static_page_generator {
}
}
/**
* Fetch and fixes all inline background images.
*/
private function update_inline_background_images() {
global $CFG;
$xpath = new \DOMXPath($this->dom);
$elements = $xpath->query("//*[contains(@style,'background')]");
foreach ($elements as $element) {
$style = $element->getAttribute("style");
$matches = $this->get_url_from_inline_style($style);
if (isset($matches[1])) {
// Allow incomplete URLs in style, assume it is from moodle root.
if (maintenance_static_page_io::is_url($matches[1])) {
$fullurl = $matches[1];
} else {
$fullurl = (string) new moodle_url($matches[1]);
}
$newurl = $this->io->generate_file_url($fullurl);
$updated = preg_replace(self::PATTERN, ' url('.$newurl.') ', $style);
$element->setAttribute('style', $updated);
}
}
}
/**
* Remove from DOM the CSS selectores defined in the plugin settings.
*/

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* maintenance_static_page_io class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local\controllers;
use auth_outage\local\outagelib;
@@ -22,6 +31,8 @@ use finfo;
use invalid_parameter_exception;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
/**
* maintenance_static_page_io class.
*

View File

@@ -14,11 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outage class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local;
use coding_exception;
use stdClass;
defined('MOODLE_INTERNAL') || die();
/**
* outage class.
*
@@ -108,11 +119,6 @@ class outage {
*/
public $lastmodified = null;
/**
* @var string|null access key, or null if not enabled.
*/
public $accesskey = null;
/**
* outage constructor.
* @param stdClass|array|null $data The data for the outage.
@@ -293,12 +299,4 @@ class outage {
// Adjust bool fields.
$this->autostart = ($this->autostart === null) ? null : (bool)$this->autostart;
}
/**
* Return json encoded outage.
* @return string Json string.
*/
public function __toString() {
return json_encode(get_object_vars($this));
}
}

View File

@@ -14,10 +14,20 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outagelib class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\local;
use auth_outage\dml\outagedb;
use auth_outage\local\controllers\maintenance_static_page;
use auth_outage\output\renderer;
use coding_exception;
use curl;
use Exception;
@@ -26,6 +36,7 @@ use invalid_parameter_exception;
use stdClass;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/../../lib.php');
/**
@@ -57,7 +68,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'])) {
@@ -157,12 +168,7 @@ class outagelib {
}
}
$config = array_merge(self::get_config_defaults(), $config);
// Combine allowed IPs config values together.
if (isset($config['allowedips_forced'])) {
$config['allowedips'] = trim($config['allowedips'] . "\n" . $config['allowedips_forced']);
}
return (object)$config;
return (object)array_merge(self::get_config_defaults(), $config);
}
/**
@@ -199,10 +205,6 @@ class outagelib {
} else {
$ongoingoutage = true;
}
// Set json formatted outage string to cache.
set_config('auth_outage_active_outage', (string)$outage);
maintenance_static_page::create_from_outage($outage)->generate();
self::update_climaintenance_code($outage);
if (!$ongoingoutage || $reenablemaint || is_null($outage)) {
@@ -235,7 +237,6 @@ class outagelib {
unset_config('maintenance_message');
}
set_config('maintenance_later', $outage->starttime);
self::maintenance_config_log($outage);
}
}
@@ -266,7 +267,7 @@ class outagelib {
// Used to test the try block in case of errors.
if (PHPUNIT_TEST && optional_param('auth_outage_break_code', false, PARAM_INT)) {
throw new coding_exception('Exception triggered');
(new stdClass())->invalidfield; // Triggers an exception.
}
// Nothing preventing the injection.
@@ -279,95 +280,57 @@ class outagelib {
* @param int $starttime Outage start time.
* @param int $stoptime Outage stop time.
* @param string $allowedips List of IPs allowed.
* @param string|null $accesskey access key, or null if no access key set.
*
* @return string
* @throws invalid_parameter_exception
*/
public static function create_climaintenancephp_code($starttime, $stoptime, $allowedips, $accesskey = null) {
global $CFG;
public static function create_climaintenancephp_code($starttime, $stoptime, $allowedips) {
if (!is_int($starttime) || !is_int($stoptime)) {
throw new invalid_parameter_exception('Make sure $startime and $stoptime are integers.');
}
if (!is_string($allowedips) || (trim($allowedips) == '')) {
throw new invalid_parameter_exception('$allowedips must be a valid string.');
}
// I know Moodle validation would clean up this field, but just in case, let's ensure no
// single-quotes (and double for the sake of it) are present otherwise it would break the code.
$allowedips = addslashes($allowedips);
$cookiesecure = is_moodle_cookie_secure();
// Since Moodle 4.3 cookiehttponly is default to true and this CFG is not set.
// so if not set, default to true.
$cookiehttponly = isset($CFG->cookiehttponly) ? (bool) $CFG->cookiehttponly : true;
$code = <<<'EOT'
<?php
if ((time() >= {{STARTTIME}}) && (time() < {{STOPTIME}})) {
if (!defined('MOODLE_INTERNAL')) {
define('MOODLE_INTERNAL', true);
}
define('MOODLE_INTERNAL', true);
require_once($CFG->dirroot.'/lib/moodlelib.php');
if (file_exists($CFG->dirroot.'/lib/classes/ip_utils.php')) {
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);
$isphpunit = defined('PHPUNIT_TEST');
if (!empty($urlaccesskey) && !$isphpunit) {
setcookie('auth_outage_accesskey', $urlaccesskey, time() + 86400, '/', '', {{COOKIESECURE}}, {{COOKIEHTTPONLY}});
}
// Use url access key if given, else the cookie, else null.
$useraccesskey = $urlaccesskey ?: $_COOKIE['auth_outage_accesskey'] ?? null;
$ipblocked = !remoteip_in_list('{{ALLOWEDIPS}}');
$accesskeyblocked = $useraccesskey != '{{ACCESSKEY}}';
$allowed = ({{USEACCESSKEY}} && !$accesskeyblocked) || ({{USEALLOWEDIPS}} && !$ipblocked);
if (!$allowed) {
if (!$isphpunit) {
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
header('Status: 503 Moodle under maintenance');
header('Retry-After: 300');
header('Content-type: text/html; charset=utf-8');
header('X-UA-Compatible: IE=edge');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Accept-Ranges: none');
header('X-Moodle-Maintenance: manager');
}
if (!$isphpunit && ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER))) {
if (!remoteip_in_list('{{ALLOWEDIPS}}')) {
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
header('Status: 503 Moodle under maintenance');
header('Retry-After: 300');
header('Content-type: text/html; charset=utf-8');
header('X-UA-Compatible: IE=edge');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Accept-Ranges: none');
header('X-Moodle-Maintenance: manager');
if ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER)) {
exit(0);
}
if ({{USEALLOWEDIPS}} && $ipblocked) {
echo '<!-- Blocked by ip, your ip: '.getremoteaddr('n/a').' -->';
}
if ({{USEACCESSKEY}} && $accesskeyblocked) {
echo '<!-- Blocked by missing or incorrect access key, access key given: '. $useraccesskey .' -->';
}
if (!$isphpunit) {
if (file_exists($CFG->dataroot.'/climaintenance.template.html')) {
require($CFG->dataroot.'/climaintenance.template.html');
exit(0);
}
// The file above should always exist, but just in case...
die('We are currently under maintentance, please try again later.');
echo '<!-- Blocked by ip, your ip: '.getremoteaddr('n/a').' -->';
if (file_exists($CFG->dataroot.'/climaintenance.template.html')) {
require($CFG->dataroot.'/climaintenance.template.html');
exit(0);
}
// The file above should always exist, but just in case...
die('We are currently under maintentance, please try again later.');
}
}
EOT;
$search = ['{{STARTTIME}}', '{{STOPTIME}}', '{{USEALLOWEDIPS}}', '{{ALLOWEDIPS}}', '{{USEACCESSKEY}}', '{{ACCESSKEY}}',
'{{YOURIP}}', '{{COOKIESECURE}}', '{{COOKIEHTTPONLY}}'];
// Note that var_export is required because (string) false == '', not 'false'.
$replace = [$starttime, $stoptime, var_export(!empty($allowedips), true), $allowedips, var_export(!empty($accesskey), true),
$accesskey, getremoteaddr('n/a'), var_export($cookiesecure, true), var_export($cookiehttponly, true)];
$search = ['{{STARTTIME}}', '{{STOPTIME}}', '{{ALLOWEDIPS}}', '{{YOURIP}}'];
$replace = [$starttime, $stoptime, $allowedips, getremoteaddr('n/a')];
return str_replace($search, $replace, $code);
}
@@ -389,15 +352,13 @@ EOT;
$config = self::get_config();
$allowedips = trim($config->allowedips);
$accesskey = $outage->accesskey ?? null;
// If no outage, or allowed ips is null and access key is null (i.e. no blocking required).
if (is_null($outage) || ($allowedips == '' && empty($accesskey))) {
if (is_null($outage) || ($allowedips == '')) {
if (file_exists($file)) {
unlink($file);
}
} else {
$code = self::create_climaintenancephp_code($outage->starttime, $outage->stoptime, $allowedips, $accesskey);
$code = self::create_climaintenancephp_code($outage->starttime, $outage->stoptime, $allowedips);
$dir = dirname($file);
if (!file_exists($dir) || !is_dir($dir)) {
@@ -444,18 +405,4 @@ EOT;
return $message;
}
/**
* Logging for maintenance mode configuration.
*
* @param outage|null $outage Outage or null if no scheduled outage.
*/
private static function maintenance_config_log(outage $outage) {
mtrace(get_string('logformaintmodeconfig', 'auth_outage'));
$timezone = ' (Timezone ' . \core_date::get_server_timezone_object()->getName() . ')';
mtrace('... updated at ' . date('H:i:s'));
$time = date("Y-m-d H:i:s", $outage->starttime);
mtrace("... enable maintenance mode at $time $timezone");
mtrace(get_string('logformaintmodeconfigcomplete', 'auth_outage'));
}
}

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* base_table class.
*
* @package auth_outage
* @author Daniel Thee Roperto <danielroperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\output\manage;
use auth_outage\local\outage;
@@ -22,6 +31,7 @@ use html_writer;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/tablelib.php');
/**
@@ -77,7 +87,12 @@ class base_table extends flexible_table {
// View button.
$buttons .= html_writer::link(
new moodle_url('/auth/outage/info.php', ['id' => $outage->id]),
$OUTPUT->pix_icon('t/preview', get_string('view'), 'moodle', array('class' => 'iconsmall')),
html_writer::empty_tag('img', [
'src' => $OUTPUT->image_url('t/preview'),
'alt' => get_string('view'),
'class' => 'iconsmall',
]),
[
'title' => get_string('view'),
'target' => '_blank',
@@ -88,7 +103,11 @@ class base_table extends flexible_table {
if ($editdelete) {
$buttons .= html_writer::link(
new moodle_url('/auth/outage/edit.php', ['edit' => $outage->id]),
$OUTPUT->pix_icon('t/edit', get_string('edit'), 'moodle', array('class' => 'iconsmall')),
html_writer::empty_tag('img', [
'src' => $OUTPUT->image_url('t/edit'),
'alt' => get_string('edit'),
'class' => 'iconsmall',
]),
['title' => get_string('edit')]
);
}
@@ -96,7 +115,12 @@ class base_table extends flexible_table {
// Clone button.
$buttons .= html_writer::link(
new moodle_url('/auth/outage/edit.php', ['clone' => $outage->id]),
$OUTPUT->pix_icon('t/copy', get_string('clone', 'auth_outage'), 'moodle', array('class' => 'iconsmall')),
html_writer::empty_tag('img', [
'src' => $OUTPUT->image_url('t/copy'),
'alt' => get_string('clone', 'auth_outage'),
'class' => 'iconsmall',
]),
['title' => get_string('clone', 'auth_outage')]
);
@@ -104,7 +128,11 @@ class base_table extends flexible_table {
if ($outage->is_ongoing()) {
$buttons .= html_writer::link(
new moodle_url('/auth/outage/finish.php', ['id' => $outage->id]),
$OUTPUT->pix_icon('t/check', get_string('finish', 'auth_outage'), 'moodle', array('class' => 'iconsmall')),
html_writer::empty_tag('img', [
'src' => $OUTPUT->image_url('t/check'),
'alt' => get_string('finish', 'auth_outage'),
'class' => 'iconsmall',
]),
['title' => get_string('finish', 'auth_outage')]
);
}
@@ -113,7 +141,11 @@ class base_table extends flexible_table {
if ($editdelete) {
$buttons .= html_writer::link(
new moodle_url('/auth/outage/delete.php', ['id' => $outage->id]),
$OUTPUT->pix_icon('t/delete', get_string('delete'), 'moodle', array('class' => 'iconsmall')),
html_writer::empty_tag('img', [
'src' => $OUTPUT->image_url('t/delete'),
'alt' => get_string('delete'),
'class' => 'iconsmall',
]),
['title' => get_string('delete')]
);
}

View File

@@ -14,11 +14,21 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* history_table class.
*
* @package auth_outage
* @author Daniel Thee Roperto <danielroperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\output\manage;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/tablelib.php');
/**

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* planned_table class.
*
* @package auth_outage
* @author Daniel Thee Roperto <danielroperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\output\manage;
use auth_outage\local\outage;
@@ -21,6 +30,7 @@ use html_writer;
use moodle_url;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/tablelib.php');
/**
@@ -58,7 +68,7 @@ class planned_table extends base_table {
public function show_data(array $outages) {
foreach ($outages as $outage) {
$title = html_writer::link(
new moodle_url('/auth/outage/edit.php', ['edit' => $outage->id]),
new moodle_url('/auth/outage/edit.php', ['id' => $outage->id]),
$outage->get_title(),
['title' => get_string('edit')]
);

View File

@@ -14,6 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* auth_outage_renderer class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\output;
use auth_outage\local\outage;
@@ -24,6 +33,8 @@ use html_writer;
use moodle_url;
use plugin_renderer_base;
defined('MOODLE_INTERNAL') || die();
/**
* auth_outage_renderer class.
*

View File

@@ -13,9 +13,6 @@
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace auth_outage\privacy;
/**
* Privacy Subsystem implementation for auth_outage.
*
@@ -23,9 +20,24 @@ namespace auth_outage\privacy;
* @copyright 2018 Olivier SECRET <olivier.secret@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\legacy_polyfill;
/**
* Privacy provider for the authentication manual.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\null_provider {
use legacy_polyfill;
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
@@ -35,7 +47,7 @@ class provider implements
*
* @return string
*/
public static function get_reason(): string {
public static function _get_reason() {
return 'privacy:no_data_reason';
}

View File

@@ -14,11 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* update_static_page class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_outage\task;
use auth_outage\local\controllers\infopage;
use auth_outage\local\outagelib;
use core\task\scheduled_task;
defined('MOODLE_INTERNAL') || die();
/**
* update_static_page class.
*

View File

@@ -1,37 +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/>.
/**
* Define capabilities for plugin.
*
* @package auth_outage
* @author Andrew Madden <andrewmadden@catalyst-au.net>
* @copyright 2021 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = [
'auth/outage:viewinfo' => [
'captype' => 'read',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => [
'guest' => CAP_ALLOW,
'user' => CAP_ALLOW,
],
],
];

View File

@@ -1,34 +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/>.
/**
* Hook callbacks for auth_outage
*
* @package auth_outage
* @author Benjamin Walker (benjaminwalker@catalyst-au.net)
* @copyright 2024 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$callbacks = [
[
'hook' => \core\hook\output\before_standard_top_of_body_html_generation::class,
'callback' => '\auth_outage\hook_callbacks::before_standard_top_of_body_html_generation',
'priority' => 0,
],
];

View File

@@ -17,7 +17,6 @@
<FIELD NAME="modifiedby" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Who last modified this entry."/>
<FIELD NAME="lastmodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="When was this entry last modified."/>
<FIELD NAME="finished" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Timestamp of when the outage really finished."/>
<FIELD NAME="accesskey" TYPE="char" LENGTH="16" NOTNULL="false" SEQUENCE="false" COMMENT="Unique key used to access during outage"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>

View File

@@ -24,6 +24,8 @@
*/
use auth_outage\local\controllers\maintenance_static_page;
defined('MOODLE_INTERNAL') || die();
/**
* Auth Outage plugin uninstall code.
* @return bool result

View File

@@ -22,6 +22,7 @@
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Outage plugin upgrade code
@@ -47,20 +48,5 @@ function xmldb_auth_outage_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2016092200, 'auth', 'outage');
}
if ($oldversion < 2024081900) {
// Define field accesskey to be added to auth_outage.
$table = new xmldb_table('auth_outage');
$field = new xmldb_field('accesskey', XMLDB_TYPE_CHAR, '16', null, null, null, null, 'finished');
// Conditionally launch add field accesskey.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Outage savepoint reached.
upgrade_plugin_savepoint(true, 2024081900, 'auth', 'outage');
}
return true;
}

View File

@@ -26,8 +26,6 @@
$string['auth_outagedescription'] = 'Auxiliary plugin that warns users about a future outage and prevents them from logging in once the outage starts.';
$string['autostart'] = 'Auto start maintenance mode.';
$string['autostart_help'] = 'If selected, when the outage starts it will automatically turn on Moodle maintenance mode.';
$string['builtinallowediplist'] = 'Builtin Allowed IP List';
$string['builtinallowediplist_desc'] = 'A second allowed IP list which makes it easier to have some IPs forced in config.php and others editable in the UI';
$string['clicreatehelp'] = 'Creates a new outage.';
$string['clicreateexamples'] = "Create an outage starting in 10 seconds\n\n> php create.php -s=10";
$string['clicreateparamautostart'] = 'must be Y or N, sets if the outage automatically triggers maintenance mode.';
@@ -89,7 +87,7 @@ $string['defaulttitledescription'] = 'Default title for outages. Use {{start}} a
$string['defaulttitlevalue'] = 'System down from {{start}} for {{duration}}';
$string['defaultdescription'] = 'Description';
$string['defaultdescriptiondescription'] = 'Default warning message for outages. Use {{start}} and {{stop}} placeholders as required.';
$string['defaultdescriptionvalue'] = 'There is maintenance scheduled from {{start}} to {{stop}} and our system will not be available during that time.';
$string['defaultdescriptionvalue'] = 'There is an scheduled maintenance from {{start}} to {{stop}} and our system will not be available during that time.';
$string['description'] = 'Public Description';
$string['description_help'] = 'A full description of the outage, publicly visible by all users.';
$string['finish'] = 'Finish';
@@ -102,13 +100,10 @@ $string['infostart'] = 'start';
$string['infostartofwarning'] = 'start of warning';
$string['infostaticpage'] = 'static page';
$string['infopagestaticgenerated'] = 'This warning was generated on {$a->time}.';
$string['ips_combine'] = 'The IPs listed above will be combined with the IPs listed below.';
$string['allowedipsempty'] = 'No one will be blocked by IP because the list is empty. You can add your own IP address (<i>{$a->ip}</i>) and block all other IPs. IP blocking is in addition to access key blocking (if setup in outage)';
$string['allowedipshasmyip'] = 'Your IP (<i>{$a->ip}</i>) is in the list and your IP will not be blocked out during an Outage.';
$string['allowedipshasntmyip'] = 'Your IP (<i>{$a->ip}</i>) is not in the list and your IP will be blocked out during an outage.';
$string['allowedipsempty'] = 'When the allowed IPs list is empty we will not block anyone. You can add your own IP address (<i>{$a->ip}</i>) and block all other IPs.';
$string['allowedipshasmyip'] = 'Your IP (<i>{$a->ip}</i>) is in the list and you will not be blocked out during an Outage.';
$string['allowedipshasntmyip'] = 'Your IP (<i>{$a->ip}</i>) is not in the list and you will be blocked out during an outage.';
$string['allowedipsnoconfig'] = 'Your config.php does not have the extra setup to allow blocking via IP.<br />Please refer to our <a href="https://github.com/catalyst/moodle-auth_outage#installation" target="_blank">README.md</a> file for more information.';
$string['logformaintmodeconfig'] = 'Update maintenance mode configuration.';
$string['logformaintmodeconfigcomplete'] = 'Updating maintenance mode configuration complete.';
$string['menusettings'] = 'Settings';
$string['menumanage'] = 'Manage outages';
$string['messageoutagebackonline'] = 'We are back online!';
@@ -117,7 +112,6 @@ $string['messageoutageongoing'] = 'Back online at {$a->stop}.';
$string['messageoutagewarning'] = 'Shutting down in {{countdown}}';
$string['na'] = 'n/a';
$string['notfound'] = 'No outages found.';
$string['outage:viewinfo'] = 'View outage info';
$string['outageedit'] = 'Edit outage';
$string['outageeditcrumb'] = 'Edit';
$string['outageclone'] = 'Clone outage';
@@ -162,10 +156,6 @@ $string['warningdurationerrorinvalid'] = 'Warning duration must be positive.';
$string['warningduration'] = 'Warning duration';
$string['warningduration_help'] = 'How long before the start of the outage should the warning be displayed.';
$string['warningreenablemaintenancemode'] = 'Please note that saving this outage will re-enable maintenance mode.<br />Untick "Auto start maintenance mode" if you want to prevent this.';
$string['accesskey'] = 'Access key';
$string['accesskey_help'] = 'Testers should pass the access key initially in the url parameters e.g. ?accesskey=xyz. This will then be stored in a cookie for 24 hours, during which the url parameter will not be necessary.<br /><b>Note:</b> the access key is in addition to any IP restrictions setup.';
$string['useaccesskey'] = 'Use access key';
$string['useaccesskey:desc'] = 'Require testers to access site during outage by providing the access key below';
/*
* Privacy provider (GDPR)

18
lib.php
View File

@@ -25,6 +25,8 @@
use auth_outage\local\outagelib;
defined('MOODLE_INTERNAL') || die;
/**
* Used for adminlib::set_updatedcallback which requires a string that resolves to a function.
*
@@ -66,14 +68,22 @@ function auth_outage_get_climaintenance_resource_file($file) {
}
/**
* Inject the warning bar into the page if there is currently an outage.
* Display required icon for the calendar events.
*
* This is a legacy callback that is used for compatibility with older Moodle versions.
* Moodle 4.4+ will use auth_outage\hook_callbacks::before_standard_top_of_body_html_generation instead.
* @return array
*/
function auth_outage_get_fontawesome_icon_map() {
return [
'core:i/auth_outageevent' => 'fa-power-off',
];
}
/**
* Inject the warning bar into the page if there is currently an outage.
*
* @return string|void
*/
function auth_outage_before_standard_top_of_body_html() {
// Get code to inject.
return outagelib::get_inject_code();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512" preserveAspectRatio="xMinYMid meet"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M288 32c0-17.7-14.3-32-32-32s-32 14.3-32 32V256c0 17.7 14.3 32 32 32s32-14.3 32-32V32zM143.5 120.6c13.6-11.3 15.4-31.5 4.1-45.1s-31.5-15.4-45.1-4.1C49.7 115.4 16 181.8 16 256c0 132.5 107.5 240 240 240s240-107.5 240-240c0-74.2-33.8-140.6-86.6-184.6c-13.6-11.3-33.8-9.4-45.1 4.1s-9.4 33.8 4.1 45.1c38.9 32.3 63.5 81 63.5 135.4c0 97.2-78.8 176-176 176s-176-78.8-176-176c0-54.4 24.7-103.1 63.5-135.4z"/></svg>

Before

Width:  |  Height:  |  Size: 686 B

View File

@@ -26,6 +26,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* auth_outage_renderer class.
*

View File

@@ -26,30 +26,25 @@
* @var admin_settingpage $settings
* @var bootstrap_renderer $OUTPUT
* @var admin_root $ADMIN
* @var moodle_page $PAGE
*/
use auth_outage\local\outagelib;
defined('MOODLE_INTERNAL') || die;
if ($hassiteconfig) {
if ($hassiteconfig && is_enabled_auth('outage')) {
$defaults = outagelib::get_config_defaults();
$settings->visiblename = get_string('menusettings', 'auth_outage');
$description = outagelib::generate_plugin_configuration_warning();
$settings->add(new admin_setting_heading(
'defaults',
get_string('settingssectiondefaults', 'auth_outage'),
get_string('settingssectiondefaultsdescription', 'auth_outage') . $description
));
get_string('settingssectiondefaultsdescription', 'auth_outage')));
$settings->add(new admin_setting_configcheckbox(
'auth_outage/default_autostart',
get_string('defaultoutageautostart', 'auth_outage'),
get_string('defaultoutageautostartdescription', 'auth_outage'),
$defaults['default_autostart']
));
$settings->add(new admin_setting_configduration(
'auth_outage/default_warning_duration',
get_string('defaultwarningduration', 'auth_outage'),
@@ -101,23 +96,20 @@ if ($hassiteconfig) {
// Create 'Allowed IPs' settings.
$allowedips = outagelib::get_config()->allowedips;
$description = outagelib::generate_plugin_configuration_warning();
if (trim($allowedips) == '') {
$message = 'allowedipsempty';
$type = 'notifymessage';
} else if (remoteip_in_list($allowedips)) {
$message = 'allowedipshasmyip';
$type = 'notifysuccess';
} else {
if (remoteip_in_list($allowedips)) {
$message = 'allowedipshasmyip';
$type = 'notifysuccess';
} else {
$message = 'allowedipshasntmyip';
$type = 'notifyerror';
}
$message = 'allowedipshasntmyip';
$type = 'notifyerror';
};
$description = $OUTPUT->notification(get_string($message, 'auth_outage', ['ip' => getremoteaddr()]), $type);
$description .= '<p>' . get_string('ipblockersyntax', 'admin') . '</p>';
$description .= '<p>' . get_string('ips_combine', 'auth_outage') . '</p>';
$description .= $OUTPUT->notification(get_string($message, 'auth_outage', ['ip' => getremoteaddr()]), $type);
$description .= '<p>'.get_string('ipblockersyntax', 'admin').'</p>';
$iplist = new admin_setting_configiplist(
'auth_outage/allowedips',
get_string('allowediplist', 'admin'),
@@ -127,14 +119,6 @@ if ($hassiteconfig) {
$iplist->set_updatedcallback('auth_outage_outagelib_prepare_next_outage');
$settings->add($iplist);
$iplist = new admin_setting_configiplist(
'auth_outage/allowedips_forced',
get_string('builtinallowediplist', 'auth_outage'),
get_string('builtinallowediplist_desc', 'auth_outage'),
''
);
$settings->add($iplist);
// Create 'Static Page - Elements to Remove' settings.
$toremove = new admin_setting_configtextarea(
'auth_outage/remove_selectors',
@@ -156,7 +140,7 @@ if ($hassiteconfig) {
new admin_externalpage(
'auth_outage_manage',
get_string('menumanage', 'auth_outage'),
new moodle_url($CFG->wwwroot . '/auth/outage/manage.php')
new moodle_url($CFG->wwwroot.'/auth/outage/manage.php')
)
);
}

View File

@@ -1,171 +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/>.
/**
* Tests performed on infopage controller class and update_static_page task class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\outage;
use auth_outage\local\controllers\infopage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
/**
* Tests performed on infopage controller class and update_static_page task class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\controllers\infopage
*/
class controllers_infopage_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
/**
* Tests the constructor.
*/
public function test_constructor() {
$this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance()));
new infopage();
}
/**
* 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();
}
/**
* Tests the constructor with different id and outage id.
*/
public function test_constructor_idmismatch() {
$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]);
}
/**
* Tests the constructor with an invalid outage.
*/
public function test_constructor_invalidoutage() {
$this->assertTrue(has_capability('auth/outage:viewinfo', context_system::instance()));
$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() {
$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);
}
}

View File

@@ -1,7 +0,0 @@
a {
font-size: 200%;
}
div {
background-image: url('/moodle/auth/outage/tests/fixtures/catalyst.png');
}

View File

@@ -1,7 +0,0 @@
a {
font-size: 200%;
}
div {
background-image: url(/moodle/auth/outage/tests/fixtures/catalyst.png);
}

View File

@@ -14,9 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
/**
* Base testcase for auth outage tests.
*
@@ -33,7 +30,20 @@ use auth_outage\local\outage;
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base_testcase extends \core_phpunit\testcase {
use auth_outage\dml\outagedb;
defined('MOODLE_INTERNAL') || die();
/**
* auth_outage_base_testcase class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class auth_outage_base_testcase extends advanced_testcase {
/**
* Checks PHPUnit version and calls the functions accordingly.
* @param string $exception Expected exception class.
@@ -55,37 +65,6 @@ abstract class base_testcase extends \core_phpunit\testcase {
}
}
/**
* Revoke permission to see info page.
*/
protected function revoke_info_page_permissions() {
global $DB;
$guestrole = $DB->get_record('role', ['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.
*/
@@ -105,6 +84,5 @@ abstract class base_testcase extends \core_phpunit\testcase {
foreach (outagedb::get_all() as $i => $outage) {
$DB->delete_records('auth_outage', ['id' => $outage->id]);
}
parent::tearDown();
}
}

View File

@@ -23,8 +23,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\outage;
use auth_outage\calendar\calendar;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
/**
* calendar_test test class.
@@ -36,9 +38,8 @@ use auth_outage\calendar\calendar;
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\calendar\calendar
*/
class calendar_test extends \core_phpunit\testcase {
class calendar_test extends advanced_testcase {
/**
* @var outage|null The calendar entry owner.
*/
@@ -133,8 +134,8 @@ class calendar_test extends \core_phpunit\testcase {
]);
calendar::update($outage);
self::assertCount(1, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(1, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**
@@ -145,8 +146,8 @@ class calendar_test extends \core_phpunit\testcase {
self::setAdminUser();
calendar::delete(1);
self::assertCount(1, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(1, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**

View File

@@ -23,11 +23,11 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\outage;
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../base_testcase.php');
/**
* outagedb_test tests class.
@@ -36,14 +36,8 @@ require_once(__DIR__.'/base_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\dml\outagedb
*/
class dml_outagedb_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
class outagedb_test extends auth_outage_base_testcase {
/**
* Creates an array of ids in from the given outages array.
* @param outage[] $outages An array of outages.
@@ -250,15 +244,6 @@ class dml_outagedb_test extends base_testcase {
$activeid = self::saveoutage(false, $now, -2, 1, 2, 'An outage in warning period.');
self::assertSame($activeid, outagedb::get_active($now)->id, 'Wrong active outage picked.');
$activeid = self::saveoutage(false, $now, -2, 0, 2, 'An outage starts now.');
self::assertSame($activeid, outagedb::get_active($now)->id, 'Wrong active outage picked.');
self::saveoutage(false, $now, -2, 0, -1, 'Invalid outage.');
self::assertSame($activeid, outagedb::get_active($now)->id, 'Wrong active outage picked.');
self::saveoutage(false, $now, -2, 0, 0, 'Invalid outage.');
self::assertSame($activeid, outagedb::get_active($now)->id, 'Wrong active outage picked.');
self::saveoutage(false, $now, -1, 2, 3,
'Another outage in warning period, but ignored as it starts after the previous one.');
self::assertSame($activeid, outagedb::get_active($now)->id, 'Wrong active outage picked.');
@@ -442,8 +427,8 @@ class dml_outagedb_test extends base_testcase {
public function test_finish_now_notfound() {
$this->resetAfterTest(true);
outagedb::finish(1);
self::assertCount(1, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(1, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**
@@ -464,8 +449,8 @@ class dml_outagedb_test extends base_testcase {
self::assertTrue(!$outage->is_ongoing($time));
outagedb::finish($id, $time);
self::assertCount(1, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(1, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**

View File

@@ -23,8 +23,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\outage;
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
/**
* events_test tests class.
@@ -36,9 +38,8 @@ use auth_outage\dml\outagedb;
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\dml\outagedb
*/
class dml_events_test extends \core_phpunit\testcase {
class events_test extends advanced_testcase {
/**
* @var outage|null Outage used in the tests.
*/

View File

@@ -23,13 +23,13 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\outage;
use auth_outage\form\outage\delete;
use auth_outage\form\outage\finish;
use auth_outage\form\outage\edit;
use auth_outage\form\outage\finish;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../base_testcase.php');
/**
* forms_test test class.
@@ -38,14 +38,8 @@ require_once(__DIR__.'/base_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\form\outage\edit
*/
class forms_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
class forms_test extends auth_outage_base_testcase {
/**
* Create a delete form.
*/
@@ -152,8 +146,8 @@ class forms_test extends base_testcase {
$_POST['description'] = ['text' => 'The <b>description</b>.', 'format' => '2'];
$edit = new edit();
self::assertNull($edit->get_data());
self::assertCount(1, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(1, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**

View File

@@ -26,7 +26,6 @@
*/
use auth_outage\local\outage;
use auth_outage\dml\outagedb;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
@@ -40,14 +39,8 @@ require_once(__DIR__.'/base_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\dml\outagedb
*/
class dml_installation_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
class installation_test extends auth_outage_base_testcase {
/**
* Checks if plugin cleans up data after uninstall.
*
@@ -70,19 +63,15 @@ class dml_installation_test extends base_testcase {
'title' => 'Title',
'description' => 'Description',
]);
ob_start();
outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
\auth_outage\dml\outagedb::save($outage);
self::assertSame(1, $DB->count_records_select('event', "eventtype = 'auth_outage'", null));
// Uninstall plugin.
require_once($CFG->libdir.'/adminlib.php');
$progress = new \progress_trace_buffer(new \text_progress_trace(), false);
\core_plugin_manager::instance()->uninstall_plugin('auth_outage', $progress);
$progress = new progress_trace_buffer(new text_progress_trace(), false);
core_plugin_manager::instance()->uninstall_plugin('auth_outage', $progress);
$progress->finished();
self::assertStringContainsString('++ Success ++', $progress->get_buffer());
self::assertContains('++ Success ++', $progress->get_buffer());
// Check ...
self::assertSame(0, $DB->count_records_select('event', "eventtype = 'auth_outage'", null),

View File

@@ -14,9 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* tests for lib.php
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2017 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../lib.php');
require_once(__DIR__.'/../../lib.php');
/**
* tests for lib.php
@@ -25,9 +34,8 @@ require_once(__DIR__.'/../lib.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2017 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers ::auth_outage_get_climaintenance_resource_file
*/
class lib_test extends \core_phpunit\testcase {
class lib_test extends auth_outage_base_testcase {
/**
* Test this plugin gets climaintenance resource file.
*/

View File

@@ -36,14 +36,8 @@ require_once(__DIR__.'/cli_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\cli\create
*/
class cli_test extends cli_testcase {
public function tearDown(): void {
parent::tearDown();
}
class cli_test extends auth_outage_cli_testcase {
/**
* Tests providing an unknown parameter.
*/
@@ -87,8 +81,8 @@ class cli_test extends cli_testcase {
$this->set_parameters(['-h']);
$cli = new create();
$output = $this->execute($cli);
self::assertStringContainsString('-h', $output);
self::assertStringContainsString('--help', $output);
self::assertContains('-h', $output);
self::assertContains('--help', $output);
}
/**
@@ -106,7 +100,7 @@ class cli_test extends cli_testcase {
// Disable all auth plugins.
set_config('auth', '');
\core\session\manager::gc(); // Remove stale sessions.
\core_plugin_manager::reset_caches();
core_plugin_manager::reset_caches();
// Try to create an CLI object.
$this->set_expected_cli_exception(cli_exception::ERROR_PLUGIN_CONFIGURATION);
new create();

View File

@@ -15,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* cli_testcase class.
* auth_outage_cli_testcase class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
@@ -23,23 +23,20 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\cli\clibase;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../../base_testcase.php');
/**
* cli_testcase class.
* auth_outage_cli_testcase class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class cli_testcase extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
abstract class auth_outage_cli_testcase extends auth_outage_base_testcase {
/**
* Always enable the auth outage plugin, resets after test and set no parameters.
*/
@@ -52,7 +49,7 @@ abstract class cli_testcase extends base_testcase {
// Enable auth plugins.
set_config('auth', 'outage');
\core\session\manager::gc(); // Remove stale sessions.
\core_plugin_manager::reset_caches();
core_plugin_manager::reset_caches();
$this->set_parameters([]);
parent::setUp();
@@ -76,7 +73,7 @@ abstract class cli_testcase extends base_testcase {
*
* @return string The output text.
*/
protected function execute(mixed $cli) {
protected function execute(clibase $cli) {
ob_start();
try {
$cli->execute();

View File

@@ -24,9 +24,9 @@
*/
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
use auth_outage\local\cli\create;
use auth_outage\local\cli\cli_exception;
use auth_outage\local\cli\create;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/cli_testcase.php');
@@ -38,14 +38,8 @@ require_once(__DIR__.'/cli_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\cli\create
*/
class cli_create_test extends cli_testcase {
public function tearDown(): void {
parent::tearDown();
}
class create_test extends auth_outage_cli_testcase {
/**
* Tests without any arguments.
*/
@@ -126,8 +120,8 @@ class cli_create_test extends cli_testcase {
$this->set_parameters(['--help']);
$cli = new create();
$output = $this->execute($cli);
self::assertStringContainsString('Creates', $output);
self::assertStringContainsString('--help', $output);
self::assertContains('Creates', $output);
self::assertContains('--help', $output);
}
/**
@@ -163,10 +157,10 @@ class cli_create_test extends cli_testcase {
$cli = new create();
$cli->set_referencetime($now);
$text = $this->execute($cli);
self::assertStringContainsString('created', $text);
self::assertContains('created', $text);
// Check creted outage.
$clioutput = explode(':', $text);
$id = (int)end($clioutput);
list(, $id) = explode(':', $text);
$id = (int)$id;
$outage = outagedb::get_by_id($id);
self::assertSame($now, $outage->starttime);
self::assertSame(10, $outage->get_warning_duration());
@@ -227,10 +221,10 @@ class cli_create_test extends cli_testcase {
'description' => 'Default Description',
]);
$text = $this->execute($cli);
self::assertStringContainsString('created', $text);
self::assertContains('created', $text);
// Check creted outage.
$clioutput = explode(':', $text);
$id = (int)end($clioutput);
list(, $id) = explode(':', $text);
$id = (int)$id;
$outage = outagedb::get_by_id($id);
self::assertSame($now + 50, $outage->starttime, 'Wrong starttime.');
self::assertSame($outage->starttime - 100, $outage->warntime, 'Wrong warntime.');
@@ -305,8 +299,8 @@ class cli_create_test extends cli_testcase {
$cli = new create();
$cli->set_referencetime($now);
$text = $this->execute($cli);
self::assertStringContainsString('created', $text);
self::assertStringContainsString('started', $text);
self::assertContains('created', $text);
self::assertContains('started', $text);
}
/**

View File

@@ -24,9 +24,9 @@
*/
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
use auth_outage\local\cli\finish;
use auth_outage\local\cli\cli_exception;
use auth_outage\local\cli\finish;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/cli_testcase.php');
@@ -38,14 +38,8 @@ require_once(__DIR__.'/cli_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\cli\finish
*/
class cli_finish_test extends cli_testcase {
public function tearDown(): void {
parent::tearDown();
}
class finish_test extends auth_outage_cli_testcase {
/**
* Tests the constructor.
*/
@@ -78,8 +72,8 @@ class cli_finish_test extends cli_testcase {
$this->set_parameters(['--help']);
$cli = new finish();
$text = $this->execute($cli);
self::assertStringContainsString('Finishes', $text);
self::assertStringContainsString('--help', $text);
self::assertContains('Finishes', $text);
self::assertContains('--help', $text);
}
/**

View File

@@ -24,9 +24,9 @@
*/
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
use auth_outage\local\cli\waitforit;
use auth_outage\local\cli\cli_exception;
use auth_outage\local\cli\waitforit;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/cli_testcase.php');
@@ -38,14 +38,8 @@ require_once(__DIR__.'/cli_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\cli\waitforit
*/
class cli_waitforit_test extends cli_testcase {
public function tearDown(): void {
parent::tearDown();
}
class waitforit_test extends auth_outage_cli_testcase {
/**
* Tests the constructor.
*/
@@ -84,8 +78,8 @@ class cli_waitforit_test extends cli_testcase {
$this->set_parameters(['--help']);
$cli = new waitforit();
$text = $this->execute($cli);
self::assertStringContainsString('Waits', $text);
self::assertStringContainsString('--help', $text);
self::assertContains('Waits', $text);
self::assertContains('--help', $text);
}
/**
@@ -157,9 +151,9 @@ class cli_waitforit_test extends cli_testcase {
$cli = new waitforit();
$cli->set_referencetime($now);
$output = $this->execute($cli);
self::assertStringContainsString('Verbose mode', $output);
self::assertStringContainsString('starting in 1 sec', $output);
self::assertStringContainsString('started', $output);
self::assertContains('Verbose mode', $output);
self::assertContains('starting in 1 sec', $output);
self::assertContains('started', $output);
}
/**
@@ -184,11 +178,11 @@ class cli_waitforit_test extends cli_testcase {
return $now;
});
$output = $this->execute($cli);
self::assertStringContainsString("starting in 45", $output);
self::assertStringContainsString("sleep 30 second", $output);
self::assertStringContainsString("starting in 15", $output);
self::assertStringContainsString("sleep 15 second", $output);
self::assertStringContainsString("started!", $output);
self::assertContains("starting in 45", $output);
self::assertContains("sleep 30 second", $output);
self::assertContains("starting in 15", $output);
self::assertContains("sleep 15 second", $output);
self::assertContains("started!", $output);
}
/**

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,7 @@
a {
font-size: 200%;
}
div {
background-image: url('/moodle/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png');
}

View File

@@ -0,0 +1,7 @@
a {
font-size: 200%;
}
div {
background-image: url(/moodle/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png);
}

View File

@@ -0,0 +1,118 @@
<?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/>.
/**
* Tests performed on infopage controller class and update_static_page task class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\controllers\infopage;
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/../../base_testcase.php');
/**
* Tests performed on infopage controller class and update_static_page task class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class infopagecontroller_test extends auth_outage_base_testcase {
/**
* Tests the constructor.
*/
public function test_constructor() {
new infopage();
}
/**
* Tests the constructor with given parameters.
*/
public function test_constructor_withparams() {
$_GET = ['id' => 1, 'static' => 'true'];
new infopage();
}
/**
* 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');
new infopage(['id' => 2, 'outage' => $outage]);
}
/**
* Tests the constructor with an invalid outage.
*/
public function test_constructor_invalidoutage() {
$this->set_expected_exception('coding_exception');
new infopage(['outage' => 'My outage']);
}
/**
* 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();
}
/**
* 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',
]);
$info = new infopage(['outage' => $outage]);
$output = $info->get_output();
self::assertContains('auth_outage_info', $output);
}
/**
* Tests the constructor enables SVG support.
*/
public function test_svgicons_is_true() {
global $CFG;
$CFG->svgicons = false;
new infopage();
self::assertTrue($CFG->svgicons);
}
}

View File

@@ -23,13 +23,13 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\task\update_static_page;
use auth_outage\local\controllers\maintenance_static_page;
use auth_outage\local\controllers\maintenance_static_page_io;
use auth_outage\local\controllers\maintenance_static_page_generator;
use auth_outage\task\update_static_page;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../../base_testcase.php');
/**
* maintenance_static_page_test class.
@@ -38,14 +38,8 @@ require_once(__DIR__.'/base_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\controllers\maintenance_static_page_generator
*/
class controllers_maintenance_static_page_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
class maintenance_static_page_test extends auth_outage_base_testcase {
/**
* Test template file.
*/
@@ -96,30 +90,30 @@ class controllers_maintenance_static_page_test extends base_testcase {
maintenance_static_page::create_from_html($html)->generate();
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString('<script', $generated);
self::assertNotContains('<script', $generated);
}
/**
* Test remove script tags.
*/
public function test_updatelinkstylesheet() {
$localcsslink = $this->get_fixture_path_location('simple.css');
$localcsslink = $this->get_fixture_path('simple.css');
$externalcsslink = 'http://google.com/coolstuff.css';
$html = "<!DOCTYPE html>\n".
'<html><head><link href="'.$localcsslink.'" rel="stylesheet" /><title>Title</title></head>'.
'<body>Content<link rel="stylesheet" href="'.$externalcsslink.'"></body></html>';
$generated = $this->generated_page_html($html);
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=', $generated);
self::assertStringNotContainsString($localcsslink, $generated);
self::assertStringContainsString($externalcsslink, $generated);
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=', $generated);
self::assertNotContains($localcsslink, $generated);
self::assertContains($externalcsslink, $generated);
}
/**
* Test update link style sheet urls.
*/
public function test_updatelinkstylesheet_urls() {
$localcsslink = $this->get_fixture_path_location('withurls.css');
$localcsslink = $this->get_fixture_path('withurls.css');
$html = "<!DOCTYPE html>\n".
'<html><head><link href="'.$localcsslink.'" rel="stylesheet" /><title>Title</title></head>'.
'<body>Content</body></html>';
@@ -127,7 +121,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
$page->generate();
// Check for css file.
self::assertFileExists($page->get_io()->get_resources_folder().'/b09bd4b66cc3964d5fc5978752fc554f5666daa3.dGV4dC9wbGFpbg');
self::assertFileExists($page->get_io()->get_resources_folder().'/d8643101d96b093e642b15544e4d1f7815b5ba55.dGV4dC9wbGFpbg');
// Check for catalyst.png file referenced in url(..) of css.
self::assertFileExists($page->get_io()->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n');
@@ -137,7 +131,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
* Test update link style sheet urls quoted.
*/
public function test_updatelinkstylesheet_urls_quoted() {
$localcsslink = $this->get_fixture_path_location('withurls-quoted.css');
$localcsslink = $this->get_fixture_path('withurls-quoted.css');
$html = "<!DOCTYPE html>\n".
'<html><head><link href="'.$localcsslink.'" rel="stylesheet" /><title>Title</title></head>'.
'<body>Content</body></html>';
@@ -145,7 +139,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
$page->generate();
// Check for css file.
self::assertFileExists($page->get_io()->get_resources_folder().'/2ec04228cc8bb37782f511aaeb01ee553cc884a4.dGV4dC9wbGFpbg');
self::assertFileExists($page->get_io()->get_resources_folder().'/9fe2374b03953e1949d54ab750be2d8706891c03.dGV4dC9wbGFpbg');
// Check for catalyst.png file referenced in url(..) of css.
self::assertFileExists($page->get_io()->get_resources_folder().'/ff7f7f87a26a908fc72930eaefb6b57306361d16.aW1hZ2UvcG5n');
@@ -155,7 +149,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
* Test update link style sheet urls with sub dir.
*/
public function test_updatelinkstylesheet_urls_subdir() {
$localcsslink = $this->get_fixture_path_location('subdir/withurls-subdir.css');
$localcsslink = $this->get_fixture_path('subdir/withurls-subdir.css');
$html = "<!DOCTYPE html>\n".
'<html><head><link href="'.$localcsslink.'" rel="stylesheet" /><title>Title</title></head>'.
'<body>Content</body></html>';
@@ -173,92 +167,37 @@ class controllers_maintenance_static_page_test extends base_testcase {
* Test update images to file.php style link.
*/
public function test_updateimages() {
$localimglink = $this->get_fixture_path_location('catalyst.png');
$localimglink = $this->get_fixture_path('catalyst.png');
$externalimglink = 'http://google.com/coolstyle.css';
$html = "<!DOCTYPE html>\n".
'<html><head><title>Title</title></head>'.
'<body><img src="'.$localimglink.'">Content<img src="'.$externalimglink.'" /></body></html>';
$generated = $this->generated_page_html($html);
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=', $generated);
self::assertStringNotContainsString($localimglink, $generated);
self::assertStringContainsString($externalimglink, $generated);
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=', $generated);
self::assertNotContains($localimglink, $generated);
self::assertContains($externalimglink, $generated);
}
/**
* Test update favicon to file.php style link.
*/
public function test_updatelinkfavicon() {
$link = $this->get_fixture_path_location('catalyst.png');
$link = $this->get_fixture_path('catalyst.png');
$html = "<!DOCTYPE html>\n".
'<html><head><title>Title</title><link rel="shortcut icon" href="'.$link.'""></head>'.
'<body>Content</body></html>';
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString($link, $generated);
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=', $generated);
}
/**
* Data provider for test_update_inline_background_images
* @return array
*/
public static function update_inline_background_images_provider(): array {
return [
// Empty string.
["", false],
// URLs that should be retrieved.
["color: #FF00FF; background: lightblue url(/pluginfile.php/1/theme_custom/banner/251298630/0001.png) no-repeat", true],
["background: lightblue
url(https://www.example.com/moodle/pluginfile.php/1/theme_custom/banner/251298630/0001.png) no-repeat", true],
["background:url('https://www.example.com/moodle/pluginfile.php/1/theme_custom/banner/251298630/0001.png')", true],
["background-image : url( /pix/help.png);", true],
["background-image: url ('/pix/help.png')", true],
// URLs that should not be retrieved.
["background-image:url(data:image/gif;base64,R0lGODlhYADIAP=)", false],
["background-image:url('data:image/gif;base64,R0lGODlhYADIAP=')", false],
];
}
/**
* Tests update_inline_background_images() method to update the background images.
*
* @dataProvider update_inline_background_images_provider
* @param string $stylecontent Content of the style to test
* @param bool $rewrite Flag if URL should be rewritten
* @throws coding_exception
*/
public function test_update_inline_background_images($stylecontent, $rewrite) {
global $CFG;
$this->resetAfterTest(true);
$generator = new maintenance_static_page_generator(new DOMDocument(), new maintenance_static_page_io());
$html = '<!DOCTYPE html>\n'.
'<html><head><title>Title</title></head>'.
'<body><div style="'.$stylecontent.'">Content</div></body></html>';
// Temporarily disable debugging to prevent errors because file does not exist.
$debuglevel = $CFG->debug;
$CFG->debug = '';
$generated = $this->generated_page_html($html);
// Restore debugging level.
$CFG->debug = $debuglevel;
$matches = $generator->get_url_from_inline_style($stylecontent);
if ($rewrite) {
self::assertStringNotContainsString($matches[1], $generated);
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=', $generated);
self::assertIsArray($matches);
} else {
self::assertStringContainsString($stylecontent, $generated);
}
self::assertNotContains($link, $generated);
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=', $generated);
}
/**
* Test update preview path to file.php style link.
*/
public function test_previewpath() {
$link = $this->get_fixture_path_location('catalyst.png');
$link = $this->get_fixture_path('catalyst.png');
$html = "<!DOCTYPE html>\n".
'<html><head><title>Title</title><link rel="shortcut icon" href="'.$link.'""></head>'.
'<body>Content</body></html>';
@@ -267,8 +206,8 @@ class controllers_maintenance_static_page_test extends base_testcase {
$page->generate();
$generated = trim(file_get_contents($page->get_io()->get_template_file()));
self::assertStringNotContainsString($link, $generated);
self::assertStringContainsString('www.example.com/moodle/auth/outage/file.php?file=preview%2F', $generated);
self::assertNotContains($link, $generated);
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=preview%2F', $generated);
}
/**
@@ -304,12 +243,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
touch($file);
self::assertFileExists($file);
maintenance_static_page::create_from_outage(null)->generate();
// Backwards compatibility with older PHPUnit - use old assertFile method.
if (method_exists($this, 'assertFileDoesNotExist')) {
self::assertFileDoesNotExist($file);
} else {
self::assertFileNotExists($file);
}
self::assertFileNotExists($file);
}
/**
@@ -318,7 +252,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
public function test_createdfile() {
global $CFG;
$link = $this->get_fixture_path_location('catalyst.png');
$link = $this->get_fixture_path('catalyst.png');
$html = "<!DOCTYPE html>\n".
'<html><head><title>Title</title></head>'.
'<body>Content<img src="'.$link.'" /></body></html>';
@@ -331,7 +265,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
// We can still assert the contents really match, not just the hash.
$found = file_get_contents($file);
$expected = file_get_contents(__DIR__.'/fixtures/catalyst.png');
$expected = file_get_contents($CFG->dirroot.'/auth/outage/tests/phpunit/local/controllers/fixtures/catalyst.png');
self::assertSame($found, $expected);
}
@@ -342,8 +276,8 @@ class controllers_maintenance_static_page_test extends base_testcase {
*
* @return string
*/
private function get_fixture_path_location($file) {
return (string)new \moodle_url('/auth/outage/tests/fixtures/'.$file);
private function get_fixture_path($file) {
return (string)new moodle_url('/auth/outage/tests/phpunit/local/controllers/fixtures/'.$file);
}
/**
@@ -369,23 +303,20 @@ class controllers_maintenance_static_page_test extends base_testcase {
*/
public function test_get_url_for_file() {
$io = new maintenance_static_page_io();
self::assertStringContainsString(
'www.example.com/moodle/auth/outage/file.php?file=img.png',
$io->get_url_for_file('img.png')
);
self::assertContains('www.example.com/moodle/auth/outage/file.php?file=img.png', $io->get_url_for_file('img.png'));
}
/**
* Return array of url data provider and true or false.
*/
public static function is_url_dataprovider(): array {
public function is_url_dataprovider() {
return [
[true, 'http://catalyst.net.nz'],
[true, 'https://www.catalyst-au.net/'],
[false, '/homepage'],
[false, 'file://homepage'],
[true, '//catalyst-au.net/img/test.jpg'],
[false, '://www.catalyst-au.net/img/test.jpg'],
[false, '://www.catalyst-au.net/img/test.jpg']
];
}
@@ -416,8 +347,8 @@ class controllers_maintenance_static_page_test extends base_testcase {
$found = maintenance_static_page_io::file_get_data(__DIR__.'/fixtures/invalidfile');
self::assertSame('', $found['contents']);
self::assertSame('unknown', $found['mime']);
self::assertCount(1, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(1, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**
@@ -428,37 +359,6 @@ class controllers_maintenance_static_page_test extends 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() {
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.
*/
@@ -470,8 +370,8 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', '.removeme', 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString('removeme', $generated);
self::assertStringNotContainsString('Goodbye cruel world', $generated);
self::assertNotContains('removeme', $generated);
self::assertNotContains('Goodbye cruel world', $generated);
}
/**
@@ -485,8 +385,8 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', '#removeme', 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString('removeme', $generated);
self::assertStringNotContainsString('Goodbye cruel world', $generated);
self::assertNotContains('removeme', $generated);
self::assertNotContains('Goodbye cruel world', $generated);
}
/**
@@ -503,9 +403,9 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', ".removeme\n.deleteme", 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString('removeme', $generated);
self::assertStringNotContainsString('deleteme', $generated);
self::assertStringNotContainsString('Goodbye cruel world', $generated);
self::assertNotContains('removeme', $generated);
self::assertNotContains('deleteme', $generated);
self::assertNotContains('Goodbye cruel world', $generated);
}
/**
@@ -522,9 +422,9 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', " .removeme \n .deleteme ", 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString('removeme', $generated);
self::assertStringNotContainsString('deleteme', $generated);
self::assertStringNotContainsString('Goodbye cruel world', $generated);
self::assertNotContains('removeme', $generated);
self::assertNotContains('deleteme', $generated);
self::assertNotContains('Goodbye cruel world', $generated);
}
/**
@@ -541,9 +441,9 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', "\n\n.removeme\n\n\n\n.deleteme\n\n", 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringNotContainsString('removeme', $generated);
self::assertStringNotContainsString('deleteme', $generated);
self::assertStringNotContainsString('Goodbye cruel world', $generated);
self::assertNotContains('removeme', $generated);
self::assertNotContains('deleteme', $generated);
self::assertNotContains('Goodbye cruel world', $generated);
}
/**
@@ -557,8 +457,8 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', '#invalidid', 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringContainsString('removeme', $generated);
self::assertStringContainsString('Goodbye cruel world', $generated);
self::assertContains('removeme', $generated);
self::assertContains('Goodbye cruel world', $generated);
}
/**
@@ -572,7 +472,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
set_config('remove_selectors', '#invalidid', 'auth_outage');
$generated = $this->generated_page_html($html);
self::assertStringContainsString('<meta http-equiv="refresh" content="300">', $generated);
self::assertContains('<meta http-equiv="refresh" content="300">', $generated);
}
/**
@@ -590,14 +490,14 @@ class controllers_maintenance_static_page_test extends base_testcase {
$generated = trim(file_get_contents($page->get_io()->get_template_file()));
return $generated;
self::assertStringContainsString('<meta http-equiv="refresh" content="5">', $generated);
self::assertContains('<meta http-equiv="refresh" content="5">', $generated);
}
/**
* Data provider for test_get_urls_from_stylesheet
* @return array
*/
public static function get_urls_from_stylesheet_provider(): array {
public function test_get_urls_from_stylesheet_provider() {
return [
// Empty string.
["", 0],
@@ -619,7 +519,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
/**
* Tests get_urls_from_stylesheet() method to get all appropriate URLS from the file.
*
* @dataProvider get_urls_from_stylesheet_provider
* @dataProvider test_get_urls_from_stylesheet_provider
* @param string $filecontent Content of the file
* @param int $count Expected quantity of found URLs
* @throws coding_exception
@@ -629,7 +529,7 @@ class controllers_maintenance_static_page_test extends base_testcase {
$generator = new maintenance_static_page_generator(new DOMDocument(), new maintenance_static_page_io());
$matches = $generator->get_urls_from_stylesheet($filecontent);
self::assertIsArray($matches);
self::assertInternalType('array', $matches);
self::assertCount(2, $matches);
self::assertCount($count, $matches[1]);
}

View File

@@ -14,10 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outage_test test class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\local\outage;
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../base_testcase.php');
/**
* outage_test test class.
@@ -26,14 +35,8 @@ require_once(__DIR__.'/base_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\outage
*/
class outage_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
class outage_test extends auth_outage_base_testcase {
/**
* Tests the constructor.
*/
@@ -51,7 +54,7 @@ class outage_test extends base_testcase {
* Tests the constructor, giving data as an object.
*/
public function test_constructor_object() {
$obj = new \stdClass();
$obj = new stdClass();
$obj->id = 1;
$obj->autostart = true;
$obj->warntime = 2;
@@ -277,11 +280,11 @@ class outage_test extends base_testcase {
'description' => 'Description {{start}} {{stop}} {{duration}}',
]);
$title = $outage->get_title();
self::assertStringNotContainsString('{', $title);
self::assertStringNotContainsString('}', $title);
self::assertNotContains('{', $title);
self::assertNotContains('}', $title);
$description = $outage->get_description();
self::assertStringNotContainsString('{', $description);
self::assertStringNotContainsString('}', $description);
self::assertNotContains('{', $description);
self::assertNotContains('}', $description);
}
/**

View File

@@ -14,14 +14,24 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* outagelib_test test class.
*
* @package auth_outage
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use auth_outage\dml\outagedb;
use auth_outage\local\outage;
use auth_outage\local\outagelib;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir.'/adminlib.php');
require_once(__DIR__.'/base_testcase.php');
require_once(__DIR__.'/../base_testcase.php');
/**
* outagelib_test test class.
@@ -30,14 +40,8 @@ require_once(__DIR__.'/base_testcase.php');
* @author Daniel Thee Roperto <daniel.roperto@catalyst-au.net>
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \auth_outage\local\outagelib
*/
class outagelib_test extends base_testcase {
public function tearDown(): void {
parent::tearDown();
}
class outagelib_test extends auth_outage_base_testcase {
/**
* Check if maintenance message is disabled as needed.
*/
@@ -56,14 +60,10 @@ class outagelib_test extends base_testcase {
]);
set_config('maintenance_message', 'A message.');
ob_start();
outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
self::assertFalse((bool)get_config('moodle', 'maintenance_message'));
self::assertCount(2, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(2, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**
@@ -94,23 +94,19 @@ class outagelib_test extends base_testcase {
'title' => 'Title',
'description' => 'Description',
]);
ob_start();
$outage->id = outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
outagelib::reset_injectcalled();
// Get full header to avoid interactions with other single inject plugins.
$header1 = $OUTPUT->standard_top_of_body_html();
self::assertStringContainsString('<style>', $header1);
self::assertStringContainsString('<script>', $header1);
self::assertContains('<style>', $header1);
self::assertContains('<script>', $header1);
// Should not inject more than once.
$size = strlen($OUTPUT->standard_top_of_body_html());
self::assertSame($size, strlen($OUTPUT->standard_top_of_body_html()));
// Check styles aren't reinjected.
self::assertStringNotContainsString('<style>', $OUTPUT->standard_top_of_body_html());
self::assertNotContains('<style>', $OUTPUT->standard_top_of_body_html());
}
/**
@@ -120,8 +116,8 @@ class outagelib_test extends base_testcase {
$_GET = ['auth_outage_break_code' => '1'];
outagelib::reset_injectcalled();
$header = outagelib::get_inject_code();
self::assertCount(2, $this->getDebuggingMessages());
$this->resetDebugging();
self::assertCount(2, phpunit_util::get_debugging_messages());
phpunit_util::reset_debugging();
}
/**
@@ -140,18 +136,14 @@ class outagelib_test extends base_testcase {
'title' => 'Title',
'description' => 'Description',
]);
ob_start();
$outage->id = outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
$_GET = ['auth_outage_preview' => (string)$outage->id];
outagelib::reset_injectcalled();
$header = outagelib::get_inject_code();
self::assertStringContainsString('<style>', $header);
self::assertStringContainsString('<script>', $header);
self::assertContains('<style>', $header);
self::assertContains('<script>', $header);
}
/**
@@ -183,11 +175,8 @@ class outagelib_test extends base_testcase {
'title' => 'Title',
'description' => 'Description',
]);
ob_start();
$outage->id = outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
$_GET = ['auth_outage_preview' => (string)$outage->id, 'auth_outage_delta' => '500'];
outagelib::reset_injectcalled();
$header = outagelib::get_inject_code();
@@ -227,10 +216,6 @@ class outagelib_test extends base_testcase {
foreach ($keys as $k) {
self::assertSame($config->$k, $k.'_value', 'auth_outage');
}
set_config('allowedips_forced', 'allowedips_forced_value', 'auth_outage');
$config = outagelib::get_config();
self::assertSame($config->allowedips, "allowedips_value\nallowedips_forced_value", 'auth_outage');
}
/**
@@ -293,11 +278,7 @@ class outagelib_test extends base_testcase {
'title' => 'Title',
'description' => 'Description',
]);
ob_start();
$outage->id = outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
// Pretend we are there...
$_SERVER['SCRIPT_FILENAME'] = '/var/www/alternativepath/admin/settings.php'; // Issue #88 regression test.
@@ -313,161 +294,93 @@ class outagelib_test extends base_testcase {
* Test create maintenance php code
*/
public function test_createmaintenancephpcode() {
global $CFG;
$CFG->cookiehttponly = false;
$expected = <<<'EOT'
<?php
if ((time() >= 123) && (time() < 456)) {
if (!defined('MOODLE_INTERNAL')) {
define('MOODLE_INTERNAL', true);
}
define('MOODLE_INTERNAL', true);
require_once($CFG->dirroot.'/lib/moodlelib.php');
if (file_exists($CFG->dirroot.'/lib/classes/ip_utils.php')) {
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);
$isphpunit = defined('PHPUNIT_TEST');
if (!empty($urlaccesskey) && !$isphpunit) {
setcookie('auth_outage_accesskey', $urlaccesskey, time() + 86400, '/', '', true, false);
}
// Use url access key if given, else the cookie, else null.
$useraccesskey = $urlaccesskey ?: $_COOKIE['auth_outage_accesskey'] ?? null;
$ipblocked = !remoteip_in_list('hey\'\"you
if (!remoteip_in_list('hey\'\"you
a.b.c.d
e.e.e.e/20');
$accesskeyblocked = $useraccesskey != '12345';
$allowed = (true && !$accesskeyblocked) || (true && !$ipblocked);
if (!$allowed) {
if (!$isphpunit) {
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
header('Status: 503 Moodle under maintenance');
header('Retry-After: 300');
header('Content-type: text/html; charset=utf-8');
header('X-UA-Compatible: IE=edge');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Accept-Ranges: none');
header('X-Moodle-Maintenance: manager');
}
if (!$isphpunit && ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER))) {
e.e.e.e/20')) {
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
header('Status: 503 Moodle under maintenance');
header('Retry-After: 300');
header('Content-type: text/html; charset=utf-8');
header('X-UA-Compatible: IE=edge');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Accept-Ranges: none');
header('X-Moodle-Maintenance: manager');
if ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER)) {
exit(0);
}
if (true && $ipblocked) {
echo '<!-- Blocked by ip, your ip: '.getremoteaddr('n/a').' -->';
}
if (true && $accesskeyblocked) {
echo '<!-- Blocked by missing or incorrect access key, access key given: '. $useraccesskey .' -->';
}
if (!$isphpunit) {
if (file_exists($CFG->dataroot.'/climaintenance.template.html')) {
require($CFG->dataroot.'/climaintenance.template.html');
exit(0);
}
// The file above should always exist, but just in case...
die('We are currently under maintentance, please try again later.');
echo '<!-- Blocked by ip, your ip: '.getremoteaddr('n/a').' -->';
if (file_exists($CFG->dataroot.'/climaintenance.template.html')) {
require($CFG->dataroot.'/climaintenance.template.html');
exit(0);
}
// The file above should always exist, but just in case...
die('We are currently under maintentance, please try again later.');
}
}
EOT;
$found = outagelib::create_climaintenancephp_code(123, 456, "hey'\"you\na.b.c.d\ne.e.e.e/20", '12345');
$found = outagelib::create_climaintenancephp_code(123, 456, "hey'\"you\na.b.c.d\ne.e.e.e/20");
self::assertSame($expected, $found);
}
/**
* Test create maintenance php code without age
*
* @param string $configkey The key of the config.
* @dataProvider createmaintenancephpcode_withoutage_provider
*/
public function test_createmaintenancephpcode_withoutage($configkey) {
public function test_createmaintenancephpcode_withoutage() {
global $CFG;
$this->resetAfterTest(true);
$CFG->cookiehttponly = false;
$expected = <<<'EOT'
<?php
if ((time() >= 123) && (time() < 456)) {
if (!defined('MOODLE_INTERNAL')) {
define('MOODLE_INTERNAL', true);
}
define('MOODLE_INTERNAL', true);
require_once($CFG->dirroot.'/lib/moodlelib.php');
if (file_exists($CFG->dirroot.'/lib/classes/ip_utils.php')) {
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);
$isphpunit = defined('PHPUNIT_TEST');
if (!empty($urlaccesskey) && !$isphpunit) {
setcookie('auth_outage_accesskey', $urlaccesskey, time() + 86400, '/', '', true, false);
}
// Use url access key if given, else the cookie, else null.
$useraccesskey = $urlaccesskey ?: $_COOKIE['auth_outage_accesskey'] ?? null;
$ipblocked = !remoteip_in_list('127.0.0.1');
$accesskeyblocked = $useraccesskey != '5678';
$allowed = (true && !$accesskeyblocked) || (true && !$ipblocked);
if (!$allowed) {
if (!$isphpunit) {
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
header('Status: 503 Moodle under maintenance');
header('Retry-After: 300');
header('Content-type: text/html; charset=utf-8');
header('X-UA-Compatible: IE=edge');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Accept-Ranges: none');
header('X-Moodle-Maintenance: manager');
}
if (!$isphpunit && ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER))) {
if (!remoteip_in_list('127.0.0.1')) {
header($_SERVER['SERVER_PROTOCOL'] . ' 503 Moodle under maintenance');
header('Status: 503 Moodle under maintenance');
header('Retry-After: 300');
header('Content-type: text/html; charset=utf-8');
header('X-UA-Compatible: IE=edge');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Accept-Ranges: none');
header('X-Moodle-Maintenance: manager');
if ((defined('AJAX_SCRIPT') && AJAX_SCRIPT) || (defined('WS_SERVER') && WS_SERVER)) {
exit(0);
}
if (true && $ipblocked) {
echo '<!-- Blocked by ip, your ip: '.getremoteaddr('n/a').' -->';
}
if (true && $accesskeyblocked) {
echo '<!-- Blocked by missing or incorrect access key, access key given: '. $useraccesskey .' -->';
}
if (!$isphpunit) {
if (file_exists($CFG->dataroot.'/climaintenance.template.html')) {
require($CFG->dataroot.'/climaintenance.template.html');
exit(0);
}
// The file above should always exist, but just in case...
die('We are currently under maintentance, please try again later.');
echo '<!-- Blocked by ip, your ip: '.getremoteaddr('n/a').' -->';
if (file_exists($CFG->dataroot.'/climaintenance.template.html')) {
require($CFG->dataroot.'/climaintenance.template.html');
exit(0);
}
// The file above should always exist, but just in case...
die('We are currently under maintentance, please try again later.');
}
}
EOT;
$outage = new outage([
'starttime' => 123,
'stoptime' => 456,
'accesskey' => '5678',
]);
$file = $CFG->dataroot.'/climaintenance.php';
set_config($configkey, '127.0.0.1', 'auth_outage');
set_config('allowedips', '127.0.0.1', 'auth_outage');
outagelib::update_climaintenance_code($outage);
self::assertFileExists($file);
@@ -476,37 +389,22 @@ EOT;
}
/**
* Provides values to test_createmaintenancephpcode_withoutage
* @return array
* Test create maintenance php code without IPs
*/
public static function createmaintenancephpcode_withoutage_provider(): array {
return [['allowedips'], ['allowedips_forced']];
}
/**
* Test create maintenance php code without IPs or accesskey
*/
public function test_createmaintenancephpcode_withoutips_or_accesskey() {
public function test_createmaintenancephpcode_withoutips() {
global $CFG;
$this->resetAfterTest(true);
$outage = new outage([
'starttime' => 123,
'stoptime' => 456,
'accesskey' => null,
]);
$file = $CFG->dataroot.'/climaintenance.php';
set_config('allowedips', '', 'auth_outage');
set_config('allowedips_forced', '', 'auth_outage');
touch($file);
outagelib::update_climaintenance_code($outage);
// Backwards compatibility with older PHPUnit - use old assertFile method.
if (method_exists($this, 'assertFileDoesNotExist')) {
self::assertFileDoesNotExist($file);
} else {
self::assertFileNotExists($file);
}
self::assertFileNotExists($file);
}
/**
@@ -518,12 +416,7 @@ EOT;
touch($file);
outagelib::update_climaintenance_code(null);
// Backwards compatibility with older PHPUnit - use old assertFile method.
if (method_exists($this, 'assertFileDoesNotExist')) {
self::assertFileDoesNotExist($file);
} else {
self::assertFileNotExists($file);
}
self::assertFileNotExists($file);
}
/**
@@ -550,7 +443,9 @@ EOT;
$this->create_outage();
// Change settings.
set_config('s_auth_outage_allowedips', '127', 'auth_outage');
admin_write_settings((object)[
's_auth_outage_allowedips' => '127',
]);
// The method outagelib::prepare_next_outage() should have been called from admin_write_settings().
foreach ([$CFG->dataroot.'/climaintenance.template.html', $CFG->dataroot.'/climaintenance.php'] as $file) {
@@ -568,7 +463,9 @@ EOT;
$this->create_outage();
// Change settings.
set_config('s_auth_outage_remove_selectors', '.something', 'auth_outage');
admin_write_settings((object)[
's_auth_outage_remove_selectors' => '.something',
]);
// The method outagelib::prepare_next_outage() should have been called from admin_write_settings().
foreach ([$CFG->dataroot.'/climaintenance.template.html', $CFG->dataroot.'/climaintenance.php'] as $file) {
@@ -599,12 +496,7 @@ EOT;
// The method outagelib::prepare_next_outage() should have been called by save().
self::assertFalse(get_config('moodle', 'maintenance_later'));
// This file should not exist even if the statement above fails as Moodle does not create it immediately but test anyway.
// Backwards compatibility with older PHPUnit - use old assertFile method.
if (method_exists($this, 'assertFileDoesNotExist')) {
self::assertFileDoesNotExist($CFG->dataroot.'/climaintenance.html');
} else {
self::assertFileNotExists($CFG->dataroot.'/climaintenance.html');
}
self::assertFileNotExists($CFG->dataroot.'/climaintenance.html');
}
/**
@@ -624,11 +516,8 @@ EOT;
'title' => 'Title',
'description' => 'Description',
]);
ob_start();
$outage->id = outagedb::save($outage);
$text = trim(ob_get_contents());
ob_end_clean();
self::assertStringContainsString('Update maintenance mode configuration', $text);
// Pretend we are there...
$_SERVER['SCRIPT_FILENAME'] = '/var/www/alternativepath/admin/settings.php'; // Issue #88 regression test.
$_SERVER['SCRIPT_NAME'] = '/admin/settings.php';
@@ -660,150 +549,6 @@ EOT;
// Enable outage plugin so settings can be changed.
set_config('auth', 'outage');
\core\session\manager::gc(); // Remove stale sessions.
\core_plugin_manager::reset_caches();
}
/**
* Provides values to test_evaluation_maintenancepage
* @return array
*/
public static function evaluation_maintenancepage_provider(): array {
$blockedipout = '<!-- Blocked by ip, your ip:';
$blockedaccesskeyout = '<!-- Blocked by missing or incorrect access key, access key given:';
return [
// IP set up, access key not set up.
'ip allowed, no access key setup' => [
'allowedips' => '127.0.0.1',
'iptouse' => '127.0.0.1',
'accesskey' => null,
'accesskeytouse' => null,
'expectedoutputs' => [],
],
'ip not allowed, no access key setup' => [
'allowedips' => '5.5.5.5',
'iptouse' => '127.0.0.1',
'accesskey' => null,
'accesskeytouse' => null,
'expectedoutputs' => [$blockedipout],
],
// IP not set up, access key set up.
'access key incorrect, no ip setup' => [
'allowedips' => null,
'iptouse' => null,
'accesskey' => '12345',
'accesskeytouse' => 'wrong',
'expectedoutputs' => [$blockedaccesskeyout],
],
'access key correct, no ip setup' => [
'allowedips' => null,
'iptouse' => null,
'accesskey' => '12345',
'accesskeytouse' => '12345',
'expectedoutputs' => [],
],
// Both IP and access key set up.
'access key incorrect, ip incorrect' => [
'allowedips' => '127.0.0.1',
'iptouse' => '5.5.5.5',
'accesskey' => '12345',
'accesskeytouse' => 'wrong',
'expectedoutputs' => [$blockedipout, $blockedaccesskeyout],
],
'access key correct, ip incorrect' => [
'allowedips' => '127.0.0.1',
'iptouse' => '5.5.5.5',
'accesskey' => '12345',
'accesskeytouse' => '12345',
'expectedoutputs' => [],
],
'access key incorrect, ip correct' => [
'allowedips' => '127.0.0.1',
'iptouse' => '127.0.0.1',
'accesskey' => '12345',
'accesskeytouse' => 'wrong',
'expectedoutputs' => [],
],
'access key correct, ip correct' => [
'allowedips' => '127.0.0.1',
'iptouse' => '127.0.0.1',
'accesskey' => '12345',
'accesskeytouse' => '12345',
'expectedoutputs' => [],
],
];
}
/**
* Tests the evaluation logic of the generated maintenance page.
*
* @param string|null $allowedips config to set as allowed ips - null to not set
* @param string|null $iptouse ip to 'fake' as the remote ip, or null to not set.
* @param string|null $accesskey config to set as the access key in the outage - null to not set
* @param string|null $accesskeytouse access key to pass in as fake url params - null to not set
* @param array $expectedoutputs expected output strings, if empty will test that the output was also empty.
*
* @dataProvider evaluation_maintenancepage_provider
*
* We need this because we modify the request headers,
* see https://github.com/sebastianbergmann/phpunit/issues/720#issuecomment-10421092
* @runClassInSeparateProcess
*/
public function test_evaluation_maintenancepage(?string $allowedips, ?string $iptouse, ?string $accesskey,
?string $accesskeytouse, array $expectedoutputs) {
global $CFG, $_SERVER, $_GET;
$this->resetAfterTest(true);
self::setAdminUser();
$now = time();
$outage = new outage([
'autostart' => false,
'warntime' => $now - 200,
'starttime' => $now - 100,
'stoptime' => $now + 200,
'title' => 'Title',
'description' => 'Description',
'accesskey' => $accesskey,
]);
if (!is_null($allowedips)) {
set_config('allowedips', $allowedips, 'auth_outage');
}
// Ensure if the file exists we clean it (e.g. from a previous test run).
$file = $CFG->dataroot.'/climaintenance.php';
if (file_exists($file)) {
unlink($file);
}
// This basically sets the output of getremoteaddr().
if (!is_null($iptouse)) {
$_SERVER['REMOTE_ADDR'] = $iptouse;
}
// This sets the output of optional_param().
if (!is_null($accesskeytouse)) {
$_GET['accesskey'] = $accesskeytouse;
}
outagelib::update_climaintenance_code($outage);
self::assertFileExists($file);
// Require the file to execute it.
// Normally this would die, but we have baked some goodies in there
// that stop it die'ing during a unit test.
ob_start();
require($file);
$contents = ob_get_clean();
// Check each output is as expected.
foreach ($expectedoutputs as $expectedoutput) {
$this->assertStringContainsString($expectedoutput, $contents);
}
// Ensure if nothing was expected, that it is empty.
if (empty($expectedoutputs)) {
$this->assertEmpty($contents);
}
core_plugin_manager::reset_caches();
}
}

View File

@@ -28,8 +28,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = "auth_outage";
$plugin->version = 2024081900; // The current plugin version (Date: YYYYMMDDXX).
$plugin->release = 2024081900; // Human-readable release information.
$plugin->requires = 2017111309; // 2017111309 = T13, but this really requires 3.9 and higher.
$plugin->version = 2021032500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->release = 2021032500; // Human-readable release information.
$plugin->requires = 2017051500; // Requires 3.3 and higher.
$plugin->maturity = MATURITY_STABLE; // Suitable for PRODUCTION environments!
$plugin->supported = [39, 405]; // A range of branch numbers of supported moodle versions.

View File

@@ -24,7 +24,6 @@
*
* @var array $viewbag
*/
// phpcs:disable moodle.Commenting.MissingDocblock.File
defined('MOODLE_INTERNAL') || die();
?>

View File

@@ -22,7 +22,6 @@
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// phpcs:disable moodle.Commenting.MissingDocblock.File
use auth_outage\output\manage\history_table;
use auth_outage\output\manage\planned_table;

View File

@@ -12,21 +12,12 @@ If you need to make changes here, remember to update your settings inside Moodle
padding: 0;
position: fixed;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
top: 0;
transition: background 3s ease-out;
width: 100%;
z-index: 9999;
}
#auth_outage_warningbar_box .auth_outage_warningbar_center {
/* fix to prevent existing theme hacks to fix issue */
margin-top: 0;
position: static;
}
#auth_outage_warningbar_box.auth_outage_warning_period {
background:
repeating-linear-gradient(
@@ -75,10 +66,16 @@ If you need to make changes here, remember to update your settings inside Moodle
background-color: #090;
}
.auth_outage_warningbar_center {
margin-top: -35px;
position: relative;
top: 50%;
}
#auth_outage_warningbar_message {
font-size: 200%;
font-weight: bold;
margin: 0;
margin: 10px 0;
}
a.auth_outage_warningbar_box_title {
@@ -90,7 +87,6 @@ a.auth_outage_warningbar_box_finish {
border: 1px solid black;
border-radius: 5px;
color: darkgray;
white-space: nowrap;
font-weight: bold;
margin-left: 10px;
padding-left: 5px;
@@ -130,9 +126,3 @@ body.auth_outage .layout.fullscreen {
body.auth_outage .modal-dialog {
margin: calc(150px + 1.75rem) auto;
}
@media (max-width: 767px) {
#auth_outage_warningbar_message {
font-size: 120%;
}
}

View File

@@ -56,8 +56,6 @@ var authOutageWarningBar = {
},
tickOngoing: function() {
const MINSECS = 60;
if (this.finished) {
return;
}
@@ -80,8 +78,13 @@ var authOutageWarningBar = {
xmlhttp.open("GET", this.checkfinishedurl, true);
xmlhttp.send();
// Checking if the site is back online every 4-6 minutes.
var sleepSeconds = 4 * MINSECS + (2 * MINSECS * Math.random());
var estimatedServerTime = this.servertime + (Date.now() - this.clienttime);
var sleepSeconds = this.stops - estimatedServerTime; // How long to sleep until it stops.
if (sleepSeconds <= 0) {
sleepSeconds = 5; // It should be back, keep checking every 5 seconds.
} else {
sleepSeconds = Math.min(sleepSeconds, (5 * 60)); // Check at least every 5 minutes.
}
setTimeout(function() {
$this.tickOngoing();

View File

@@ -22,7 +22,6 @@
* @copyright 2016 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// phpcs:disable moodle.Commenting.MissingDocblock.File
use auth_outage\local\outagelib;
@@ -47,15 +46,17 @@ if (!$viewbag['static']) {
['target' => '_blank', 'class' => 'auth_outage_warningbar_box_title']
);
if (is_siteadmin()) {
$link = html_writer::link(
new moodle_url('/auth/outage/finish.php', ['id' => $viewbag['outage']->id]),
$OUTPUT->pix_icon('t/check', get_string('finish', 'auth_outage'), 'moodle', array('class' => 'iconsmall')) . get_string('finish', 'auth_outage'),
[
'title' => get_string('finish', 'auth_outage'),
'class' => 'auth_outage_warningbar_box_finish',
]
);
$title .= ' '.html_writer::span($link, '', ['id' => 'auth_outage_warningbar_button']);
$url = new moodle_url('/auth/outage/finish.php', ['id' => $viewbag['outage']->id]);
$text = html_writer::empty_tag('img', [
'src' => $OUTPUT->image_url('t/check'),
'alt' => get_string('finish', 'auth_outage'),
'class' => 'iconsmall',
]).' '.get_string('finish', 'auth_outage');
$attr = [
'title' => get_string('finish', 'auth_outage'),
'class' => 'auth_outage_warningbar_box_finish',
];
$title .= ' '.html_writer::span(html_writer::link($url, $text, $attr), '', ['id' => 'auth_outage_warningbar_button']);
}
}
?>