mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
Merge branch 'MDL-53777-master' of git://github.com/jleyva/moodle
This commit is contained in:
commit
27ed5be84f
@ -320,22 +320,7 @@ if ($hassiteconfig) {
|
||||
|
||||
/// Web services
|
||||
$ADMIN->add('modules', new admin_category('webservicesettings', new lang_string('webservices', 'webservice')));
|
||||
// Mobile
|
||||
$temp = new admin_settingpage('mobile', new lang_string('mobile','admin'), 'moodle/site:config', false);
|
||||
|
||||
// We should wait to the installation to finish since we depend on some configuration values that are set once
|
||||
// the admin user profile is configured.
|
||||
if (!during_initial_install()) {
|
||||
$enablemobiledocurl = new moodle_url(get_docs_url('Enable_mobile_web_services'));
|
||||
$enablemobiledoclink = html_writer::link($enablemobiledocurl, new lang_string('documentation'));
|
||||
$default = is_https() ? 1 : 0;
|
||||
$temp->add(new admin_setting_enablemobileservice('enablemobilewebservice',
|
||||
new lang_string('enablemobilewebservice', 'admin'),
|
||||
new lang_string('configenablemobilewebservice', 'admin', $enablemobiledoclink), $default));
|
||||
}
|
||||
|
||||
$temp->add(new admin_setting_configtext('mobilecssurl', new lang_string('mobilecssurl', 'admin'), new lang_string('configmobilecssurl','admin'), '', PARAM_URL));
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
/// overview page
|
||||
$temp = new admin_settingpage('webservicesoverview', new lang_string('webservicesoverview', 'webservice'));
|
||||
$temp->add(new admin_setting_webservicesoverview());
|
||||
|
@ -27,6 +27,7 @@ namespace tool_mobile;
|
||||
use core_component;
|
||||
use core_plugin_manager;
|
||||
use context_system;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* API exposed by tool_mobile
|
||||
@ -37,6 +38,13 @@ use context_system;
|
||||
*/
|
||||
class api {
|
||||
|
||||
/** @var int to identify the login via app. */
|
||||
const LOGIN_VIA_APP = 1;
|
||||
/** @var int to identify the login via browser. */
|
||||
const LOGIN_VIA_BROWSER = 2;
|
||||
/** @var int to identify the login via an embedded browser. */
|
||||
const LOGIN_VIA_EMBEDDED_BROWSER = 3;
|
||||
|
||||
/**
|
||||
* Returns a list of Moodle plugins supporting the mobile app.
|
||||
*
|
||||
@ -111,6 +119,19 @@ class api {
|
||||
'maintenanceenabled' => $CFG->maintenance_enabled,
|
||||
'maintenancemessage' => format_text($CFG->maintenance_message),
|
||||
);
|
||||
|
||||
$typeoflogin = get_config('tool_mobile', 'typeoflogin');
|
||||
// Not found, edge case.
|
||||
if ($typeoflogin === false) {
|
||||
$typeoflogin = self::LOGIN_VIA_APP; // Defaults to via app.
|
||||
}
|
||||
$settings['typeoflogin'] = $typeoflogin;
|
||||
|
||||
if ($typeoflogin == self::LOGIN_VIA_BROWSER or
|
||||
$typeoflogin == self::LOGIN_VIA_EMBEDDED_BROWSER) {
|
||||
$url = new moodle_url("/$CFG->admin/tool/mobile/launch.php");
|
||||
$settings['launchurl'] = $url->out(false);
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,8 @@ class external extends external_api {
|
||||
'enablemobilewebservice' => new external_value(PARAM_INT, 'Whether the Mobile service is enabled.'),
|
||||
'maintenanceenabled' => new external_value(PARAM_INT, 'Whether site maintenance is enabled.'),
|
||||
'maintenancemessage' => new external_value(PARAM_RAW, 'Maintenance message.'),
|
||||
'typeoflogin' => new external_value(PARAM_INT, 'The type of login. 1 for app, 2 for browser, 3 for embedded.'),
|
||||
'launchurl' => new external_value(PARAM_URL, 'SSO login launch URL. Empty if it won\'t be used.', VALUE_OPTIONAL),
|
||||
'warnings' => new external_warnings(),
|
||||
)
|
||||
);
|
||||
|
@ -22,4 +22,12 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['clickheretolaunchtheapp'] = 'Please, click here if the app does not open automatically.';
|
||||
$string['forcedurlscheme'] = 'The URL scheme allows to open the mobile app from other apps like the browser. Use this setting if you want to allow only your custom branded app to be opened by the browser.';
|
||||
$string['forcedurlscheme_key'] = 'URL scheme';
|
||||
$string['loginintheapp'] = 'Via the app';
|
||||
$string['logininthebrowser'] = 'Via a browser window (for SSO plugins)';
|
||||
$string['loginintheembeddedbrowser'] = 'Via an embedded browser (for SSO plugins)';
|
||||
$string['pluginname'] = 'Moodle Mobile tools';
|
||||
$string['typeoflogin'] = 'Type of login';
|
||||
$string['typeoflogin_desc'] = 'Choose the type of login.';
|
||||
|
102
admin/tool/mobile/launch.php
Normal file
102
admin/tool/mobile/launch.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Launch page, launch the app using custom URL schemes.
|
||||
*
|
||||
* If the user is not logged when visiting this page, he will be redirected to the login page.
|
||||
* Once he is logged, he will be redirected again to this page and the app launched via custom URL schemes.
|
||||
*
|
||||
* @package tool_mobile
|
||||
* @copyright 2016 Juan Leyva
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->libdir . '/externallib.php');
|
||||
|
||||
$serviceshortname = required_param('service', PARAM_ALPHANUMEXT);
|
||||
$passport = required_param('passport', PARAM_RAW); // Passport send from the app to validate the response URL.
|
||||
$urlscheme = optional_param('urlscheme', 'moodlemobile', PARAM_NOTAGS); // The URL scheme the app supports.
|
||||
|
||||
// Check web services enabled.
|
||||
if (!$CFG->enablewebservices) {
|
||||
throw new moodle_exception('enablewsdescription', 'webservice');
|
||||
}
|
||||
|
||||
// Check if the plugin is properly configured.
|
||||
$typeoflogin = get_config('tool_mobile', 'typeoflogin');
|
||||
if ($typeoflogin != tool_mobile\api::LOGIN_VIA_BROWSER and
|
||||
$typeoflogin != tool_mobile\api::LOGIN_VIA_EMBEDDED_BROWSER) {
|
||||
throw new moodle_exception('pluginnotenabledorconfigured', 'local_mobile');
|
||||
}
|
||||
|
||||
// Check if the service exists and is enabled.
|
||||
$service = $DB->get_record('external_services', array('shortname' => $serviceshortname, 'enabled' => 1));
|
||||
if (empty($service)) {
|
||||
throw new moodle_exception('servicenotavailable', 'webservice');
|
||||
}
|
||||
|
||||
require_login(0, false);
|
||||
|
||||
// Require an active user: not guest, not suspended.
|
||||
core_user::require_active_user($USER);
|
||||
|
||||
// Get an existing token or create a new one.
|
||||
$token = external_generate_token_for_current_user($service);
|
||||
|
||||
// Log token access.
|
||||
$DB->set_field('external_tokens', 'lastaccess', time(), array('id' => $token->id));
|
||||
|
||||
$params = array(
|
||||
'objectid' => $token->id,
|
||||
);
|
||||
$event = \core\event\webservice_token_sent::create($params);
|
||||
$event->add_record_snapshot('external_tokens', $token);
|
||||
$event->trigger();
|
||||
|
||||
// Passport is generated in the mobile app, so the app opening can be validated using that variable.
|
||||
// Passports are valid only one time, it's deleted in the app once used.
|
||||
$siteid = md5($CFG->wwwroot . $passport);
|
||||
$apptoken = base64_encode($siteid . ':::' . $token->token);
|
||||
|
||||
// Redirect using the custom URL scheme checking first if a URL scheme is forced in the site settings.
|
||||
$forcedurlscheme = get_config('tool_mobile', 'forcedurlscheme');
|
||||
if (!empty($forcedurlscheme)) {
|
||||
$urlscheme = $forcedurlscheme;
|
||||
}
|
||||
|
||||
$location = "$urlscheme://token=$apptoken";
|
||||
|
||||
// For iOS 10 onwards, we have to simulate a user click.
|
||||
if (core_useragent::is_ios()) {
|
||||
$PAGE->set_context(null);
|
||||
$PAGE->set_url('/local/mobile/launch.php', array('service' => $serviceshortname, 'passport' => $passport, 'urlscheme' => $urlscheme));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
$notice = get_string('clickheretolaunchtheapp', 'tool_mobile');
|
||||
echo html_writer::link($location, $notice, array('id' => 'launchapp'));
|
||||
echo html_writer::script(
|
||||
"window.onload = function() {
|
||||
document.getElementById('launchapp').click();
|
||||
};"
|
||||
);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
// For Android a http redirect will do fine.
|
||||
header('Location: ' . $location);
|
||||
die;
|
||||
}
|
62
admin/tool/mobile/settings.php
Normal file
62
admin/tool/mobile/settings.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Settings
|
||||
*
|
||||
* This file contains settings used by tool_mobile
|
||||
*
|
||||
* @package tool_mobile
|
||||
* @copyright 2016 Juan Leyva
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if ($hassiteconfig) {
|
||||
|
||||
$temp = new admin_settingpage('mobile', new lang_string('mobile', 'admin'), 'moodle/site:config', false);
|
||||
|
||||
// We should wait to the installation to finish since we depend on some configuration values that are set once
|
||||
// the admin user profile is configured.
|
||||
if (!during_initial_install()) {
|
||||
$enablemobiledocurl = new moodle_url(get_docs_url('Enable_mobile_web_services'));
|
||||
$enablemobiledoclink = html_writer::link($enablemobiledocurl, new lang_string('documentation'));
|
||||
$default = is_https() ? 1 : 0;
|
||||
$temp->add(new admin_setting_enablemobileservice('enablemobilewebservice',
|
||||
new lang_string('enablemobilewebservice', 'admin'),
|
||||
new lang_string('configenablemobilewebservice', 'admin', $enablemobiledoclink), $default));
|
||||
}
|
||||
|
||||
$temp->add(new admin_setting_configtext('mobilecssurl', new lang_string('mobilecssurl', 'admin'),
|
||||
new lang_string('configmobilecssurl', 'admin'), '', PARAM_URL));
|
||||
|
||||
// Type of login.
|
||||
$options = array(
|
||||
tool_mobile\api::LOGIN_VIA_APP => new lang_string('loginintheapp', 'tool_mobile'),
|
||||
tool_mobile\api::LOGIN_VIA_BROWSER => new lang_string('logininthebrowser', 'tool_mobile'),
|
||||
tool_mobile\api::LOGIN_VIA_EMBEDDED_BROWSER => new lang_string('loginintheembeddedbrowser', 'tool_mobile'),
|
||||
);
|
||||
$temp->add(new admin_setting_configselect('tool_mobile/typeoflogin',
|
||||
new lang_string('typeoflogin', 'tool_mobile'),
|
||||
new lang_string('typeoflogin_desc', 'tool_mobile'), 1, $options));
|
||||
|
||||
$temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
|
||||
new lang_string('forcedurlscheme_key', 'tool_mobile'),
|
||||
new lang_string('forcedurlscheme', 'tool_mobile'), '', PARAM_NOTAGS));
|
||||
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
}
|
@ -31,6 +31,7 @@ global $CFG;
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
|
||||
use tool_mobile\external;
|
||||
use tool_mobile\api;
|
||||
|
||||
/**
|
||||
* External learning plans webservice API tests.
|
||||
@ -78,17 +79,21 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
|
||||
'enablemobilewebservice' => $CFG->enablemobilewebservice,
|
||||
'maintenanceenabled' => $CFG->maintenance_enabled,
|
||||
'maintenancemessage' => format_text($CFG->maintenance_message),
|
||||
'typeoflogin' => api::LOGIN_VIA_APP,
|
||||
'warnings' => array()
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
// Change a value.
|
||||
// Change some values.
|
||||
set_config('registerauth', 'email');
|
||||
$authinstructions = 'Something with <b>html tags</b>';
|
||||
set_config('auth_instructions', $authinstructions);
|
||||
set_config('typeoflogin', api::LOGIN_VIA_BROWSER, 'tool_mobile');
|
||||
|
||||
$expected['registerauth'] = 'email';
|
||||
$expected['authinstructions'] = format_text($authinstructions);
|
||||
$expected['typeoflogin'] = api::LOGIN_VIA_BROWSER;
|
||||
$expected['launchurl'] = "$CFG->wwwroot/$CFG->admin/tool/mobile/launch.php";;
|
||||
|
||||
$result = external::get_site_public_settings();
|
||||
$result = external_api::clean_returnvalue(external::get_site_public_settings_returns(), $result);
|
||||
|
@ -23,6 +23,6 @@
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->version = 2016052301; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2016052302; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2016051900; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
|
||||
|
@ -33,7 +33,12 @@ defined('MOODLE_INTERNAL') || die();
|
||||
class tool extends base {
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
// Some mobile settings are used by the core.
|
||||
if ($this->name === 'mobile') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -997,4 +997,61 @@ class core_useragent {
|
||||
$instance = self::instance();
|
||||
return (bool) $instance->is_useragent_web_crawler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the client appears to be a device using iOS (iPhone, iPad, iPod).
|
||||
*
|
||||
* @param scalar $version The version if we need to find out if it is equal to or greater than that specified.
|
||||
* @return bool true if the client is using iOS
|
||||
* @since Moodle 3.2
|
||||
*/
|
||||
public static function is_ios($version = null) {
|
||||
$useragent = self::get_user_agent_string();
|
||||
if ($useragent === false) {
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'AppleWebKit') === false) {
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'Windows')) {
|
||||
// Reject Windows Safari.
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'Macintosh')) {
|
||||
// Reject MacOS Safari.
|
||||
return false;
|
||||
}
|
||||
// Look for AppleWebKit, excluding strings with OmniWeb, Shiira and SymbianOS and any other mobile devices.
|
||||
if (strpos($useragent, 'OmniWeb')) {
|
||||
// Reject OmniWeb.
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'Shiira')) {
|
||||
// Reject Shiira.
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'SymbianOS')) {
|
||||
// Reject SymbianOS.
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'Android')) {
|
||||
// Reject Androids too.
|
||||
return false;
|
||||
}
|
||||
if (strpos($useragent, 'Chrome')) {
|
||||
// Reject chrome browsers - it needs to be tested explicitly.
|
||||
// This will also reject Edge, which pretends to be both Chrome, and Safari.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($version)) {
|
||||
return true; // No version specified.
|
||||
}
|
||||
if (preg_match("/AppleWebKit\/([0-9.]+)/i", $useragent, $match)) {
|
||||
if (version_compare($match[1], $version) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -954,6 +954,122 @@ function external_format_text($text, $textformat, $contextid, $component = null,
|
||||
return array($text, $textformat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate or return an existing token for the current authenticated user.
|
||||
* This function is used for creating a valid token for users authenticathing via login/token.php or admin/tool/mobile/launch.php.
|
||||
*
|
||||
* @param stdClass $service external service object
|
||||
* @return stdClass token object
|
||||
* @since Moodle 3.2
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
function external_generate_token_for_current_user($service) {
|
||||
global $DB, $USER;
|
||||
|
||||
core_user::require_active_user($USER, true, true);
|
||||
|
||||
// Check if there is any required system capability.
|
||||
if ($service->requiredcapability and !has_capability($service->requiredcapability, context_system::instance())) {
|
||||
throw new moodle_exception('missingrequiredcapability', 'webservice', '', $service->requiredcapability);
|
||||
}
|
||||
|
||||
// Specific checks related to user restricted service.
|
||||
if ($service->restrictedusers) {
|
||||
$authoriseduser = $DB->get_record('external_services_users',
|
||||
array('externalserviceid' => $service->id, 'userid' => $USER->id));
|
||||
|
||||
if (empty($authoriseduser)) {
|
||||
throw new moodle_exception('usernotallowed', 'webservice', '', $service->shortname);
|
||||
}
|
||||
|
||||
if (!empty($authoriseduser->validuntil) and $authoriseduser->validuntil < time()) {
|
||||
throw new moodle_exception('invalidtimedtoken', 'webservice');
|
||||
}
|
||||
|
||||
if (!empty($authoriseduser->iprestriction) and !address_in_subnet(getremoteaddr(), $authoriseduser->iprestriction)) {
|
||||
throw new moodle_exception('invalidiptoken', 'webservice');
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a token has already been created for this user and this service.
|
||||
$conditions = array(
|
||||
'userid' => $USER->id,
|
||||
'externalserviceid' => $service->id,
|
||||
'tokentype' => EXTERNAL_TOKEN_PERMANENT
|
||||
);
|
||||
$tokens = $DB->get_records('external_tokens', $conditions, 'timecreated ASC');
|
||||
|
||||
// A bit of sanity checks.
|
||||
foreach ($tokens as $key => $token) {
|
||||
|
||||
// Checks related to a specific token. (script execution continue).
|
||||
$unsettoken = false;
|
||||
// If sid is set then there must be a valid associated session no matter the token type.
|
||||
if (!empty($token->sid)) {
|
||||
if (!\core\session\manager::session_exists($token->sid)) {
|
||||
// This token will never be valid anymore, delete it.
|
||||
$DB->delete_records('external_tokens', array('sid' => $token->sid));
|
||||
$unsettoken = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove token is not valid anymore.
|
||||
if (!empty($token->validuntil) and $token->validuntil < time()) {
|
||||
$DB->delete_records('external_tokens', array('token' => $token->token, 'tokentype' => EXTERNAL_TOKEN_PERMANENT));
|
||||
$unsettoken = true;
|
||||
}
|
||||
|
||||
// Remove token if its ip not in whitelist.
|
||||
if (isset($token->iprestriction) and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
|
||||
$unsettoken = true;
|
||||
}
|
||||
|
||||
if ($unsettoken) {
|
||||
unset($tokens[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// If some valid tokens exist then use the most recent.
|
||||
if (count($tokens) > 0) {
|
||||
$token = array_pop($tokens);
|
||||
} else {
|
||||
$context = context_system::instance();
|
||||
$isofficialservice = $service->shortname == MOODLE_OFFICIAL_MOBILE_SERVICE;
|
||||
|
||||
if (($isofficialservice and has_capability('moodle/webservice:createmobiletoken', $context)) or
|
||||
(!is_siteadmin($USER) && has_capability('moodle/webservice:createtoken', $context))) {
|
||||
|
||||
// Create a new token.
|
||||
$token = new stdClass;
|
||||
$token->token = md5(uniqid(rand(), 1));
|
||||
$token->userid = $USER->id;
|
||||
$token->tokentype = EXTERNAL_TOKEN_PERMANENT;
|
||||
$token->contextid = context_system::instance()->id;
|
||||
$token->creatorid = $USER->id;
|
||||
$token->timecreated = time();
|
||||
$token->externalserviceid = $service->id;
|
||||
// MDL-43119 Token valid for 3 months (12 weeks).
|
||||
$token->validuntil = $token->timecreated + 12 * WEEKSECS;
|
||||
$token->id = $DB->insert_record('external_tokens', $token);
|
||||
|
||||
$params = array(
|
||||
'objectid' => $token->id,
|
||||
'relateduserid' => $USER->id,
|
||||
'other' => array(
|
||||
'auto' => true
|
||||
)
|
||||
);
|
||||
$event = \core\event\webservice_token_created::create($params);
|
||||
$event->add_record_snapshot('external_tokens', $token);
|
||||
$event->trigger();
|
||||
} else {
|
||||
throw new moodle_exception('cannotcreatetoken', 'webservice', '', $service->shortname);
|
||||
}
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Singleton to handle the external settings.
|
||||
*
|
||||
|
@ -890,6 +890,7 @@ class core_useragent_testcase extends advanced_testcase {
|
||||
array(
|
||||
// Note: We do *not* identify mobile Safari as Safari.
|
||||
'is_safari_ios' => true,
|
||||
'is_ios' => true,
|
||||
'check_safari_ios_version' => array(
|
||||
'527' => true,
|
||||
),
|
||||
@ -911,6 +912,7 @@ class core_useragent_testcase extends advanced_testcase {
|
||||
array(
|
||||
// Note: We do *not* identify mobile Safari as Safari.
|
||||
'is_safari_ios' => true,
|
||||
'is_ios' => true,
|
||||
'check_safari_ios_version' => array(
|
||||
'527' => true,
|
||||
'590' => true,
|
||||
@ -934,6 +936,7 @@ class core_useragent_testcase extends advanced_testcase {
|
||||
array(
|
||||
// Note: We do *not* identify mobile Safari as Safari.
|
||||
'is_safari_ios' => true,
|
||||
'is_ios' => true,
|
||||
'check_safari_ios_version' => array(
|
||||
'527' => true,
|
||||
),
|
||||
@ -1222,6 +1225,7 @@ class core_useragent_testcase extends advanced_testcase {
|
||||
'is_web_crawler' => true,
|
||||
'is_webkit' => true,
|
||||
'is_safari_ios' => true,
|
||||
'is_ios' => true,
|
||||
'check_safari_ios_version' => array(
|
||||
'527' => true,
|
||||
),
|
||||
@ -1703,6 +1707,24 @@ class core_useragent_testcase extends advanced_testcase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider user_agents_providers
|
||||
*/
|
||||
public function test_useragent_ios($useragent, $tests) {
|
||||
// Setup the core_useragent instance.
|
||||
core_useragent::instance(true, $useragent);
|
||||
|
||||
if (isset($tests['is_ios']) && $tests['is_ios']) {
|
||||
$this->assertTrue(core_useragent::is_ios(),
|
||||
"Browser was not identified as an iOS device browser");
|
||||
$this->assertTrue(core_useragent::check_safari_ios_version());
|
||||
} else {
|
||||
$this->assertFalse(core_useragent::is_ios(),
|
||||
"Browser was incorrectly identified as an iOS device browser");
|
||||
$this->assertFalse(core_useragent::check_safari_ios_version());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider user_agents_providers
|
||||
*/
|
||||
|
104
login/token.php
104
login/token.php
@ -26,6 +26,7 @@ define('REQUIRE_CORRECT_ACCESS', true);
|
||||
define('NO_MOODLE_COOKIES', true);
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_once($CFG->libdir . '/externallib.php');
|
||||
|
||||
// Allow CORS requests.
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
@ -89,107 +90,8 @@ if (!empty($user)) {
|
||||
throw new moodle_exception('servicenotavailable', 'webservice');
|
||||
}
|
||||
|
||||
//check if there is any required system capability
|
||||
if ($service->requiredcapability and !has_capability($service->requiredcapability, context_system::instance(), $user)) {
|
||||
throw new moodle_exception('missingrequiredcapability', 'webservice', '', $service->requiredcapability);
|
||||
}
|
||||
|
||||
//specific checks related to user restricted service
|
||||
if ($service->restrictedusers) {
|
||||
$authoriseduser = $DB->get_record('external_services_users',
|
||||
array('externalserviceid' => $service->id, 'userid' => $user->id));
|
||||
|
||||
if (empty($authoriseduser)) {
|
||||
throw new moodle_exception('usernotallowed', 'webservice', '', $serviceshortname);
|
||||
}
|
||||
|
||||
if (!empty($authoriseduser->validuntil) and $authoriseduser->validuntil < time()) {
|
||||
throw new moodle_exception('invalidtimedtoken', 'webservice');
|
||||
}
|
||||
|
||||
if (!empty($authoriseduser->iprestriction) and !address_in_subnet(getremoteaddr(), $authoriseduser->iprestriction)) {
|
||||
throw new moodle_exception('invalidiptoken', 'webservice');
|
||||
}
|
||||
}
|
||||
|
||||
//Check if a token has already been created for this user and this service
|
||||
//Note: this could be an admin created or an user created token.
|
||||
// It does not really matter we take the first one that is valid.
|
||||
$tokenssql = "SELECT t.id, t.sid, t.token, t.validuntil, t.iprestriction
|
||||
FROM {external_tokens} t
|
||||
WHERE t.userid = ? AND t.externalserviceid = ? AND t.tokentype = ?
|
||||
ORDER BY t.timecreated ASC";
|
||||
$tokens = $DB->get_records_sql($tokenssql, array($user->id, $service->id, EXTERNAL_TOKEN_PERMANENT));
|
||||
|
||||
//A bit of sanity checks
|
||||
foreach ($tokens as $key=>$token) {
|
||||
|
||||
/// Checks related to a specific token. (script execution continue)
|
||||
$unsettoken = false;
|
||||
//if sid is set then there must be a valid associated session no matter the token type
|
||||
if (!empty($token->sid)) {
|
||||
if (!\core\session\manager::session_exists($token->sid)){
|
||||
//this token will never be valid anymore, delete it
|
||||
$DB->delete_records('external_tokens', array('sid'=>$token->sid));
|
||||
$unsettoken = true;
|
||||
}
|
||||
}
|
||||
|
||||
//remove token if no valid anymore
|
||||
//Also delete this wrong token (similar logic to the web service servers
|
||||
// /webservice/lib.php/webservice_server::authenticate_by_token())
|
||||
if (!empty($token->validuntil) and $token->validuntil < time()) {
|
||||
$DB->delete_records('external_tokens', array('token'=>$token->token, 'tokentype'=> EXTERNAL_TOKEN_PERMANENT));
|
||||
$unsettoken = true;
|
||||
}
|
||||
|
||||
// remove token if its ip not in whitelist
|
||||
if (isset($token->iprestriction) and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
|
||||
$unsettoken = true;
|
||||
}
|
||||
|
||||
if ($unsettoken) {
|
||||
unset($tokens[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// if some valid tokens exist then use the most recent
|
||||
if (count($tokens) > 0) {
|
||||
$token = array_pop($tokens);
|
||||
} else {
|
||||
if ( ($serviceshortname == MOODLE_OFFICIAL_MOBILE_SERVICE and has_capability('moodle/webservice:createmobiletoken', context_system::instance()))
|
||||
//Note: automatically token generation is not available to admin (they must create a token manually)
|
||||
or (!is_siteadmin($user) && has_capability('moodle/webservice:createtoken', context_system::instance()))) {
|
||||
// if service doesn't exist, dml will throw exception
|
||||
$service_record = $DB->get_record('external_services', array('shortname'=>$serviceshortname, 'enabled'=>1), '*', MUST_EXIST);
|
||||
|
||||
// Create a new token.
|
||||
$token = new stdClass;
|
||||
$token->token = md5(uniqid(rand(), 1));
|
||||
$token->userid = $user->id;
|
||||
$token->tokentype = EXTERNAL_TOKEN_PERMANENT;
|
||||
$token->contextid = context_system::instance()->id;
|
||||
$token->creatorid = $user->id;
|
||||
$token->timecreated = time();
|
||||
$token->externalserviceid = $service_record->id;
|
||||
// MDL-43119 Token valid for 3 months (12 weeks).
|
||||
$token->validuntil = $token->timecreated + 12 * WEEKSECS;
|
||||
$token->id = $DB->insert_record('external_tokens', $token);
|
||||
|
||||
$params = array(
|
||||
'objectid' => $token->id,
|
||||
'relateduserid' => $user->id,
|
||||
'other' => array(
|
||||
'auto' => true
|
||||
)
|
||||
);
|
||||
$event = \core\event\webservice_token_created::create($params);
|
||||
$event->add_record_snapshot('external_tokens', $token);
|
||||
$event->trigger();
|
||||
} else {
|
||||
throw new moodle_exception('cannotcreatetoken', 'webservice', '', $serviceshortname);
|
||||
}
|
||||
}
|
||||
// Get an existing token or create a new one.
|
||||
$token = external_generate_token_for_current_user($service);
|
||||
|
||||
// log token access
|
||||
$DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2016100300.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2016100400.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user