Merge branch 'MDL-69555-master' of git://github.com/jleyva/moodle

This commit is contained in:
Shamim Rezaie 2022-01-12 14:41:48 +11:00
commit 9142285ad6
8 changed files with 59 additions and 12 deletions

View File

@ -53,7 +53,7 @@ class api {
const LOGIN_KEY_TTL = 60;
/** @var string URL of the Moodle Apps Portal */
const MOODLE_APPS_PORTAL_URL = 'https://apps.moodle.com';
/** @var int seconds a QR login key will expire. */
/** @var int default value in seconds a QR login key will expire. */
const LOGIN_QR_KEY_TTL = 600;
/** @var int QR code disabled value */
const QR_CODE_DISABLED = 0;
@ -306,6 +306,10 @@ class api {
$settings->tool_mobile_filetypeexclusionlist = get_config('tool_mobile', 'filetypeexclusionlist');
$settings->tool_mobile_custommenuitems = get_config('tool_mobile', 'custommenuitems');
$settings->tool_mobile_apppolicy = get_config('tool_mobile', 'apppolicy');
// This setting could be not set in some edge cases such as bad upgrade.
$mintimereq = get_config('tool_mobile', 'autologinmintimebetweenreq');
$mintimereq = empty($mintimereq) ? 6 * MINSECS : $mintimereq;
$settings->tool_mobile_autologinmintimebetweenreq = $mintimereq;
}
if (empty($section) or $section == 'calendar') {
@ -383,17 +387,19 @@ class api {
* Creates a QR login key for the current user, this key is restricted by time and ip address.
* This key is used for automatically login the user in the site when the user scans a QR code in the Moodle app.
*
* @param stdClass $mobilesettings mobile app plugin settings
* @return string the key
* @since Moodle 3.9
*/
public static function get_qrlogin_key() {
public static function get_qrlogin_key(stdClass $mobilesettings) {
global $USER;
// Delete previous keys.
delete_user_key('tool_mobile', $USER->id);
// Create a new key.
$iprestriction = getremoteaddr(null);
$validuntil = time() + self::LOGIN_QR_KEY_TTL;
$qrkeyttl = !empty($mobilesettings->qrkeyttl) ? $mobilesettings->qrkeyttl : self::LOGIN_QR_KEY_TTL;
$validuntil = time() + $qrkeyttl;
return create_user_key('tool_mobile', $USER->id, null, $iprestriction, $validuntil);
}
@ -687,7 +693,7 @@ class api {
$data = $urlscheme . '://' . $CFG->wwwroot;
if ($mobilesettings->qrcodetype == static::QR_CODE_LOGIN) {
$qrloginkey = static::get_qrlogin_key();
$qrloginkey = static::get_qrlogin_key($mobilesettings);
$data .= '?qrlogin=' . $qrloginkey . '&userid=' . $USER->id;
}

View File

@ -311,9 +311,12 @@ class external extends external_api {
// Between each request 6 minutes are required.
$last = get_user_preferences('tool_mobile_autologin_request_last', 0, $USER);
// Check if we must reset the count.
$mintimereq = get_config('tool_mobile', 'autologinmintimebetweenreq');
$mintimereq = empty($mintimereq) ? 6 * MINSECS : $mintimereq;
$timenow = time();
if ($timenow - $last < 6 * MINSECS) {
throw new moodle_exception('autologinkeygenerationlockout', 'tool_mobile');
if ($timenow - $last < $mintimereq) {
$minutes = $mintimereq / MINSECS;
throw new moodle_exception('autologinkeygenerationlockout', 'tool_mobile', $minutes);
}
set_user_preference('tool_mobile_autologin_request_last', $timenow, $USER);

View File

@ -28,7 +28,9 @@ $string['androidappid_desc'] = 'This setting may be left as default unless you h
$string['apppolicy'] = 'App policy URL';
$string['apppolicy_help'] = 'The URL of a policy for app users which is listed on the About page in the app. If the field is left empty, the site policy URL will be used instead.';
$string['apprequired'] = 'This functionality is only available when accessed via the Moodle mobile or desktop app.';
$string['autologinkeygenerationlockout'] = 'Auto-login key generation is blocked. You need to wait 6 minutes between requests.';
$string['autologinkeygenerationlockout'] = 'Auto-login key generation is blocked. You need to wait {$a} minutes between requests.';
$string['autologinmintimebetweenreq'] = 'Minimum time between auto-login requests.';
$string['autologinmintimebetweenreq_desc'] = 'This setting determines the minimum time between auto-login requests from the app. You should set this setting to a low value if mobile app users are frequently asked to enter their credentials when visualising content embedded from the site.';
$string['autologinnotallowedtoadmins'] = 'Auto-login is not allowed for site admins.';
$string['cachedef_plugininfo'] = 'This stores the list of plugins with mobile addons';
$string['cachedef_subscriptiondata'] = 'This stores the Moodle app subscription information.';
@ -114,13 +116,15 @@ $string['pluginname'] = 'Moodle app tools';
$string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
$string['qrcodedisabled'] = 'Access via QR code disabled';
$string['qrcodeformobileappaccess'] = 'QR code for mobile app access';
$string['qrcodeformobileapploginabout'] = 'Scan the QR code with your mobile app and you will be automatically logged in. The QR code will expire in {$a} minutes.';
$string['qrcodeformobileapploginabout'] = 'Scan the QR code with your mobile app and you will be automatically logged in. The QR code will expire in {$a}.';
$string['qrcodeformobileappurlabout'] = 'Scan the QR code with your mobile app to fill in the site URL in your app.';
$string['qrsiteadminsnotallowed'] = 'For security reasons login via QR code is not allowed for site administrators or if you are logged in as another user.';
$string['qrcodetype'] = 'QR code access';
$string['qrcodetype_desc'] = 'A QR code can be provided for mobile app users to scan. This can be used to fill in the site URL, or where the site is secured using HTTPS, to automatically log the user in without having to enter their username and password.';
$string['qrcodetypeurl'] = 'QR code with site URL';
$string['qrcodetypelogin'] = 'QR code with automatic login';
$string['qrkeyttl'] = 'QR authentication key duration';
$string['qrkeyttl_desc'] = 'Length of time for which a QR code for authentication is valid. Empty values are not allowed, in that case the default value for the setting will be used.';
$string['readingthisemailgettheapp'] = 'Reading this in an email? <a href="{$a}">Download the mobile app and receive notifications on your mobile device</a>.';
$string['remoteaddons'] = 'Remote add-ons';
$string['scanqrcode'] = 'Scan QR code';

View File

@ -149,8 +149,9 @@ function tool_mobile_myprofile_navigation(\core_user\output\myprofile\tree $tree
} else {
$qrcodeimg = tool_mobile\api::generate_login_qrcode($mobilesettings);
$minutes = tool_mobile\api::LOGIN_QR_KEY_TTL / MINSECS;
$mobileqr = html_writer::tag('p', get_string('qrcodeformobileapploginabout', 'tool_mobile', $minutes));
$qrkeyttl = !empty($mobilesettings->qrkeyttl) ? $mobilesettings->qrkeyttl : tool_mobile\api::LOGIN_QR_KEY_TTL;
$mobileqr = html_writer::tag('p', get_string('qrcodeformobileapploginabout', 'tool_mobile',
format_time($qrkeyttl)));
$mobileqr .= html_writer::link('#qrcode', get_string('viewqrcode', 'tool_mobile'),
['class' => 'btn btn-primary mt-2', 'data-toggle' => 'collapse',
'role' => 'button', 'aria-expanded' => 'false']);

View File

@ -117,6 +117,11 @@ if ($hassiteconfig) {
new lang_string('qrcodetype', 'tool_mobile'),
new lang_string('qrcodetype_desc', 'tool_mobile'), $qrcodetypedefault, $options));
$temp->add(new admin_setting_configduration('tool_mobile/qrkeyttl',
new lang_string('qrkeyttl', 'tool_mobile'),
new lang_string('qrkeyttl_desc', 'tool_mobile'), tool_mobile\api::LOGIN_QR_KEY_TTL, MINSECS));
$temp->hide_if('tool_mobile/qrkeyttl', 'tool_mobile/qrcodetype', 'neq', tool_mobile\api::QR_CODE_LOGIN);
$temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
new lang_string('forcedurlscheme_key', 'tool_mobile'),
new lang_string('forcedurlscheme', 'tool_mobile'), 'moodlemobile', PARAM_NOTAGS));
@ -125,6 +130,18 @@ if ($hassiteconfig) {
new lang_string('minimumversion_key', 'tool_mobile'),
new lang_string('minimumversion', 'tool_mobile'), '', PARAM_NOTAGS));
$options = [
60 => new lang_string('numminutes', '', 1),
180 => new lang_string('numminutes', '', 3),
360 => new lang_string('numminutes', '', 6),
900 => new lang_string('numminutes', '', 15),
1800 => new lang_string('numminutes', '', 30),
3600 => new lang_string('numminutes', '', 60)
];
$temp->add(new admin_setting_configselect('tool_mobile/autologinmintimebetweenreq',
new lang_string('autologinmintimebetweenreq', 'tool_mobile'),
new lang_string('autologinmintimebetweenreq_desc', 'tool_mobile'), 360, $options));
$ADMIN->add('mobileapp', $temp);
// Appearance related settings.

View File

@ -219,6 +219,7 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
array('name' => 'tool_mobile_filetypeexclusionlist', 'value' => ''),
array('name' => 'tool_mobile_custommenuitems', 'value' => ''),
array('name' => 'tool_mobile_apppolicy', 'value' => ''),
array('name' => 'tool_mobile_autologinmintimebetweenreq', 'value' => 6 * MINSECS),
array('name' => 'calendartype', 'value' => $CFG->calendartype),
array('name' => 'calendar_site_timeformat', 'value' => $CFG->calendar_site_timeformat),
array('name' => 'calendar_startwday', 'value' => $CFG->calendar_startwday),
@ -387,6 +388,15 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
$result = external::get_autologin_key($token->privatetoken);
$result = external_api::clean_returnvalue(external::get_autologin_key_returns(), $result);
// Change min time between requests to 30 seconds.
set_config('autologinmintimebetweenreq', 30, 'tool_mobile');
// Mock a previous request, 60 seconds ago.
$mocktime = time() - MINSECS;
set_user_preference('tool_mobile_autologin_request_last', $mocktime, $USER);
$result = external::get_autologin_key($token->privatetoken); // All good, we were expecint 30 seconds or more.
$result = external_api::clean_returnvalue(external::get_autologin_key_returns(), $result);
// We just requested one token, we must wait.
$this->expectException('moodle_exception');
$this->expectExceptionMessage(get_string('autologinkeygenerationlockout', 'tool_mobile'));
@ -623,7 +633,8 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$qrloginkey = api::get_qrlogin_key();
$mobilesettings = get_config('tool_mobile');
$qrloginkey = api::get_qrlogin_key($mobilesettings);
// Generate new tokens, the ones we expect to receive.
$service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));

View File

@ -1,6 +1,11 @@
This files describes changes in tool_mobile code.
Information provided here is intended especially for developers.
=== 4.0 ===
* The function tool_mobile\api::get_qrlogin_key() now requires as parameter an object with all the mobile plugin settings.
* The tool_mobile_external::get_config external function now returns the tool_mobile_autologinmintimebetweenreq setting.
=== 3.7 ===
* New external function tool_mobile::tool_mobile_call_external_function allows calling multiple external functions and returns all responses.

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2022011100.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2022011100.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.0dev+ (Build: 20220111)'; // Human-friendly version name