MDL-68294 tool_mobile: WebService for validating subscription key
This commit is contained in:
@@ -688,6 +688,10 @@ class api {
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
$credentials[] = ['type' => 'siteid', 'value' => $CFG->siteidentifier];
|
||||
}
|
||||
// Generate a hash key for validating that the request is coming from this site via WS.
|
||||
$sitesubscriptionkey = json_encode(['validuntil' => time() + 10 * MINSECS, 'key' => complex_random_string(32)]);
|
||||
set_config('sitesubscriptionkey', $sitesubscriptionkey, 'tool_mobile');
|
||||
$credentials[] = ['type' => 'sitesubscriptionkey', 'value' => $sitesubscriptionkey];
|
||||
|
||||
// Parameters for the WebService returning site information.
|
||||
$fnparams = (object) [
|
||||
|
||||
@@ -692,4 +692,63 @@ class external extends external_api {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of validate_subscription_key() parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.9
|
||||
*/
|
||||
public static function validate_subscription_key_parameters() {
|
||||
return new external_function_parameters(
|
||||
[
|
||||
'key' => new external_value(PARAM_RAW, 'Site subscription temporary key.'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given site subscription key is valid
|
||||
*
|
||||
* @param string $key subscriptiion temporary key
|
||||
* @return array with the settings and warnings
|
||||
* @since Moodle 3.9
|
||||
*/
|
||||
public static function validate_subscription_key(string $key): array {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
$params = self::validate_parameters(self::validate_subscription_key_parameters(), ['key' => $key]);
|
||||
|
||||
$context = context_system::instance();
|
||||
$PAGE->set_context($context);
|
||||
|
||||
$validated = false;
|
||||
$sitesubscriptionkey = get_config('tool_mobile', 'sitesubscriptionkey');
|
||||
if (!empty($sitesubscriptionkey) && $CFG->enablemobilewebservice && empty($CFG->disablemobileappsubscription)) {
|
||||
$sitesubscriptionkey = json_decode($sitesubscriptionkey);
|
||||
$validated = time() < $sitesubscriptionkey->validuntil && $params['key'] === $sitesubscriptionkey->key;
|
||||
// Delete existing, even if not validated to enforce security and attacks prevention.
|
||||
unset_config('sitesubscriptionkey', 'tool_mobile');
|
||||
}
|
||||
|
||||
return [
|
||||
'validated' => $validated,
|
||||
'warnings' => [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of validate_subscription_key() result value.
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.9
|
||||
*/
|
||||
public static function validate_subscription_key_returns() {
|
||||
return new external_single_structure(
|
||||
[
|
||||
'validated' => new external_value(PARAM_BOOL, 'Whether the key is validated or not.'),
|
||||
'warnings' => new external_warnings(),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,16 @@ $functions = array(
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
|
||||
'tool_mobile_validate_subscription_key' => array(
|
||||
'classname' => 'tool_mobile\external',
|
||||
'methodname' => 'validate_subscription_key',
|
||||
'description' => 'Check if the given site subscription key is valid.',
|
||||
'type' => 'write',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
'ajax' => true,
|
||||
'loginrequired' => false,
|
||||
),
|
||||
|
||||
'tool_mobile_get_tokens_for_qr_login' => array(
|
||||
'classname' => 'tool_mobile\external',
|
||||
'methodname' => 'get_tokens_for_qr_login',
|
||||
|
||||
@@ -725,4 +725,67 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
|
||||
$this->expectExceptionMessage(get_string('apprequired', 'tool_mobile'));
|
||||
$result = external::get_tokens_for_qr_login('', $USER->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test validate subscription key.
|
||||
*/
|
||||
public function test_validate_subscription_key_valid() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$sitesubscriptionkey = ['validuntil' => time() + MINSECS, 'key' => complex_random_string(32)];
|
||||
set_config('sitesubscriptionkey', json_encode($sitesubscriptionkey), 'tool_mobile');
|
||||
|
||||
$result = external::validate_subscription_key($sitesubscriptionkey['key']);
|
||||
$result = external_api::clean_returnvalue(external::validate_subscription_key_returns(), $result);
|
||||
$this->assertEmpty($result['warnings']);
|
||||
$this->assertTrue($result['validated']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test validate subscription key invalid first and then a valid one.
|
||||
*/
|
||||
public function test_validate_subscription_key_invalid_key_first() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$sitesubscriptionkey = ['validuntil' => time() + MINSECS, 'key' => complex_random_string(32)];
|
||||
set_config('sitesubscriptionkey', json_encode($sitesubscriptionkey), 'tool_mobile');
|
||||
|
||||
$result = external::validate_subscription_key('fakekey');
|
||||
$result = external_api::clean_returnvalue(external::validate_subscription_key_returns(), $result);
|
||||
$this->assertEmpty($result['warnings']);
|
||||
$this->assertFalse($result['validated']);
|
||||
|
||||
// The valid one has been invalidated because the previous attempt.
|
||||
$result = external::validate_subscription_key($sitesubscriptionkey['key']);
|
||||
$result = external_api::clean_returnvalue(external::validate_subscription_key_returns(), $result);
|
||||
$this->assertEmpty($result['warnings']);
|
||||
$this->assertFalse($result['validated']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test validate subscription key invalid.
|
||||
*/
|
||||
public function test_validate_subscription_key_invalid_key() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$result = external::validate_subscription_key('fakekey');
|
||||
$result = external_api::clean_returnvalue(external::validate_subscription_key_returns(), $result);
|
||||
$this->assertEmpty($result['warnings']);
|
||||
$this->assertFalse($result['validated']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test validate subscription key invalid.
|
||||
*/
|
||||
public function test_validate_subscription_key_outdated() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$sitesubscriptionkey = ['validuntil' => time() - MINSECS, 'key' => complex_random_string(32)];
|
||||
set_config('sitesubscriptionkey', json_encode($sitesubscriptionkey), 'tool_mobile');
|
||||
|
||||
$result = external::validate_subscription_key($sitesubscriptionkey['key']);
|
||||
$result = external_api::clean_returnvalue(external::validate_subscription_key_returns(), $result);
|
||||
$this->assertEmpty($result['warnings']);
|
||||
$this->assertFalse($result['validated']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->version = 2019111801; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2019111802; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2019111200; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
|
||||
$plugin->dependencies = array(
|
||||
|
||||
Reference in New Issue
Block a user