From d42593d2acc98b8b510ef9cd2bd5296b4f48d128 Mon Sep 17 00:00:00 2001 From: Dan Marsden Date: Thu, 6 Jul 2023 13:31:34 +1200 Subject: [PATCH] MDL-78509 tool_mfa: Fix from upstream and internal 1. Add missing authenticator name lang string 2. Check nosetup factor correctly to display menu 3. Align email page controls with manager 4. Add explanation text to login page 5. Fixed "Access to an undefined property .." from PHPStan 6. Fixed all the "Variable $.. might not be defined" from PHPStan 7. Fixed the issue from https://github.com/catalyst/moodle-tool_mfa/issues/379 Co-authored-by: Peter Burnett Co-authored-by: Alex Morris --- admin/tool/mfa/.github/workflows/ci.yml | 15 ---- admin/tool/mfa/README.md | 10 --- admin/tool/mfa/factor/admin/version.php | 4 +- admin/tool/mfa/factor/auth/version.php | 4 +- admin/tool/mfa/factor/capability/version.php | 4 +- .../mfa/factor/cohort/tests/factor_test.php | 6 +- admin/tool/mfa/factor/cohort/version.php | 4 +- admin/tool/mfa/factor/email/email.php | 12 ++- .../mfa/factor/email/tests/factor_test.php | 4 +- admin/tool/mfa/factor/email/version.php | 4 +- .../mfa/factor/grace/tests/factor_test.php | 8 +- admin/tool/mfa/factor/grace/version.php | 4 +- admin/tool/mfa/factor/iprange/version.php | 4 +- .../mfa/factor/nosetup/classes/factor.php | 12 +-- admin/tool/mfa/factor/nosetup/version.php | 4 +- admin/tool/mfa/factor/role/classes/factor.php | 2 +- .../mfa/factor/role/tests/factor_test.php | 4 +- admin/tool/mfa/factor/role/version.php | 4 +- .../mfa/factor/token/tests/factor_test.php | 19 +++- admin/tool/mfa/factor/token/version.php | 4 +- .../mfa/factor/totp/tests/factor_test.php | 2 +- admin/tool/mfa/factor/totp/version.php | 4 +- .../factor/webauthn/amd/build/utils.min.js | 2 +- .../webauthn/amd/build/utils.min.js.map | 2 +- .../tool/mfa/factor/webauthn/amd/src/utils.js | 29 ++++--- .../mfa/factor/webauthn/classes/factor.php | 4 +- .../webauthn/lang/en/factor_webauthn.php | 11 ++- admin/tool/mfa/factor/webauthn/version.php | 4 +- admin/tool/mfa/patch/MOODLE_35_STABLE.diff | 86 ------------------ admin/tool/mfa/patch/MOODLE_36_STABLE.diff | 87 ------------------- admin/tool/mfa/patch/MOODLE_37_STABLE.diff | 34 -------- admin/tool/mfa/patch/TOTARA_16.patch | 61 ------------- admin/tool/mfa/renderer.php | 2 +- .../tests/admin_setting_managemfa_test.php | 2 +- admin/tool/mfa/tests/manager_test.php | 2 +- .../mfa/tests/object_factor_base_test.php | 4 +- .../tool/mfa/tests/plugininfo_factor_test.php | 2 +- admin/tool/mfa/tests/secret_manager_test.php | 2 +- admin/tool/mfa/tests/tool_mfa_testcase.php | 2 +- admin/tool/mfa/version.php | 6 +- 40 files changed, 108 insertions(+), 372 deletions(-) delete mode 100644 admin/tool/mfa/.github/workflows/ci.yml delete mode 100644 admin/tool/mfa/README.md delete mode 100644 admin/tool/mfa/patch/MOODLE_35_STABLE.diff delete mode 100644 admin/tool/mfa/patch/MOODLE_36_STABLE.diff delete mode 100644 admin/tool/mfa/patch/MOODLE_37_STABLE.diff delete mode 100644 admin/tool/mfa/patch/TOTARA_16.patch diff --git a/admin/tool/mfa/.github/workflows/ci.yml b/admin/tool/mfa/.github/workflows/ci.yml deleted file mode 100644 index 4d92066f98fa..000000000000 --- a/admin/tool/mfa/.github/workflows/ci.yml +++ /dev/null @@ -1,15 +0,0 @@ -# .github/workflows/ci.yml -name: ci - -on: [push, pull_request] - -jobs: - test: - uses: catalyst/catalyst-moodle-workflows/.github/workflows/ci.yml@main - secrets: - # Required if you plan to publish (uncomment the below) - moodle_org_token: ${{ secrets.MOODLE_ORG_TOKEN }} - with: - #Grunt fails due to CSS styling needing an !important. - disable_grunt: true - release_branches: master diff --git a/admin/tool/mfa/README.md b/admin/tool/mfa/README.md deleted file mode 100644 index fba3d86234bb..000000000000 --- a/admin/tool/mfa/README.md +++ /dev/null @@ -1,10 +0,0 @@ -#NOTE: This master branch has been deprecated. Please see the table below for the correct supported branches. - -## Branches - -| Version | Branch | Patches | -|-----------------|--------------|----------------------| -| Moodle 4.0 - 4.2| MOODLE_400_STABLE | None | -| Moodle 3.8 -3.9 | MOODLE_35_STABLE | None | -| Moodle 3.7 | MOODLE_35_STABLE | MDL-66340 | -| Moodle 3.5-3.6 | MOODLE_35_STABLE | MDL-66340, MDL-60470 | diff --git a/admin/tool/mfa/factor/admin/version.php b/admin/tool/mfa/factor/admin/version.php index 106d62cf6de5..d42890ec6fb6 100644 --- a/admin/tool/mfa/factor/admin/version.php +++ b/admin/tool/mfa/factor/admin/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2019102400; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_admin'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/auth/version.php b/admin/tool/mfa/factor/auth/version.php index 696cbd19b459..c9c1c2e4c83f 100644 --- a/admin/tool/mfa/factor/auth/version.php +++ b/admin/tool/mfa/factor/auth/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021020500; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_auth'; $plugin->release = 2021020500; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/capability/version.php b/admin/tool/mfa/factor/capability/version.php index f3fd415522a2..f760a10e7662 100644 --- a/admin/tool/mfa/factor/capability/version.php +++ b/admin/tool/mfa/factor/capability/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2020071400; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_capability'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/cohort/tests/factor_test.php b/admin/tool/mfa/factor/cohort/tests/factor_test.php index 6da3e3a2797a..80d69df9dcd6 100644 --- a/admin/tool/mfa/factor/cohort/tests/factor_test.php +++ b/admin/tool/mfa/factor/cohort/tests/factor_test.php @@ -14,9 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace factor_cohort\tests; - -defined('MOODLE_INTERNAL') || die(); +namespace factor_cohort; /** * Tests for cohort factor. @@ -43,7 +41,7 @@ public function test_get_summary_condition() { // Create a cohort. $cohortid = $DB->insert_record('cohort', [ - 'idnumber' => NULL, + 'idnumber' => null, 'name' => 'test', 'contextid' => \context_system::instance()->id, 'description' => '', diff --git a/admin/tool/mfa/factor/cohort/version.php b/admin/tool/mfa/factor/cohort/version.php index 80885d2a8704..5bfeab77a2f0 100644 --- a/admin/tool/mfa/factor/cohort/version.php +++ b/admin/tool/mfa/factor/cohort/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2022101100; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_cohort'; $plugin->release = 'v0.2'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/email/email.php b/admin/tool/mfa/factor/email/email.php index c0e83ce23e45..7c4f0e64835a 100644 --- a/admin/tool/mfa/factor/email/email.php +++ b/admin/tool/mfa/factor/email/email.php @@ -39,13 +39,21 @@ $PAGE->set_title(get_string('unauthemail', 'factor_email')); $PAGE->set_cacheable(false); $instance = $DB->get_record('tool_mfa', ['id' => $instanceid]); +$factor = \tool_mfa\plugininfo\factor::get_factor('email'); // If pass is set, require login to force $SESSION and user, and pass for that session. if (!empty($instance) && $pass != 0 && $secret != 0) { + require_login(); + if ($factor->get_state() === \tool_mfa\plugininfo\factor::STATE_LOCKED) { + // Redirect through to auth, this will bounce them to the next factor. + redirect(new moodle_url('/admin/tool/mfa/auth.php')); + } + // Check the code with the same measures on the page entry. if ($instance->secret != $secret) { + \tool_mfa\manager::sleep_timer(); + $factor->increment_lock_counter(); throw new moodle_exception('error:parameters', 'factor_email'); } - require_login(); $factor = \tool_mfa\plugininfo\factor::get_factor('email'); $factor->set_state(\tool_mfa\plugininfo\factor::STATE_PASS); // If wantsurl is already set in session, go to it. @@ -80,7 +88,7 @@ // Suspend user account. if (get_config('factor_email', 'suspend')) { - $DB->set_field('user', 'suspended', 1, ['id' => $userid]); + $DB->set_field('user', 'suspended', 1, ['id' => $user->id]); } $message = get_string('email:revokesuccess', 'factor_email', fullname($user)); diff --git a/admin/tool/mfa/factor/email/tests/factor_test.php b/admin/tool/mfa/factor/email/tests/factor_test.php index ab9ea9128cbf..82fc0a856348 100644 --- a/admin/tool/mfa/factor/email/tests/factor_test.php +++ b/admin/tool/mfa/factor/email/tests/factor_test.php @@ -14,9 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace factor_email\tests; - -defined('MOODLE_INTERNAL') || die(); +namespace factor_email; /** * Tests for email factor. diff --git a/admin/tool/mfa/factor/email/version.php b/admin/tool/mfa/factor/email/version.php index 36c31451d941..221c20b142e2 100644 --- a/admin/tool/mfa/factor/email/version.php +++ b/admin/tool/mfa/factor/email/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2019102400; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_email'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/grace/tests/factor_test.php b/admin/tool/mfa/factor/grace/tests/factor_test.php index f5d8b86ae6cd..140f29b7b266 100644 --- a/admin/tool/mfa/factor/grace/tests/factor_test.php +++ b/admin/tool/mfa/factor/grace/tests/factor_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace factor_grace\tests; +namespace factor_grace; /** * Tests for grace factor. @@ -26,6 +26,12 @@ */ class factor_test extends \advanced_testcase { + /** + * Test affecting factors + * + * @covers ::get_affecting_factors + * @return void + */ public function test_affecting_factors() { $this->resetAfterTest(true); $user = $this->getDataGenerator()->create_user(); diff --git a/admin/tool/mfa/factor/grace/version.php b/admin/tool/mfa/factor/grace/version.php index c461b9a5f85a..34f2a5589e18 100644 --- a/admin/tool/mfa/factor/grace/version.php +++ b/admin/tool/mfa/factor/grace/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2022020401; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_grace'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/iprange/version.php b/admin/tool/mfa/factor/iprange/version.php index e61e7eea2350..37e7400cc401 100644 --- a/admin/tool/mfa/factor/iprange/version.php +++ b/admin/tool/mfa/factor/iprange/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2019102400; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_iprange'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/nosetup/classes/factor.php b/admin/tool/mfa/factor/nosetup/classes/factor.php index ccbaefad12d9..6a07410121ad 100644 --- a/admin/tool/mfa/factor/nosetup/classes/factor.php +++ b/admin/tool/mfa/factor/nosetup/classes/factor.php @@ -92,15 +92,9 @@ public function get_state() { * @return void */ public function possible_states($user) { - // Check if user has any other input or setup factors active. - $factors = \tool_mfa\plugininfo\factor::get_active_other_user_factor_types($user); - foreach ($factors as $factor) { - if ($factor->has_input() || $factor->has_setup()) { - return [\tool_mfa\plugininfo\factor::STATE_NEUTRAL]; - } - } - - return [\tool_mfa\plugininfo\factor::STATE_PASS]; + // We return Neutral here because to support optional rollouts + // it needs to report neutral or the menu to setup will not display. + return [\tool_mfa\plugininfo\factor::STATE_NEUTRAL]; } /** diff --git a/admin/tool/mfa/factor/nosetup/version.php b/admin/tool/mfa/factor/nosetup/version.php index 2710e02d5934..c29d7b3a1817 100644 --- a/admin/tool/mfa/factor/nosetup/version.php +++ b/admin/tool/mfa/factor/nosetup/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2020042302; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_nosetup'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/role/classes/factor.php b/admin/tool/mfa/factor/role/classes/factor.php index fc208d0ba7ee..123ff054c381 100644 --- a/admin/tool/mfa/factor/role/classes/factor.php +++ b/admin/tool/mfa/factor/role/classes/factor.php @@ -163,7 +163,7 @@ public function get_roles(string $selectedroles) : string { $roles[] = get_string('administrator'); } else { $record = $DB->get_record('role', ['id' => $role]); - $roles[] = role_get_name($record); + $roles[] = $record ? role_get_name($record) : null; } } return implode(', ', $roles); diff --git a/admin/tool/mfa/factor/role/tests/factor_test.php b/admin/tool/mfa/factor/role/tests/factor_test.php index 4172a3874e23..c14939115dd1 100644 --- a/admin/tool/mfa/factor/role/tests/factor_test.php +++ b/admin/tool/mfa/factor/role/tests/factor_test.php @@ -14,9 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace factor_role\tests; - -defined('MOODLE_INTERNAL') || die(); +namespace factor_role; /** * Tests for role factor. diff --git a/admin/tool/mfa/factor/role/version.php b/admin/tool/mfa/factor/role/version.php index ff9125e9a1ff..6b2b1532246b 100644 --- a/admin/tool/mfa/factor/role/version.php +++ b/admin/tool/mfa/factor/role/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2020072100; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_role'; $plugin->release = 'v0.1'; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/token/tests/factor_test.php b/admin/tool/mfa/factor/token/tests/factor_test.php index c14e8d4edd32..afc0567bd871 100644 --- a/admin/tool/mfa/factor/token/tests/factor_test.php +++ b/admin/tool/mfa/factor/token/tests/factor_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace factor_token\tests; +namespace factor_token; /** * Tests for MFA manager class. @@ -27,11 +27,24 @@ */ class factor_test extends \advanced_testcase { + /** + * Holds specific requested factor, which is token factor. + * + * @var \factor_token\factor $factor + */ + public \factor_token\factor $factor; + public function setUp(): void { $this->resetAfterTest(); $this->factor = new \factor_token\factor('token'); } + /** + * Test calculating expiry time in general + * + * @covers ::calculate_expiry_time + * @return void + */ public function test_calculate_expiry_time_in_general() { $timestamp = 1642213800; // 1230 UTC. @@ -75,6 +88,7 @@ public function test_calculate_expiry_time_in_general() { * value, provided it never goes past raw value expiry time, and when it * needs to be 2am, it's 2am on the following morning. * + * @covers ::calculate_expiry_time * @param int $timestamp * @dataProvider timestamp_provider */ @@ -123,6 +137,7 @@ public function test_calculate_expiry_time_for_overnight_expiry_with_one_day_exp * value, provided it never goes past raw value expiry time, and when it * needs to be 2am, it's 2am on the morning after tomorrow. * + * @covers ::calculate_expiry_time * @param int $timestamp * @dataProvider timestamp_provider */ @@ -173,6 +188,7 @@ public function test_calculate_expiry_time_for_overnight_expiry_with_two_day_exp /** * This should check if the 3am expiry is pushed back to 2am as expected, but everything else appears as expected * + * @covers ::calculate_expiry_time * @param int $timestamp * @dataProvider timestamp_provider */ @@ -217,6 +233,7 @@ public function test_calculate_expiry_time_for_overnight_expiry_with_three_hour_ /** * Only relevant based on the hour padding used, which is currently set to 2 hours (2am). * + * @covers ::calculate_expiry_time * @param int $timestamp * @dataProvider timestamp_provider */ diff --git a/admin/tool/mfa/factor/token/version.php b/admin/tool/mfa/factor/token/version.php index 30b006d01202..3de6d93944cb 100644 --- a/admin/tool/mfa/factor/token/version.php +++ b/admin/tool/mfa/factor/token/version.php @@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2022011700; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_token'; $plugin->release = 2022011700; $plugin->maturity = MATURITY_STABLE; diff --git a/admin/tool/mfa/factor/totp/tests/factor_test.php b/admin/tool/mfa/factor/totp/tests/factor_test.php index af0765d6f4c7..fe36fa7c07f5 100644 --- a/admin/tool/mfa/factor/totp/tests/factor_test.php +++ b/admin/tool/mfa/factor/totp/tests/factor_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace factor_totp\tests; +namespace factor_totp; defined('MOODLE_INTERNAL') || die(); diff --git a/admin/tool/mfa/factor/totp/version.php b/admin/tool/mfa/factor/totp/version.php index 16232549d8d3..a197b8bfcd33 100644 --- a/admin/tool/mfa/factor/totp/version.php +++ b/admin/tool/mfa/factor/totp/version.php @@ -26,9 +26,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021021700; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). $plugin->release = 2021021700; -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_totp'; $plugin->maturity = MATURITY_STABLE; $plugin->dependencies = ['tool_mfa' => 2019102400]; diff --git a/admin/tool/mfa/factor/webauthn/amd/build/utils.min.js b/admin/tool/mfa/factor/webauthn/amd/build/utils.min.js index f4caf2699f14..1e0e2eaf8aac 100644 --- a/admin/tool/mfa/factor/webauthn/amd/build/utils.min.js +++ b/admin/tool/mfa/factor/webauthn/amd/build/utils.min.js @@ -6,6 +6,6 @@ * @author Alex Morris * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("factor_webauthn/utils",[],(function(){return{recursiveBase64StrToArrayBuffer:function(obj){if("object"==typeof obj)for(let key in obj)if("string"==typeof obj[key]){let str=obj[key];if("=?BINARY?B?"===str.substring(0,"=?BINARY?B?".length)&&"?="===str.substring(str.length-"?=".length)){str=str.substring("=?BINARY?B?".length,str.length-"?=".length);let binary_string=window.atob(str),len=binary_string.length,bytes=new Uint8Array(len);for(let i=0;i.\n\n/**\n * WebAuthn utility functions, for handling array buffers.\n *\n * @module factor_webauthn/utils\n * @copyright Catalyst IT\n * @author Alex Morris \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine([], function() {\n return {\n recursiveBase64StrToArrayBuffer: function(obj) {\n let prefix = '=?BINARY?B?';\n let suffix = '?=';\n if (typeof obj === 'object') {\n for (let key in obj) {\n if (typeof obj[key] === 'string') {\n let str = obj[key];\n if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {\n str = str.substring(prefix.length, str.length - suffix.length);\n\n let binary_string = window.atob(str);\n let len = binary_string.length;\n let bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binary_string.charCodeAt(i);\n }\n obj[key] = bytes.buffer;\n }\n } else {\n this.recursiveBase64StrToArrayBuffer(obj[key]);\n }\n }\n }\n },\n arrayBufferToBase64: function(buffer) {\n let binary = '';\n let bytes = new Uint8Array(buffer);\n let len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return window.btoa(binary);\n },\n };\n});\n"],"names":["define","recursiveBase64StrToArrayBuffer","obj","key","str","substring","length","binary_string","window","atob","len","bytes","Uint8Array","i","charCodeAt","buffer","arrayBufferToBase64","binary","byteLength","String","fromCharCode","btoa"],"mappings":";;;;;;;;AAwBAA,+BAAO,IAAI,iBACA,CACHC,gCAAiC,SAASC,QAGnB,iBAARA,QACF,IAAIC,OAAOD,OACY,iBAAbA,IAAIC,KAAmB,KAC1BC,IAAMF,IAAIC,QALb,gBAMGC,IAAIC,UAAU,EANjB,cAM2BC,SAL3B,OAKiDF,IAAIC,UAAUD,IAAIE,OALnE,KAKmFA,QAAoB,CACpGF,IAAMA,IAAIC,UAPb,cAO8BC,OAAQF,IAAIE,OAN1C,KAM0DA,YAEnDC,cAAgBC,OAAOC,KAAKL,KAC5BM,IAAMH,cAAcD,OACpBK,MAAQ,IAAIC,WAAWF,SACtB,IAAIG,EAAI,EAAGA,EAAIH,IAAKG,IACrBF,MAAME,GAAKN,cAAcO,WAAWD,GAExCX,IAAIC,KAAOQ,MAAMI,kBAGhBd,gCAAgCC,IAAIC,OAKzDa,oBAAqB,SAASD,YACtBE,OAAS,GACTN,MAAQ,IAAIC,WAAWG,QACvBL,IAAMC,MAAMO,eACX,IAAIL,EAAI,EAAGA,EAAIH,IAAKG,IACrBI,QAAUE,OAAOC,aAAaT,MAAME,WAEjCL,OAAOa,KAAKJ"} \ No newline at end of file +{"version":3,"file":"utils.min.js","sources":["../src/utils.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * WebAuthn utility functions, for handling array buffers.\n *\n * @module factor_webauthn/utils\n * @copyright Catalyst IT\n * @author Alex Morris \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine([], function() {\n return {\n recursiveBase64StrToArrayBuffer: function(obj) {\n let prefix = '=?BINARY?B?';\n let suffix = '?=';\n if (typeof obj === 'object') {\n for (let key in obj) {\n let isString = true;\n if (typeof obj[key] !== 'string') {\n this.recursiveBase64StrToArrayBuffer(obj[key]);\n isString = false;\n }\n\n let str = obj[key];\n if (isString && str.substring(0, prefix.length) === prefix &&\n str.substring(str.length - suffix.length) === suffix) {\n str = str.substring(prefix.length, str.length - suffix.length);\n\n let binaryString = window.atob(str);\n let len = binaryString.length;\n let bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n obj[key] = bytes.buffer;\n }\n }\n }\n },\n arrayBufferToBase64: function(buffer) {\n let binary = '';\n let bytes = new Uint8Array(buffer);\n let len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return window.btoa(binary);\n },\n };\n});\n"],"names":["define","recursiveBase64StrToArrayBuffer","obj","key","isString","str","substring","length","binaryString","window","atob","len","bytes","Uint8Array","i","charCodeAt","buffer","arrayBufferToBase64","binary","byteLength","String","fromCharCode","btoa"],"mappings":";;;;;;;;AAwBAA,+BAAO,IAAI,iBACA,CACHC,gCAAiC,SAASC,QAGnB,iBAARA,QACF,IAAIC,OAAOD,IAAK,KACbE,UAAW,EACS,iBAAbF,IAAIC,YACNF,gCAAgCC,IAAIC,MACzCC,UAAW,OAGXC,IAAMH,IAAIC,QACVC,UAXC,gBAWWC,IAAIC,UAAU,EAXzB,cAWmCC,SAVnC,OAWAF,IAAIC,UAAUD,IAAIE,OAXlB,KAWkCA,QAAoB,CACvDF,IAAMA,IAAIC,UAbT,cAa0BC,OAAQF,IAAIE,OAZtC,KAYsDA,YAEnDC,aAAeC,OAAOC,KAAKL,KAC3BM,IAAMH,aAAaD,OACnBK,MAAQ,IAAIC,WAAWF,SACtB,IAAIG,EAAI,EAAGA,EAAIH,IAAKG,IACrBF,MAAME,GAAKN,aAAaO,WAAWD,GAEvCZ,IAAIC,KAAOS,MAAMI,UAKjCC,oBAAqB,SAASD,YACtBE,OAAS,GACTN,MAAQ,IAAIC,WAAWG,QACvBL,IAAMC,MAAMO,eACX,IAAIL,EAAI,EAAGA,EAAIH,IAAKG,IACrBI,QAAUE,OAAOC,aAAaT,MAAME,WAEjCL,OAAOa,KAAKJ"} \ No newline at end of file diff --git a/admin/tool/mfa/factor/webauthn/amd/src/utils.js b/admin/tool/mfa/factor/webauthn/amd/src/utils.js index 2985fb52bdf0..94144ce9e211 100644 --- a/admin/tool/mfa/factor/webauthn/amd/src/utils.js +++ b/admin/tool/mfa/factor/webauthn/amd/src/utils.js @@ -29,21 +29,24 @@ define([], function() { let suffix = '?='; if (typeof obj === 'object') { for (let key in obj) { - if (typeof obj[key] === 'string') { - let str = obj[key]; - if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) { - str = str.substring(prefix.length, str.length - suffix.length); + let isString = true; + if (typeof obj[key] !== 'string') { + this.recursiveBase64StrToArrayBuffer(obj[key]); + isString = false; + } - let binary_string = window.atob(str); - let len = binary_string.length; - let bytes = new Uint8Array(len); - for (let i = 0; i < len; i++) { - bytes[i] = binary_string.charCodeAt(i); - } - obj[key] = bytes.buffer; + let str = obj[key]; + if (isString && str.substring(0, prefix.length) === prefix && + str.substring(str.length - suffix.length) === suffix) { + str = str.substring(prefix.length, str.length - suffix.length); + + let binaryString = window.atob(str); + let len = binaryString.length; + let bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); } - } else { - this.recursiveBase64StrToArrayBuffer(obj[key]); + obj[key] = bytes.buffer; } } } diff --git a/admin/tool/mfa/factor/webauthn/classes/factor.php b/admin/tool/mfa/factor/webauthn/classes/factor.php index 6c8feb079d19..f87389d65b3d 100644 --- a/admin/tool/mfa/factor/webauthn/classes/factor.php +++ b/admin/tool/mfa/factor/webauthn/classes/factor.php @@ -150,6 +150,8 @@ public function get_setup_string() { public function login_form_definition($mform) { global $PAGE, $USER, $SESSION; + $mform->addElement('html', get_string('loginexplanation', 'factor_webauthn')); + $mform->addElement('hidden', 'response_input', '', ['id' => 'id_response_input']); $mform->setType('response_input', PARAM_RAW); @@ -237,7 +239,7 @@ public function login_form_validation($data) { public function setup_factor_form_definition($mform) { global $PAGE, $USER, $SESSION; - $mform->addElement('text', 'webauthn_name', 'Authenticator Name'); + $mform->addElement('text', 'webauthn_name', get_string('authenticatorname', 'factor_webauthn')); $mform->setType('webauthn_name', PARAM_ALPHANUM); $mform->addRule('webauthn_name', get_string('required'), 'required', null, 'client'); diff --git a/admin/tool/mfa/factor/webauthn/lang/en/factor_webauthn.php b/admin/tool/mfa/factor/webauthn/lang/en/factor_webauthn.php index 04b4dba4589f..7e38d11c5662 100644 --- a/admin/tool/mfa/factor/webauthn/lang/en/factor_webauthn.php +++ b/admin/tool/mfa/factor/webauthn/lang/en/factor_webauthn.php @@ -29,11 +29,14 @@ $string['authenticator:internal'] = 'Internal'; $string['authenticator:nfc'] = 'NFC'; $string['authenticator:usb'] = 'USB'; +$string['authenticatorname'] = 'Security key name'; +$string['authenticatortypelimitation'] = 'Please note that you can only use security keys of one of these types: {$a}.
Registering other security keys is possible, but you cannot use them during login.'; $string['error'] = 'Failed to authenticate'; -$string['info'] = '

