mirror of
https://github.com/moodle/moodle.git
synced 2025-08-09 02:46:40 +02:00
MDL-81924 factor_sms: Add support for SMS gateway selection
Includes migrating AWS settings from the SMS MFA factor to a new gateway in the SMS subsystem and notifying admins of the update. Originally implemented as MDL-81732 and MDL-82660. Co-authored by: Michael Hawkins <michaelh@moodle.com>
This commit is contained in:
parent
cf75a3aad1
commit
a1209ab882
8 changed files with 260 additions and 21 deletions
|
@ -409,10 +409,11 @@ class factor extends object_factor_base {
|
||||||
recipientnumber: $phonenumber,
|
recipientnumber: $phonenumber,
|
||||||
content: $message,
|
content: $message,
|
||||||
component: 'factor_sms',
|
component: 'factor_sms',
|
||||||
messagetype: 'factor',
|
messagetype: 'mfa',
|
||||||
recipientuserid: null,
|
recipientuserid: null,
|
||||||
sensitive: true,
|
issensitive: true,
|
||||||
async: false,
|
async: false,
|
||||||
|
gatewayid: get_config('factor_sms', 'smsgateway'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
admin/tool/mfa/factor/sms/classes/hook_listener.php
Normal file
50
admin/tool/mfa/factor/sms/classes/hook_listener.php
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?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 factor_sms;
|
||||||
|
|
||||||
|
use core_sms\hook\before_gateway_deleted;
|
||||||
|
use core_sms\hook\before_gateway_disabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook listener for SMS factor.
|
||||||
|
*
|
||||||
|
* @package factor_sms
|
||||||
|
* @copyright 2024 Safat Shahin <safat.shahin@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
class hook_listener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook listener before a gateway is deleted or disabled.
|
||||||
|
*
|
||||||
|
* This listener will check if the SMS gateway is currently in use before disabling or deleting the gateway.
|
||||||
|
*
|
||||||
|
* @param before_gateway_deleted|before_gateway_disabled $hook Hook instance before the gateway is deleted
|
||||||
|
*/
|
||||||
|
public static function check_gateway_usage_in_mfa(
|
||||||
|
before_gateway_deleted|before_gateway_disabled $hook,
|
||||||
|
): void {
|
||||||
|
try {
|
||||||
|
$smsgatewayid = (int)get_config('factor_sms', 'smsgateway');
|
||||||
|
if ($smsgatewayid && $smsgatewayid === (int)$hook->gateway->id) {
|
||||||
|
$hook->stop_propagation();
|
||||||
|
}
|
||||||
|
} catch (\dml_exception $exception) {
|
||||||
|
$hook->stop_propagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?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 factor_sms\task;
|
||||||
|
|
||||||
|
use core\task\adhoc_task;
|
||||||
|
use moodle_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification for admins to notify about the migration of SMS setup from MFA to SMS gateway plugins.
|
||||||
|
*
|
||||||
|
* @package factor_sms
|
||||||
|
* @copyright 2024 Safat Shahin <safat.shahin@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
class sms_gateway_migration_notification extends adhoc_task {
|
||||||
|
|
||||||
|
public function execute(): void {
|
||||||
|
|
||||||
|
$siteadmins = get_admins();
|
||||||
|
foreach ($siteadmins as $siteadmin) {
|
||||||
|
$smsconfigureurl = new moodle_url('/sms/sms_gateways.php');
|
||||||
|
$messagebody = get_string('notification:smsgatewaymigrationinfo', 'factor_sms', $smsconfigureurl);
|
||||||
|
$messagesubject = get_string('notification:smsgatewaymigration', 'factor_sms');
|
||||||
|
|
||||||
|
$message = new \core\message\message();
|
||||||
|
$message->component = 'moodle';
|
||||||
|
$message->name = 'notices';
|
||||||
|
$message->userfrom = \core_user::get_noreply_user();
|
||||||
|
$message->subject = $messagesubject;
|
||||||
|
$message->fullmessageformat = FORMAT_HTML;
|
||||||
|
$message->notification = 1;
|
||||||
|
$message->userto = $siteadmin;
|
||||||
|
$message->smallmessage = $messagesubject;
|
||||||
|
$message->fullmessagehtml = $messagebody;
|
||||||
|
$message->fullmessage = html_to_text($messagebody);
|
||||||
|
$message->contexturl = $smsconfigureurl;
|
||||||
|
$message->contexturlname = $messagesubject;
|
||||||
|
|
||||||
|
// Send message.
|
||||||
|
message_send($message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
admin/tool/mfa/factor/sms/db/hooks.php
Normal file
36
admin/tool/mfa/factor/sms/db/hooks.php
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<?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/>.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks register for SMS factor.
|
||||||
|
*
|
||||||
|
* @package factor_sms
|
||||||
|
* @copyright 2024 Safat Shahin <safat.shahin@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
|
$callbacks = [
|
||||||
|
[
|
||||||
|
'hook' => \core_sms\hook\before_gateway_deleted::class,
|
||||||
|
'callback' => \factor_sms\hook_listener::class . '::check_gateway_usage_in_mfa',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'hook' => \core_sms\hook\before_gateway_disabled::class,
|
||||||
|
'callback' => \factor_sms\hook_listener::class . '::check_gateway_usage_in_mfa',
|
||||||
|
],
|
||||||
|
];
|
|
@ -29,7 +29,7 @@
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function xmldb_factor_sms_upgrade(int $oldversion): bool {
|
function xmldb_factor_sms_upgrade(int $oldversion): bool {
|
||||||
if ($oldversion < 2024050300) {
|
if ($oldversion < 2024082200) {
|
||||||
$config = get_config('factor_sms');
|
$config = get_config('factor_sms');
|
||||||
// If the sms factor is enabled, then do the migration to the sms subsystem.
|
// If the sms factor is enabled, then do the migration to the sms subsystem.
|
||||||
if ((int)$config->enabled === 1) {
|
if ((int)$config->enabled === 1) {
|
||||||
|
@ -43,14 +43,21 @@ function xmldb_factor_sms_upgrade(int $oldversion): bool {
|
||||||
$smsconfig->api_region = $config->api_region;
|
$smsconfig->api_region = $config->api_region;
|
||||||
// Now insert the record.
|
// Now insert the record.
|
||||||
$manager = \core\di::get(\core_sms\manager::class);
|
$manager = \core\di::get(\core_sms\manager::class);
|
||||||
$manager->create_gateway_instance(
|
$gateway = $manager->create_gateway_instance(
|
||||||
classname: \smsgateway_aws\gateway::class,
|
classname: \smsgateway_aws\gateway::class,
|
||||||
|
name: 'MFA AWS',
|
||||||
enabled: $config->enabled,
|
enabled: $config->enabled,
|
||||||
config: $smsconfig,
|
config: $smsconfig,
|
||||||
);
|
);
|
||||||
|
// Set the mfa config for the sms gateway.
|
||||||
|
set_config('smsgateway', $gateway->id, 'factor_sms');
|
||||||
|
|
||||||
|
// Now add the task to send notification to admins about this migration.
|
||||||
|
$task = new \factor_sms\task\sms_gateway_migration_notification();
|
||||||
|
\core\task\manager::queue_adhoc_task($task, true);
|
||||||
}
|
}
|
||||||
// MFA savepoint reached.
|
// MFA savepoint reached.
|
||||||
upgrade_plugin_savepoint(true, 2024050300, 'factor', 'sms');
|
upgrade_plugin_savepoint(true, 2024082200, 'factor', 'sms');
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -44,6 +44,8 @@ $string['loginsubmit'] = 'Continue';
|
||||||
$string['managefactor'] = 'Manage SMS';
|
$string['managefactor'] = 'Manage SMS';
|
||||||
$string['managefactorbutton'] = 'Manage';
|
$string['managefactorbutton'] = 'Manage';
|
||||||
$string['manageinfo'] = 'You are using \'{$a}\' to authenticate.';
|
$string['manageinfo'] = 'You are using \'{$a}\' to authenticate.';
|
||||||
|
$string['notification:smsgatewaymigration'] = 'SMS settings have moved';
|
||||||
|
$string['notification:smsgatewaymigrationinfo'] = 'A new SMS subsystem is now available for managing and configuring all SMS-related functions. Your existing SMS configurations have been seamlessly migrated. You can find and manage them on the new <a href="{$a}">SMS Gateways page</a>.';
|
||||||
$string['logintitle'] = 'Enter the verification code sent to your mobile';
|
$string['logintitle'] = 'Enter the verification code sent to your mobile';
|
||||||
$string['phonehelp'] = 'Enter your mobile number (including country code) to receive a verification code.';
|
$string['phonehelp'] = 'Enter your mobile number (including country code) to receive a verification code.';
|
||||||
$string['pluginname'] = 'SMS mobile phone';
|
$string['pluginname'] = 'SMS mobile phone';
|
||||||
|
@ -65,6 +67,12 @@ $string['settings:duration'] = 'Validity duration';
|
||||||
$string['settings:duration_help'] = 'The period of time that the code is valid.';
|
$string['settings:duration_help'] = 'The period of time that the code is valid.';
|
||||||
$string['settings:gateway'] = 'SMS gateway';
|
$string['settings:gateway'] = 'SMS gateway';
|
||||||
$string['settings:gateway_help'] = 'The SMS provider you wish to send messages via';
|
$string['settings:gateway_help'] = 'The SMS provider you wish to send messages via';
|
||||||
|
$string['settings:heading'] = 'Users will receive an SMS with 6-digit code during login, which they must enter to complete the login process.
|
||||||
|
|
||||||
|
Users will need to register their mobile phone number first.';
|
||||||
|
$string['settings:setupdesc'] = '<br><br>To use SMS as an authentication factor, you first need to <a href="{$a}">set up an SMS gateway</a>.';
|
||||||
|
$string['settings:smsgateway'] = 'SMS gateway';
|
||||||
|
$string['settings:smsgateway_help'] = 'Select a gateway from the list, or <a href="{$a}">create a new gateway</a>.';
|
||||||
$string['setupfactor'] = 'Set up SMS';
|
$string['setupfactor'] = 'Set up SMS';
|
||||||
$string['setupfactorbutton'] = 'Set up';
|
$string['setupfactorbutton'] = 'Set up';
|
||||||
$string['setupsubmitcode'] = 'Save';
|
$string['setupsubmitcode'] = 'Save';
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings
|
* Settings for SMS MFA factor.
|
||||||
*
|
*
|
||||||
* @package factor_sms
|
* @package factor_sms
|
||||||
* @author Peter Burnett <peterburnett@catalyst-au.net>
|
* @author Peter Burnett <peterburnett@catalyst-au.net>
|
||||||
|
@ -24,24 +24,103 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
global $CFG, $OUTPUT;
|
|
||||||
|
|
||||||
$enabled = new admin_setting_configcheckbox('factor_sms/enabled',
|
global $CFG;
|
||||||
new lang_string('settings:enablefactor', 'tool_mfa'),
|
// Get the gateway records.
|
||||||
new lang_string('settings:enablefactor_help', 'tool_mfa'), 0);
|
$manager = \core\di::get(\core_sms\manager::class);
|
||||||
$enabled->set_updatedcallback(function () {
|
$gatewayrecords = $manager->get_gateway_records(['enabled' => 1]);
|
||||||
\tool_mfa\manager::do_factor_action('sms', get_config('factor_sms', 'enabled') ? 'enable' : 'disable');
|
$smsconfigureurl = new moodle_url(
|
||||||
});
|
'/sms/configure.php',
|
||||||
$settings->add($enabled);
|
[
|
||||||
|
'returnurl' => new moodle_url(
|
||||||
|
'/admin/settings.php',
|
||||||
|
['section' => 'factor_sms'],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
$smsconfigureurl = $smsconfigureurl->out();
|
||||||
|
|
||||||
$settings->add(new admin_setting_configtext('factor_sms/weight',
|
$settings->add(
|
||||||
new lang_string('settings:weight', 'tool_mfa'),
|
new admin_setting_heading(
|
||||||
new lang_string('settings:weight_help', 'tool_mfa'), 100, PARAM_INT));
|
'factor_sms/heading',
|
||||||
|
'',
|
||||||
|
new lang_string(
|
||||||
|
'settings:heading',
|
||||||
|
'factor_sms',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
$settings->add(new admin_setting_configduration('factor_sms/duration',
|
if (count($gatewayrecords) > 0) {
|
||||||
get_string('settings:duration', 'tool_mfa'),
|
$gateways = [0 => new lang_string('none')];
|
||||||
get_string('settings:duration_help', 'tool_mfa'), 30 * MINSECS, MINSECS));
|
foreach ($gatewayrecords as $record) {
|
||||||
|
$values = explode('\\', $record->gateway);
|
||||||
|
$gatewayname = new lang_string('pluginname', $values[0]);
|
||||||
|
$gateways[$record->id] = $record->name . ' (' . $gatewayname . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings->add(
|
||||||
|
new admin_setting_configselect(
|
||||||
|
'factor_sms/smsgateway',
|
||||||
|
new lang_string('settings:smsgateway', 'factor_sms'),
|
||||||
|
new lang_string('settings:smsgateway_help', 'factor_sms', $smsconfigureurl),
|
||||||
|
0,
|
||||||
|
$gateways,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$enabled = new admin_setting_configcheckbox(
|
||||||
|
'factor_sms/enabled',
|
||||||
|
new lang_string('settings:enablefactor', 'tool_mfa'),
|
||||||
|
new lang_string('settings:enablefactor_help', 'tool_mfa'),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
$enabled->set_updatedcallback(function () {
|
||||||
|
\tool_mfa\manager::do_factor_action(
|
||||||
|
'sms',
|
||||||
|
get_config('factor_sms', 'enabled') ? 'enable' : 'disable',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
$settings->add($enabled);
|
||||||
|
|
||||||
|
$settings->add(
|
||||||
|
new admin_setting_configtext(
|
||||||
|
'factor_sms/weight',
|
||||||
|
new lang_string('settings:weight', 'tool_mfa'),
|
||||||
|
new lang_string('settings:weight_help', 'tool_mfa'),
|
||||||
|
100,
|
||||||
|
PARAM_INT,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$settings->hide_if('factor_sms/weight', 'factor_sms/enabled');
|
||||||
|
|
||||||
|
$settings->add(
|
||||||
|
new admin_setting_configduration(
|
||||||
|
'factor_sms/duration',
|
||||||
|
new lang_string('settings:duration', 'tool_mfa'),
|
||||||
|
new lang_string('settings:duration_help', 'tool_mfa'),
|
||||||
|
30 * MINSECS,
|
||||||
|
MINSECS,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$settings->hide_if('factor_sms/duration', 'factor_sms/enabled');
|
||||||
|
} else {
|
||||||
|
$settings->add(
|
||||||
|
new admin_setting_description(
|
||||||
|
'factor_sms/setupdesc',
|
||||||
|
'',
|
||||||
|
new lang_string(
|
||||||
|
'settings:setupdesc',
|
||||||
|
'factor_sms',
|
||||||
|
$smsconfigureurl,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO MDL-80962 Remove these settings, strings and associated codes (if any).
|
||||||
|
/*
|
||||||
$codeslink = 'https://en.wikipedia.org/wiki/List_of_country_calling_codes';
|
$codeslink = 'https://en.wikipedia.org/wiki/List_of_country_calling_codes';
|
||||||
$link = \html_writer::link($codeslink, $codeslink);
|
$link = \html_writer::link($codeslink, $codeslink);
|
||||||
|
|
||||||
|
@ -64,3 +143,4 @@ if (empty(get_config('factor_sms', 'gateway'))) {
|
||||||
|
|
||||||
$class = '\factor_sms\local\smsgateway\\' . get_config('factor_sms', 'gateway');
|
$class = '\factor_sms\local\smsgateway\\' . get_config('factor_sms', 'gateway');
|
||||||
call_user_func($class . '::add_settings', $settings);
|
call_user_func($class . '::add_settings', $settings);
|
||||||
|
*/
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
$plugin->version = 2024050300; // The current plugin version (Date: YYYYMMDDXX).
|
$plugin->version = 2024082200; // The current plugin version (Date: YYYYMMDDXX).
|
||||||
$plugin->requires = 2024041600; // Requires this Moodle version.
|
$plugin->requires = 2024041600; // Requires this Moodle version.
|
||||||
$plugin->component = 'factor_sms'; // Full name of the plugin (used for diagnostics).
|
$plugin->component = 'factor_sms'; // Full name of the plugin (used for diagnostics).
|
||||||
$plugin->maturity = MATURITY_STABLE;
|
$plugin->maturity = MATURITY_STABLE;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue