submit orginal turnitin submission

Fixes Plat-1168

Test-plan:
Submit a turnitin assignment using the lti tool
it should create a submission with the submitted file as an attachment

Change-Id: I37b24f8d2cb5c78f1247a0096f1afe2f3528abcb
Reviewed-on: https://gerrit.instructure.com/59701
Reviewed-by: Brad Horrocks <bhorrocks@instructure.com>
Tested-by: Jenkins
Product-Review: Nathan Mills <nathanm@instructure.com>
QA-Review: Nathan Mills <nathanm@instructure.com>
This commit is contained in:
Nathan Mills 2015-07-30 11:03:49 -06:00
parent ddc363b7b3
commit ac14a09bd1
7 changed files with 130 additions and 31 deletions

View File

@ -145,9 +145,14 @@ class LtiApiController < ApplicationController
def turnitin_outcomes_placement
verify_oauth
course, assignment, user = BasicLTI::BasicOutcomes.decode_source_id(@tool, params['lis_result_sourcedid'])
_course, assignment, user = BasicLTI::BasicOutcomes.decode_source_id(@tool, params['lis_result_sourcedid'])
assignment.update_attribute(:turnitin_enabled, false) if assignment.turnitin_enabled?
request.body.rewind
turnitin_processor = Turnitin::OutcomeResponseProcessor.new(@tool, assignment, user, JSON.parse(request.body.read))
turnitin_processor.process
render json: {}, status: 200
rescue BasicLTI::BasicOutcomes::Unauthorized => e
return render :text => e, status:401
end

View File

@ -4,9 +4,7 @@ require 'simple_oauth'
require 'faraday'
require 'faraday_middleware'
module TurnitinApi
require 'turnitin_api/version'
require 'turnitin_api/outcomes_response_transformer'
module TurnitinApi
end

View File

@ -1,5 +1,3 @@
require "turnitin_api/version"
module TurnitinApi
class OutcomesResponseTransformer
@ -7,10 +5,11 @@ module TurnitinApi
# secret
# turnitin_api response
attr_accessor :outcomes_response_json, :key
def initialize(key, secret, outcomes_response_json)
attr_accessor :outcomes_response_json, :key, :lti_params
def initialize(key, secret, lti_params, outcomes_response_json)
@key = key
@secret = secret
@lti_params = lti_params || {}
@outcomes_response_json = outcomes_response_json
end
@ -39,13 +38,22 @@ module TurnitinApi
conn.request :multipart
conn.request :url_encoded
conn.response :json, :content_type => /\bjson$/
conn.use FaradayMiddleware::FollowRedirects
conn.adapter :net_http
end
end
def make_call(url)
header = SimpleOAuth::Header.new(:post, url, {}, consumer_key: @key, consumer_secret: @secret, callback: 'about:blank')
connection.post url, header.signed_attributes
default_params = {
'roles' => 'Learner',
'lti_message_type' => 'basic-lti-launch-request',
'lti_version' => 'LTI-1p0',
'resource_link_id' => SecureRandom.hex(32),
}
params = default_params.merge(lti_params)
header = SimpleOAuth::Header.new(:post, url, params, consumer_key: @key, consumer_secret: @secret,
callback: 'about:blank')
connection.post url, params.merge(header.signed_attributes)
end
end

View File

@ -3,6 +3,7 @@ require 'spec_helper'
describe TurnitinApi::OutcomesResponseTransformer do
let(:oauth_key) { 'key' }
let(:oauth_secret) { 'secret' }
let(:lti_params) { {lti_verions: '1p0'} }
let(:outcomes_response_json) do
{
'lis_result_sourcedid' => "6",
@ -10,12 +11,13 @@ describe TurnitinApi::OutcomesResponseTransformer do
'outcomes_tool_placement_url' => "http://turnitin.com/api/lti/1p0/outcome_tool_data/4321"
}
end
subject { described_class.new(oauth_key, oauth_secret, outcomes_response_json) }
subject { described_class.new(oauth_key, oauth_secret, lti_params, outcomes_response_json) }
describe 'initialize' do
it 'initializes properly' do
expect(subject.key).to eq oauth_key
expect(subject.lti_params). to eq lti_params
expect(subject.outcomes_response_json).to eq outcomes_response_json
end
end

