@SuppressWarnings("unchecked") protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String ipAddress = request.getRemoteAddr(); if (M_log.isDebugEnabled()) { M_log.debug("Basic LTI Provider request from IP=" + ipAddress); } String enabled = ServerConfigurationService.getString("basiclti.provider.enabled", null); if (enabled == null || !("true".equals(enabled))) { M_log.warn("Basic LTI Provider is Disabled IP=" + ipAddress); response.sendError(HttpServletResponse.SC_FORBIDDEN, "Basic LTI Provider is Disabled"); return; } if ("/casa.json".equals(request.getPathInfo())) { if (ServerConfigurationService.getBoolean("casa.provider.enabled", true)) { handleCASAList(request, response); return; } else { M_log.warn("CASA Provider is Disabled IP=" + ipAddress); response.sendError(HttpServletResponse.SC_FORBIDDEN, "CASA Provider is Disabled"); return; } } if ("/canvas-config.xml".equals(request.getPathInfo())) { if (ServerConfigurationService.getBoolean("canvas.config.enabled", true)) { handleCanvasConfig(request, response); return; } else { M_log.warn("Canvas config is Disabled IP=" + ipAddress); response.sendError(HttpServletResponse.SC_FORBIDDEN, "Canvas config is Disabled"); return; } } // If this is a LTI request of any kind, make sure we don't have any // prior payload in the session. if (BasicLTIUtil.isRequest(request)) { Session sess = SessionManager.getCurrentSession(); sess.removeAttribute("payload"); } // Check if we support ContentItem. // If we are doing ContentItem and have a payload and are not a launch // short-circuit to ContentItem if ("/content.item".equals(request.getPathInfo())) { if (!ServerConfigurationService.getBoolean("contentitem.provider", true)) { M_log.warn("ContentItem is Disabled IP=" + ipAddress); response.sendError(HttpServletResponse.SC_FORBIDDEN, "ContentItem is Disabled"); return; } else { Session sess = SessionManager.getCurrentSession(); Map session_payload = (Map) sess.getAttribute("payload"); if (session_payload != null) { // Post-Login requests to content.item M_log.debug("ContentItem already logged in " + sess.getUserId()); handleContentItem(request, response, session_payload); return; } } } if (M_log.isDebugEnabled()) { Map<String, String[]> params = (Map<String, String[]>) request.getParameterMap(); for (Map.Entry<String, String[]> param : params.entrySet()) { M_log.debug(param.getKey() + ":" + param.getValue()[0]); } } Map payload = getPayloadAsMap(request); // Get the list of highly trusted consumers from sakai.properties. // If the incoming consumer is highly trusted, we use the context_id and // site_id as is, // ie without prefixing them with the oauth_consumer_key first. // We also don't both checking their roles in the site. boolean isTrustedConsumer = BasicLTIProviderUtil.isHighlyTrustedConsumer(payload); /* * Get the list of email trusted consumers from sakai.properties. If the * incoming consumer is email trusted, we use the email address provided * by the consumer and look up the "user" info from sakai instead of * consumer's. This use case is especially valuable if 2 different LMS's * acting as TP and TC referring to same user and can be uniquely * identified by email address. more details SAK-29372 */ boolean isEmailTrustedConsumer = BasicLTIProviderUtil.isEmailTrustedConsumer(payload); /* * Checking if the email trusted consumer property and trusted consumer * and not both enabled. the case would be an error condition */ if (isTrustedConsumer && isEmailTrustedConsumer) { M_log.warn( "Both Email Trusted and Trusted Consumer property is enabled, this is invalid IP=" + ipAddress); response.sendError( HttpServletResponse.SC_FORBIDDEN, "Both Email Trusted and Trusted Consumer property is enabled, this is invalid "); return; } try { invokeProcessors(payload, isTrustedConsumer, ProcessingState.beforeValidation); validate(payload, isTrustedConsumer); invokeProcessors(payload, isTrustedConsumer, ProcessingState.afterValidation); User user = userFinderOrCreator.findOrCreateUser(payload, isTrustedConsumer, isEmailTrustedConsumer); invokeProcessors(payload, isTrustedConsumer, ProcessingState.afterUserCreation, user); // Check if we are loop-backing on the same server, and already logged in as same user Session sess = SessionManager.getCurrentSession(); String serverUrl = SakaiBLTIUtil.getOurServerUrl(); String ext_sakai_server = (String) payload.get("ext_sakai_server"); if ("/content.item".equals(request.getPathInfo()) && isTrustedConsumer && ext_sakai_server != null && ext_sakai_server.equals(serverUrl) && user.getId().equals(sess.getUserId())) { M_log.debug("ContentItem looping back as " + sess.getUserId()); sess.setAttribute("payload", payload); handleContentItem(request, response, payload); return; } loginUser(ipAddress, user); // Re-grab the session sess = SessionManager.getCurrentSession(); invokeProcessors(payload, isTrustedConsumer, ProcessingState.afterLogin, user); // This needs to happen after login, when we have a session for the user. userLocaleSetter.setupUserLocale(payload, user, isTrustedConsumer, isEmailTrustedConsumer); userPictureSetter.setupUserPicture(payload, user, isTrustedConsumer, isEmailTrustedConsumer); // The first launch of content.item - no site needed if ("/content.item".equals(request.getPathInfo())) { M_log.debug("ContentItem inital external login " + sess.getUserId()); sess.setAttribute("payload", payload); handleContentItem(request, response, payload); return; } Site site = findOrCreateSite(payload, isTrustedConsumer); invokeProcessors(payload, isTrustedConsumer, ProcessingState.afterSiteCreation, user, site); siteEmailPreferenceSetter.setupUserEmailPreferenceForSite( payload, user, site, isTrustedConsumer); site = siteMembershipUpdater.addOrUpdateSiteMembership(payload, isTrustedConsumer, user, site); invokeProcessors(payload, isTrustedConsumer, ProcessingState.afterSiteMembership, user, site); String toolPlacementId = addOrCreateTool(payload, isTrustedConsumer, user, site); invokeProcessors(payload, isTrustedConsumer, ProcessingState.beforeLaunch, user, site); syncSiteMembershipsOnceThenSchedule(payload, site, isTrustedConsumer, isEmailTrustedConsumer); // Construct a URL to this tool StringBuilder url = new StringBuilder(); url.append(SakaiBLTIUtil.getOurServerUrl()); url.append(ServerConfigurationService.getString("portalPath", "/portal")); url.append("/tool-reset/"); url.append(toolPlacementId); url.append("?panel=Main"); if (M_log.isDebugEnabled()) { M_log.debug("url=" + url.toString()); } // String toolLink = ServerConfigurationService.getPortalUrl()+ "/tool-reset/" + placement_id // + "?panel=Main"; // Compensate for bug in getPortalUrl() // toolLink = toolLink.replace("IMS BLTI Portlet", "portal"); response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_FOUND); response.sendRedirect(url.toString()); } catch (LTIException ltiException) { doError( request, response, ltiException.getErrorKey(), ltiException.getMessage(), ltiException.getCause()); } /* PrintWriter out = response.getWriter(); out.println("<body><div style=\"text-align: center\">"); out.println(" <br/> <br/> <br/> <br/>"); out.println(" <br/> <br/> <br/> <br/>"); out.println("<a href=\"" + url.toString() + "\">"); out.println("<span id=\"hideme\">" + rb.getString("launch.continue") + "</span>"); out.println("</a>"); out.println(" <script language=\"javascript\"> \n" + " document.getElementById(\"hideme\").style.display = \"none\";\n" + " location.href=\"" + url.toString() + "\";\n" + " </script> \n"); out.println("</div>"); out.println("</body>"); out.close(); */ }