Skip to content

Commit

Permalink
Merge pull request sakaiproject#835 from pushyamig/SAK-29372
Browse files Browse the repository at this point in the history
SAK-29372 sakai as LTI provider to trust TC emailaddress as userid
  • Loading branch information
bethkirschner committed Jul 14, 2015
2 parents 593aece + 6ef7c47 commit bee36d1
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

public interface SiteMembershipsSynchroniser {

public void synchroniseSiteMemberships(String siteId, String membershipsId, String membershipsUrl, String oauth_consumer_key, String callbackType);
public void synchroniseSiteMemberships(String siteId, String membershipsId, String membershipsUrl, String oauth_consumer_key, boolean isEmailTrustedConsumer, String callbackType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@
*/
public interface UserFinderOrCreator {

public User findOrCreateUser(Map payload, boolean trustedConsumer) throws LTIException;
public User findOrCreateUser(Map payload, boolean trustedConsumer, boolean isEmailTrustedConsumer) throws LTIException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
*/
public interface UserLocaleSetter {

public void setupUserLocale(Map payload, User user, boolean isTrustedConsumer);
public void setupUserLocale(Map payload, User user, boolean isTrustedConsumer, boolean isEmailTrustedConsumer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public interface UserPictureSetter {
* @param user The provisioned user who MUST be already logged in.
* @param isTrustedConsumer If this is true, do nothing as we assume that a local
* user corresponding to the consumer user already exists
* @param isEmailTrustedConsumer If this is true, do nothing as we assume that a local
* user corresponding to the consumer user already exists
*/
public void setupUserPicture(Map payload, User user, boolean isTrustedConsumer);
public void setupUserPicture(Map payload, User user, boolean isTrustedConsumer, boolean isEmailTrustedConsumer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private void popAdvisor() {
SecurityService.popAdvisor();
}

public void synchroniseSiteMemberships(final String siteId, final String membershipsId, final String membershipsUrl, final String oauth_consumer_key, final String callbackType) {
public void synchroniseSiteMemberships(final String siteId, final String membershipsId, final String membershipsUrl, final String oauth_consumer_key, boolean isEmailTrustedConsumer, final String callbackType) {

Site site = null;

Expand All @@ -92,17 +92,17 @@ public void synchroniseSiteMemberships(final String siteId, final String members
}

if (BasicLTIConstants.LTI_VERSION_1.equals(callbackType)) {
synchronizeLTI1SiteMemberships(site, membershipsId, membershipsUrl, oauth_consumer_key);
synchronizeLTI1SiteMemberships(site, membershipsId, membershipsUrl, oauth_consumer_key, isEmailTrustedConsumer);
} else if ("ext-moodle-2".equals(callbackType)) {
// This is non standard. Moodle's core LTI plugin does not currently do memberships and
// a fix for this has been proposed at https://tracker.moodle.org/browse/MDL-41724. I don't
// think this will ever become core and the first time memberships will appear in core lti
// is with LTI2. At that point this code will be replaced with standard LTI2 JSON type stuff.
synchronizeMoodleExtSiteMemberships(site, membershipsId, membershipsUrl, oauth_consumer_key);
synchronizeMoodleExtSiteMemberships(site, membershipsId, membershipsUrl, oauth_consumer_key, isEmailTrustedConsumer);
}
}

private final void synchronizeLTI1SiteMemberships(final Site site, final String membershipsId, final String membershipsUrl, final String oauth_consumer_key) {
private final void synchronizeLTI1SiteMemberships(final Site site, final String membershipsId, final String membershipsUrl, final String oauth_consumer_key, boolean isEmailTrustedConsumer) {

// Lookup the secret
final String configPrefix = "basiclti.provider." + oauth_consumer_key + ".";
Expand Down Expand Up @@ -140,13 +140,13 @@ private final void synchronizeLTI1SiteMemberships(final Site site, final String
bw.flush();
bw.close();

processMembershipsResponse(connection, site, oauth_consumer_key);
processMembershipsResponse(connection, site, oauth_consumer_key, isEmailTrustedConsumer);
} catch (Exception e) {
e.printStackTrace();
}
}

private final void synchronizeMoodleExtSiteMemberships(final Site site, final String membershipsId, final String membershipsUrl, final String oauth_consumer_key) {
private final void synchronizeMoodleExtSiteMemberships(final Site site, final String membershipsId, final String membershipsUrl, final String oauth_consumer_key, boolean isEmailTrustedConsumer) {

// Lookup the secret
final String configPrefix = "basiclti.provider." + oauth_consumer_key + ".";
Expand Down Expand Up @@ -214,13 +214,13 @@ private final void synchronizeMoodleExtSiteMemberships(final Site site, final St
bw.flush();
bw.close();

processMembershipsResponse(connection, site, oauth_consumer_key);
processMembershipsResponse(connection, site, oauth_consumer_key, isEmailTrustedConsumer);
} catch (Exception e) {
e.printStackTrace();
}
}

private void processMembershipsResponse(HttpURLConnection connection, Site site, String oauth_consumer_key) throws Exception {
private void processMembershipsResponse(HttpURLConnection connection, Site site, String oauth_consumer_key, boolean isEmailTrustedConsumer) throws Exception {

M_log.debug("processMembershipsResponse");

Expand Down Expand Up @@ -264,7 +264,7 @@ private void processMembershipsResponse(HttpURLConnection connection, Site site,
map.put(OAuth.OAUTH_CONSUMER_KEY, oauth_consumer_key);
map.put("tool_id", "n/a");

User user = userFinderOrCreator.findOrCreateUser(map, false);
User user = userFinderOrCreator.findOrCreateUser(map, false,isEmailTrustedConsumer);
member.userId = user.getId();
siteMembershipUpdater.addOrUpdateSiteMembership(map, false, user, site);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.sakaiproject.lti.impl;

import java.util.Collection;
import java.util.Map;

import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -43,13 +44,17 @@ public void setUserDirectoryService(UserDirectoryService userDirectoryService) {
this.userDirectoryService = userDirectoryService;
}

public User findOrCreateUser(Map payload, boolean trustedConsumer) throws LTIException {
public User findOrCreateUser(Map payload, boolean trustedConsumer, boolean emailtrusted) throws LTIException {

User user;
String eid=null;
String user_id = (String) payload.get(BasicLTIConstants.USER_ID);

// Get the eid, either from the value provided or if trusted get it from the user_id,otherwise construct it.
String eid = getEid(payload, trustedConsumer, user_id);
if(!emailtrusted){
eid = getEid(payload, trustedConsumer, user_id);
}


// If we did not get first and last name, split lis_person_name_full
final String fullname = (String) payload.get(BasicLTIConstants.LIS_PERSON_NAME_FULL);
Expand All @@ -67,47 +72,65 @@ public User findOrCreateUser(Map payload, boolean trustedConsumer) throws LTIExc
}
}

// If trusted consumer, login, otherwise check for existing user and create one if required
// If trusted consumer, login, if email trusted consumer then we look up the user info based on the email address otherwise check for existing user and create one if required
// Note that if trusted, then the user must have already logged into Sakai in order to have an account stub created for them
// otherwise this will fail since they don't exist. Perhaps this should be addressed?
if (trustedConsumer) {
try {
if (BasicLTIUtil.isNotBlank((String) payload.get(BasicLTIConstants.EXT_SAKAI_PROVIDER_EID))) {
user = userDirectoryService.getUserByEid(eid);
} else {
user = userDirectoryService.getUser(user_id);
}
} catch (UserNotDefinedException e) {
throw new LTIException("launch.user.invalid", "user_id=" + user_id, e);
}

} else {

try {
user = userDirectoryService.getUserByEid(eid);
} catch (Exception e) {
if (M_log.isDebugEnabled()) {
M_log.debug(e.getLocalizedMessage(), e);
}
user = null;
}
try {
if (BasicLTIUtil.isNotBlank((String) payload.get(BasicLTIConstants.EXT_SAKAI_PROVIDER_EID))) {
user = userDirectoryService.getUserByEid(eid);
} else {
user = userDirectoryService.getUser(user_id);
}
} catch (UserNotDefinedException e) {
throw new LTIException("launch.user.invalid", "user_id=" + user_id, e);
}
return user;
}
/*
* looking up user based on email address may return multiple results,
* this is not a valid case hence this is an error condition with this
* work flow
*/
if (emailtrusted) {
Collection<User> findUsersByEmail = userDirectoryService.findUsersByEmail((String) email);
if (!findUsersByEmail.isEmpty()) {
if (findUsersByEmail.size() > 1) {
M_log.warn("multiple user id's exist for emailaddress= " + email);
throw new LTIException("launch.user.multiple.emailaddress", "email=" + email,null);
}
user = (User) findUsersByEmail.toArray()[0];
} else {
M_log.warn("Invalid user for emailaddress= " + email);
throw new LTIException("launch.user.invalid", "email=" + email,null);
}
return user;
}

if (user == null) {
try {
String hiddenPW = IdManager.createUuid();
userDirectoryService.addUser(null, eid, fname, lname, email, hiddenPW, "registered", null);
M_log.info("Created user=" + eid);
user = userDirectoryService.getUserByEid(eid);
} catch (Exception e) {
throw new LTIException("launch.create.user", "user_id=" + user_id, e);
}
}
try {
user = userDirectoryService.getUserByEid(eid);
} catch (Exception e) {
if (M_log.isDebugEnabled()) {
M_log.debug(e.getLocalizedMessage(), e);
}
user = null;
}

// post the login event
// eventTrackingService().post(eventTrackingService().newEvent(EVENT_LOGIN,
// null, true));
if (user == null) {
try {
String hiddenPW = IdManager.createUuid();
userDirectoryService.addUser(null, eid, fname, lname, email, hiddenPW, "registered", null);
M_log.info("Created user=" + eid);
user = userDirectoryService.getUserByEid(eid);
} catch (Exception e) {
throw new LTIException("launch.create.user", "user_id=" + user_id, e);
}
}

// post the login event
// eventTrackingService().post(eventTrackingService().newEvent(EVENT_LOGIN,
// null, true));

return user;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ public class UserLocaleSetterImpl implements UserLocaleSetter {
public void setPreferencesService(PreferencesService preferencesService) {
this.preferencesService = preferencesService;
}

public void setupUserLocale(Map payload, User user, boolean isTrustedConsumer) {
/* Email Trusted consumer case we are not creating the user, we look up the user based on the email address.
snd user Locale must already be set and simply return*/
public void setupUserLocale(Map payload, User user, boolean isTrustedConsumer, boolean isEmailTrustedConsumer) {

if(isTrustedConsumer) return;
if(isEmailTrustedConsumer)return;

// BLTI-153. Set up user's language.
String locale = (String) payload.get(BasicLTIConstants.LAUNCH_PRESENTATION_LOCALE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,13 @@ public void setProfilePreferencesLogic(ProfilePreferencesLogic profilePreference
* @param user The provisioned user who MUST be already logged in.
* @param isTrustedConsumer If this is true, do nothing as we assume that a local
* user corresponding to the consumer user already exists
* @param isEmailTrustedConsumer If this is true, do nothing as we assume that a local
* user corresponding to the consumer user already exists
*/
public void setupUserPicture(Map payload, User user, boolean isTrustedConsumer) {
public void setupUserPicture(Map payload, User user, boolean isTrustedConsumer, boolean isEmailTrustedConsumer) {

if(isTrustedConsumer) return;
if(isEmailTrustedConsumer)return;

String imageUrl = (String) payload.get(BasicLTIConstants.USER_IMAGE);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.imsglobal.basiclti.BasicLTIProviderUtil;

import java.util.List;
import java.util.Map;

import org.sakaiproject.lti.api.LTIException;
import org.sakaiproject.lti.api.LTIService;
import org.sakaiproject.lti.api.SiteMembershipsSynchroniser;
Expand All @@ -29,7 +29,7 @@ public void setSiteMembershipsSynchroniser(SiteMembershipsSynchroniser siteMembe
}

public void execute(JobExecutionContext context) throws JobExecutionException {

M_log.info("SiteMembershipsSyncJob.execute");

// Get the current list of jobs
Expand All @@ -41,8 +41,9 @@ public void execute(JobExecutionContext context) throws JobExecutionException {
String membershipsUrl = (String) job.get("memberships_url");
String consumerKey = (String) job.get("consumerkey");
String ltiVersion = (String) job.get("lti_version");
boolean isEmailTrustedConsumer= BasicLTIProviderUtil.isEmailTrustedConsumer(consumerKey);

siteMembershipsSynchroniser.synchroniseSiteMemberships(siteId, membershipsId, membershipsUrl, consumerKey, ltiVersion);
siteMembershipsSynchroniser.synchroniseSiteMemberships(siteId, membershipsId, membershipsUrl, consumerKey, isEmailTrustedConsumer,ltiVersion);
}
}
}
1 change: 1 addition & 0 deletions basiclti/basiclti-portlet/src/bundle/basiclti.properties
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ launch.site.tool.missing = Unable to find tool in site
launch.site.tool.denied = Not allowed to access tool
launch.provided.eid.invalid = The provided eid was invalid
launch.user.site.unknown = Could not determine the user's site ID
launch.user.multiple.emailaddress=multiple user id's exist for emailaddress

gradable.information=Routing Grades to the Gradebook
gradable.title=Select Gradebook Item: <br/>
Expand Down
Loading

0 comments on commit bee36d1

Please sign in to comment.