add preview url to attachments graphql response

fixes COMMS-2099

TEST PLAN
* Create a course.
* Add two or more students to the course.
* Create an assignment with file upload submission type. Note the
  assignemnt id in the url.
* Masquerade as one of the users and submit the assignment. Use a zip
  file and an image file (or any other canvadocable mime type) as the
  submission files.
* Masquerade and submit the assignment as your other students, using
  different canvadocable file types (e.g. pdf, png, jpeg).
* As the instructor/site admin Navigate to the /graphiql endpoint.
* run the following query substituting in the assignment id:

  {
    assignment(id: "<your_assignment_id>") {
      submissionsConnection {
        nodes {
          _id
          user {
            name
          }
        }
      }
    }
  }

* Using those submission ids, run the following query for each
  submission id to view the submission preview urls:

  {
    assignment(id: "<your_assignment_id>") {
      submissionsConnection {
        nodes {
          _id
          user {
            name
          }
          attachments {
            submissionPreviewUrl(submissionId: "<submission_id>")
            displayName
          }
        }
      }
    }
  }

* Note that the zip file does not have a preview url and verify that the
  other attachments do.

Change-Id: Ic8e8c0be994f1d6e4979755674a9e8c3d35c038a
Reviewed-on: https://gerrit.instructure.com/196418
Tested-by: Jenkins
Reviewed-by: Cameron Matheson <cameron@instructure.com>
Reviewed-by: Landon Gilbert-Bland <lbland@instructure.com>
QA-Review: Steven Burnett <sburnett@instructure.com>
Product-Review: Steven Burnett <sburnett@instructure.com>
This commit is contained in:
Matthew Lemon 2019-06-03 16:25:25 -06:00
parent adbdbdcd9c
commit 54838b2803
4 changed files with 116 additions and 0 deletions

View File

@ -60,5 +60,59 @@ module Types
opts[:verifier] = object.uuid if context[:in_app] opts[:verifier] = object.uuid if context[:in_app]
GraphQLHelpers::UrlHelpers.file_download_url(object, opts) GraphQLHelpers::UrlHelpers.file_download_url(object, opts)
end end
field :submission_preview_url, Types::UrlType, null: true do
argument :submission_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func("Submission")
end
def submission_preview_url(submission_id:)
return if object.locked_for?(current_user, check_policies: true)
Loaders::IDLoader.for(Submission).load(submission_id).then do |submission|
next unless submission.grants_right?(current_user, session, :read)
# We are checking first to see if the attachment is associated with the given submission id
# to potentially avoid needing to load submission histories which is expensive.
if submission.attachment_ids_for_version.include?(object.id)
load_submission_associations(submission) do |course, assignment|
get_canvadoc_url(course, assignment, submission)
end
else
load_submission_history_associations(submission) do |course, assignment|
attachment_ids = submission.submission_history.map(&:attachment_ids_for_version).flatten
next unless attachment_ids.include?(object.id)
get_canvadoc_url(course, assignment, submission)
end
end
end
end
private
def load_submission_associations(submission)
Loaders::AssociationLoader.for(Submission, :assignment).load(submission).then do |assignment|
Loaders::AssociationLoader.for(Assignment, :context).load(assignment).then do |course|
yield(course, assignment)
end
end
end
def load_submission_history_associations(submission)
load_submission_associations(submission) do |course, assignment|
Loaders::AssociationLoader.for(Submission, :versions).load(submission).then do
yield(course, assignment)
end
end
end
def get_canvadoc_url(course, assignment, submission)
opts = {
anonymous_instructor_annotations: course.grants_right?(current_user, :manage_grade) && assignment.anonymous_instructor_annotations,
moderated_grading_whitelist: submission.moderated_grading_whitelist,
submission_id: submission.id,
enable_annotations: true,
enrollment_type: CoursesHelper.user_type(course, current_user)
}
object.canvadoc_url(current_user, opts)
end
end end
end end

View File

@ -120,6 +120,7 @@ module CoursesHelper
type type
end end
module_function :user_type
def why_cant_i_enable_master_course(course) def why_cant_i_enable_master_course(course)
return nil if MasterCourses::MasterTemplate.is_master_course?(course) return nil if MasterCourses::MasterTemplate.is_master_course?(course)

View File

@ -1052,6 +1052,7 @@ type File implements ModuleItemInterface & Node & Timestamped {
id: ID! id: ID!
mimeClass: String mimeClass: String
modules: [Module!] modules: [Module!]
submissionPreviewUrl(submissionId: ID!): URL
thumbnailUrl: URL thumbnailUrl: URL
updatedAt: DateTime updatedAt: DateTime
url: URL url: URL

View File

@ -61,4 +61,64 @@ describe Types::FileType do
file_type.resolve('url', request: ActionDispatch::TestRequest.create, current_user: @student) file_type.resolve('url', request: ActionDispatch::TestRequest.create, current_user: @student)
).to be_nil ).to be_nil
end end
context 'submission preview url' do
before(:once) do
@assignment = assignment_model(course: @course)
@student_file = attachment_with_context(@student, content_type: "application/pdf")
@submission = @assignment.submit_homework(
@student,
body: 'Attempt 1',
submitted_at: 2.hours.ago,
submission_type: "online_upload",
attachments: [@student_file]
)
AttachmentAssociation.create!(attachment: @student_file, context: @submission, context_type: "Submission")
@resolver = GraphQLTypeTester.new(@student_file, current_user: @student)
end
it 'returns nil if the the file is locked' do
file.update!(locked: true)
expect(
file_type.resolve(
'submissionPreviewUrl(submissionId: "' + @submission.id.to_s + '")',
request: ActionDispatch::TestRequest.create,
current_user: @student
)
).to be_nil
end
it 'returns nil if the file is not a canvadocable type' do
allow(Canvadocs).to receive(:enabled?).and_return true
@student_file.update!(content_type: 'application/loser')
expect(
@resolver.resolve('submissionPreviewUrl(submissionId: "' + @submission.id.to_s + '")')
).to be_nil
end
it 'returns nil if canvadocs is not enabled' do
allow(Canvadocs).to receive(:enabled?).and_return false
expect(
@resolver.resolve('submissionPreviewUrl(submissionId: "' + @submission.id.to_s + '")')
).to be_nil
end
it 'returns nil if the given submission id is not associated with the attachment' do
other_assignment = assignment_model(course: @course)
other_submission = other_assignment.submit_homework(
@student,
body: 'Attempt 1',
submitted_at: 2.hours.ago,
)
resp = @resolver.resolve('submissionPreviewUrl(submissionId: "' + other_submission.id.to_s + '")')
expect(resp).to be_nil
end
it 'returns the submission preview url' do
allow(Canvadocs).to receive(:enabled?).and_return true
resp = @resolver.resolve('submissionPreviewUrl(submissionId: "' + @submission.id.to_s + '")')
expect(resp).not_to be_nil
expect(resp.start_with?('/api/v1/canvadoc_session')).to be true
end
end
end end