From 77eb49b6956de6b79659bcb4c55514b6dc10865a Mon Sep 17 00:00:00 2001 From: Alexander Bias Date: Tue, 6 Aug 2024 15:57:12 +0200 Subject: [PATCH] Multiple improvements * Remove close button from notification banner and show the installer notifications in CLI as well, resolves #2. * Move apc.php to Moodledata to ease using the plugin on Moodle instances with immutable / non-writeable Moodle codebases, resolves #4. --- CHANGES.md | 5 +++++ README.md | 10 +++++----- UPGRADE.md | 2 +- apc.conf.php | 2 +- db/install.php | 10 ++++++++-- db/uninstall.php | 39 +++++++++++++++++++++++++++++++++++++++ db/upgrade.php | 17 ++++++++++++----- index.php | 20 +++++++++++++++++--- lang/en/tool_apcu.php | 9 +++++---- lib/apcu-gui/.gitignore | 4 ---- locallib.php | 37 ++++++++++++++++++++++++++++++++----- thirdpartylibs.xml | 2 +- version.php | 2 +- 13 files changed, 127 insertions(+), 32 deletions(-) create mode 100644 db/uninstall.php delete mode 100644 lib/apcu-gui/.gitignore diff --git a/CHANGES.md b/CHANGES.md index d55ddbe..b64323e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,11 @@ moodle-tool_apcu Changes ------- +### Unreleased + +* 2024-08-06 - Remove close button from notification banner and show the installer notifications in CLI as well, resolves #2. +* 2024-08-06 - Move apc.php to Moodledata to ease using the plugin on Moodle instances with immutable / non-writeable Moodle codebases, resolves #4. + ### v4.3-r1 * 2023-10-20 - Prepare compatibility for Moodle 4.3. diff --git a/README.md b/README.md index aad40dc..5844a72 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,13 @@ APCu management GUI file installation This plugin wraps the APCu management GUI which was built by the APCu developers. This APCu management GUI is just a small PHP file. Unfortunately, this file can't be shipped together with this plugin's code as its PHP license is incompatible with Moodle's GPL license. -During installation, the plugin tries to download and store the APCu management GUI file to your wwwroot automatically. If this mechanism fails, especially because of the lack of permissions, you have to download the APCu management GUI file manually and store it to your webserver. Until you download and store this file, the plugin will not work. +During installation, the plugin tries to download and store the APCu management GUI file to MOODLEDATA automatically. If this mechanism fails, you have to download and store the APCu management GUI file manually . Until you download and store this file, the plugin will not work. The APCu management GUI is to be downloaded from: https://raw.githubusercontent.com/krakjoe/apcu/master/apc.php The APCu management GUI is to be stored to: -/tool/apcu/lib/apcu-gui/apcu.php.inc +MOODLEDATA/tool_apcu/apcu.php.inc Usage @@ -71,11 +71,11 @@ This plugin works in a really simple way. It adds an admin tool page to Moodle's Security note ------------- -The APCu management GUI file is stored as a library to this Moodle plugin and is renamed to /lib/apcu-gui/apcu.php.inc. +The APCu management GUI file is stored as a library to MOODLEDATA. -There is a potential for sensitive data leak, not personal data but data about the webserver's PHP configuration, if your webserver is configured to interpret *.inc files as PHP. An anonymous user could then visit the library's index page directly via https://yourmoodle.com/admin/tool/apcu/lib/apcu-gui/apcu.php.inc and would see the APCu management GUI circumventing Moodle's access control. +There is a potential for sensitive data leak, not personal data but data about the webserver's PHP configuration, if your webserver is configured to interpret *.inc files as PHP and if an attacker would find a way to execute this PHP file within the MOODLEDATA directory. -Please make sure that your webserver does not interpret *.inc files as PHP (which should be the default) or take any other measure that this file can not be accessed directly by a browser. +Please make sure that your webserver does not interpret *.inc files as PHP (which should be the default) and make sure that attackers cannot execute this file directly within MOODLEDATA. Theme support diff --git a/UPGRADE.md b/UPGRADE.md index 3cf7f42..f6ca1a7 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -14,7 +14,7 @@ General Upstream changes ---------------- -* This plugin relies on the thiry-party apc.php file which is dropped manually or automatically into the plugin directory. This file is under active development. +* This plugin relies on the thiry-party apc.php file which is dropped manually or automatically into the MOODLEDATA/tool_apcu directory. This file is under active development. Automated tests diff --git a/apc.conf.php b/apc.conf.php index 33eb0ef..8f88ebc 100644 --- a/apc.conf.php +++ b/apc.conf.php @@ -17,7 +17,7 @@ /** * Admin tool "APCu management" - APCu GUI configuration override file * - * The APCu GUI code which we have placed into lib/apcu-gui/apcu.php.inc + * The APCu GUI code which we have placed into MOODLEDATA/tool_apcu/apcu.php.inc * is looking for a file called apc.conf.php and includes this file. * In this file, we can override the configuration of the APCu GUI. * diff --git a/db/install.php b/db/install.php index f55f51e..ac443d5 100644 --- a/db/install.php +++ b/db/install.php @@ -32,6 +32,8 @@ * @return bool */ function xmldb_tool_apcu_install() { + global $OUTPUT; + // Install the APCu GUI file from the web - either automatically or manually. // Try to download and store APCu management GUI file. @@ -49,9 +51,13 @@ function xmldb_tool_apcu_install() { // Output message. if ($guidropsuccessful == true) { - \core\notification::success($message); + $notification = new \core\output\notification($message, \core\output\notification::NOTIFY_SUCCESS); + $notification->set_show_closebutton(false); + echo $OUTPUT->render($notification); } else { - \core\notification::warning($message); + $notification = new \core\output\notification($message, \core\output\notification::NOTIFY_WARNING); + $notification->set_show_closebutton(false); + echo $OUTPUT->render($notification); } return true; diff --git a/db/uninstall.php b/db/uninstall.php new file mode 100644 index 0000000..67ae88e --- /dev/null +++ b/db/uninstall.php @@ -0,0 +1,39 @@ +. + +/** + * Admin tool "APCu management" - Uninstall file + * + * @package tool_apcu + * @copyright 2024 Alexander Bias, lern.link GmbH + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/apcu/locallib.php'); + +/** + * Function to uninstall tool_apcu. + * + * @return bool + */ +function xmldb_tool_apcu_uninstall() { + // Remove the APCu management GUI file. + tool_apcu_remove_guidrop_file(); + + return true; +} diff --git a/db/upgrade.php b/db/upgrade.php index 0c542fe..91182d1 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -33,11 +33,12 @@ * @return bool result */ function xmldb_tool_apcu_upgrade($oldversion) { + global $OUTPUT; + // Verify the existence of the APCu GUI file. // This is done everytime the plugin is upgraded, i.e. there is no oldversion check and no savepoint set. - // If the APCu tool does not exist on disk. - // (This can especially happen when a new ZIP file from moodle.org/plugins has been placed on the server). + // If the APCu tool does not exist in MOODLEDATA. if (tool_apcu_verify_guidrop_file() != true) { // Try to re-download and store the APCu management GUI file. @@ -54,9 +55,13 @@ function xmldb_tool_apcu_upgrade($oldversion) { // Output message. if ($guidropsuccessful == true) { - \core\notification::success($message); + $notification = new \core\output\notification($message, \core\output\notification::NOTIFY_SUCCESS); + $notification->set_show_closebutton(false); + echo $OUTPUT->render($notification); } else { - \core\notification::warning($message); + $notification = new \core\output\notification($message, \core\output\notification::NOTIFY_WARNING); + $notification->set_show_closebutton(false); + echo $OUTPUT->render($notification); } // Otherwise. @@ -65,7 +70,9 @@ function xmldb_tool_apcu_upgrade($oldversion) { $message = get_string('guidropupgradechecksuccess', 'tool_apcu'); // Output message. - \core\notification::success($message); + $notification = new \core\output\notification($message, \core\output\notification::NOTIFY_SUCCESS); + $notification->set_show_closebutton(false); + echo $OUTPUT->render($notification); } return true; diff --git a/index.php b/index.php index 9b5cf38..3e92d15 100644 --- a/index.php +++ b/index.php @@ -25,7 +25,7 @@ require(__DIR__ . '/../../../config.php'); require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/apcu/locallib.php'); -global $CFG; +global $CFG, $FULLME; // Set up the plugin's main page as external admin page. admin_externalpage_setup('tool_apcu'); @@ -91,7 +91,21 @@ // Otherwise. } else { - // Output message about missing APCu GUI file. - throw new \moodle_exception('guidropmissing', 'tool_apcu'); + // Try to download and store APCu management GUI file on-the-fly. + $guidropsuccessful = tool_apcu_do_guidrop(); + + // If the download was successful. + if ($guidropsuccessful) { + // Add a notification to the stack. + core\notification::success(get_string('guidropmissingonthefly', 'tool_apcu')); + + // Redirect to the same page again. + redirect($FULLME); + + // Otherwise. + } else { + // Output message about missing APCu GUI file. + throw new \moodle_exception('guidropmissing', 'tool_apcu'); + } } diff --git a/lang/en/tool_apcu.php b/lang/en/tool_apcu.php index 6e0d753..fdd37c3 100644 --- a/lang/en/tool_apcu.php +++ b/lang/en/tool_apcu.php @@ -25,11 +25,12 @@ defined('MOODLE_INTERNAL') || die(); $string['pluginname'] = 'APCu management'; -$string['guidroperror'] = 'Sadly, this Moodle installation did not have enough permissions to download and store the APCu management GUI file to your wwwroot directly. Please download the APCu management GUI file from {$a->source} manually and store it to {$a->target} on your webserver. Until you download and store this file, the tool_apcu plugin will not work.'; +$string['guidroperror'] = 'Sadly, this Moodle installation did not have enough permissions to download and store the APCu management GUI file to your MOODLEDATA directly. Please download the APCu management GUI file from {$a->source} manually and store it to {$a->target} on your webserver. Until you download and store this file, the tool_apcu plugin will not work.'; $string['guidropinstallintro'] = 'The tool_apcu admin report plugin includes a APCu management GUI which was built by the APCu developers. This APCu management GUI is just a small PHP file. Unfortunately, this file can\'t be shipped together with this plugin\'s code as its PHP license is incompatible with Moodle\'s GPL license.'; $string['guidropinstalloutro'] = 'Please note: With "license incompatibility", it is just meant that code licensed under the PHP license must not be hosted on moodle.org/plugins. For you as administrator, it\'s fine to download, host and run the APCu management GUI file and add it to your local installation of this Moodle plugin.'; -$string['guidropsuccess'] = 'Luckily, this Moodle installation had enough permissions to download and store the APCu management GUI file to your wwwroot directly. It was downloaded from {$a->source} and stored to {$a->target}. After finishing the installation wizard, the tool_apcu plugin will work for you as expected.'; +$string['guidropsuccess'] = 'Luckily, this Moodle installation had enough permissions to download and store the APCu management GUI file to your MOODLEDATA directly. It was downloaded from {$a->source} and stored to {$a->target}. After finishing the installation wizard, the tool_apcu plugin will work for you as expected.'; $string['guidropmissing'] = 'This plugin is missing the APCu management GUI file or the file does not contain the expected PHP code. Please consult the plugin\'s README file for further assistance. Until you download and store the APCu management GUI file, the plugin will not work.'; -$string['guidropupgradecheckfail'] = 'The necessary APCu management GUI file is missing in the wwwroot after the plugin upgrade.'; -$string['guidropupgradechecksuccess'] = 'The necessary APCu management GUI file still exists in the wwwroot after the plugin upgrade.'; +$string['guidropmissingonthefly'] = 'This plugin was missing the APCu management GUI file or the file did not contain the expected PHP code. It was downloaded on the fly to your MOODLEDATA so that you can use the plugin directly (again).'; +$string['guidropupgradecheckfail'] = 'The necessary APCu management GUI file is missing in the MOODLEDATA after the plugin upgrade.'; +$string['guidropupgradechecksuccess'] = 'The necessary APCu management GUI file still exists in the MOODLEDATA after the plugin upgrade.'; $string['privacy:metadata'] = 'The APCu management plugin provides extended functionality to Moodle admins, but does not store any personal data.'; diff --git a/lib/apcu-gui/.gitignore b/lib/apcu-gui/.gitignore deleted file mode 100644 index 5e7d273..0000000 --- a/lib/apcu-gui/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/locallib.php b/locallib.php index a2d31db..59ca8e3 100644 --- a/locallib.php +++ b/locallib.php @@ -95,8 +95,19 @@ function tool_apcu_do_guidrop() { $targetdir = tool_apcu_get_guidrop_directory(); $targetpath = tool_apcu_get_guidrop_path(); - // If we would be unable to store the APCu GUI file, return. - if (is_dir($targetdir) != true || is_writable($targetdir) != true) { + // If the target directory does not exist yet. + if (is_dir($targetdir) != true) { + // Create it. + $retmakedir = make_writable_directory($targetdir); + + // If something went wrong, return. + if ($retmakedir != true) { + return false; + } + } + + // If we would be unable to store the APCu GUI file now, return. + if (is_writable($targetdir) != true) { return false; } @@ -148,7 +159,7 @@ function tool_apcu_get_guidrop_directory() { global $CFG; // The directory where the APCu GUI file should be stored. - return $CFG->dirroot.'/'.$CFG->admin.'/tool/apcu/lib/apcu-gui'; + return $CFG->dataroot.'/tool_apcu'; } /** @@ -160,13 +171,13 @@ function tool_apcu_get_guidrop_path() { global $CFG; // The directory and filename where the APCu GUI file should be stored. - return $CFG->dirroot.'/'.$CFG->admin.'/tool/apcu/lib/apcu-gui/apcu.php.inc'; + return $CFG->dataroot.'/tool_apcu/apcu.php.inc'; } /** * Helper function to verify if the APCu management GUI file exists and has the right content. * - * @return string + * @return bool */ function tool_apcu_verify_guidrop_file() { // Get the path where the file is expected. @@ -190,3 +201,19 @@ function tool_apcu_verify_guidrop_file() { // If we have reached this point, the APCu GUI management file should be fine. return true; } + +/** + * Helper function to remove the APCu management GUI file. + * + * @return string + */ +function tool_apcu_remove_guidrop_file() { + // Get the directory where the file is expected. + $directory = tool_apcu_get_guidrop_directory(); + + // Remove the directory. + $ret = remove_dir($directory); + + // Return the result of the removal. + return $ret; +} diff --git a/thirdpartylibs.xml b/thirdpartylibs.xml index ff0a9c9..a5a2c14 100644 --- a/thirdpartylibs.xml +++ b/thirdpartylibs.xml @@ -1,7 +1,7 @@ - lib/apcu-gui + APCu GUI PHP License diff --git a/version.php b/version.php index 702004b..f948c98 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'tool_apcu'; -$plugin->version = 2023102000; +$plugin->version = 2023102004; $plugin->release = 'v4.3-r1'; $plugin->requires = 2023100900; $plugin->supported = [403, 403];