示例#1
1
 /**
  * Check the authenticity of the LTI launch request.
  *
  * The consumer, resource link and user objects will be initialised if the request is valid.
  *
  * @return boolean True if the request has been successfully validated.
  */
 private function authenticate()
 {
     // Get the consumer
     $doSaveConsumer = false;
     // Check all required launch parameters
     $this->ok = isset($_POST['lti_message_type']) && array_key_exists($_POST['lti_message_type'], self::$MESSAGE_TYPES);
     if (!$this->ok) {
         $this->reason = 'Invalid or missing lti_message_type parameter.';
     }
     if ($this->ok) {
         $this->ok = isset($_POST['lti_version']) && in_array($_POST['lti_version'], self::$LTI_VERSIONS);
         if (!$this->ok) {
             $this->reason = 'Invalid or missing lti_version parameter.';
         }
     }
     if ($this->ok) {
         if ($_POST['lti_message_type'] === 'basic-lti-launch-request') {
             $this->ok = isset($_POST['resource_link_id']) && strlen(trim($_POST['resource_link_id'])) > 0;
             if (!$this->ok) {
                 $this->reason = 'Missing resource link ID.';
             }
         } else {
             if ($_POST['lti_message_type'] === 'ContentItemSelectionRequest') {
                 if (isset($_POST['accept_media_types']) && strlen(trim($_POST['accept_media_types'])) > 0) {
                     $mediaTypes = array_filter(explode(',', str_replace(' ', '', $_POST['accept_media_types'])), 'strlen');
                     $mediaTypes = array_unique($mediaTypes);
                     $this->ok = count($mediaTypes) > 0;
                     if (!$this->ok) {
                         $this->reason = 'No accept_media_types found.';
                     } else {
                         $this->mediaTypes = $mediaTypes;
                     }
                 } else {
                     $this->ok = false;
                 }
                 if ($this->ok && isset($_POST['accept_presentation_document_targets']) && strlen(trim($_POST['accept_presentation_document_targets'])) > 0) {
                     $documentTargets = array_filter(explode(',', str_replace(' ', '', $_POST['accept_presentation_document_targets'])), 'strlen');
                     $documentTargets = array_unique($documentTargets);
                     $this->ok = count($documentTargets) > 0;
                     if (!$this->ok) {
                         $this->reason = 'Missing or empty accept_presentation_document_targets parameter.';
                     } else {
                         foreach ($documentTargets as $documentTarget) {
                             $this->ok = $this->checkValue($documentTarget, array('embed', 'frame', 'iframe', 'window', 'popup', 'overlay', 'none'), 'Invalid value in accept_presentation_document_targets parameter: %s.');
                             if (!$this->ok) {
                                 break;
                             }
                         }
                         if ($this->ok) {
                             $this->documentTargets = $documentTargets;
                         }
                     }
                 } else {
                     $this->ok = false;
                 }
                 if ($this->ok) {
                     $this->ok = isset($_POST['content_item_return_url']) && strlen(trim($_POST['content_item_return_url'])) > 0;
                     if (!$this->ok) {
                         $this->reason = 'Missing content_item_return_url parameter.';
                     }
                 }
             } else {
                 if ($_POST['lti_message_type'] == 'ToolProxyRegistrationRequest') {
                     $this->ok = isset($_POST['reg_key']) && strlen(trim($_POST['reg_key'])) > 0 && (isset($_POST['reg_password']) && strlen(trim($_POST['reg_password'])) > 0) && (isset($_POST['tc_profile_url']) && strlen(trim($_POST['tc_profile_url'])) > 0) && (isset($_POST['launch_presentation_return_url']) && strlen(trim($_POST['launch_presentation_return_url'])) > 0);
                     if ($this->debugMode && !$this->ok) {
                         $this->reason = 'Missing message parameters.';
                     }
                 }
             }
         }
     }
     $now = time();
     // Check consumer key
     if ($this->ok && $_POST['lti_message_type'] != 'ToolProxyRegistrationRequest') {
         $this->ok = isset($_POST['oauth_consumer_key']);
         if (!$this->ok) {
             $this->reason = 'Missing consumer key.';
         }
         if ($this->ok) {
             $this->consumer = new ToolConsumer($_POST['oauth_consumer_key'], $this->dataConnector);
             $this->ok = !is_null($this->consumer->created);
             if (!$this->ok) {
                 $this->reason = 'Invalid consumer key.';
             }
         }
         if ($this->ok) {
             $today = date('Y-m-d', $now);
             if (is_null($this->consumer->lastAccess)) {
                 $doSaveConsumer = true;
             } else {
                 $last = date('Y-m-d', $this->consumer->lastAccess);
                 $doSaveConsumer = $doSaveConsumer || $last !== $today;
             }
             $this->consumer->last_access = $now;
             try {
                 $store = new OAuthDataStore($this);
                 $server = new OAuth\OAuthServer($store);
                 $method = new OAuth\OAuthSignatureMethod_HMAC_SHA1();
                 $server->add_signature_method($method);
                 $request = OAuth\OAuthRequest::from_request();
                 $res = $server->verify_request($request);
             } catch (\Exception $e) {
                 $this->ok = false;
                 if (empty($this->reason)) {
                     if ($this->debugMode) {
                         $consumer = new OAuth\OAuthConsumer($this->consumer->getKey(), $this->consumer->secret);
                         $signature = $request->build_signature($method, $consumer, false);
                         $this->reason = $e->getMessage();
                         if (empty($this->reason)) {
                             $this->reason = 'OAuth exception';
                         }
                         $this->details[] = 'Timestamp: ' . time();
                         $this->details[] = "Signature: {$signature}";
                         $this->details[] = "Base string: {$request->base_string}]";
                     } else {
                         $this->reason = 'OAuth signature check failed - perhaps an incorrect secret or timestamp.';
                     }
                 }
             }
         }
         if ($this->ok) {
             $today = date('Y-m-d', $now);
             if (is_null($this->consumer->lastAccess)) {
                 $doSaveConsumer = true;
             } else {
                 $last = date('Y-m-d', $this->consumer->lastAccess);
                 $doSaveConsumer = $doSaveConsumer || $last !== $today;
             }
             $this->consumer->last_access = $now;
             if ($this->consumer->protected) {
                 if (!is_null($this->consumer->consumerGuid)) {
                     $this->ok = empty($_POST['tool_consumer_instance_guid']) || $this->consumer->consumerGuid === $_POST['tool_consumer_instance_guid'];
                     if (!$this->ok) {
                         $this->reason = 'Request is from an invalid tool consumer.';
                     }
                 } else {
                     $this->ok = isset($_POST['tool_consumer_instance_guid']);
                     if (!$this->ok) {
                         $this->reason = 'A tool consumer GUID must be included in the launch request.';
                     }
                 }
             }
             if ($this->ok) {
                 $this->ok = $this->consumer->enabled;
                 if (!$this->ok) {
                     $this->reason = 'Tool consumer has not been enabled by the tool provider.';
                 }
             }
             if ($this->ok) {
                 $this->ok = is_null($this->consumer->enableFrom) || $this->consumer->enableFrom <= $now;
                 if ($this->ok) {
                     $this->ok = is_null($this->consumer->enableUntil) || $this->consumer->enableUntil > $now;
                     if (!$this->ok) {
                         $this->reason = 'Tool consumer access has expired.';
                     }
                 } else {
                     $this->reason = 'Tool consumer access is not yet available.';
                 }
             }
         }
         // Validate other message parameter values
         if ($this->ok) {
             if ($_POST['lti_message_type'] === 'ContentItemSelectionRequest') {
                 if (isset($_POST['accept_unsigned'])) {
                     $this->ok = $this->checkValue($_POST['accept_unsigned'], array('true', 'false'), 'Invalid value for accept_unsigned parameter: %s.');
                 }
                 if ($this->ok && isset($_POST['accept_multiple'])) {
                     $this->ok = $this->checkValue($_POST['accept_multiple'], array('true', 'false'), 'Invalid value for accept_multiple parameter: %s.');
                 }
                 if ($this->ok && isset($_POST['accept_copy_advice'])) {
                     $this->ok = $this->checkValue($_POST['accept_copy_advice'], array('true', 'false'), 'Invalid value for accept_copy_advice parameter: %s.');
                 }
                 if ($this->ok && isset($_POST['auto_create'])) {
                     $this->ok = $this->checkValue($_POST['auto_create'], array('true', 'false'), 'Invalid value for auto_create parameter: %s.');
                 }
                 if ($this->ok && isset($_POST['can_confirm'])) {
                     $this->ok = $this->checkValue($_POST['can_confirm'], array('true', 'false'), 'Invalid value for can_confirm parameter: %s.');
                 }
             } else {
                 if (isset($_POST['launch_presentation_document_target'])) {
                     $this->ok = $this->checkValue($_POST['launch_presentation_document_target'], array('embed', 'frame', 'iframe', 'window', 'popup', 'overlay'), 'Invalid value for launch_presentation_document_target parameter: %s.');
                 }
             }
         }
     }
     if ($this->ok && $_POST['lti_message_type'] === 'ToolProxyRegistrationRequest') {
         $this->ok = $_POST['lti_version'] == self::LTI_VERSION2;
         if (!$this->ok) {
             $this->reason = 'Invalid lti_version parameter';
         }
         if ($this->ok) {
             $http = new HTTPMessage($_POST['tc_profile_url'], 'GET', null, 'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
             $this->ok = $http->send();
             if (!$this->ok) {
                 $this->reason = 'Tool consumer profile not accessible.';
             } else {
                 $tcProfile = json_decode($http->response);
                 $this->ok = !is_null($tcProfile);
                 if (!$this->ok) {
                     $this->reason = 'Invalid JSON in tool consumer profile.';
                 }
             }
         }
         // Check for required capabilities
         if ($this->ok) {
             $this->consumer = new ToolConsumer($_POST['reg_key'], $this->dataConnector);
             $this->consumer->profile = $tcProfile;
             $capabilities = $this->consumer->profile->capability_offered;
             $missing = array();
             foreach ($this->resourceHandlers as $resourceHandler) {
                 foreach ($resourceHandler->requiredMessages as $message) {
                     if (!in_array($message->type, $capabilities)) {
                         $missing[$message->type] = true;
                     }
                 }
             }
             foreach ($this->constraints as $name => $constraint) {
                 if ($constraint['required']) {
                     if (!in_array($name, $capabilities) && !in_array($name, array_flip($capabilities))) {
                         $missing[$name] = true;
                     }
                 }
             }
             if (!empty($missing)) {
                 ksort($missing);
                 $this->reason = 'Required capability not offered - \'' . implode('\', \'', array_keys($missing)) . '\'';
                 $this->ok = false;
             }
         }
         // Check for required services
         if ($this->ok) {
             foreach ($this->requiredServices as $service) {
                 foreach ($service->formats as $format) {
                     if (!$this->findService($format, $service->actions)) {
                         if ($this->ok) {
                             $this->reason = 'Required service(s) not offered - ';
                             $this->ok = false;
                         } else {
                             $this->reason .= ', ';
                         }
                         $this->reason .= "'{$format}' [" . implode(', ', $service->actions) . ']';
                     }
                 }
             }
         }
         if ($this->ok) {
             if ($_POST['lti_message_type'] === 'ToolProxyRegistrationRequest') {
                 $this->consumer->profile = $tcProfile;
                 $this->consumer->secret = $_POST['reg_password'];
                 $this->consumer->ltiVersion = $_POST['lti_version'];
                 $this->consumer->name = $tcProfile->product_instance->service_owner->service_owner_name->default_value;
                 $this->consumer->consumerName = $this->consumer->name;
                 $this->consumer->consumerVersion = "{$tcProfile->product_instance->product_info->product_family->code}-{$tcProfile->product_instance->product_info->product_version}";
                 $this->consumer->consumerGuid = $tcProfile->product_instance->guid;
                 $this->consumer->enabled = true;
                 $this->consumer->protected = true;
                 $doSaveConsumer = true;
             }
         }
     } else {
         if ($this->ok && !empty($_POST['custom_tc_profile_url']) && empty($this->consumer->profile)) {
             $http = new HTTPMessage($_POST['custom_tc_profile_url'], 'GET', null, 'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
             if ($http->send()) {
                 $tcProfile = json_decode($http->response);
                 if (!is_null($tcProfile)) {
                     $this->consumer->profile = $tcProfile;
                     $doSaveConsumer = true;
                 }
             }
         }
     }
     // Validate message parameter constraints
     if ($this->ok) {
         $invalidParameters = array();
         foreach ($this->constraints as $name => $constraint) {
             if (empty($constraint['messages']) || in_array($_POST['lti_message_type'], $constraint['messages'])) {
                 $ok = true;
                 if ($constraint['required']) {
                     if (!isset($_POST[$name]) || strlen(trim($_POST[$name])) <= 0) {
                         $invalidParameters[] = "{$name} (missing)";
                         $ok = false;
                     }
                 }
                 if ($ok && !is_null($constraint['max_length']) && isset($_POST[$name])) {
                     if (strlen(trim($_POST[$name])) > $constraint['max_length']) {
                         $invalidParameters[] = "{$name} (too long)";
                     }
                 }
             }
         }
         if (count($invalidParameters) > 0) {
             $this->ok = false;
             if (empty($this->reason)) {
                 $this->reason = 'Invalid parameter(s): ' . implode(', ', $invalidParameters) . '.';
             }
         }
     }
     if ($this->ok) {
         // Set the request context
         if (isset($_POST['context_id'])) {
             $this->context = Context::fromConsumer($this->consumer, trim($_POST['context_id']));
             $title = '';
             if (isset($_POST['context_title'])) {
                 $title = trim($_POST['context_title']);
             }
             if (empty($title)) {
                 $title = "Course {$this->context->getId()}";
             }
             if (isset($_POST['context_type'])) {
                 $this->context->type = trim($_POST['context_type']);
             }
             $this->context->title = $title;
         }
         // Set the request resource link
         if (isset($_POST['resource_link_id'])) {
             $contentItemId = '';
             if (isset($_POST['custom_content_item_id'])) {
                 $contentItemId = $_POST['custom_content_item_id'];
             }
             $this->resourceLink = ResourceLink::fromConsumer($this->consumer, trim($_POST['resource_link_id']), $contentItemId);
             if (!empty($this->context)) {
                 $this->resourceLink->setContextId($this->context->getRecordId());
             }
             $title = '';
             if (isset($_POST['resource_link_title'])) {
                 $title = trim($_POST['resource_link_title']);
             }
             if (empty($title)) {
                 $title = "Resource {$this->resourceLink->getId()}";
             }
             $this->resourceLink->title = $title;
             // Delete any existing custom parameters
             foreach ($this->consumer->getSettings() as $name => $value) {
                 if (strpos($name, 'custom_') === 0) {
                     $this->consumer->setSetting($name);
                     $doSaveConsumer = true;
                 }
             }
             if (!empty($this->context)) {
                 foreach ($this->context->getSettings() as $name => $value) {
                     if (strpos($name, 'custom_') === 0) {
                         $this->context->setSetting($name);
                     }
                 }
             }
             foreach ($this->resourceLink->getSettings() as $name => $value) {
                 if (strpos($name, 'custom_') === 0) {
                     $this->resourceLink->setSetting($name);
                 }
             }
             // Save LTI parameters
             foreach (self::$LTI_CONSUMER_SETTING_NAMES as $name) {
                 if (isset($_POST[$name])) {
                     $this->consumer->setSetting($name, $_POST[$name]);
                 } else {
                     $this->consumer->setSetting($name);
                 }
             }
             if (!empty($this->context)) {
                 foreach (self::$LTI_CONTEXT_SETTING_NAMES as $name) {
                     if (isset($_POST[$name])) {
                         $this->context->setSetting($name, $_POST[$name]);
                     } else {
                         $this->context->setSetting($name);
                     }
                 }
             }
             foreach (self::$LTI_RESOURCE_LINK_SETTING_NAMES as $name) {
                 if (isset($_POST[$name])) {
                     $this->resourceLink->setSetting($name, $_POST[$name]);
                 } else {
                     $this->resourceLink->setSetting($name);
                 }
             }
             // Save other custom parameters
             foreach ($_POST as $name => $value) {
                 if (strpos($name, 'custom_') === 0 && !in_array($name, array_merge(self::$LTI_CONSUMER_SETTING_NAMES, self::$LTI_CONTEXT_SETTING_NAMES, self::$LTI_RESOURCE_LINK_SETTING_NAMES))) {
                     $this->resourceLink->setSetting($name, $value);
                 }
             }
         }
         // Set the user instance
         $userId = '';
         if (isset($_POST['user_id'])) {
             $userId = trim($_POST['user_id']);
         }
         $this->user = User::fromResourceLink($this->resourceLink, $userId);
         // Set the user name
         $firstname = isset($_POST['lis_person_name_given']) ? $_POST['lis_person_name_given'] : '';
         $lastname = isset($_POST['lis_person_name_family']) ? $_POST['lis_person_name_family'] : '';
         $fullname = isset($_POST['lis_person_name_full']) ? $_POST['lis_person_name_full'] : '';
         $this->user->setNames($firstname, $lastname, $fullname);
         // Set the user email
         $email = isset($_POST['lis_person_contact_email_primary']) ? $_POST['lis_person_contact_email_primary'] : '';
         $this->user->setEmail($email, $this->defaultEmail);
         // Set the user image URI
         if (isset($_POST['user_image'])) {
             $this->user->image = $_POST['user_image'];
         }
         // Set the user roles
         if (isset($_POST['roles'])) {
             $this->user->roles = self::parseRoles($_POST['roles']);
         }
         // Initialise the consumer and check for changes
         $this->consumer->defaultEmail = $this->defaultEmail;
         if ($this->consumer->ltiVersion !== $_POST['lti_version']) {
             $this->consumer->ltiVersion = $_POST['lti_version'];
             $doSaveConsumer = true;
         }
         if (isset($_POST['tool_consumer_instance_name'])) {
             if ($this->consumer->consumerName !== $_POST['tool_consumer_instance_name']) {
                 $this->consumer->consumerName = $_POST['tool_consumer_instance_name'];
                 $doSaveConsumer = true;
             }
         }
         if (isset($_POST['tool_consumer_info_product_family_code'])) {
             $version = $_POST['tool_consumer_info_product_family_code'];
             if (isset($_POST['tool_consumer_info_version'])) {
                 $version .= "-{$_POST['tool_consumer_info_version']}";
             }
             // do not delete any existing consumer version if none is passed
             if ($this->consumer->consumerVersion !== $version) {
                 $this->consumer->consumerVersion = $version;
                 $doSaveConsumer = true;
             }
         } else {
             if (isset($_POST['ext_lms']) && $this->consumer->consumerName !== $_POST['ext_lms']) {
                 $this->consumer->consumerVersion = $_POST['ext_lms'];
                 $doSaveConsumer = true;
             }
         }
         if (isset($_POST['tool_consumer_instance_guid'])) {
             if (is_null($this->consumer->consumerGuid)) {
                 $this->consumer->consumerGuid = $_POST['tool_consumer_instance_guid'];
                 $doSaveConsumer = true;
             } else {
                 if (!$this->consumer->protected) {
                     $doSaveConsumer = $this->consumer->consumerGuid !== $_POST['tool_consumer_instance_guid'];
                     if ($doSaveConsumer) {
                         $this->consumer->consumerGuid = $_POST['tool_consumer_instance_guid'];
                     }
                 }
             }
         }
         if (isset($_POST['launch_presentation_css_url'])) {
             if ($this->consumer->cssPath !== $_POST['launch_presentation_css_url']) {
                 $this->consumer->cssPath = $_POST['launch_presentation_css_url'];
                 $doSaveConsumer = true;
             }
         } else {
             if (isset($_POST['ext_launch_presentation_css_url']) && $this->consumer->cssPath !== $_POST['ext_launch_presentation_css_url']) {
                 $this->consumer->cssPath = $_POST['ext_launch_presentation_css_url'];
                 $doSaveConsumer = true;
             } else {
                 if (!empty($this->consumer->cssPath)) {
                     $this->consumer->cssPath = null;
                     $doSaveConsumer = true;
                 }
             }
         }
     }
     // Persist changes to consumer
     if ($doSaveConsumer) {
         $this->consumer->save();
     }
     if ($this->ok && isset($this->context)) {
         $this->context->save();
     }
     if ($this->ok && isset($this->resourceLink)) {
         // Check if a share arrangement is in place for this resource link
         $this->ok = $this->checkForShare();
         // Persist changes to resource link
         $this->resourceLink->save();
         // Save the user instance
         if (isset($_POST['lis_result_sourcedid'])) {
             if ($this->user->ltiResultSourcedId !== $_POST['lis_result_sourcedid']) {
                 $this->user->ltiResultSourcedId = $_POST['lis_result_sourcedid'];
                 $this->user->save();
             }
         } else {
             if (!empty($this->user->ltiResultSourcedId)) {
                 $this->user->ltiResultSourcedId = '';
                 $this->user->save();
             }
         }
     }
     return $this->ok;
 }
示例#2
0
文件: lib_test.php 项目: dg711/moodle
 /**
  * Test for enrol_lti_plugin::delete_instance().
  */
 public function test_delete_instance()
 {
     global $DB;
     // Create tool enrolment instance.
     $data = new stdClass();
     $data->enrolstartdate = time();
     $data->secret = 'secret';
     $tool = $this->getDataGenerator()->create_lti_tool($data);
     // Create consumer and related data.
     $dataconnector = new data_connector();
     $consumer = new ToolConsumer('testkey', $dataconnector);
     $consumer->secret = $tool->secret;
     $consumer->ltiVersion = ToolProvider::LTI_VERSION1;
     $consumer->name = 'TEST CONSUMER NAME';
     $consumer->consumerName = 'TEST CONSUMER INSTANCE NAME';
     $consumer->consumerGuid = 'TEST CONSUMER INSTANCE GUID';
     $consumer->consumerVersion = 'TEST CONSUMER INFO VERSION';
     $consumer->enabled = true;
     $consumer->protected = true;
     $consumer->save();
     $resourcelink = ResourceLink::fromConsumer($consumer, 'testresourcelinkid');
     $resourcelink->save();
     $ltiuser = User::fromResourceLink($resourcelink, '');
     $ltiuser->ltiResultSourcedId = 'testLtiResultSourcedId';
     $ltiuser->ltiUserId = 'testuserid';
     $ltiuser->email = '*****@*****.**';
     $ltiuser->save();
     $tp = new tool_provider($tool->id);
     $tp->user = $ltiuser;
     $tp->resourceLink = $resourcelink;
     $tp->consumer = $consumer;
     $tp->map_tool_to_consumer();
     $mappingparams = ['toolid' => $tool->id, 'consumerid' => $tp->consumer->getRecordId()];
     // Check first that the related records exist.
     $this->assertTrue($DB->record_exists('enrol_lti_tool_consumer_map', $mappingparams));
     $this->assertTrue($DB->record_exists('enrol_lti_lti2_consumer', ['id' => $consumer->getRecordId()]));
     $this->assertTrue($DB->record_exists('enrol_lti_lti2_resource_link', ['id' => $resourcelink->getRecordId()]));
     $this->assertTrue($DB->record_exists('enrol_lti_lti2_user_result', ['id' => $ltiuser->getRecordId()]));
     // Perform deletion.
     $enrollti = new enrol_lti_plugin();
     $instance = $DB->get_record('enrol', ['id' => $tool->enrolid]);
     $enrollti->delete_instance($instance);
     // Check that the related records have been deleted.
     $this->assertFalse($DB->record_exists('enrol_lti_tool_consumer_map', $mappingparams));
     $this->assertFalse($DB->record_exists('enrol_lti_lti2_consumer', ['id' => $consumer->getRecordId()]));
     $this->assertFalse($DB->record_exists('enrol_lti_lti2_resource_link', ['id' => $resourcelink->getRecordId()]));
     $this->assertFalse($DB->record_exists('enrol_lti_lti2_user_result', ['id' => $ltiuser->getRecordId()]));
     // Check that the enrolled users and the tool instance has been deleted.
     $this->assertFalse($DB->record_exists('enrol_lti_users', ['toolid' => $tool->id]));
     $this->assertFalse($DB->record_exists('enrol_lti_tools', ['id' => $tool->id]));
     $this->assertFalse($DB->record_exists('enrol', ['id' => $instance->id]));
 }
示例#3
0
 /**
  * Perform a Memberships service request.
  *
  * The user table is updated with the new list of user objects.
  *
  * @param boolean $withGroups True is group information is to be requested as well
  *
  * @return mixed Array of User objects or False if the request was not successful
  */
 public function doMembershipsService($withGroups = false)
 {
     $users = array();
     $oldUsers = $this->getUserResultSourcedIDs(true, ToolProvider::ID_SCOPE_RESOURCE);
     $this->extResponse = null;
     $url = $this->getSetting('ext_ims_lis_memberships_url');
     $params = array();
     $params['id'] = $this->getSetting('ext_ims_lis_memberships_id');
     $ok = false;
     if ($withGroups) {
         $ok = $this->doService('basic-lis-readmembershipsforcontextwithgroups', $url, $params);
     }
     if ($ok) {
         $this->groupSets = array();
         $this->groups = array();
     } else {
         $ok = $this->doService('basic-lis-readmembershipsforcontext', $url, $params);
     }
     if ($ok) {
         if (!isset($this->extNodes['memberships']['member'])) {
             $members = array();
         } else {
             if (!isset($this->extNodes['memberships']['member'][0])) {
                 $members = array();
                 $members[0] = $this->extNodes['memberships']['member'];
             } else {
                 $members = $this->extNodes['memberships']['member'];
             }
         }
         for ($i = 0; $i < count($members); $i++) {
             $user = User::fromResourceLink($this, $members[$i]['user_id']);
             // Set the user name
             $firstname = isset($members[$i]['person_name_given']) ? $members[$i]['person_name_given'] : '';
             $lastname = isset($members[$i]['person_name_family']) ? $members[$i]['person_name_family'] : '';
             $fullname = isset($members[$i]['person_name_full']) ? $members[$i]['person_name_full'] : '';
             $user->setNames($firstname, $lastname, $fullname);
             // Set the user email
             $email = isset($members[$i]['person_contact_email_primary']) ? $members[$i]['person_contact_email_primary'] : '';
             $user->setEmail($email, $this->getConsumer()->defaultEmail);
             /// Set the user roles
             if (isset($members[$i]['roles'])) {
                 $user->roles = ToolProvider::parseRoles($members[$i]['roles']);
             }
             // Set the user groups
             if (!isset($members[$i]['groups']['group'])) {
                 $groups = array();
             } else {
                 if (!isset($members[$i]['groups']['group'][0])) {
                     $groups = array();
                     $groups[0] = $members[$i]['groups']['group'];
                 } else {
                     $groups = $members[$i]['groups']['group'];
                 }
             }
             for ($j = 0; $j < count($groups); $j++) {
                 $group = $groups[$j];
                 if (isset($group['set'])) {
                     $set_id = $group['set']['id'];
                     if (!isset($this->groupSets[$set_id])) {
                         $this->groupSets[$set_id] = array('title' => $group['set']['title'], 'groups' => array(), 'num_members' => 0, 'num_staff' => 0, 'num_learners' => 0);
                     }
                     $this->groupSets[$set_id]['num_members']++;
                     if ($user->isStaff()) {
                         $this->groupSets[$set_id]['num_staff']++;
                     }
                     if ($user->isLearner()) {
                         $this->groupSets[$set_id]['num_learners']++;
                     }
                     if (!in_array($group['id'], $this->groupSets[$set_id]['groups'])) {
                         $this->groupSets[$set_id]['groups'][] = $group['id'];
                     }
                     $this->groups[$group['id']] = array('title' => $group['title'], 'set' => $set_id);
                 } else {
                     $this->groups[$group['id']] = array('title' => $group['title']);
                 }
                 $user->groups[] = $group['id'];
             }
             // If a result sourcedid is provided save the user
             if (isset($members[$i]['lis_result_sourcedid'])) {
                 $user->ltiResultSourcedId = $members[$i]['lis_result_sourcedid'];
                 $user->save();
             }
             $users[] = $user;
             // Remove old user (if it exists)
             unset($oldUsers[$user->getId(ToolProvider::ID_SCOPE_RESOURCE)]);
         }
         // Delete any old users which were not in the latest list from the tool consumer
         foreach ($oldUsers as $id => $user) {
             $user->delete();
         }
     } else {
         $users = false;
     }
     return $users;
 }
示例#4
0
 /**
  * Get the memberships.
  *
  * @param string    $role   Role for which memberships are to be requested (optional, default is all roles)
  * @param int       $limit  Limit on the number of memberships to be returned (optional, default is all)
  *
  * @return mixed The array of User objects if successful, otherwise false
  */
 public function get($role = null, $limit = 0)
 {
     $isLink = is_a($this->source, 'IMSGlobal\\LTI\\ToolProvider\\ResourceLink');
     $parameters = array();
     if (!empty($role)) {
         $parameters['role'] = $role;
     }
     if ($limit > 0) {
         $parameters['limit'] = strval($limit);
     }
     if ($isLink) {
         $parameters['rlid'] = $this->source->getId();
     }
     $http = $this->send('GET', $parameters);
     if (!$http->ok) {
         $users = false;
     } else {
         $users = array();
         if ($isLink) {
             $oldUsers = $this->source->getUserResultSourcedIDs(true, ToolProvider\ToolProvider::ID_SCOPE_RESOURCE);
         }
         foreach ($http->responseJson->pageOf->membershipSubject->membership as $membership) {
             $member = $membership->member;
             if ($isLink) {
                 $user = ToolProvider\User::fromResourceLink($this->source, $member->userId);
             } else {
                 $user = new ToolProvider\User();
                 $user->ltiUserId = $member->userId;
             }
             // Set the user name
             $firstname = isset($member->givenName) ? $member->givenName : '';
             $lastname = isset($member->familyName) ? $member->familyName : '';
             $fullname = isset($member->name) ? $member->name : '';
             $user->setNames($firstname, $lastname, $fullname);
             // Set the user email
             $email = isset($member->email) ? $member->email : '';
             $user->setEmail($email, $this->source->getConsumer()->defaultEmail);
             // Set the user roles
             if (isset($membership->role)) {
                 $user->roles = ToolProvider\ToolProvider::parseRoles($membership->role);
             }
             // If a result sourcedid is provided save the user
             if ($isLink) {
                 if (isset($member->message)) {
                     foreach ($member->message as $message) {
                         if (isset($message->message_type) && $message->message_type === 'basic-lti-launch-request') {
                             if (isset($message->lis_result_sourcedid)) {
                                 $user->ltiResultSourcedId = $message->lis_result_sourcedid;
                                 $user->save();
                             }
                             break;
                         }
                     }
                 }
             }
             $users[] = $user;
             // Remove old user (if it exists)
             if ($isLink) {
                 unset($oldUsers[$user->getId(ToolProvider\ToolProvider::ID_SCOPE_RESOURCE)]);
             }
         }
         // Delete any old users which were not in the latest list from the tool consumer
         if ($isLink) {
             foreach ($oldUsers as $id => $user) {
                 $user->delete();
             }
         }
     }
     return $users;
 }
示例#5
0
 /**
  * Get array of user objects.
  *
  * Obtain an array of User objects for users with a result sourcedId.  The array may include users from other
  * resource links which are sharing this resource link.  It may also be optionally indexed by the user ID of a specified scope.
  *
  * @param ResourceLink $resourceLink      Resource link object
  * @param boolean     $localOnly True if only users within the resource link are to be returned (excluding users sharing this resource link)
  * @param int         $idScope     Scope value to use for user IDs
  *
  * @return array Array of User objects
  */
 public function getUserResultSourcedIDsResourceLink($resourceLink, $localOnly, $idScope)
 {
     $users = array();
     if ($localOnly) {
         $sql = sprintf('SELECT u.user_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' . "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' AS u ' . "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' AS rl ' . 'ON u.resource_link_pk = rl.resource_link_pk ' . "WHERE (rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)", $resourceLink->getRecordId());
     } else {
         $sql = sprintf('SELECT u.user_pk, u.lti_result_sourcedid, u.lti_user_id, u.created, u.updated ' . "FROM {$this->dbTableNamePrefix}" . DataConnector::USER_RESULT_TABLE_NAME . ' AS u ' . "INNER JOIN {$this->dbTableNamePrefix}" . DataConnector::RESOURCE_LINK_TABLE_NAME . ' AS rl ' . 'ON u.resource_link_pk = rl.resource_link_pk ' . 'WHERE ((rl.resource_link_pk = %d) AND (rl.primary_resource_link_pk IS NULL)) OR ' . '((rl.primary_resource_link_pk = %d) AND (share_approved = 1))', $resourceLink->getRecordId(), $resourceLink->getRecordId());
     }
     $rsUser = mysql_query($sql);
     if ($rsUser) {
         while ($row = mysql_fetch_object($rsUser)) {
             $user = ToolProvider\User::fromResourceLink($resourceLink, $row->lti_user_id);
             $user->setRecordId(intval($row->user_pk));
             $user->ltiResultSourcedId = $row->lti_result_sourcedid;
             $user->created = strtotime($row->created);
             $user->updated = strtotime($row->updated);
             if (is_null($idScope)) {
                 $users[] = $user;
             } else {
                 $users[$user->getId($idScope)] = $user;
             }
         }
     }
     return $users;
 }
示例#6
0
 /**
  * Test for data_connector::deleteUser().
  */
 public function test_delete_user()
 {
     $dc = new data_connector();
     $consumer = new ToolConsumer(null, $dc);
     $consumer->name = 'TestName';
     $consumer->setKey('TestKey');
     $consumer->secret = 'TestSecret';
     $consumer->save();
     $resourcelink = ResourceLink::fromConsumer($consumer, 'testresourcelinkid');
     $resourcelink->save();
     $user = User::fromResourceLink($resourcelink, '');
     $user->ltiResultSourcedId = 'testLtiResultSourcedId';
     $user->firstname = 'First';
     $user->lastname = 'Last';
     $user->fullname = 'Full name';
     $user->email = '*****@*****.**';
     $user->roles = ['a', 'b'];
     $user->groups = ['1', '2'];
     $user->save();
     // Delete user.
     $this->assertTrue($dc->deleteUser($user));
     // User record should have been deleted from the DB.
     $this->assertFalse($dc->loadUser($user));
     // User object should have been initialised().
     $this->assertEmpty($user->firstname);
     $this->assertEmpty($user->lastname);
     $this->assertEmpty($user->fullname);
     $this->assertEmpty($user->email);
     $this->assertEmpty($user->roles);
     $this->assertEmpty($user->groups);
     $this->assertNull($user->ltiResultSourcedId);
     $this->assertNull($user->created);
     $this->assertNull($user->updated);
 }
示例#7
0
 /**
  * Get array of user objects.
  *
  * Obtain an array of User objects for users with a result sourcedId.  The array may include users from other
  * resource links which are sharing this resource link.  It may also be optionally indexed by the user ID of a specified scope.
  *
  * @param ResourceLink $resourcelink Resource link object
  * @param boolean $localonly True if only users within the resource link are to be returned
  *                           (excluding users sharing this resource link)
  * @param int $idscope Scope value to use for user IDs
  * @return array Array of User objects
  */
 public function getUserResultSourcedIDsResourceLink($resourcelink, $localonly, $idscope)
 {
     global $DB;
     $users = [];
     $params = ['resourcelinkid' => $resourcelink->getRecordId()];
     // Where clause for the subquery.
     $subwhere = "(id = :resourcelinkid AND primaryresourcelinkid IS NULL)";
     if (!$localonly) {
         $subwhere .= " OR (primaryresourcelinkid = :resourcelinkid2 AND shareapproved = 1)";
         $params['resourcelinkid2'] = $resourcelink->getRecordId();
     }
     // The subquery.
     $subsql = "SELECT id\n                     FROM {{$this->resourcelinktable}}\n                    WHERE {$subwhere}";
     // Our main where clause.
     $where = "resourcelinkid IN ({$subsql})";
     // Fields to be queried.
     $fields = 'id, ltiresultsourcedid, ltiuserkey, created, updated';
     // Fetch records.
     $rs = $DB->get_recordset_select($this->userresulttable, $where, $params, '', $fields);
     foreach ($rs as $row) {
         $user = User::fromResourceLink($resourcelink, $row->ltiuserkey);
         $user->setRecordId($row->id);
         $user->ltiResultSourcedId = $row->ltiresultsourcedid;
         $user->created = $row->created;
         $user->updated = $row->updated;
         if (is_null($idscope)) {
             $users[] = $user;
         } else {
             $users[$user->getId($idscope)] = $user;
         }
     }
     $rs->close();
     return $users;
 }
示例#8
0
 /**
  * Builds a dummy tool provider object.
  *
  * @param string $secret Consumer secret.
  * @param array|stdClass $proxy Tool proxy data.
  * @param null $resourcelinksettings Key-value array for resource link settings.
  * @return dummy_tool_provider
  */
 protected function build_dummy_tp($secret = null, $proxy = null, $resourcelinksettings = null)
 {
     $tool = $this->tool;
     $dataconnector = new data_connector();
     $consumer = new ToolConsumer('testkey', $dataconnector);
     $ltiversion = ToolProvider::LTI_VERSION2;
     if ($secret === null && $proxy === null) {
         $consumer->secret = $tool->secret;
         $ltiversion = ToolProvider::LTI_VERSION1;
     } else {
         $consumer->secret = $secret;
     }
     $consumer->ltiVersion = $ltiversion;
     $consumer->name = 'TEST CONSUMER NAME';
     $consumer->consumerName = 'TEST CONSUMER INSTANCE NAME';
     $consumer->consumerGuid = 'TEST CONSUMER INSTANCE GUID';
     $consumer->consumerVersion = 'TEST CONSUMER INFO VERSION';
     $consumer->enabled = true;
     $consumer->protected = true;
     if ($proxy !== null) {
         $consumer->toolProxy = json_encode($proxy);
     }
     $consumer->save();
     $resourcelink = ResourceLink::fromConsumer($consumer, 'testresourcelinkid');
     if (!empty($resourcelinksettings)) {
         foreach ($resourcelinksettings as $setting => $value) {
             $resourcelink->setSetting($setting, $value);
         }
     }
     $resourcelink->save();
     $ltiuser = User::fromResourceLink($resourcelink, '');
     $ltiuser->ltiResultSourcedId = 'testLtiResultSourcedId';
     $ltiuser->ltiUserId = 'testuserid';
     $ltiuser->email = '*****@*****.**';
     $ltiuser->save();
     $tp = new dummy_tool_provider($tool->id);
     $tp->user = $ltiuser;
     $tp->resourceLink = $resourcelink;
     $tp->consumer = $consumer;
     return $tp;
 }