canvas-lms/lib/lti/content_item_response.rb

210 lines
6.6 KiB
Ruby

# frozen_string_literal: true
#
# Copyright (C) 2015 - 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/>.
#
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
module Lti
class ContentItemResponse
MEDIA_TYPES = [:assignments, :discussion_topics, :modules, :module_items, :pages, :quizzes, :files]
SUPPORTED_EXPORT_TYPES = %w(common_cartridge)
def initialize(context, controller, current_user, media_types, export_type)
@context = context
@controller = controller #for url generation
@current_user = current_user
@media_types = media_types.with_indifferent_access
@export_type = export_type || 'common_cartridge' #legacy API behavior defaults to common cartridge
raise Lti::Errors::InvalidMediaTypeError unless media_types_valid?
raise Lti::Errors::UnsupportedExportTypeError unless SUPPORTED_EXPORT_TYPES.include? @export_type
end
def query_params
unless @query_params
select = {}
@media_types.each { |k, v| select[k] = v }
@query_params = {"export_type" => @export_type}
@query_params['select'] = select if select.present?
end
@query_params
end
def media_type
unless @media_type
if canvas_media_type == 'module_item'
case tag.content
when Assignment
@media_type = 'assignment'
when DiscussionTopic
@media_type = 'discussion_topic'
when Quizzes::Quiz
@media_type = 'quiz'
when WikiPage
@media_type = 'page'
end
else
@media_type = canvas_media_type
end
end
@media_type
end
def tag
unless @tag
if @media_types.include? :module_items
@tag = @context.context_module_tags.where(id: @media_types[:module_items].first).first
end
end
@tag
end
def file
return unless @media_types.include? :files
unless @file
@file = Attachment.where(:id => @media_types[:files].first).first
if @context.is_a?(Account)
raise ActiveRecord::RecordNotFound unless @file.context == @current_user
elsif @file.context.is_a?(Course)
raise ActiveRecord::RecordNotFound unless @file.context == @context
elsif @file.context.is_a?(Group)
raise ActiveRecord::RecordNotFound unless @file.context.context == @context
end
raise Lti::Errors::UnauthorizedError if @file.locked_for?(@current_user, check_policies: true)
end
@file
end
def title
@title ||= case canvas_media_type
when 'file'
file.display_name
when 'assignment'
@context.assignments.where(id: @media_types[:assignments].first).first.title
when 'discussion_topic'
@context.discussion_topics.where(id: @media_types[:discussion_topics].first).first.title
when 'module'
@context.context_modules.where(id: @media_types[:modules].first).first.name
when 'page'
@context.wiki_pages.where(id: @media_types[:pages].first).first.title
when 'module_item'
tag.title
when 'quiz'
@context.quizzes.where(id: @media_types[:quizzes].first).first.title
when 'course'
@context.name
end
end
def content_type
@content_type ||= @media_types.include?(:files) ? file.content_type : "application/vnd.instructure.api.content-exports.#{media_type}"
end
def url
@url ||= @media_types.include?(:files) ? @controller.file_download_url(file, {:verifier => file.uuid, :download => '1', :download_frd => '1'}) : @controller.api_v1_course_content_exports_url(@context) + '?' + query_params.to_query
end
def as_json(opts={})
case opts[:lti_message_type]
when 'ContentItemSelectionResponse'
content_item_selection_response_json
when 'ContentItemSelection'
content_item_selection_json
else
raise Lti::Errors::UnsupportedMessageTypeError
end
end
private
def canvas_media_type
@canvas_media_type ||= if @media_types.keys.size == 1
@media_types.keys.first.to_s.singularize
else
'course'
end
end
def media_types_valid?
@media_types.each do |type, ids|
scope = case type
when 'files'
Attachment
when 'assignments'
@context.assignments
when 'discussion_topics'
@context.discussion_topics
when 'modules'
@context.context_modules
when 'pages'
@context.wiki_pages
when 'module_items'
@context.context_module_tags
when 'quizzes'
@context.quizzes
end
return false if scope.where(:id => ids).count != ids.count
end
true
end
##
# This message type is deprecated, please use content_item_selection_json
##
def content_item_selection_response_json
{
"@context" => "http://purl.imsglobal.org/ctx/lti/v1/ContentItemPlacement",
"@graph" => [
{
"@type" => "ContentItemPlacement",
"placementOf" => {
"@type" => "FileItem",
"@id" => url,
"mediaType" => content_type,
"title" => title
}
}
]
}
end
def content_item_selection_json
{
"@context" => "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
"@graph" => [
{
"@type" => "FileItem",
"url" => url,
"mediaType" => content_type,
"title" => title,
"copyAdvice" => true
}
]
}
end
end
end