net.paulgray.mocklti2.tools.LtiToolController.java Source code

Java tutorial

Introduction

Here is the source code for net.paulgray.mocklti2.tools.LtiToolController.java

Source

/*
 * 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 net.paulgray.mocklti2.tools;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.paulgray.mocklti2.web.LtiLaunchRequest;
import org.apache.commons.lang3.StringUtils;
import org.imsglobal.aspect.Lti;
import org.imsglobal.basiclti.LtiSigner;
import org.imsglobal.basiclti.LtiSigningException;
import org.imsglobal.basiclti.LtiVerificationResult;
import org.imsglobal.lti2.LTI2Config;
import org.imsglobal.lti2.objects.consumer.ServiceOffered;
import org.imsglobal.lti2.objects.consumer.ToolConsumer;
import org.imsglobal.lti2.objects.consumer.ToolConsumer.LtiCapability;
import org.imsglobal.lti2.objects.provider.ToolProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 * @author paul
 */
@Controller
public class LtiToolController {

    @Autowired
    LTI2Config config;

    @Autowired
    LtiToolService ltiToolService;

    @Autowired
    LtiSigner ltiSigner;

    private final static Logger logger = Logger.getLogger(LtiToolController.class.getName());

    @RequestMapping(value = "/api/tools", method = RequestMethod.GET)
    public ResponseEntity getTools() {
        return new ResponseEntity(ltiToolService.getAll(), HttpStatus.OK);
    }

    @RequestMapping(value = "/api/tools/{toolId}", method = RequestMethod.GET)
    public ResponseEntity getToolForId(@PathVariable("toolId") Integer toolId) {
        return new ResponseEntity(ltiToolService.getToolForId(toolId), HttpStatus.OK);
    }

    @RequestMapping(value = "/api/tools", method = RequestMethod.POST)
    public ResponseEntity addTool(@RequestBody LtiTool tool) {
        return new ResponseEntity(ltiToolService.addTool(tool), HttpStatus.CREATED);
    }

    @RequestMapping(value = "/api/profile", method = RequestMethod.GET)
    public ResponseEntity getConsumerProfile(HttpServletRequest request, HttpServletResponse response,
            @RequestParam String toolId) {
        response.setHeader("Content-type", "application/vnd.ims.lti.v2.ToolConsumerProfile+json");
        ToolConsumer me = new ToolConsumer("guid", "version", "tcp", config);
        me.addCapabilites(Arrays.asList(LtiCapability.BASICLTI_LAUNCH, LtiCapability.USER_ID,
                LtiCapability.USER_IMAGE, LtiCapability.COURSE_SECTION_ID, LtiCapability.MEMBERSHIP_ROLE));
        String endpoint = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
                + request.getContextPath() + "/api/tool_proxy_registration?toolId=" + toolId;
        me.addServiceOffered(new ServiceOffered(endpoint, "tcp:ToolProxy.collection", "RestService",
                ToolProxy.CONTENT_TYPE, "POST"));
        return new ResponseEntity(me, HttpStatus.OK);
    }

    @Lti
    @RequestMapping(value = "/api/tool_proxy_registration", method = RequestMethod.POST)
    public ResponseEntity registerConsumerProfile(HttpServletRequest request, LtiVerificationResult result,
            @RequestBody ToolProxy toolProxy, @RequestParam Integer toolId) throws JsonProcessingException {
        if (!result.getSuccess()) {
            return new ResponseEntity(result.getError() + result.getMessage(), HttpStatus.BAD_REQUEST);
        } else {
            LtiToolProxy ltiToolProxy = new LtiToolProxy();

            //TODO: refactor this whole block... there needs to be a better way!
            ObjectMapper mapper = new ObjectMapper();

            //find the base url for lti launch messages
            String defaultBaseUrl = "";
            String secureBaseUrl = "";
            if (toolProxy.getTool_profile().getBase_url_choice().isArray()) {
                for (JsonNode url_choice : toolProxy.getTool_profile().getBase_url_choice()) {
                    System.out.println("Looking at choice's selector: " + url_choice.get("selector"));
                    if (url_choice.get("selector") != null && url_choice.get("selector").get("applies_to") != null
                            && url_choice.get("selector").get("applies_to").isArray()) {
                        for (JsonNode url_application : url_choice.get("selector").get("applies_to")) {
                            //Does 'MessageHandler' in this context refer to an *lti launch message* ?
                            if (url_application.asText().equals("MessageHandler")) {

                                defaultBaseUrl = url_choice.get("default_base_url").asText();
                                secureBaseUrl = url_choice.get("secure_base_url").asText();
                            }
                        }
                    }
                }
            }
            logger.info("Extracted base url: " + defaultBaseUrl);
            logger.info("Extracted secure base url: " + secureBaseUrl);

            //find the basic-lti-launch-request.
            //This part I'm unsure of. Why is there a "message" attribute on the tool_profile itself, as well as one each resource_handler definition?
            for (JsonNode resource_handler : toolProxy.getTool_profile().getResource_handler()) {
                if (resource_handler.get("message") != null && resource_handler.get("message").isArray()) {
                    for (JsonNode message : resource_handler.get("message")) {
                        if (message.get("message_type") != null && message.get("message_type").asText()
                                .equals(ToolConsumer.LtiCapability.BASICLTI_LAUNCH)) {
                            ltiToolProxy.setDefaultUrl(defaultBaseUrl + message.get("path").asText());
                            ltiToolProxy.setSecureUrl(secureBaseUrl + message.get("path").asText());
                        }
                    }
                }
            }

            ltiToolProxy.setKey(toolProxy.getTool_proxy_guid());
            ltiToolProxy.setSecret(toolProxy.getSecurity_contract().getShared_secret());

            //change the tool's state to "registered"
            LtiTool ltiTool = ltiToolService.getToolForId(toolId);
            ltiTool.getToolProxies().add(ltiToolProxy);
            ltiTool.setState(LtiTool.State.registered);
            ltiToolProxy.setTool(ltiTool);
            ltiToolService.updateTool(ltiTool);
            return new ResponseEntity(HttpStatus.CREATED);
        }
    }

    @RequestMapping(value = "/api/tools/{toolId}/launch", method = RequestMethod.GET)
    public ResponseEntity getToolLaunchForId(@PathVariable("toolId") Integer toolId) {
        LtiTool tool = ltiToolService.getToolForId(toolId);
        List<LtiToolProxy> tools = tool.getToolProxies();
        if (tools.size() > 0) {
            Map<String, String> params = new HashMap<>();
            params.put("user_id", "mockconsumeradmin");
            params.put("lis_person_name_full", "Mock Consumer Admin");

            //These are required for Campus Pack:
            params.put("lti_message_type", "basic-lti-launch-request");
            params.put("lti_version", "LTI-1p0");
            params.put("resource_link_id", "1");
            params.put("tool_consumer_instance_guid", "mock_lti2_consumer");
            params.put("roles", "administrator");

            LtiToolProxy proxy = tools.get(tools.size() - 1);
            String url = proxy.getSecureUrl();
            String secret = proxy.getSecret();
            String key = proxy.getKey();
            String method = "POST";

            Map<String, String> signedParameters = null;
            try {
                signedParameters = ltiSigner.signParameters(params, key, secret, url, method);
            } catch (LtiSigningException e) {
                e.printStackTrace();
                return new ResponseEntity("LtiSigningException occurred: " + e.getMessage(),
                        HttpStatus.INTERNAL_SERVER_ERROR);
            }
            return new ResponseEntity(new LtiLaunchRequest(signedParameters, url, method), HttpStatus.OK);
        } else {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
    }

}