Skip to content

Commit

Permalink
SAK-50682 LTI Add support for 1EdTech PNP URL to launch data
Browse files Browse the repository at this point in the history
  • Loading branch information
csev committed Nov 16, 2024
1 parent fcebf08 commit 4f5f76e
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5932,3 +5932,17 @@
# lti.encryption.key=some-string-that-you-keep-secret
# DEFAULT: none

# Configure a 1EdTech Personal Needs & Preferences (PNP) Server
# The @ sign is a place holder in the PNP URL for either the user_id or email (see below)
# lti.pnp.baseurl=https://pnp.amp-up.io/ims/afapnp/v1p0/users/@/afapnprecords
# DEFAULT: none

# Normally for PNP we include the user_id value from the LTI launch. How the user_id is
# set in Sakai and in the PNP server is a bit of a complex issue but using the user_id
# from the launch if the right default. However, sometimes for testing it is simpler to
# user the email so a tester can reliable re-create a user on an empty system to test
# PNP. Setting this to true is fine on dev or test servers but probably is not suitable
# on a production system. If there is no PNP base URL, this value has no effect.
# lti.pnp.use_email=false
# DEFAULT: false

Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
import org.tsugi.lti13.objects.LaunchLIS;
import org.tsugi.lti13.objects.NamesAndRoles;
import org.tsugi.lti13.objects.GroupService;
import org.tsugi.lti13.objects.PNPService;
import org.tsugi.lti13.objects.ResourceLink;
import org.tsugi.lti13.objects.ToolPlatform;
import org.tsugi.lti13.objects.ForUser;
Expand Down Expand Up @@ -2048,6 +2049,22 @@ public static String[] postLaunchJWT(Properties toolProps, Properties ltiProps,
lj.group_service = gs;
}

// SAK-50682 - Add support for PNPService
String pnpBaseUrl = ServerConfigurationService.getString("lti.pnp.baseurl", null);
Boolean pnpUseEmail = ServerConfigurationService.getBoolean("lti.pnp.use_email", false);
String user_email = ltiProps.getProperty(LTIConstants.LIS_PERSON_CONTACT_EMAIL_PRIMARY);
if ( StringUtils.isNotEmpty(user_id) && StringUtils.isNotEmpty(pnpBaseUrl) ) {
PNPService ps = new PNPService();
String pnp_settings_service_url = pnpBaseUrl;
if ( pnpUseEmail && StringUtils.isNotEmpty(user_email) ) {
pnp_settings_service_url = pnp_settings_service_url.replace("@", user_email);
} else {
pnp_settings_service_url = pnp_settings_service_url.replace("@", user_id);
}
ps.pnp_settings_service_url = pnp_settings_service_url;
lj.pnp_service = ps;
}

// Add Sakai Extensions from ltiProps
SakaiExtension se = new SakaiExtension();
se.copyFromPost(ltiProps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ public class LaunchJWT extends BaseJWT {
@JsonProperty("https://purl.imsglobal.org/spec/lti-gs/claim/groupsservice")
public GroupService group_service;

@JsonProperty("https://purl.imsglobal.org/spec/lti-pnp/claim/pnpservice")
public PNPService pnp_service;

// This is in LaunchJWTs
@JsonProperty("nonce")
public String nonce;
Expand Down
42 changes: 42 additions & 0 deletions lti/tsugi-util/src/java/org/tsugi/lti13/objects/PNPService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.tsugi.lti13.objects;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.List;
import java.util.ArrayList;

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)

/* Spec in Draft - This is from Paul G
$pnpHost = 'https://pnp.amp-up.io';
$pnpBase = '/ims/afapnp/v1p0';
$requestparams['launch_pnp_settings_service_url'] = $pnpHost . $pnpBase . '/users/' . $USER->id . '/afapnprecords';
$pnp_launch_settings = array(
'pnp_settings_service_url' => $parms['launch_pnp_settings_service_url'],
'scope' => array('https://purl.imsglobal.org/spec/lti-pnp/scope/pnpsettings.readonly'),
'pnp_supported_versions' => array('http://purl.imsglobal.org/spec/afapnp/v1p0/schema/openapi/afapnpv1p0service_openapi3_v1p0')
);
$payload['https://purl.imsglobal.org/spec/lti-pnp/claim/pnpservice'] = $pnp_launch_settings;
*/

public class PNPService extends org.tsugi.jackson.objects.JacksonBase {
public static String SCOPE_PNP_READONLY = "https://purl.imsglobal.org/spec/lti-pnp/scope/pnpsettings.readonly";
public static String VERSION_1_0 = "http://purl.imsglobal.org/spec/afapnp/v1p0/schema/openapi/afapnpv1p0service_openapi3_v1p0";

@JsonProperty("scope")
public List<String> scope = new ArrayList<String>();
@JsonProperty("pnp_settings_service_url")
public String pnp_settings_service_url;
@JsonProperty("pnp_supported_versions")
public List<String> pnp_supported_versions = new ArrayList<String>();

public PNPService() {
this.scope.add(SCOPE_PNP_READONLY);
this.pnp_supported_versions.add(VERSION_1_0);
}

}
50 changes: 50 additions & 0 deletions lti/tsugi-util/src/test/org/tsugi/lti13/PNPServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.tsugi.lti13;

import static org.junit.Assert.*;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

import org.tsugi.lti13.objects.PNPService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;

/**
*
* @author csev
*/
public class PNPServiceTest {

@Test
public void testConstructor() throws com.fasterxml.jackson.core.JsonProcessingException {

PNPService ps = new PNPService();
assertNotNull(ps);
assertEquals(ps.pnp_supported_versions.size(),1);
assertEquals(ps.pnp_supported_versions.get(0), ps.VERSION_1_0);

assertEquals(ps.scope.size(),1);
assertEquals(ps.scope.get(0), ps.SCOPE_PNP_READONLY);
ps.pnp_settings_service_url = "https://www.myuniv.example.com/2344/groups";

ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(ps);
String jsonTest = "{\"scope\":[\"https://purl.imsglobal.org/spec/lti-pnp/scope/pnpsettings.readonly\"],\"pnp_settings_service_url\":\"https://www.myuniv.example.com/2344/groups\",\"pnp_supported_versions\":[\"http://purl.imsglobal.org/spec/afapnp/v1p0/schema/openapi/afapnpv1p0service_openapi3_v1p0\"]}";
assertEquals(jsonString, jsonTest);
}

@Test
public void testAddServiceVersion() {
PNPService groupService = new PNPService();
groupService.pnp_supported_versions.add("1.1");
assertTrue(groupService.pnp_supported_versions.contains("1.1"));
}

}

0 comments on commit 4f5f76e

Please sign in to comment.