Use a WebAuthn supported authenticator

'; -$string['loginskip'] = 'I don\'t have my authenticator'; -$string['loginsubmit'] = 'Verify authenticator'; -$string['pluginname'] = 'WebAuthn'; +$string['info'] = '

Use a security key

'; +$string['loginexplanation'] = 'Your account settings require that you authenticate with your security key in addition to your password.'; +$string['loginskip'] = 'I don\'t have my security key'; +$string['loginsubmit'] = 'Verify security key'; +$string['pluginname'] = 'Security Key'; $string['privacy:metadata'] = 'The WebAuthn factor plugin does not store any personal data'; $string['register'] = 'Register authenticator'; $string['settings:authenticatortypes'] = 'Types of authenticator'; diff --git a/admin/tool/mfa/factor/webauthn/version.php b/admin/tool/mfa/factor/webauthn/version.php index 25a1a43118ad..953275ec486d 100644 --- a/admin/tool/mfa/factor/webauthn/version.php +++ b/admin/tool/mfa/factor/webauthn/version.php @@ -25,9 +25,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023062900; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). $plugin->release = 2023062900; -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'factor_webauthn'; $plugin->maturity = MATURITY_ALPHA; $plugin->dependencies = ['tool_mfa' => 2023031600]; diff --git a/admin/tool/mfa/patch/MOODLE_35_STABLE.diff b/admin/tool/mfa/patch/MOODLE_35_STABLE.diff deleted file mode 100644 index 735a581724ac..000000000000 --- a/admin/tool/mfa/patch/MOODLE_35_STABLE.diff +++ /dev/null @@ -1,86 +0,0 @@ -From 6d6f2d3543cd4b172aa85f0e47d7f531b7ec4d53 Mon Sep 17 00:00:00 2001 -From: Brendan Heywood -Date: Wed, 18 Oct 2017 16:20:33 +1100 -Subject: [PATCH 1/2] MDL-60470 core: New hook 'after_require_login' - -This adds a hook towards the end of the require_login function. ---- - lib/moodlelib.php | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/lib/moodlelib.php b/lib/moodlelib.php -index 3ac3d8be1b7..d9e5baa175e 100644 ---- a/lib/moodlelib.php -+++ b/lib/moodlelib.php -@@ -2705,6 +2705,8 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - $CFG->forceclean = true; - } - -+ $afterlogins = get_plugins_with_function('after_require_login', 'lib.php'); -+ - // Do not bother admins with any formalities, except for activities pending deletion. - if (is_siteadmin() && !($cm && $cm->deletioninprogress)) { - // Set the global $COURSE. -@@ -2716,6 +2718,12 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - } - // Set accesstime or the user will appear offline which messes up messaging. - user_accesstime_log($course->id); -+ -+ foreach ($afterlogins as $plugintype => $plugins) { -+ foreach ($plugins as $pluginfunction) { -+ $pluginfunction($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); -+ } -+ } - return; - } - -@@ -2923,6 +2931,12 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - $PAGE->set_course($course); - } - -+ foreach ($afterlogins as $plugintype => $plugins) { -+ foreach ($plugins as $pluginfunction) { -+ $pluginfunction($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); -+ } -+ } -+ - // Finally access granted, update lastaccess times. - user_accesstime_log($course->id); - } --- -2.17.1 - - -From 7235752ed449ab6662a317f059e444598bf1a862 Mon Sep 17 00:00:00 2001 -From: Brendan Heywood -Date: Thu, 8 Aug 2019 13:26:50 +1000 -Subject: [PATCH 2/2] MDL-66340 setup: Add after_config for after setup.php is - loaded - ---- - lib/setup.php | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/lib/setup.php b/lib/setup.php -index b1cb7e054ec..df1a2d978a5 100644 ---- a/lib/setup.php -+++ b/lib/setup.php -@@ -1042,3 +1042,16 @@ if (false) { - $OUTPUT = new core_renderer(null, null); - $PAGE = new moodle_page(); - } -+ -+// Allow plugins to callback as soon possible after setup.php is loaded. -+$pluginswithfunction = get_plugins_with_function('after_config', 'lib.php'); -+foreach ($pluginswithfunction as $plugins) { -+ foreach ($plugins as $function) { -+ try { -+ $function(); -+ } catch (Exception $e) { -+ debugging("Exception calling '$function'", DEBUG_DEVELOPER, $e->getTrace()); -+ } -+ } -+} -+ --- -2.17.1 diff --git a/admin/tool/mfa/patch/MOODLE_36_STABLE.diff b/admin/tool/mfa/patch/MOODLE_36_STABLE.diff deleted file mode 100644 index 259ef93ea961..000000000000 --- a/admin/tool/mfa/patch/MOODLE_36_STABLE.diff +++ /dev/null @@ -1,87 +0,0 @@ -From 51484a595701e56897b0913974c566c6a13c1f32 Mon Sep 17 00:00:00 2001 -From: Brendan Heywood -Date: Wed, 18 Oct 2017 16:20:33 +1100 -Subject: [PATCH 1/2] MDL-60470 core: New hook 'after_require_login' - -This adds a hook towards the end of the require_login function. ---- - lib/moodlelib.php | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/lib/moodlelib.php b/lib/moodlelib.php -index e2016a8bf75..29e11632233 100644 ---- a/lib/moodlelib.php -+++ b/lib/moodlelib.php -@@ -2769,6 +2769,8 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - $CFG->forceclean = true; - } - -+ $afterlogins = get_plugins_with_function('after_require_login', 'lib.php'); -+ - // Do not bother admins with any formalities, except for activities pending deletion. - if (is_siteadmin() && !($cm && $cm->deletioninprogress)) { - // Set the global $COURSE. -@@ -2783,6 +2785,12 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - if (!WS_SERVER && !AJAX_SCRIPT) { - user_accesstime_log($course->id); - } -+ -+ foreach ($afterlogins as $plugintype => $plugins) { -+ foreach ($plugins as $pluginfunction) { -+ $pluginfunction($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); -+ } -+ } - return; - } - -@@ -2990,6 +2998,12 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - $PAGE->set_course($course); - } - -+ foreach ($afterlogins as $plugintype => $plugins) { -+ foreach ($plugins as $pluginfunction) { -+ $pluginfunction($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); -+ } -+ } -+ - // Finally access granted, update lastaccess times. - // Do not update access time for webservice or ajax requests. - if (!WS_SERVER && !AJAX_SCRIPT) { --- -2.17.1 - - -From 838ad593636395e4c4884e1bf47836504413b702 Mon Sep 17 00:00:00 2001 -From: Brendan Heywood -Date: Thu, 8 Aug 2019 13:26:50 +1000 -Subject: [PATCH 2/2] MDL-66340 setup: Add after_config for after setup.php is - loaded - ---- - lib/setup.php | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/lib/setup.php b/lib/setup.php -index 2cf12822c6d..a4e0acf0bb8 100644 ---- a/lib/setup.php -+++ b/lib/setup.php -@@ -1041,3 +1041,16 @@ if (false) { - $OUTPUT = new core_renderer(null, null); - $PAGE = new moodle_page(); - } -+ -+// Allow plugins to callback as soon possible after setup.php is loaded. -+$pluginswithfunction = get_plugins_with_function('after_config', 'lib.php'); -+foreach ($pluginswithfunction as $plugins) { -+ foreach ($plugins as $function) { -+ try { -+ $function(); -+ } catch (Exception $e) { -+ debugging("Exception calling '$function'", DEBUG_DEVELOPER, $e->getTrace()); -+ } -+ } -+} -+ --- -2.17.1 - diff --git a/admin/tool/mfa/patch/MOODLE_37_STABLE.diff b/admin/tool/mfa/patch/MOODLE_37_STABLE.diff deleted file mode 100644 index c8edc6eded37..000000000000 --- a/admin/tool/mfa/patch/MOODLE_37_STABLE.diff +++ /dev/null @@ -1,34 +0,0 @@ -From 1275e9b283c81b80b73d1c87c64449eb472cc037 Mon Sep 17 00:00:00 2001 -From: Brendan Heywood -Date: Thu, 8 Aug 2019 13:26:50 +1000 -Subject: [PATCH] MDL-66340 setup: Add after_config for after setup.php is - loaded - ---- - lib/setup.php | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/lib/setup.php b/lib/setup.php -index 2cf12822c6d..a4e0acf0bb8 100644 ---- a/lib/setup.php -+++ b/lib/setup.php -@@ -1041,3 +1041,16 @@ if (false) { - $OUTPUT = new core_renderer(null, null); - $PAGE = new moodle_page(); - } -+ -+// Allow plugins to callback as soon possible after setup.php is loaded. -+$pluginswithfunction = get_plugins_with_function('after_config', 'lib.php'); -+foreach ($pluginswithfunction as $plugins) { -+ foreach ($plugins as $function) { -+ try { -+ $function(); -+ } catch (Exception $e) { -+ debugging("Exception calling '$function'", DEBUG_DEVELOPER, $e->getTrace()); -+ } -+ } -+} -+ --- -2.17.1 - diff --git a/admin/tool/mfa/patch/TOTARA_16.patch b/admin/tool/mfa/patch/TOTARA_16.patch deleted file mode 100644 index 0d3ea86ab0d9..000000000000 --- a/admin/tool/mfa/patch/TOTARA_16.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff --git a/server/lib/moodlelib.php b/server/lib/moodlelib.php -index e80b84cb652..033de11df7f 100644 ---- a/server/lib/moodlelib.php -+++ b/server/lib/moodlelib.php -@@ -2895,6 +2895,8 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - // Make sure the USER has a sesskey set up. Used for CSRF protection. - sesskey(); - -+ $afterlogins = get_plugins_with_function('after_require_login', 'lib.php'); -+ - // Do not bother admins with any formalities, except for activities pending deletion. - if (is_siteadmin() && !($cm && $cm->deletioninprogress)) { - // Set the global $COURSE. -@@ -2906,6 +2908,12 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - } - // Set accesstime or the user will appear offline which messes up messaging. - user_accesstime_log($course->id); -+ -+ foreach ($afterlogins as $plugintype => $plugins) { -+ foreach ($plugins as $pluginfunction) { -+ $pluginfunction($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); -+ } -+ } - return; - } - -@@ -3176,6 +3184,12 @@ function require_login($courseorid = null, $autologinguest = true, $cm = null, $ - } - } - -+ foreach ($afterlogins as $plugintype => $plugins) { -+ foreach ($plugins as $pluginfunction) { -+ $pluginfunction($courseorid, $autologinguest, $cm, $setwantsurltome, $preventredirect); -+ } -+ } -+ - // Finally access granted, update lastaccess times. - user_accesstime_log($course->id); - } -diff --git a/server/lib/setup.php b/server/lib/setup.php -index c05e13b03aa..4d89eda0713 100644 ---- a/server/lib/setup.php -+++ b/server/lib/setup.php -@@ -800,3 +800,17 @@ if (!function_exists('hash_equals')) { - return false; - } - } -+ -+ -+// Allow plugins to callback as soon possible after setup.php is loaded. -+$pluginswithfunction = get_plugins_with_function('after_config', 'lib.php'); -+foreach ($pluginswithfunction as $plugins) { -+ foreach ($plugins as $function) { -+ try { -+ $function(); -+ } catch (Throwable $e) { -+ debugging("Exception calling '$function'", DEBUG_DEVELOPER, $e->getTrace()); -+ } -+ } -+} -+ diff --git a/admin/tool/mfa/renderer.php b/admin/tool/mfa/renderer.php index 4029fbadf7d4..9bcb89817d63 100644 --- a/admin/tool/mfa/renderer.php +++ b/admin/tool/mfa/renderer.php @@ -326,8 +326,8 @@ public function factors_in_use_table($lookback) { // Auth rows. $authtypes = get_enabled_auth_plugins(true); + $row = []; foreach ($authtypes as $authtype) { - $row = []; $row[] = \html_writer::tag('b', $authtype); // Setup the overall totals columns. diff --git a/admin/tool/mfa/tests/admin_setting_managemfa_test.php b/admin/tool/mfa/tests/admin_setting_managemfa_test.php index 175197556bbb..c35f337b27b3 100644 --- a/admin/tool/mfa/tests/admin_setting_managemfa_test.php +++ b/admin/tool/mfa/tests/admin_setting_managemfa_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace tool_mfa\tests; +namespace tool_mfa; defined('MOODLE_INTERNAL') || die(); diff --git a/admin/tool/mfa/tests/manager_test.php b/admin/tool/mfa/tests/manager_test.php index d3dd26159a4e..c362fd37d45a 100644 --- a/admin/tool/mfa/tests/manager_test.php +++ b/admin/tool/mfa/tests/manager_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace tool_mfa\tests; +namespace tool_mfa; defined('MOODLE_INTERNAL') || die(); require_once(__DIR__ . '/tool_mfa_testcase.php'); diff --git a/admin/tool/mfa/tests/object_factor_base_test.php b/admin/tool/mfa/tests/object_factor_base_test.php index aa658d175a26..9d4adc1a47a3 100644 --- a/admin/tool/mfa/tests/object_factor_base_test.php +++ b/admin/tool/mfa/tests/object_factor_base_test.php @@ -13,8 +13,10 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace tool_mfa\tests; +namespace tool_mfa; + +defined('MOODLE_INTERNAL') || die(); require_once(__DIR__ . '/tool_mfa_testcase.php'); /** diff --git a/admin/tool/mfa/tests/plugininfo_factor_test.php b/admin/tool/mfa/tests/plugininfo_factor_test.php index 99247fb6d97d..4a1003b7cf08 100644 --- a/admin/tool/mfa/tests/plugininfo_factor_test.php +++ b/admin/tool/mfa/tests/plugininfo_factor_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace tool_mfa\tests; +namespace tool_mfa; /** * Tests for plugininfo. diff --git a/admin/tool/mfa/tests/secret_manager_test.php b/admin/tool/mfa/tests/secret_manager_test.php index cb5b62e5a391..a514c3f99361 100644 --- a/admin/tool/mfa/tests/secret_manager_test.php +++ b/admin/tool/mfa/tests/secret_manager_test.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace tool_mfa\tests; +namespace tool_mfa; /** * Tests for MFA secret manager class. diff --git a/admin/tool/mfa/tests/tool_mfa_testcase.php b/admin/tool/mfa/tests/tool_mfa_testcase.php index 5d15a5a99085..1ff45ddf71b1 100644 --- a/admin/tool/mfa/tests/tool_mfa_testcase.php +++ b/admin/tool/mfa/tests/tool_mfa_testcase.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -namespace tool_mfa\tests; +namespace tool_mfa; defined('MOODLE_INTERNAL') || die(); diff --git a/admin/tool/mfa/version.php b/admin/tool/mfa/version.php index 8fd475175be5..f65316753cc0 100644 --- a/admin/tool/mfa/version.php +++ b/admin/tool/mfa/version.php @@ -25,9 +25,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023031600; // The current plugin version (Date: YYYYMMDDXX). -$plugin->release = 2023031600; // Same as version. -$plugin->requires = 2017051500.00; // Support back to 3.3. +$plugin->version = 2023072100; // The current plugin version (Date: YYYYMMDDXX). +$plugin->release = 2023072100; // Same as version. +$plugin->requires = 2023042400.00; // Supports from 4.2. $plugin->component = 'tool_mfa'; $plugin->maturity = MATURITY_STABLE; $plugin->supported = [35, 402];