/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { global $CFG, $DB; $params = $this->parse_template(); $role = optional_param('role', '', PARAM_TEXT); $limitnum = optional_param('limit', 0, PARAM_INT); $limitfrom = optional_param('from', 0, PARAM_INT); if ($limitnum <= 0) { $limitfrom = 0; } try { if (!$this->get_service()->check_tool_proxy($params['product_code'])) { throw new \Exception(null, 401); } if (!($course = $DB->get_record('course', array('id' => $params['context_id']), 'id', IGNORE_MISSING))) { throw new \Exception(null, 404); } if (!($context = \context_course::instance($course->id))) { throw new \Exception(null, 404); } if (!($tool = $DB->get_record('lti_types', array('id' => $params['tool_code']), 'toolproxyid,enabledcapability,parameter', IGNORE_MISSING))) { throw new \Exception(null, 404); } $toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $tool->toolproxyid), 'guid', IGNORE_MISSING); if (!$toolproxy || $toolproxy->guid !== $this->get_service()->get_tool_proxy()->guid) { throw new \Exception(null, 400); } $json = memberships::get_users_json($this, $context, $course->id, $tool, $role, $limitfrom, $limitnum, null, null); $response->set_content_type($this->formats[0]); $response->set_body($json); } catch (\Exception $e) { $response->set_code($e->getCode()); } }
/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { global $CFG, $DB; $params = $this->parse_template(); $linkid = $params['link_id']; $role = optional_param('role', '', PARAM_TEXT); $limitnum = optional_param('limit', 0, PARAM_INT); $limitfrom = optional_param('from', 0, PARAM_INT); if ($limitnum <= 0) { $limitfrom = 0; } try { if (empty($linkid)) { throw new \Exception(null, 404); } if (!($lti = $DB->get_record('lti', array('id' => $linkid), 'id,course,typeid,servicesalt', IGNORE_MISSING))) { throw new \Exception(null, 404); } $tool = $DB->get_record('lti_types', array('id' => $lti->typeid)); $toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $tool->toolproxyid)); if (!$this->check_tool_proxy($toolproxy->guid, $response->get_request_data())) { throw new \Exception(null, 401); } if (!($course = $DB->get_record('course', array('id' => $lti->course), 'id', IGNORE_MISSING))) { throw new \Exception(null, 404); } if (!($context = \context_course::instance($lti->course))) { throw new \Exception(null, 404); } $modinfo = get_fast_modinfo($course); $cm = get_coursemodule_from_instance('lti', $linkid, $lti->course, false, MUST_EXIST); $cm = $modinfo->get_cm($cm->id); $info = new info_module($cm); if ($info->is_available_for_all()) { $info = null; } $json = memberships::get_users_json($this, $context, $lti->course, $tool, $role, $limitfrom, $limitnum, $lti, $info); $response->set_content_type($this->formats[0]); $response->set_body($json); } catch (\Exception $e) { $response->set_code($e->getCode()); } }
/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { $params = $this->parse_template(); $contexttype = $params['context_type']; $contextid = $params['context_id']; $vendorcode = $params['vendor_code']; $productcode = $params['product_code']; $bubble = optional_param('bubble', '', PARAM_ALPHA); $ok = !empty($contexttype) && !empty($contextid) && !empty($vendorcode) && !empty($productcode) && $this->check_tool_proxy($productcode, $response->get_request_data()); if (!$ok) { $response->set_code(401); } $contenttype = $response->get_accept(); $simpleformat = !empty($contenttype) && $contenttype == $this->formats[1]; if ($ok) { $ok = (empty($bubble) || ($bubble == 'distinct' || $bubble == 'all')) && (!$simpleformat || empty($bubble) || $bubble != 'all') && (empty($bubble) || $response->get_request_method() == 'GET'); } if (!$ok) { $response->set_code(404); } else { $systemsetting = null; $contextsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id, $contextid); if (!empty($bubble)) { $systemsetting = new systemsettings($this->get_service()); $systemsetting->params['tool_proxy_id'] = $productcode; $systemsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id); if ($bubble == 'distinct') { toolsettings::distinct_settings($systemsettings, $contextsettings, null); } } else { $systemsettings = null; } if ($response->get_request_method() == 'GET') { $json = ''; if ($simpleformat) { $response->set_content_type($this->formats[1]); $json .= "{"; } else { $response->set_content_type($this->formats[0]); $json .= "{\n \"@context\":\"http://purl.imsglobal.org/ctx/lti/v2/ToolSettings\",\n \"@graph\":[\n"; } $settings = toolsettings::settings_to_json($systemsettings, $simpleformat, 'ToolProxy', $systemsetting); $json .= $settings; $isfirst = strlen($settings) <= 0; $settings = toolsettings::settings_to_json($contextsettings, $simpleformat, 'ToolProxyBinding', $this); if (strlen($settings) > 0 && !$isfirst) { $json .= ","; } $json .= $settings; if ($simpleformat) { $json .= "\n}"; } else { $json .= "\n ]\n}"; } $response->set_body($json); } else { // PUT. $settings = null; if ($response->get_content_type() == $this->formats[0]) { $json = json_decode($response->get_request_data()); $ok = !empty($json); if ($ok) { $ok = isset($json->{"@graph"}) && is_array($json->{"@graph"}) && count($json->{"@graph"}) == 1 && $json->{"@graph"}[0]->{"@type"} == 'ToolProxyBinding'; } if ($ok) { $settings = $json->{"@graph"}[0]->custom; } } else { // Simple JSON. $json = json_decode($response->get_request_data(), true); $ok = !empty($json); if ($ok) { $ok = is_array($json); } if ($ok) { $settings = $json; } } if ($ok) { lti_set_tool_settings($settings, $this->get_service()->get_tool_proxy()->id, $contextid); } else { $response->set_code(406); } } } }
/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { global $DB, $COURSE; $params = $this->parse_template(); $linkid = $params['link_id']; $bubble = optional_param('bubble', '', PARAM_ALPHA); $contenttype = $response->get_accept(); $simpleformat = !empty($contenttype) && $contenttype == $this->formats[1]; $ok = (empty($bubble) || ($bubble == 'distinct' || $bubble == 'all')) && (!$simpleformat || empty($bubble) || $bubble != 'all') && (empty($bubble) || $response->get_request_method() == 'GET'); if (!$ok) { $response->set_code(406); } $systemsetting = null; $contextsetting = null; if ($ok) { $ok = !empty($linkid); if ($ok) { $lti = $DB->get_record('lti', array('id' => $linkid), 'course,typeid', MUST_EXIST); $ltitype = $DB->get_record('lti_types', array('id' => $lti->typeid)); $toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $ltitype->toolproxyid)); $ok = $this->check_tool_proxy($toolproxy->guid, $response->get_request_data()); } if (!$ok) { $response->set_code(401); } } if ($ok) { $linksettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id, $lti->course, $linkid); if (!empty($bubble)) { $contextsetting = new contextsettings($this->get_service()); if ($COURSE == 'site') { $contextsetting->params['context_type'] = 'Group'; } else { $contextsetting->params['context_type'] = 'CourseSection'; } $contextsetting->params['context_id'] = $lti->course; $contextsetting->params['vendor_code'] = $this->get_service()->get_tool_proxy()->vendorcode; $contextsetting->params['product_code'] = $this->get_service()->get_tool_proxy()->id; $contextsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id, $lti->course); $systemsetting = new systemsettings($this->get_service()); $systemsetting->params['tool_proxy_id'] = $this->get_service()->get_tool_proxy()->id; $systemsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id); if ($bubble == 'distinct') { toolsettings::distinct_settings($systemsettings, $contextsettings, $linksettings); } } else { $contextsettings = null; $systemsettings = null; } if ($response->get_request_method() == 'GET') { $json = ''; if ($simpleformat) { $response->set_content_type($this->formats[1]); $json .= "{"; } else { $response->set_content_type($this->formats[0]); $json .= "{\n \"@context\":\"http://purl.imsglobal.org/ctx/lti/v2/ToolSettings\",\n \"@graph\":[\n"; } $settings = toolsettings::settings_to_json($systemsettings, $simpleformat, 'ToolProxy', $systemsetting); $json .= $settings; $isfirst = strlen($settings) <= 0; $settings = toolsettings::settings_to_json($contextsettings, $simpleformat, 'ToolProxyBinding', $contextsetting); if (strlen($settings) > 0) { if (!$isfirst) { $json .= ","; if (!$simpleformat) { $json .= "\n"; } } $isfirst = false; } $json .= $settings; $settings = toolsettings::settings_to_json($linksettings, $simpleformat, 'LtiLink', $this); if (strlen($settings) > 0 && !$isfirst) { $json .= ","; if (!$simpleformat) { $json .= "\n"; } } $json .= $settings; if ($simpleformat) { $json .= "\n}"; } else { $json .= "\n ]\n}"; } $response->set_body($json); } else { // PUT. $settings = null; if ($response->get_content_type() == $this->formats[0]) { $json = json_decode($response->get_request_data()); $ok = !empty($json); if ($ok) { $ok = isset($json->{"@graph"}) && is_array($json->{"@graph"}) && count($json->{"@graph"}) == 1 && $json->{"@graph"}[0]->{"@type"} == 'LtiLink'; } if ($ok) { $settings = $json->{"@graph"}[0]->custom; } } else { // Simple JSON. $json = json_decode($response->get_request_data(), true); $ok = !empty($json); if ($ok) { $ok = is_array($json); } if ($ok) { $settings = $json; } } if ($ok) { lti_set_tool_settings($settings, $this->get_service()->get_tool_proxy()->id, $lti->course, $linkid); } else { $response->set_code(406); } } } }
// // 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 a controller for receiving LTI service requests * * @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 */ define('NO_DEBUG_DISPLAY', true); define('NO_MOODLE_COOKIES', true); require_once dirname(__FILE__) . '/../../config.php'; require_once $CFG->dirroot . '/mod/lti/locallib.php'; $response = new \mod_lti\local\ltiservice\response(); $isget = $response->get_request_method() == 'GET'; if ($isget) { $response->set_accept(isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : ''); } else { $response->set_content_type(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : ''); } $ok = false; $path = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; $accept = $response->get_accept(); $services = lti_get_services(); foreach ($services as $service) { $resources = $service->get_resources(); foreach ($resources as $resource) { if ($isget && !empty($accept) && strpos($accept, '*/*') === false && !in_array($accept, $resource->get_formats()) || !$isget && !in_array($response->get_content_type(), $resource->get_formats())) { continue;
/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { $ok = $this->check_tool_proxy(null, $response->get_request_data()); if ($ok) { $toolproxy = $this->get_service()->get_tool_proxy(); } else { $toolproxy = null; $response->set_code(401); } $tools = array(); // Ensure all required elements are present in the Tool Proxy. if ($ok) { $toolproxyjson = json_decode($response->get_request_data()); $ok = !empty($toolproxyjson); if (!$ok) { debugging('Tool proxy is not properly formed JSON'); } else { $ok = isset($toolproxyjson->tool_profile->product_instance->product_info->product_family->vendor->code); $ok = $ok && isset($toolproxyjson->security_contract->shared_secret); $ok = $ok && isset($toolproxyjson->tool_profile->resource_handler); if (!$ok) { debugging('One or more missing elements from tool proxy: vendor code, shared secret or resource handlers'); } } } // Check all capabilities requested were offered. if ($ok) { $offeredcapabilities = explode("\n", $toolproxy->capabilityoffered); $resources = $toolproxyjson->tool_profile->resource_handler; $errors = array(); foreach ($resources as $resource) { if (isset($resource->message)) { foreach ($resource->message as $message) { if (!in_array($message->message_type, $offeredcapabilities)) { $errors[] = $message->message_type; } else { if (isset($resource->parameter)) { foreach ($message->parameter as $parameter) { if (isset($parameter->variable) && !in_array($parameter->variable, $offeredcapabilities)) { $errors[] = $parameter->variable; } } } } } } } if (count($errors) > 0) { $ok = false; debugging('Tool proxy contains capabilities which were not offered: ' . implode(', ', $errors)); } } // Check all services requested were offered (only tool services currently supported). if ($ok && isset($toolproxyjson->security_contract->tool_service)) { $contexts = lti_get_contexts($toolproxyjson); $profileservice = lti_get_service_by_name('profile'); $profileservice->set_tool_proxy($toolproxy); $context = $profileservice->get_service_path() . $profileservice->get_resources()[0]->get_path() . '#'; $offeredservices = explode("\n", $toolproxy->serviceoffered); $services = lti_get_services(); $tpservices = $toolproxyjson->security_contract->tool_service; $errors = array(); foreach ($tpservices as $service) { $fqid = lti_get_fqid($contexts, $service->service); if (substr($fqid, 0, strlen($context)) !== $context) { $errors[] = $service->service; } else { $id = explode('#', $fqid, 2); $aservice = lti_get_service_by_resource_id($services, $id[1]); $classname = explode('\\', get_class($aservice)); if (empty($aservice) || !in_array($classname[count($classname) - 1], $offeredservices)) { $errors[] = $service->service; } } } if (count($errors) > 0) { $ok = false; debugging('Tool proxy contains services which were not offered: ' . implode(', ', $errors)); } } // Extract all launchable tools from the resource handlers. if ($ok) { $resources = $toolproxyjson->tool_profile->resource_handler; foreach ($resources as $resource) { $found = false; $tool = new \stdClass(); foreach ($resource->message as $message) { if ($message->message_type == 'basic-lti-launch-request') { $found = true; $tool->path = $message->path; $tool->enabled_capability = $message->enabled_capability; $tool->parameter = $message->parameter; break; } } if (!$found) { continue; } $tool->name = $resource->resource_name->default_value; $tools[] = $tool; } $ok = count($tools) > 0; if (!$ok) { debugging('No launchable messages found in tool proxy'); } } // Add tools and custom parameters. if ($ok) { $baseurl = ''; if (isset($toolproxyjson->tool_profile->base_url_choice[0]->default_base_url)) { $baseurl = $toolproxyjson->tool_profile->base_url_choice[0]->default_base_url; } $securebaseurl = ''; if (isset($toolproxyjson->tool_profile->base_url_choice[0]->secure_base_url)) { $securebaseurl = $toolproxyjson->tool_profile->base_url_choice[0]->secure_base_url; } foreach ($tools as $tool) { $config = new \stdClass(); $config->lti_toolurl = "{$baseurl}{$tool->path}"; $config->lti_typename = $tool->name; $config->lti_coursevisible = 1; $config->lti_forcessl = 0; $type = new \stdClass(); $type->state = LTI_TOOL_STATE_PENDING; $type->toolproxyid = $toolproxy->id; $type->enabledcapability = implode("\n", $tool->enabled_capability); $type->parameter = self::lti_extract_parameters($tool->parameter); if (isset($resource->icon_info[0]->default_location->path)) { $iconpath = $resource->icon_info[0]->default_location->path; $type->icon = "{$baseurl}{$iconpath}"; if (!empty($securebaseurl)) { $type->secureicon = "{$securebaseurl}{$iconpath}"; } } $ok = $ok && lti_add_type($type, $config) !== false; } if (isset($toolproxyjson->custom)) { lti_set_tool_settings($toolproxyjson->custom, $toolproxy->id); } } if (!empty($toolproxy)) { if ($ok) { // If all went OK accept the tool proxy. $toolproxy->state = LTI_TOOL_PROXY_STATE_ACCEPTED; $toolproxy->toolproxy = $response->get_request_data(); $toolproxy->secret = $toolproxyjson->security_contract->shared_secret; $toolproxy->vendorcode = $toolproxyjson->tool_profile->product_instance->product_info->product_family->vendor->code; $url = $this->get_endpoint(); $body = <<<EOD { "@context" : "http://purl.imsglobal.org/ctx/lti/v2/ToolProxyId", "@type" : "ToolProxy", "@id" : "{$url}", "tool_proxy_guid" : "{$toolproxy->guid}" } EOD; $response->set_code(201); $response->set_content_type('application/vnd.ims.lti.v2.toolproxy.id+json'); $response->set_body($body); } else { // Otherwise reject the tool proxy. $toolproxy->state = LTI_TOOL_PROXY_STATE_REJECTED; $response->set_code(400); } lti_update_tool_proxy($toolproxy); } else { $response->set_code(400); } }
/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { global $CFG; $version = service_base::LTI_VERSION2P0; $params = $this->parse_template(); $ok = $this->get_service()->check_tool_proxy($params['tool_proxy_id']); if (!$ok) { $response->set_code(404); } else { if (optional_param('lti_version', '', PARAM_ALPHANUMEXT) != $version) { $response->set_code(400); } else { $toolproxy = $this->get_service()->get_tool_proxy(); $response->set_content_type($this->formats[0]); $servicepath = $this->get_service()->get_service_path(); $id = $servicepath . $this->get_path(); $now = date('Y-m-d\\TH:iO'); $capabilityofferedarr = explode("\n", $toolproxy->capabilityoffered); $serviceofferedarr = explode("\n", $toolproxy->serviceoffered); $serviceoffered = ''; $sep = ''; $services = \core_component::get_plugin_list('ltiservice'); foreach ($services as $name => $location) { if (in_array($name, $serviceofferedarr)) { $classname = "\\ltiservice_{$name}\\local\\service\\{$name}"; $service = new $classname(); $service->set_tool_proxy($toolproxy); $resources = $service->get_resources(); foreach ($resources as $resource) { $formats = implode("\", \"", $resource->get_formats()); $methods = implode("\", \"", $resource->get_methods()); $capabilityofferedarr = array_merge($capabilityofferedarr, $resource->get_variables()); $path = $servicepath . preg_replace('/\\{?.*\\}$/', '', $resource->get_path()); $serviceoffered .= <<<EOD {$sep} { "@type":"{$resource->get_type()}", "@id":"tcp:{$resource->get_id()}", "endpoint":"{$path}", "format":["{$formats}"], "action":["{$methods}"] } EOD; $sep = ','; } } } $capabilityoffered = implode("\",\n \"", $capabilityofferedarr); if (strlen($capabilityoffered) > 0) { $capabilityoffered = "\n \"{$capabilityoffered}\""; } $urlparts = parse_url($CFG->wwwroot); $orgid = $urlparts['host']; $name = 'Moodle'; $code = 'moodle'; $vendorname = 'Moodle.org'; $vendorcode = 'mdl'; $prodversion = strval($CFG->version); if (!empty($CFG->mod_lti_institution_name)) { $consumername = $CFG->mod_lti_institution_name; $consumerdesc = ''; } else { $consumername = get_site()->fullname; $consumerdesc = strip_tags(get_site()->summary); } $profile = <<<EOD { "@context":[ "http://purl.imsglobal.org/ctx/lti/v2/ToolConsumerProfile", { "tcp":"{$id}#" } ], "@type":"ToolConsumerProfile", "@id":"{$id}", "lti_version":"{$version}", "guid":"{$toolproxy->guid}", "product_instance":{ "guid":"{$orgid}", "product_info":{ "product_name":{ "default_value":"{$name}", "key":"product.name" }, "product_version":"{$prodversion}", "product_family":{ "code":"{$code}", "vendor":{ "code":"{$vendorcode}", "vendor_name":{ "default_value":"{$vendorname}", "key":"product.vendor.name" }, "timestamp":"{$now}" } } }, "service_owner":{ "@id":"ServiceOwner", "service_owner_name":{ "default_value":"{$consumername}", "key":"service_owner.name" }, "description":{ "default_value":"{$consumerdesc}", "key":"service_owner.description" } } }, "capability_offered":[{$capabilityoffered} ], "service_offered":[{$serviceoffered} ] } EOD; $response->set_body($profile); } } }