AutorÃa | Ultima modificación | Ver Log |
<?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/>./*** This file contains an abstract definition of an LTI service** @package mod_lti* @copyright 2014 Vital Source Technologies http://vitalsource.com* @author Stephen Vickers* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/namespace mod_lti\local\ltiservice;defined('MOODLE_INTERNAL') || die();global $CFG;require_once($CFG->dirroot . '/mod/lti/locallib.php');require_once($CFG->dirroot . '/mod/lti/OAuthBody.php');// TODO: Switch to core oauthlib once implemented - MDL-30149.use moodle\mod\lti as lti;use stdClass;/*** The mod_lti\local\ltiservice\service_base class.** @package mod_lti* @since Moodle 2.8* @copyright 2014 Vital Source Technologies http://vitalsource.com* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/abstract class service_base {/** Label representing an LTI 2 message type */const LTI_VERSION2P0 = 'LTI-2p0';/** Service enabled */const SERVICE_ENABLED = 1;/** @var string ID for the service. */protected $id;/** @var string Human readable name for the service. */protected $name;/** @var boolean <code>true</code> if requests for this service do not need to be signed. */protected $unsigned;/** @var stdClass Tool proxy object for the current service request. */private $toolproxy;/** @var stdClass LTI type object for the current service request. */private $type;/** @var array LTI type config array for the current service request. */private $typeconfig;/** @var array Instances of the resources associated with this service. */protected $resources;/*** Class constructor.*/public function __construct() {$this->id = null;$this->name = null;$this->unsigned = false;$this->toolproxy = null;$this->type = null;$this->typeconfig = null;$this->resources = null;}/*** Get the service ID.** @return string*/public function get_id() {return $this->id;}/*** Get the service compoent ID.** @return string*/public function get_component_id() {return 'ltiservice_' . $this->id;}/*** Get the service name.** @return string*/public function get_name() {return $this->name;}/*** Get whether the service requests need to be signed.** @return boolean*/public function is_unsigned() {return $this->unsigned;}/*** Get the tool proxy object.** @return stdClass*/public function get_tool_proxy() {return $this->toolproxy;}/*** Set the tool proxy object.** @param object $toolproxy The tool proxy for this service request** @var stdClass*/public function set_tool_proxy($toolproxy) {$this->toolproxy = $toolproxy;}/*** Get the type object.** @return stdClass*/public function get_type() {return $this->type;}/*** Set the LTI type object.** @param object $type The LTI type for this service request** @var stdClass*/public function set_type($type) {$this->type = $type;}/*** Get the type config array.** @return array|null*/public function get_typeconfig() {return $this->typeconfig;}/*** Set the LTI type config object.** @param array $typeconfig The LTI type config for this service request** @var array*/public function set_typeconfig($typeconfig) {$this->typeconfig = $typeconfig;}/*** Get the resources for this service.** @return resource_base[]*/abstract public function get_resources();/*** Get the scope(s) permitted for this service in the context of a particular tool type.** A null value indicates that no scopes are required to access the service.** @return array|null*/public function get_permitted_scopes() {return null;}/*** Get the scope(s) permitted for this service.** A null value indicates that no scopes are required to access the service.** @return array|null*/public function get_scopes() {return null;}/*** Returns the configuration options for this service.** @param \MoodleQuickForm $mform Moodle quickform object definition*/public function get_configuration_options(&$mform) {}/*** Called when a new LTI Instance is added.** @param object $lti LTI Instance.*/public function instance_added(object $lti): void {}/*** Called when a new LTI Instance is updated.** @param object $lti LTI Instance.*/public function instance_updated(object $lti): void {}/*** Called when the launch data is created, offering a possibility to alter the* target link URI.** @param string $messagetype message type for this launch* @param string $targetlinkuri current target link uri* @param null|string $customstr concatenated list of custom parameters* @param int $courseid* @param null|object $lti LTI Instance.** @return array containing the target link URL and the custom params string to use.*/public function override_endpoint(string $messagetype, string $targetlinkuri,?string $customstr, int $courseid, ?object $lti = null): array {return [$targetlinkuri, $customstr];}/*** Called when a new LTI Instance is deleted.** @param int $id LTI Instance.*/public function instance_deleted(int $id): void {}/*** Set the form data when displaying the LTI Instance form.** @param object $defaultvalues Default form values.*/public function set_instance_form_values(object $defaultvalues): void {}/*** Return an array with the names of the parameters that the service will be saving in the configuration** @return array Names list of the parameters that the service will be saving in the configuration* @deprecated since Moodle 3.7 - please do not use this function any more.*/public function get_configuration_parameter_names() {debugging('get_configuration_parameter_names() has been deprecated.', DEBUG_DEVELOPER);return array();}/*** Default implementation will check for the existence of at least one mod_lti entry for that tool and context.** It may be overridden if other inferences can be done.** Ideally a Site Tool should be explicitly engaged with a course, the check on the presence of a link is a proxy* to infer a Site Tool engagement until an explicit Site Tool - Course relationship exists.** @param int $typeid The tool lti type id.* @param int $courseid The course id.* @return bool returns True if tool is used in context, false otherwise.*/public function is_used_in_context($typeid, $courseid) {global $DB;$ok = $DB->record_exists('lti', array('course' => $courseid, 'typeid' => $typeid));return $ok || $DB->record_exists('lti_types', array('course' => $courseid, 'id' => $typeid));}/*** Checks if there is a site tool or a course tool for this site.** @param int $typeid The tool lti type id.* @param int $courseid The course id.* @return bool returns True if tool is allowed in context, false otherwise.*/public function is_allowed_in_context($typeid, $courseid) {global $DB;// Check if it is a Course tool for this course or a Site tool.$type = $DB->get_record('lti_types', array('id' => $typeid));return $type && ($type->course == $courseid || $type->course == SITEID);}/*** Return an array of key/values to add to the launch parameters.** @param string $messagetype 'basic-lti-launch-request' or 'ContentItemSelectionRequest'.* @param string $courseid The course id.* @param string $userid The user id.* @param string $typeid The tool lti type id.* @param string $modlti The id of the lti activity.** The type is passed to check the configuration and not return parameters for services not used.** @return array Key/value pairs to add as launch parameters.*/public function get_launch_parameters($messagetype, $courseid, $userid, $typeid, $modlti = null) {return array();}/*** Return an array of key/claim mapping allowing LTI 1.1 custom parameters* to be transformed to LTI 1.3 claims.** @return array Key/value pairs of params to claim mapping.*/public function get_jwt_claim_mappings(): array {return [];}/*** Get the path for service requests.** @return string*/public static function get_service_path() {$url = new \moodle_url('/mod/lti/services.php');return $url->out(false);}/*** Parse a string for custom substitution parameter variables supported by this service's resources.** @param string $value Value to be parsed** @return string*/public function parse_value($value) {if (empty($this->resources)) {$this->resources = $this->get_resources();}if (!empty($this->resources)) {foreach ($this->resources as $resource) {$value = $resource->parse_value($value);}}return $value;}/*** Check that the request has been properly signed and is permitted.** @param string $typeid LTI type ID* @param string $body Request body (null if none)* @param string[] $scopes Array of required scope(s) for incoming request** @return boolean*/public function check_tool($typeid, $body = null, $scopes = null) {$ok = true;$toolproxy = null;$consumerkey = lti\get_oauth_key_from_headers($typeid, $scopes);if ($consumerkey === false) {$ok = $this->is_unsigned();} else {if (empty($typeid) && is_int($consumerkey)) {$typeid = $consumerkey;}if (!empty($typeid)) {$this->type = lti_get_type($typeid);$this->typeconfig = lti_get_type_config($typeid);$ok = !empty($this->type->id);if ($ok && !empty($this->type->toolproxyid)) {$this->toolproxy = lti_get_tool_proxy($this->type->toolproxyid);}} else {$toolproxy = lti_get_tool_proxy_from_guid($consumerkey);if ($toolproxy !== false) {$this->toolproxy = $toolproxy;}}}if ($ok && is_string($consumerkey)) {if (!empty($this->toolproxy)) {$key = $this->toolproxy->guid;$secret = $this->toolproxy->secret;} else {$key = $this->typeconfig['resourcekey'];$secret = $this->typeconfig['password'];}if (!$this->is_unsigned() && ($key == $consumerkey)) {$ok = $this->check_signature($key, $secret, $body);} else {$ok = $this->is_unsigned();}}return $ok;}/*** Check that the request has been properly signed.** @param string $toolproxyguid Tool Proxy GUID* @param string $body Request body (null if none)** @return boolean* @deprecated since Moodle 3.7 MDL-62599 - please do not use this function any more.* @see service_base::check_tool()*/public function check_tool_proxy($toolproxyguid, $body = null) {debugging('check_tool_proxy() is deprecated to allow LTI 1 connections to support services. ' .'Please use service_base::check_tool() instead.', DEBUG_DEVELOPER);$ok = false;$toolproxy = null;$consumerkey = lti\get_oauth_key_from_headers();if (empty($toolproxyguid)) {$toolproxyguid = $consumerkey;}if (!empty($toolproxyguid)) {$toolproxy = lti_get_tool_proxy_from_guid($toolproxyguid);if ($toolproxy !== false) {if (!$this->is_unsigned() && ($toolproxy->guid == $consumerkey)) {$ok = $this->check_signature($toolproxy->guid, $toolproxy->secret, $body);} else {$ok = $this->is_unsigned();}}}if ($ok) {$this->toolproxy = $toolproxy;}return $ok;}/*** Check that the request has been properly signed.** @param int $typeid The tool id* @param int $courseid The course we are at* @param string $body Request body (null if none)** @return bool* @deprecated since Moodle 3.7 MDL-62599 - please do not use this function any more.* @see service_base::check_tool()*/public function check_type($typeid, $courseid, $body = null) {debugging('check_type() is deprecated to allow LTI 1 connections to support services. ' .'Please use service_base::check_tool() instead.', DEBUG_DEVELOPER);$ok = false;$tool = null;$consumerkey = lti\get_oauth_key_from_headers();if (empty($typeid)) {return $ok;} else if ($this->is_allowed_in_context($typeid, $courseid)) {$tool = lti_get_type_type_config($typeid);if ($tool !== false) {if (!$this->is_unsigned() && ($tool->lti_resourcekey == $consumerkey)) {$ok = $this->check_signature($tool->lti_resourcekey, $tool->lti_password, $body);} else {$ok = $this->is_unsigned();}}}return $ok;}/*** Check the request signature.** @param string $consumerkey Consumer key* @param string $secret Shared secret* @param string $body Request body** @return boolean*/private function check_signature($consumerkey, $secret, $body) {$ok = true;try {// TODO: Switch to core oauthlib once implemented - MDL-30149.lti\handle_oauth_body_post($consumerkey, $secret, $body);} catch (\Exception $e) {debugging($e->getMessage() . "\n");$ok = false;}return $ok;}}