166 lines
6.5 KiB
Ruby
166 lines
6.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# Copyright (C) 2018 - present Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
module Lti::Messages
|
|
# A "factory" class that builds an ID Token (JWT) to be used in LTI Advantage
|
|
# LTI Deep Linking Requests. These requests indicate to the launched
|
|
# tool that Canvas expects it to return data via deep linking.
|
|
#
|
|
# This class relies on a another class (LtiAdvantage::Messages::DeepLinkingRequest)
|
|
# to model the data in the JWT body and produce a signature.
|
|
#
|
|
# For details on the data included in the ID token please refer
|
|
# to http://www.imsglobal.org/spec/lti-dl/v2p0.
|
|
#
|
|
# For implementation details on LTI Advantage launches in
|
|
# Canvas, please see the inline documentation of
|
|
# app/models/lti/lti_advantage_adapter.rb.
|
|
class DeepLinkingRequest < JwtMessage
|
|
DEEP_LINKING_DETAILS = {
|
|
"assignment_selection" => {
|
|
accept_multiple: false,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze,
|
|
"collaboration" => {
|
|
accept_multiple: false,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: true,
|
|
document_targets: %w[iframe].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze,
|
|
"conference_selection" => {
|
|
accept_multiple: false,
|
|
accept_types: %w[link html].freeze,
|
|
auto_create: true,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[text/html */*].freeze
|
|
}.freeze,
|
|
"course_assignments_menu" => {
|
|
accept_multiple: true,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze,
|
|
"editor_button" => {
|
|
accept_multiple: true,
|
|
accept_types: %w[link file html ltiResourceLink image].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[embed iframe window].freeze,
|
|
media_types: %w[image/* text/html application/vnd.ims.lti.v1.ltilink */*].freeze
|
|
}.freeze,
|
|
"homework_submission" => {
|
|
accept_multiple: false,
|
|
accept_types: %w[file ltiResourceLink].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[iframe].freeze,
|
|
media_types: %w[*/*].freeze
|
|
}.freeze,
|
|
"link_selection" => {
|
|
accept_multiple: true,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze,
|
|
"migration_selection" => {
|
|
accept_multiple: false,
|
|
accept_types: %w[file].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[iframe].freeze,
|
|
media_types: %w[application/vnd.ims.imsccv1p1 application/vnd.ims.imsccv1p2 application/vnd.ims.imsccv1p3 application/zip application/xml].freeze
|
|
}.freeze,
|
|
"module_index_menu_modal" => {
|
|
accept_multiple: true,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: true,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze,
|
|
"module_menu_modal" => {
|
|
accept_multiple: true,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: true,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze,
|
|
"submission_type_selection" => {
|
|
accept_multiple: false,
|
|
accept_types: %w[ltiResourceLink].freeze,
|
|
auto_create: false,
|
|
document_targets: %w[iframe window].freeze,
|
|
media_types: %w[application/vnd.ims.lti.v1.ltilink].freeze
|
|
}.freeze
|
|
}.freeze
|
|
|
|
MODAL_PLACEMENTS = %w[editor_button assignment_selection link_selection migration_selection course_assignments_menu module_index_menu_modal module_menu_modal].freeze
|
|
|
|
def initialize(tool:, context:, user:, expander:, return_url:, opts: {})
|
|
super
|
|
@message = LtiAdvantage::Messages::DeepLinkingRequest.new
|
|
end
|
|
|
|
def generate_post_payload_message(validate_launch: true)
|
|
add_deep_linking_request_claims!
|
|
super
|
|
end
|
|
|
|
private
|
|
|
|
def add_deep_linking_request_claims!
|
|
lti_assignment_id = Lti::Security.decoded_lti_assignment_id(@expander.controller&.params&.[]("secure_params"))
|
|
assignment = Assignment.find_by(lti_context_id: lti_assignment_id) if lti_assignment_id
|
|
content_item_id = @expander.collaboration&.id
|
|
@message.deep_linking_settings.deep_link_return_url = return_url(assignment&.id, content_item_id)
|
|
@message.deep_linking_settings.accept_types = DEEP_LINKING_DETAILS.dig(placement, :accept_types)
|
|
@message.deep_linking_settings.accept_presentation_document_targets = DEEP_LINKING_DETAILS.dig(placement, :document_targets)
|
|
@message.deep_linking_settings.accept_media_types = DEEP_LINKING_DETAILS.dig(placement, :media_types).join(",")
|
|
@message.deep_linking_settings.auto_create = DEEP_LINKING_DETAILS.dig(placement, :auto_create)
|
|
@message.deep_linking_settings.accept_multiple = DEEP_LINKING_DETAILS.dig(placement, :accept_multiple)
|
|
end
|
|
|
|
def placement
|
|
@opts[:resource_type]
|
|
end
|
|
|
|
def return_url(assignment_id = nil, content_item_id = nil)
|
|
@expander.controller.polymorphic_url(
|
|
[@context, :deep_linking_response],
|
|
deep_link_params(assignment_id, content_item_id)
|
|
)
|
|
end
|
|
|
|
def deep_link_params(assignment_id, content_item_id)
|
|
{
|
|
data: Lti::DeepLinkingData.jwt_from({
|
|
modal: MODAL_PLACEMENTS.include?(placement),
|
|
placement:,
|
|
context_module_id: @opts[:context_module_id],
|
|
assignment_id:,
|
|
content_item_id:,
|
|
parent_frame_context: @opts[:parent_frame_context]
|
|
}.compact),
|
|
}
|
|
end
|
|
end
|
|
end
|