View File

@ -1,17 +1,51 @@
require 'turnitin_api'
module Turnitin
class OutcomeResponseProcessor
class << self
def process(tool, outcomes_response_json)
def initialize(tool, assignment, user, outcomes_response_json)
@tool = tool
@assignment = assignment
@user = user
@outcomes_response_json = outcomes_response_json
end
# create new submission with the file
# save originality data
#
def process
attachment = create_attachment
@assignment.submit_homework(@user ,attachments:[attachment], submission_type: 'online_upload')
end
handle_asynchronously :process, max_attempts: 1, priority: Delayed::LOW_PRIORITY
private
def create_attachment
lti_params = {
'user_id' => Lti::Asset.opaque_identifier_for(@user),
'context_id' => Lti::Asset.opaque_identifier_for(@assignment.context),
'context_title' => @assignment.context.name,
'lis_person_contact_email_primary' => @user.email
}
turnitin_client = TurnitinApi::OutcomesResponseTransformer.new(@tool.consumer_key, @tool.shared_secret, lti_params, @outcomes_response_json)
attachment = nil
Dir.mktmpdir do |dirname|
turnitin_client.original_submission do |response|
filename = response.headers['content-disposition'].match(/filename=(\"?)(.+)\1/)[2]
path = File.join(dirname, filename)
File.open(path, 'wb') do |f|
f.write(response.body)
end
attachment = @assignment.attachments.new(
uploaded_data: Rack::Test::UploadedFile.new(path, response.headers['content-type'], true),
display_name: filename,
user: @user
)
attachment.save!
end
end
attachment
end
end
end

View File

@ -69,11 +69,6 @@ describe LtiApiController, type: :request do
end
# verify tool_id
# check resource_link_id
# verify assignment_id
# check that we a url
end

View File

@ -2,8 +2,65 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb')
module Turnitin
describe OutcomeResponseProcessor do
# attach the file
# save originality data
#
let(:lti_student) { user_model }
let(:lti_course) { course_with_student({user: lti_student}).course }
let(:tool) do
tool = lti_course.context_external_tools.new(
name: "bob",
consumer_key: "bob",
shared_secret: "bob",
tool_id: 'some_tool',
privacy_level: 'public'
)
tool.url = "http://www.example.com/basic_lti"
tool.resource_selection = {
:url => "http://#{HostUrl.default_host}/selection_test",
:selection_width => 400,
:selection_height => 400}
tool.save!
tool
end
let(:lti_assignment) do
assignment = assignment_model(course: lti_course)
tag = assignment.build_external_tool_tag(url: tool.url)
tag.content_type = 'ContextExternalTool'
tag.content_id = tool.id
tag.save!
assignment
end
let(:outcome_response_json) do
{
"paperid" => 200505101,
"outcomes_tool_placement_url" => "https://sandbox.turnitin.com/api/lti/1p0/outcome_tool_data/200505101?lang=en_us",
"lis_result_sourcedid" => Lti::LtiOutboundAdapter.new(tool, lti_student, lti_course).encode_source_id(lti_assignment)
}
end
subject { described_class.new(tool, lti_assignment, lti_student, outcome_response_json) }
describe '#process' do
let(:filename) {'my_sample_file'}
before(:each) do
mock_response = mock('response_mock')
mock_response.stubs(:headers).returns(
{'content-disposition' => "attachment; filename=#{filename}", 'content-type' => 'plain/text'}
)
mock_response.stubs(:body).returns('1234')
TurnitinApi::OutcomesResponseTransformer.any_instance.expects(:original_submission).yields(mock_response)
end
it 'creates an attachment' do
subject.process_without_send_later
attachment = lti_assignment.attachments.first
expect(lti_assignment.attachments.count).to eq 1
expect(attachment.display_name).to eq filename
end
end
end
end