canvas-lms/app/models/lti/lti_outbound_adapter.rb

109 lines
4.0 KiB
Ruby

module Lti
class LtiOutboundAdapter
cattr_writer :consumer_instance_class
def self.consumer_instance_class
@@consumer_instance_class || LtiOutbound::LTIConsumerInstance
end
def initialize(tool, user, context)
@tool = tool
@user = user
@context = context
if @context.respond_to? :root_account
@root_account = @context.root_account
elsif @tool.context.respond_to? :root_account
@root_account = @tool.context.root_account
else
raise('Root account required for generating LTI content')
end
end
# @argument opts
# resource_type:
# selected_html: selected text to be sent to the tool provider as text
# launch_url: a specific launch url for this launch
# link_code: the resource_link_id for this launch
# overrides
def prepare_tool_launch(return_url, variable_expander, opts = {})
resource_type = opts[:resource_type]
selected_html = opts[:selected_html]
launch_url = opts[:launch_url] || default_launch_url(resource_type)
link_code = opts[:link_code] || default_link_code
@overrides = opts[:overrides] || {}
lti_context = Lti::LtiContextCreator.new(@context, @tool).convert
lti_user = Lti::LtiUserCreator.new(@user, @root_account, @tool, @context).convert if @user
lti_tool = Lti::LtiToolCreator.new(@tool).convert
lti_account = Lti::LtiAccountCreator.new(@context, @tool).convert
@tool_launch = LtiOutbound::ToolLaunch.new(
{
url: launch_url,
link_code: link_code,
return_url: return_url,
resource_type: resource_type,
selected_html: selected_html,
outgoing_email_address: HostUrl.outgoing_email_address,
context: lti_context,
user: lti_user,
tool: lti_tool,
account: lti_account,
variable_expander: variable_expander,
disable_lti_post_only: @root_account.feature_enabled?(:disable_lti_post_only)
}
)
self
end
def generate_post_payload
raise('Called generate_post_payload before calling prepare_tool_launch') unless @tool_launch
@tool_launch.generate(@overrides)
end
def generate_post_payload_for_assignment(assignment, outcome_service_url, legacy_outcome_service_url, lti_turnitin_outcomes_placement_url)
raise('Called generate_post_payload_for_assignment before calling prepare_tool_launch') unless @tool_launch
lti_assignment = Lti::LtiAssignmentCreator.new(assignment, encode_source_id(assignment)).convert
@tool_launch.for_assignment!(lti_assignment, outcome_service_url, legacy_outcome_service_url, lti_turnitin_outcomes_placement_url)
generate_post_payload
end
def generate_post_payload_for_homework_submission(assignment)
raise('Called generate_post_payload_for_homework_submission before calling prepare_tool_launch') unless @tool_launch
lti_assignment = Lti::LtiAssignmentCreator.new(assignment).convert
@tool_launch.for_homework_submission!(lti_assignment)
generate_post_payload
end
def launch_url
raise('Called launch_url before calling prepare_tool_launch') unless @tool_launch
@tool_launch.url
end
# this is the lis_result_sourcedid field in the launch, and the
# sourcedGUID/sourcedId in BLTI basic outcome requests.
# it's a secure signature of the (tool, course, assignment, user). Combined with
# the pre-determined shared secret that the tool signs requests with, this
# ensures that only this launch of the tool can modify the score.
def encode_source_id(assignment)
@tool.shard.activate do
payload = [@tool.id, @context.id, assignment.id, @user.id].join('-')
"#{payload}-#{Canvas::Security.hmac_sha1(payload)}"
end
end
private
def default_launch_url(resource_type = nil)
resource_type ? @tool.extension_setting(resource_type, :url) : @tool.url
end
def default_link_code
@tool.opaque_identifier_for(@context)
end
end
end