Index: lams_build/build_base.xml =================================================================== diff -u -r3c9c1930e10bc404544e6ec6948e8f9fc9b0d1ea -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_build/build_base.xml (.../build_base.xml) (revision 3c9c1930e10bc404544e6ec6948e8f9fc9b0d1ea) +++ lams_build/build_base.xml (.../build_base.xml) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -46,6 +46,8 @@ + + Index: lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestLtiServlet.java =================================================================== diff -u -rbc4f020f3e282c00dc195b4861f85261d479fc1d -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestLtiServlet.java (.../LoginRequestLtiServlet.java) (revision bc4f020f3e282c00dc195b4861f85261d479fc1d) +++ lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestLtiServlet.java (.../LoginRequestLtiServlet.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -150,7 +150,7 @@ //In case of ContentItemSelectionRequest user must still be a stuff member in order to create a lesson. boolean isCustomMonitorRole = LtiUtils.isToolConsumerCustomRole(roles, extServer.getLtiToolConsumerMonitorRoles()); - String method = LtiUtils.isStaff(roles) || LtiUtils.isAdmin(roles) || isCustomMonitorRole + String method = LtiUtils.isStaff(roles, extServer) || LtiUtils.isAdmin(roles) || isCustomMonitorRole ? LoginRequestDispatcher.METHOD_AUTHOR : LoginRequestDispatcher.METHOD_LEARNER_STRICT_AUTHENTICATION; Index: lams_central/src/java/org/lamsfoundation/lams/web/controller/LtiController.java =================================================================== diff -u -rf2ad75cef0c507a64877942631fee13efbc6ed50 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_central/src/java/org/lamsfoundation/lams/web/controller/LtiController.java (.../LtiController.java) (revision f2ad75cef0c507a64877942631fee13efbc6ed50) +++ lams_central/src/java/org/lamsfoundation/lams/web/controller/LtiController.java (.../LtiController.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -93,6 +93,8 @@ String extUserId = request.getParameter(BasicLTIConstants.USER_ID); ExtServerLessonMap lesson = integrationService.getLtiConsumerLesson(consumerKey, resourceLinkId); + ExtServer extServer = integrationService.getExtServer(consumerKey); + //support for ContentItemSelectionRequest. If lesson was created during such request, update its ExtServerLesson's resourceLinkId for the first time boolean isContentItemSelection = WebUtil.readBooleanParam(request, "custom_isContentItemSelection", false); if (lesson == null && isContentItemSelection) { @@ -104,11 +106,17 @@ //update lessonFinishCallbackUrl. We store it one time during the very first call to LAMS and it stays the same all the time afterwards String lessonFinishCallbackUrl = request.getParameter(BasicLTIConstants.LIS_OUTCOME_SERVICE_URL); - ExtServer extServer = integrationService.getExtServer(consumerKey); if (StringUtils.isNotBlank(lessonFinishCallbackUrl) && StringUtils.isBlank(extServer.getLessonFinishUrl())) { extServer.setLessonFinishUrl(lessonFinishCallbackUrl); userManagementService.save(extServer); } + + //update MembershipUrl. We store it one time during the very first call to LAMS and it stays the same all the time afterwards + String membershipUrl = request.getParameter("custom_context_memberships_url"); + if (StringUtils.isNotBlank(membershipUrl) && StringUtils.isBlank(extServer.getMembershipUrl())) { + extServer.setMembershipUrl(membershipUrl); + userManagementService.save(extServer); + } //check if learner tries to access the link that hasn't been authored by teacher yet String method = request.getParameter("_" + LoginRequestDispatcher.PARAM_METHOD); @@ -224,20 +232,27 @@ extServer.getLiveEditEnabled(), extServer.getEnableLessonNotifications(), extServer.getForceLearnerRestart(), extServer.getAllowLearnerRestart(), extServer.getGradebookOnComplete(), null, null); + Long lessonId = lesson.getLessonId(); // 2. create lessonClass for lesson List staffList = new LinkedList(); staffList.add(user); List learnerList = new LinkedList(); Vector learnerVector = userManagementService .getUsersFromOrganisationByRole(organisation.getOrganisationId(), Role.LEARNER, true); learnerList.addAll(learnerVector); - monitoringService.createLessonClassForLesson(lesson.getLessonId(), organisation, + monitoringService.createLessonClassForLesson(lessonId, organisation, organisation.getName() + "Learners", learnerList, organisation.getName() + "Staff", staffList, user.getUserId()); // 3. start lesson - monitoringService.startLesson(lesson.getLessonId(), user.getUserId()); + monitoringService.startLesson(lessonId, user.getUserId()); // store information which extServer has started the lesson - integrationService.createExtServerLessonMap(lesson.getLessonId(), resourceLinkId, extServer); + integrationService.createExtServerLessonMap(lessonId, resourceLinkId, extServer); + + integrationService.addExtUsersToLesson(extServer, lessonId, contextId, resourceLinkId); + +// Thread t = new Thread(new AddUsersToLessonThread(serverId, datetime, username, hashValue, lsIdStr, +// courseId, country, lang, learnerIds, monitorIds, firstNames, lastNames, emails, request)); +// t.start(); //support for ContentItemSelectionRequest String ltiMessageType = request.getParameter(BasicLTIConstants.LTI_MESSAGE_TYPE); @@ -413,4 +428,146 @@ private User getRealUser(UserDTO dto) { return userManagementService.getUserByLogin(dto.getLogin()); } + +// private class AddUsersToLessonThread implements Runnable { +// +// private String serverId; +// private String datetime; +// private String username; +// private String hashValue; +// private String lsIdStr; +// private String courseId; +// private String country; +// private String lang; +// private String learnerIds; +// private String monitorIds; +// private String firstNames; +// private String lastNames; +// private String emails; +// private HttpServletRequest request; +// +// public AddUsersToLessonThread(String serverId, String datetime, String username, String hashValue, +// String lsIdStr, String courseId, String country, String lang, String learnerIds, String monitorIds, +// String firstNames, String lastNames, String emails, HttpServletRequest request) { +// this.serverId = serverId; +// this.datetime = datetime; +// this.username = username; +// this.hashValue = hashValue; +// this.lsIdStr = lsIdStr; +// this.courseId = courseId; +// this.country = country; +// this.lang = lang; +// this.learnerIds = learnerIds; +// this.monitorIds = monitorIds; +// this.firstNames = firstNames; +// this.lastNames = lastNames; +// this.emails = emails; +// this.request = request; +// } +// +// @Override +// public void run() { +// addUsersToLesson(serverId, datetime, username, hashValue, lsIdStr, courseId, country, lang, learnerIds, +// monitorIds, firstNames, lastNames, emails, request); +// } +// +// /** +// * Adds each user in learnerIds and monitorIds as learner and staff to the given lesson id; authenticates using +// * the 3rd party server requestor's username. +// * +// * @param serverId +// * @param datetime +// * @param hashValue +// * @param lsIdStr +// * @param learnerIds +// * @param monitorIds +// * @param request +// * @return +// */ +// public Boolean addUsersToLesson(String serverId, String datetime, String requestorUsername, String hashValue, +// String lsIdStr, String courseId, String countryIsoCode, String langIsoCode, String learnerIds, +// String monitorIds, String firstNames, String lastNames, String emails, HttpServletRequest request) { +// try { +// +// // get Server map +// ExtServer extServer = integrationService.getExtServer(serverId); +// // authenticate +// Authenticator.authenticate(extServer, datetime, requestorUsername, hashValue); +// +// String[] learnerIdArray = (learnerIds != null) ? learnerIds.split(",") : new String[0]; +// String[] monitorIdArray = (monitorIds != null) ? monitorIds.split(",") : new String[0]; +// String[] firstNameArray = (firstNames != null) +// ? firstNames.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1) +// : new String[0]; +// String[] lastNameArray = (lastNames != null) ? lastNames.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1) +// : new String[0]; +// String[] emailArray = (emails != null) ? emails.split(",") : new String[0]; +// +// // in case there is firstNames available - check all arrays have the same length, as otherwise it's +// // prone to ArrayOutOfBounds exceptions +// if ((firstNames != null) && ((firstNameArray.length != lastNameArray.length) +// || (firstNameArray.length != emailArray.length) +// || (firstNameArray.length != (learnerIdArray.length + monitorIdArray.length)))) { +// log.error("Invalid parameters sent: wrong array length. " + "learnerIds=" + learnerIds +// + " &monitorIds=" + monitorIds + " &firstNames=" + firstNames + " &lastNames=" + lastNames +// + " &emails=" + emails + " &array lengths=" + learnerIdArray.length + "!" +// + monitorIdArray.length + "!" + firstNameArray.length + "!" + lastNameArray.length + "!" +// + emailArray.length); +// return false; +// } +// +// int i = 0; +// for (String userName : learnerIdArray) { +// String firstName = null; +// String lastName = null; +// String email = null; +// if (firstNames != null) { +// // unescape values passed from the external server. Works OK even if the values were not escaped +// firstName = StringEscapeUtils.unescapeCsv(firstNameArray[i]); +// lastName = StringEscapeUtils.unescapeCsv(lastNameArray[i]); +// email = StringEscapeUtils.unescapeCsv(emailArray[i]); +// } +// +// if (StringUtils.isNotBlank(userName)) { +// addUserToLesson(extServer, LoginRequestDispatcher.METHOD_LEARNER, lsIdStr, userName, firstName, +// lastName, email, courseId, countryIsoCode, langIsoCode); +// } +// i++; +// } +// +// for (String userName : monitorIdArray) { +// String firstName = null; +// String lastName = null; +// String email = null; +// if (firstNames != null) { +// // unescape values passed from the external server. Works OK even if the values were not escaped +// firstName = StringEscapeUtils.unescapeCsv(firstNameArray[i]); +// lastName = StringEscapeUtils.unescapeCsv(lastNameArray[i]); +// email = StringEscapeUtils.unescapeCsv(emailArray[i]); +// } +// +// if (StringUtils.isNotBlank(userName)) { +// integrationService.addExtUserToLesson(extServer, LoginRequestDispatcher.METHOD_MONITOR, lsIdStr, +// userName, firstName, lastName, email, courseId, countryIsoCode, langIsoCode); +// } +// i++; +// } +// +// return true; +// } catch (UserInfoFetchException e) { +// log.error(e, e); +// return false; +// } catch (UserInfoValidationException e) { +// log.error(e, e); +// return false; +// } catch (AuthenticationException e) { +// log.error(e, e); +// return false; +// } +// } +// +// +// } + + } Index: lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LessonManagerServlet.java =================================================================== diff -u -rf2ad75cef0c507a64877942631fee13efbc6ed50 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LessonManagerServlet.java (.../LessonManagerServlet.java) (revision f2ad75cef0c507a64877942631fee13efbc6ed50) +++ lams_central/src/java/org/lamsfoundation/lams/webservice/xml/LessonManagerServlet.java (.../LessonManagerServlet.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -928,8 +928,10 @@ } if (StringUtils.isNotBlank(userName)) { - addUserToLesson(request, extServer, LoginRequestDispatcher.METHOD_LEARNER, lsIdStr, userName, - firstName, lastName, email, courseId, locale, country); +// integrationService.addExtUserToLesson(extServer, LoginRequestDispatcher.METHOD_LEARNER, lsIdStr, +// userName, firstName, lastName, email, courseId, countryIsoCode, langIsoCode); + integrationService.addExtUserToLesson(extServer, LoginRequestDispatcher.METHOD_LEARNER, lsIdStr, + userName, firstName, lastName, email, courseId, country, locale); } i++; } @@ -946,8 +948,8 @@ } if (StringUtils.isNotBlank(userName)) { - addUserToLesson(request, extServer, LoginRequestDispatcher.METHOD_MONITOR, lsIdStr, userName, - firstName, lastName, email, courseId, locale, country); + integrationService.addExtUserToLesson(extServer, LoginRequestDispatcher.METHOD_MONITOR, lsIdStr, + userName, firstName, lastName, email, courseId, country, locale); } i++; } @@ -964,45 +966,6 @@ return false; } } - - private void addUserToLesson(HttpServletRequest request, ExtServer extServer, String method, String lsIdStr, - String username, String firstName, String lastName, String email, String courseId, String locale, - String country) throws UserInfoFetchException, UserInfoValidationException { - - if (log.isDebugEnabled()) { - log.debug("Adding user '" + username + "' as " + method + " to lesson with id '" + lsIdStr + "'."); - } - - ExtUserUseridMap userMap = null; - if ((firstName == null) && (lastName == null)) { - userMap = integrationService.getExtUserUseridMap(extServer, username); - } else { - final boolean usePrefix = true; - final boolean isUpdateUserDetails = false; - userMap = integrationService.getImplicitExtUserUseridMap(extServer, username, firstName, lastName, - locale, country, email, usePrefix, isUpdateUserDetails); - } - - // ExtUserUseridMap userMap = integrationService.getExtUserUseridMap(extServer, - // username); - // adds user to group - ExtCourseClassMap orgMap = integrationService.getExtCourseClassMap(extServer, userMap, courseId, null, - method); - - User user = userMap.getUser(); - if (user == null) { - String error = "Unable to add user to lesson class as user is missing from the user map"; - log.error(error); - throw new UserInfoFetchException(error); - } - - if (LoginRequestDispatcher.METHOD_LEARNER.equals(method)) { - lessonService.addLearner(Long.parseLong(lsIdStr), user.getUserId()); - } else if (LoginRequestDispatcher.METHOD_MONITOR.equals(method)) { - lessonService.addStaffMember(Long.parseLong(lsIdStr), user.getUserId()); - } - - } } /** Index: lams_common/.classpath =================================================================== diff -u -r3c3ff3f2bd9e05d38823db2f4932217953acf160 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_common/.classpath (.../.classpath) (revision 3c3ff3f2bd9e05d38823db2f4932217953acf160) +++ lams_common/.classpath (.../.classpath) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -28,6 +28,8 @@ + + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190806.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190806.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190806.sql (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -0,0 +1,14 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +----------------------Put all sql statements below here------------------------- + +-- LDEV-4589 Add column for LTI Membership service +ALTER TABLE lams_ext_server_org_map ADD COLUMN `membership_url` text COLLATE utf8mb4_unicode_ci; + +----------------------Put all sql statements above here------------------------- + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/integration/ExtServer.java =================================================================== diff -u -r5b1fbc89c883857eace8c043a594a79cb0f60bc4 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_common/src/java/org/lamsfoundation/lams/integration/ExtServer.java (.../ExtServer.java) (revision 5b1fbc89c883857eace8c043a594a79cb0f60bc4) +++ lams_common/src/java/org/lamsfoundation/lams/integration/ExtServer.java (.../ExtServer.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -59,6 +59,9 @@ @Column(name = "ext_groups_url") private String extGroupsUrl; + + @Column(name = "membership_url") + private String membershipUrl; @Column private Boolean disabled; @@ -196,7 +199,15 @@ public void setExtGroupsUrl(String extGroupsUrl) { this.extGroupsUrl = extGroupsUrl; } + + public String getMembershipUrl() { + return this.membershipUrl; + } + public void setMembershipUrl(String membershipUrl) { + this.membershipUrl = membershipUrl; + } + public Boolean getDisabled() { return this.disabled; } Index: lams_common/src/java/org/lamsfoundation/lams/integration/service/IIntegrationService.java =================================================================== diff -u -ra5bb8ab1bbc5f6732acef6132286e89c80f2e8f3 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_common/src/java/org/lamsfoundation/lams/integration/service/IIntegrationService.java (.../IIntegrationService.java) (revision a5bb8ab1bbc5f6732acef6132286e89c80f2e8f3) +++ lams_common/src/java/org/lamsfoundation/lams/integration/service/IIntegrationService.java (.../IIntegrationService.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -23,9 +23,12 @@ package org.lamsfoundation.lams.integration.service; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; +import org.apache.http.client.ClientProtocolException; +import org.imsglobal.lti.launch.LtiSigningException; import org.lamsfoundation.lams.integration.ExtCourseClassMap; import org.lamsfoundation.lams.integration.ExtServerLessonMap; import org.lamsfoundation.lams.integration.ExtServer; @@ -117,7 +120,18 @@ * @return */ ExtServerLessonMap getLtiConsumerLesson(String serverId, String resourceLinkId); - + + /** + * 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 + */ + void addExtUsersToLesson(ExtServer extServer, Long lessonId, String courseId, String resourceLinkId) + throws IOException, UserInfoFetchException, UserInfoValidationException; + ExtServerLessonMap getExtServerLessonMap(Long lessonId); /** @@ -224,6 +238,10 @@ ExtCourseClassMap getExtCourseClassMap(Integer sid, Long lessonId); + ExtUserUseridMap addExtUserToLesson(ExtServer extServer, String method, String lsIdStr, String username, String firstName, + String lastName, String email, String courseId, String countryIsoCode, String langIsoCode) + throws UserInfoFetchException, UserInfoValidationException; + /** * Creates an external org and normal org. It does not set roles for the creator. */ Index: lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java =================================================================== diff -u -ra5bb8ab1bbc5f6732acef6132286e89c80f2e8f3 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java (.../IntegrationService.java) (revision a5bb8ab1bbc5f6732acef6132286e89c80f2e8f3) +++ lams_common/src/java/org/lamsfoundation/lams/integration/service/IntegrationService.java (.../IntegrationService.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -42,7 +42,18 @@ import java.util.Map; import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpResponseException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; +import org.imsglobal.lti.BasicLTIConstants; +import org.imsglobal.lti.launch.LtiOauthSigner; +import org.imsglobal.lti.launch.LtiSigner; +import org.imsglobal.lti.launch.LtiSigningException; import org.imsglobal.pox.IMSPOXRequest; import org.lamsfoundation.lams.gradebook.GradebookUserLesson; import org.lamsfoundation.lams.gradebook.service.IGradebookService; @@ -57,6 +68,7 @@ import org.lamsfoundation.lams.integration.security.RandomPasswordGenerator; import org.lamsfoundation.lams.integration.util.GroupInfoFetchException; import org.lamsfoundation.lams.integration.util.LoginRequestDispatcher; +import org.lamsfoundation.lams.integration.util.LtiUtils; import org.lamsfoundation.lams.lesson.Lesson; import org.lamsfoundation.lams.lesson.service.ILessonService; import org.lamsfoundation.lams.timezone.service.ITimezoneService; @@ -78,10 +90,10 @@ import org.lamsfoundation.lams.util.WebUtil; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import oauth.signpost.exception.OAuthException; - /** *

* View Source @@ -857,7 +869,49 @@ List list = service.findByProperties(ExtCourseClassMap.class, properties); return list == null || list.isEmpty() ? null : list.get(0); } + + @Override + public ExtUserUseridMap addExtUserToLesson(ExtServer extServer, String method, String lsIdStr, String username, + String firstName, String lastName, String email, String courseId, String countryIsoCode, String langIsoCode) + throws UserInfoFetchException, UserInfoValidationException { + if (log.isDebugEnabled()) { + log.debug("Adding user '" + username + "' as " + method + " to lesson with id '" + lsIdStr + "'."); + } + + ExtUserUseridMap userMap = null; + if ((firstName == null) && (lastName == null)) { + userMap = getExtUserUseridMap(extServer, username); + } else { + final boolean usePrefix = true; + final boolean isUpdateUserDetails = false; + userMap = getImplicitExtUserUseridMap(extServer, username, firstName, lastName, langIsoCode, countryIsoCode, + email, usePrefix, isUpdateUserDetails); + } + + // ExtUserUseridMap userMap = integrationService.getExtUserUseridMap(extServer, username); + // adds user to group + ExtCourseClassMap orgMap = getExtCourseClassMap(extServer, userMap, courseId, null, method); + //TODO when merging to newer branch, check and maybe change to the following +// getExtCourseClassMap(extServer, userMap, courseId, countryIsoCode, langIsoCode, null, +// method); + + User user = userMap.getUser(); + if (user == null) { + String error = "Unable to add user to lesson class as user is missing from the user map"; + log.error(error); + throw new UserInfoFetchException(error); + } + + if (LoginRequestDispatcher.METHOD_LEARNER.equals(method)) { + lessonService.addLearner(Long.parseLong(lsIdStr), user.getUserId()); + } else if (LoginRequestDispatcher.METHOD_MONITOR.equals(method)) { + lessonService.addStaffMember(Long.parseLong(lsIdStr), user.getUserId()); + } + + return userMap; + } + @Override public ExtServerLessonMap getLtiConsumerLesson(String serverId, String resourceLinkId) { Map properties = new HashMap<>(); @@ -898,7 +952,211 @@ return (ExtCourseClassMap) list.get(0); } } + + @Override + public void addExtUsersToLesson(ExtServer extServer, Long lessonId, String courseId, String resourceLinkId) + throws IOException, UserInfoFetchException, UserInfoValidationException { + +// $isLink = is_a($this->source, 'IMSGlobal\LTI\ToolProvider\ResourceLink'); + + log.info("addExtUsersToLesson invoked. params: courseId " + courseId + "resourceLinkId " + resourceLinkId); + JsonNode json = send(extServer, resourceLinkId); + if (json == null) { +// $users = false; + } else { + +// $users = array(); +// if ($isLink) { +// $oldUsers = $this->source->getUserResultSourcedIDs(true, ToolProvider\ToolProvider::ID_SCOPE_RESOURCE); +// } + + JsonNode memberships = json.get("pageOf").get("membershipSubject").get("membership"); + for (int i = 0; i < memberships.size(); i++) { + JsonNode membership = memberships.get(i); + log.info("membership" + i + ": " + membership.toString()); + + JsonNode member = membership.get("member"); + String extUserId = member.get("userId").asText(); + String firstName = member.get("givenName").asText(); + String lastName = member.get("familyName").asText(); + String fullName = member.get("name").asText(); + String email = member.get("email").asText(); + // Set the user name and email + String[] defaultLangCountry = LanguageUtil.getDefaultLangCountry(); + + String countryIsoCode = defaultLangCountry[1] ; + String langIsoCode = defaultLangCountry[0]; +// ExtUserUseridMap extUser = getImplicitExtUserUseridMap(extServer, extUserId, firstName, lastName, defaultLangCountry[1], +// defaultLangCountry[0], email, StringUtils.isNotBlank(extServer.getPrefix()), true); + //?? getUserDataFromExtServer + + +// Set the user roles + JsonNode jsonRoles = membership.get("role"); + log.info("membership" + i + " roles: " + jsonRoles.toString()); + String roles = new String(); + for (int j = 0; j < jsonRoles.size(); j++) { + String role = jsonRoles.get(j).asText(); + roles += role + ","; + } + + String method; + ExtUserUseridMap extUser; + if (LtiUtils.isStaff(roles, extServer) || LtiUtils.isAdmin(roles)) { + log.info("Adding user as monitor"); + method = LoginRequestDispatcher.METHOD_MONITOR; + + extUser = addExtUserToLesson(extServer, method, lessonId.toString(), extUserId, firstName, lastName, email, courseId, countryIsoCode, langIsoCode); + + } else { + log.info("Adding user as learner"); + method = LoginRequestDispatcher.METHOD_LEARNER; + extUser = addExtUserToLesson(extServer, method, lessonId.toString(), extUserId, firstName, lastName, email, courseId, countryIsoCode, langIsoCode); + } + +// if (isset($membership->role)) { +// if (!is_array($roles)) { +// $roles = explode(',', $roles); +// } +// $parsedRoles = array(); +// foreach ($roles as $role) { +// $role = trim($role); +// if (!empty($role)) { +// if (substr($role, 0, 4) !== 'urn:') { +// $role = 'urn:lti:role:ims/lis/' . $role; +// } +// $parsedRoles[] = $role; +// } +// } +// $user->roles = roles; +// } + +// If a result sourcedid is provided save the user + + + + JsonNode messages = membership.get("message"); + log.info("membership" + i + " messages: " + messages.toString()); + if (messages != null && messages.size() > 0) { + for (int k = 0; k < messages.size(); k++) { + JsonNode message = messages.get(k); + String messageType = message.get("message_type").asText(); + String tcGradebookId = message.get(BasicLTIConstants.LIS_RESULT_SOURCEDID) == null ? "" + : message.get(BasicLTIConstants.LIS_RESULT_SOURCEDID).asText(); + + if (StringUtils.isNotBlank(messageType) && "basic-lti-launch-request".equals(messageType)) { + if (StringUtils.isNotBlank(tcGradebookId)) { + log.info("User setTcGradebookId tcGradebookId:" + tcGradebookId); + extUser.setTcGradebookId(tcGradebookId); + service.save(extUser); + } + break; + } + } + } + +// 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(); +// } +// } + } + } + /** + * Send a service request. + * + * @param array + * $parameters Query parameters to add to endpoint (optional, default is none) + * + * @return HTTPMessage HTTP object containing request and response details + * @throws LtiSigningException + * @throws IOException + * @throws ClientProtocolException + */ + public JsonNode send(ExtServer extServer, String resourceLinkId) throws IOException { + + String membershipUrl = extServer.getMembershipUrl(); + //if tool consumer haven't provided membershipUrl (ToolProxyBinding.memberships.url parameter) we can't add any users + if (StringUtils.isBlank(membershipUrl)) { + return null; + } + + membershipUrl += membershipUrl.contains("?") ? "&" : "?"; + membershipUrl += "rlid=" + resourceLinkId; + + HttpGet ltiServiceGetRequest = new HttpGet(membershipUrl); + ltiServiceGetRequest.setHeader("Accept", "application/vnd.ims.lis.v2.membershipcontainer+json"); +// request.setEntity(new StringEntity(xml, "UTF-8")); +// ltiServiceGetRequest.setAdditionalParameters(parameters); +// if (empty($data)) { +// if (!empty($type)) { +// $header .= "\nAccept: {$type}"; +// } +// } else if (isset($type)) { +// $header .= "\nContent-Type: {$type}"; +// $header .= "\nContent-Length: " . strlen($data); +// } + + log.info("Call membershipUrl:" + membershipUrl); + +// BasicLTIUtil.validateMessage(request, URL, oauth_secret) + + LtiSigner ltiSigner = new LtiOauthSigner(); + try { + HttpRequest httpRequest = ltiSigner.sign(ltiServiceGetRequest, extServer.getServerid(), + extServer.getServerkey()); + } catch (LtiSigningException e) { + throw new RuntimeException(e); + } + + DefaultHttpClient client = new DefaultHttpClient(); + HttpResponse response = client.execute(ltiServiceGetRequest); + if (response.getStatusLine().getStatusCode() >= 400) { + throw new HttpResponseException(response.getStatusLine().getStatusCode(), + response.getStatusLine().getReasonPhrase()); + } + + String responseString = EntityUtils.toString(response.getEntity()); + log.info("Response: " + responseString); + JsonNode actualObj = new ObjectMapper().readTree(responseString); + +// JSONObject jsonObject = new JSONObject(EntityUtils.toString(response.getEntity())); + return actualObj; +// Gson gson = new GsonBuilder().create(); +// responseJSON.put("contributeActivities", new JSONArray(gson.toJson(contributeActivities))); + +// LtiVerifier verifier = new LtiOauthVerifier(); +// LtiVerificationResult result = verifier.verify(ltiServiceGetRequest, extServer.getServerkey()); + + + + +// if (!$this->unsigned) { +// $header = ToolProvider\ToolConsumer::addSignature(membershipUrl, $this->consumer->getKey(), $this->consumer->secret, body, "GET", $this->mediaType); +// } else { +// $header = null; +// } + + // Connect to tool consumer +// $http = new HTTPMessage(membershipUrl, "GET", body, $header); + // Parse JSON response +// if ($http->send() && !empty($http->response)) { +// $http->responseJson = json_decode($http->response); +// $http->ok = !is_null($http->responseJson); +// } +// +// return $http; + + } + // --------------------------------------------------------------------- // Inversion of Control Methods - Method injection // --------------------------------------------------------------------- Index: lams_common/src/java/org/lamsfoundation/lams/integration/util/LtiUtils.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r2e1574cede0a43314af36aa790c3ca156845cab2 --- lams_common/src/java/org/lamsfoundation/lams/integration/util/LtiUtils.java (.../LtiUtils.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_common/src/java/org/lamsfoundation/lams/integration/util/LtiUtils.java (.../LtiUtils.java) (revision 2e1574cede0a43314af36aa790c3ca156845cab2) @@ -4,6 +4,8 @@ import java.util.LinkedList; import java.util.List; +import org.lamsfoundation.lams.integration.ExtServer; + public class LtiUtils { public static final String OAUTH_CONSUMER_KEY = "oauth_consumer_key"; @@ -32,12 +34,17 @@ * * @return true if the user has a role of instructor, contentdeveloper or teachingassistant */ - public static boolean isStaff(String roles) { + public static boolean isStaff(String roles, ExtServer extServer) { List rolesToSearchFor = new LinkedList(); rolesToSearchFor.add("urn:lti:role:ims/lis/Instructor"); rolesToSearchFor.add("urn:lti:role:ims/lis/ContentDeveloper"); rolesToSearchFor.add("urn:lti:role:ims/lis/TeachingAssistant"); + String toolConsumerMonitorRoles = extServer.getLtiToolConsumerMonitorRoles(); + if (toolConsumerMonitorRoles != null) { + rolesToSearchFor.addAll(Arrays.asList(toolConsumerMonitorRoles.split(","))); + } + return hasRole(roles, rolesToSearchFor); }