prevent locked content in ePub from redirecting to Canvas web
fixes CNVS-25569 test plan: - have a module in a course locked by prerequisites - embed a link to that module in the description of a course item - export the ePub - the link to that module should direct to its proper location in the ePub instead of Canvas web - all other behaviors should be unchanged regarding locked content Change-Id: I12f9897e73d68ac12c8956fe9231ce35962661ff Reviewed-on: https://gerrit.instructure.com/69759 Tested-by: Jenkins Reviewed-by: John Corrigan <jcorrigan@instructure.com> QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Matt Berns <mberns@instructure.com>
This commit is contained in:
parent
14c8e6a250
commit
1c81f17b5c
|
@ -22,7 +22,7 @@ module CC
|
|||
include TextHelper
|
||||
|
||||
ZIP_DIR = 'zip_dir'
|
||||
|
||||
|
||||
attr_accessor :course, :user, :export_dir, :manifest, :zip_file, :for_course_copy
|
||||
delegate :add_error, :add_item_to_export, :to => :@content_export, :allow_nil => true
|
||||
|
||||
|
@ -61,7 +61,7 @@ module CC
|
|||
@manifest.close
|
||||
copy_all_to_zip
|
||||
@zip_file.close
|
||||
|
||||
|
||||
if @content_export && File.exist?(@zip_path)
|
||||
att = Attachment.new
|
||||
att.context = @content_export
|
||||
|
@ -88,15 +88,15 @@ module CC
|
|||
def referenced_files
|
||||
@manifest ? @manifest.referenced_files : {}
|
||||
end
|
||||
|
||||
|
||||
def set_progress(progress)
|
||||
@content_export.fast_update_progress(progress) if @content_export
|
||||
@content_export.fast_update_progress(progress) if @content_export
|
||||
end
|
||||
|
||||
|
||||
def errors
|
||||
@content_export ? @content_export.error_messages : []
|
||||
end
|
||||
|
||||
|
||||
def export_id
|
||||
@content_export ? @content_export.id : nil
|
||||
end
|
||||
|
@ -108,9 +108,13 @@ module CC
|
|||
def export_symbol?(obj)
|
||||
@content_export ? @content_export.export_symbol?(obj) : true
|
||||
end
|
||||
|
||||
|
||||
def epub_export?
|
||||
@content_export ? @content_export.epub_export.present? : nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def copy_all_to_zip
|
||||
Dir["#{@export_dir}/**/**"].each do |file|
|
||||
file_path = file.sub(@export_dir+'/', '')
|
||||
|
|
|
@ -20,24 +20,24 @@ require 'nokogiri'
|
|||
|
||||
module CC
|
||||
module CCHelper
|
||||
|
||||
|
||||
CANVAS_NAMESPACE = 'http://canvas.instructure.com/xsd/cccv1p0'
|
||||
XSD_URI = 'http://canvas.instructure.com/xsd/cccv1p0.xsd'
|
||||
|
||||
|
||||
# IMS formats/types
|
||||
IMS_DATE = "%Y-%m-%d"
|
||||
IMS_DATETIME = "%Y-%m-%dT%H:%M:%S"
|
||||
CC_EXTENSION = 'imscc'
|
||||
QTI_EXTENSION = ".xml.qti"
|
||||
CANVAS_PLATFORM = 'canvas.instructure.com'
|
||||
|
||||
|
||||
# Common Cartridge 1.0
|
||||
# associatedcontent/imscc_xmlv1p0/learning-application-resource
|
||||
# imsdt_xmlv1p0
|
||||
# imswl_xmlv1p0
|
||||
# imsqti_xmlv1p2/imscc_xmlv1p0/assessment
|
||||
# imsqti_xmlv1p2/imscc_xmlv1p0/question-bank
|
||||
|
||||
|
||||
# Common Cartridge 1.1 (What Canvas exports)
|
||||
ASSESSMENT_TYPE = 'imsqti_xmlv1p2/imscc_xmlv1p1/assessment'
|
||||
QUESTION_BANK = 'imsqti_xmlv1p2/imscc_xmlv1p1/question-bank'
|
||||
|
@ -47,7 +47,7 @@ module CCHelper
|
|||
WEBCONTENT = "webcontent"
|
||||
BASIC_LTI = 'imsbasiclti_xmlv1p0'
|
||||
BLTI_NAMESPACE = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"
|
||||
|
||||
|
||||
# Common Cartridge 1.2
|
||||
# associatedcontent/imscc_xmlv1p2/learning-application-resource
|
||||
# imsdt_xmlv1p2
|
||||
|
@ -63,7 +63,7 @@ module CCHelper
|
|||
|
||||
# QTI-only export
|
||||
QTI_ASSESSMENT_TYPE = 'imsqti_xmlv1p2'
|
||||
|
||||
|
||||
# substitution tokens
|
||||
OBJECT_TOKEN = "$CANVAS_OBJECT_REFERENCE$"
|
||||
COURSE_TOKEN = "$CANVAS_COURSE_REFERENCE$"
|
||||
|
@ -98,15 +98,15 @@ module CCHelper
|
|||
def create_key(object, prepend="")
|
||||
CCHelper.create_key(object, prepend)
|
||||
end
|
||||
|
||||
|
||||
def ims_date(date=nil)
|
||||
CCHelper.ims_date(date)
|
||||
end
|
||||
|
||||
|
||||
def ims_datetime(date=nil)
|
||||
CCHelper.ims_datetime(date)
|
||||
end
|
||||
|
||||
|
||||
def self.create_key(object, prepend="")
|
||||
if object.is_a? ActiveRecord::Base
|
||||
key = object.asset_string
|
||||
|
@ -115,17 +115,17 @@ module CCHelper
|
|||
end
|
||||
"i" + Digest::MD5.hexdigest(prepend + key)
|
||||
end
|
||||
|
||||
|
||||
def self.ims_date(date=nil)
|
||||
date ||= Time.now
|
||||
date.respond_to?(:utc) ? date.utc.strftime(IMS_DATE) : date.strftime(IMS_DATE)
|
||||
end
|
||||
|
||||
|
||||
def self.ims_datetime(date=nil)
|
||||
date ||= Time.now
|
||||
date.respond_to?(:utc) ? date.utc.strftime(IMS_DATETIME) : date.strftime(IMS_DATETIME)
|
||||
end
|
||||
|
||||
|
||||
def get_html_title_and_body_and_id(doc)
|
||||
id = get_node_val(doc, 'html head meta[name=identifier] @content')
|
||||
get_html_title_and_body(doc) << id
|
||||
|
@ -140,7 +140,7 @@ module CCHelper
|
|||
end
|
||||
get_html_title_and_body(doc) << meta_fields
|
||||
end
|
||||
|
||||
|
||||
def get_html_title_and_body(doc)
|
||||
title = get_node_val(doc, 'html head title')
|
||||
body = doc.at_css('html body').to_s.gsub(%r{</?body>}, '').strip
|
||||
|
@ -161,6 +161,7 @@ module CCHelper
|
|||
@user = user
|
||||
@track_referenced_files = opts[:track_referenced_files]
|
||||
@for_course_copy = opts[:for_course_copy]
|
||||
@for_epub_export = opts[:for_epub_export]
|
||||
@referenced_files = {}
|
||||
|
||||
@rewriter.set_handler('file_contents') do |match|
|
||||
|
@ -220,7 +221,7 @@ module CCHelper
|
|||
new_url = match.url
|
||||
if match.obj_id && match.obj_class
|
||||
obj = match.obj_class.where(id: match.obj_id).first
|
||||
if obj && @rewriter.user_can_view_content?(obj)
|
||||
if obj && (@rewriter.user_can_view_content?(obj) || @for_epub_export)
|
||||
# for all other types,
|
||||
# create a migration id for the object, and use that as the new link
|
||||
migration_id = CCHelper.create_key(obj)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
# 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
|
||||
# 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
|
||||
|
@ -27,7 +27,7 @@ module CC
|
|||
include WebResources
|
||||
include WebLinks
|
||||
include BasicLTILinks
|
||||
|
||||
|
||||
delegate :add_error, :set_progress, :export_object?, :export_symbol?, :for_course_copy, :add_item_to_export, :to => :@manifest
|
||||
delegate :referenced_files, :to => :@html_exporter
|
||||
|
||||
|
@ -44,16 +44,17 @@ module CC
|
|||
@html_exporter = CCHelper::HtmlContentExporter.new(@course,
|
||||
@manifest.exporter.user,
|
||||
:for_course_copy => for_course_copy,
|
||||
:for_epub_export => @manifest.exporter.epub_export?,
|
||||
:track_referenced_files => true,
|
||||
:media_object_flavor => Setting.get('exporter_media_object_flavor', nil).presence)
|
||||
end
|
||||
|
||||
|
||||
def self.create_resources(manifest, manifest_node)
|
||||
r = new(manifest, manifest_node)
|
||||
r.create_resources
|
||||
r
|
||||
end
|
||||
|
||||
|
||||
def create_resources
|
||||
@manifest_node.resources do |resources|
|
||||
@resources = resources
|
||||
|
@ -87,6 +88,6 @@ module CC
|
|||
set_progress(progress) if progress
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -570,6 +570,38 @@ describe "Common Cartridge exporting" do
|
|||
check_resource_node(@published, CC::CCHelper::LOR)
|
||||
check_resource_node(@unpublished, CC::CCHelper::LOR, false)
|
||||
end
|
||||
|
||||
it "should always use relevant migration ids in anchor tags when exporting for ePub" do
|
||||
cm1 = @course.context_modules.create!(name: "unlocked module")
|
||||
cm1.publish
|
||||
cm2 = @course.context_modules.create!({
|
||||
name: "locked module",
|
||||
prerequisites: [{:id=>cm1.id, :type=>"context_module", :name=>cm1.name}]
|
||||
})
|
||||
cm2.publish
|
||||
cm1link = %{<a href="/courses/#{@course.id}/modules/#{cm1.id}">Mod 1</a>}
|
||||
cm2link = %{<a href="/courses/#{@course.id}/modules/#{cm2.id}">Mod 2</a>}
|
||||
assignment = @course.assignments.create!({
|
||||
title: 'Assignment 1',
|
||||
description: "go to module 1 at #{cm1link} and module 2 at #{cm2link}"
|
||||
})
|
||||
cm1.completion_requirements = [{:id=>assignment.id, :type=>"must_mark_done"}]
|
||||
cm1.save!
|
||||
|
||||
student_in_course(active_all: true, user_name: "a student")
|
||||
@ce.epub_export = EpubExport.create!({course: @course})
|
||||
@ce.user = @student
|
||||
@ce.save!
|
||||
|
||||
run_export
|
||||
|
||||
assignment_html = @manifest_doc.at_css("file[href$='#{mig_id(assignment)}/assignment-1.html']")
|
||||
html_content = @zip_file.read(assignment_html["href"])
|
||||
|
||||
expect(html_content.match(/\$CANVAS_OBJECT_REFERENCE\$\/modules\/#{mig_id(cm1)}/)).not_to be_nil
|
||||
expect(html_content.match(/\$CANVAS_OBJECT_REFERENCE\$\/modules\/#{mig_id(cm2)}/)).not_to be_nil
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context 'attachment permissions' do
|
||||
|
|
|
@ -15,13 +15,13 @@ describe "Exporter" do
|
|||
|
||||
@attachment = Attachment.create({
|
||||
context: course,
|
||||
filename: 'exortable-test-file',
|
||||
filename: 'exportable-test-file',
|
||||
uploaded_data: File.open(cartridge_path)
|
||||
})
|
||||
|
||||
@attachment_without_modules = Attachment.create({
|
||||
context: course,
|
||||
filename: 'exortable-test-file',
|
||||
filename: 'exportable-test-file',
|
||||
uploaded_data: File.open(cartridge_without_modules_path)
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue