lti2 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/lti2/version.rb +1 -1
- data/lti2_tc/Gemfile +14 -0
- data/lti2_tc/Gemfile.lock +94 -0
- data/lti2_tc/MIT-LICENSE +20 -0
- data/lti2_tc/README.rdoc +3 -0
- data/lti2_tc/Rakefile +34 -0
- data/lti2_tc/app/assets/javascripts/lti2_tc/application.js +13 -0
- data/lti2_tc/app/assets/stylesheets/lti2_tc/application.css +13 -0
- data/lti2_tc/app/controllers/lti2_tc/application_controller.rb +13 -0
- data/lti2_tc/app/controllers/lti2_tc/deployment_requests_controller.rb +9 -0
- data/lti2_tc/app/controllers/lti2_tc/tool_consumer_profiles_controller.rb +23 -0
- data/lti2_tc/app/controllers/lti2_tc/tool_proxies_controller.rb +8 -0
- data/lti2_tc/app/controllers/lti2_tc/tool_settings_controller.rb +215 -0
- data/lti2_tc/app/controllers/lti2_tc/tools_controller.rb +361 -0
- data/lti2_tc/app/models/lti2_tc/deployment_request.rb +43 -0
- data/lti2_tc/app/models/lti2_tc/link.rb +24 -0
- data/lti2_tc/app/models/lti2_tc/registry.rb +4 -0
- data/lti2_tc/app/models/lti2_tc/resource.rb +6 -0
- data/lti2_tc/app/models/lti2_tc/tool.rb +12 -0
- data/lti2_tc/app/models/lti2_tc/tool_consumer_profile.rb +4 -0
- data/lti2_tc/app/models/lti2_tc/tool_consumer_registry.rb +24 -0
- data/lti2_tc/app/models/lti2_tc/tool_registration.rb +83 -0
- data/lti2_tc/app/models/lti2_tc/tool_setting.rb +61 -0
- data/lti2_tc/app/services/lti2_tc/authorizer.rb +36 -0
- data/lti2_tc/app/services/lti2_tc/lti2_launch.rb +259 -0
- data/lti2_tc/app/views/layouts/lti2_tc/application.html.erb +14 -0
- data/lti2_tc/app/views/lti2_tc/deployment_requests/show.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tool_consumer_profiles/index.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tool_consumer_profiles/show.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tool_proxies_controller/index.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tool_settings_controller/show.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tool_settings_controller/update.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tools_controller/create.html.erb +2 -0
- data/lti2_tc/app/views/lti2_tc/tools_controller/show.html.erb +2 -0
- data/lti2_tc/bin/rails +8 -0
- data/lti2_tc/config/routes.rb +20 -0
- data/lti2_tc/db/migrate/20140826141858_create_lti2_tool_consumer_tables.rb +94 -0
- data/lti2_tc/db/migrate/20140826150753_create_lti2_tc_resources.rb +37 -0
- data/lti2_tc/db/migrate/20141027193548_insert_tool_guid.rb +5 -0
- data/lti2_tc/lib/lti2_tc.rb +4 -0
- data/lti2_tc/lib/lti2_tc/engine.rb +5 -0
- data/lti2_tc/lib/lti2_tc/version.rb +3 -0
- data/lti2_tc/lib/tasks/lti2_tc_tasks.rake +4 -0
- data/lti2_tc/lti2_tc.gemspec +27 -0
- data/lti2_tc/test/controllers/lti2_tc/deployment_requests_controller_test.rb +11 -0
- data/lti2_tc/test/controllers/lti2_tc/tool_consumer_profiles_controller_test.rb +16 -0
- data/lti2_tc/test/controllers/lti2_tc/tool_proxies_controller_controller_test.rb +11 -0
- data/lti2_tc/test/controllers/lti2_tc/tool_settings_controller_controller_test.rb +16 -0
- data/lti2_tc/test/controllers/lti2_tc/tools_controller_controller_test.rb +16 -0
- data/lti2_tc/test/dummy/README.rdoc +28 -0
- data/lti2_tc/test/dummy/Rakefile +6 -0
- data/lti2_tc/test/dummy/app/assets/javascripts/application.js +13 -0
- data/lti2_tc/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/lti2_tc/test/dummy/app/controllers/application_controller.rb +5 -0
- data/lti2_tc/test/dummy/app/helpers/application_helper.rb +2 -0
- data/lti2_tc/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/lti2_tc/test/dummy/bin/bundle +3 -0
- data/lti2_tc/test/dummy/bin/rails +4 -0
- data/lti2_tc/test/dummy/bin/rake +4 -0
- data/lti2_tc/test/dummy/config.ru +4 -0
- data/lti2_tc/test/dummy/config/application.rb +23 -0
- data/lti2_tc/test/dummy/config/boot.rb +5 -0
- data/lti2_tc/test/dummy/config/database.yml +39 -0
- data/lti2_tc/test/dummy/config/environment.rb +5 -0
- data/lti2_tc/test/dummy/config/environments/development.rb +29 -0
- data/lti2_tc/test/dummy/config/environments/production.rb +80 -0
- data/lti2_tc/test/dummy/config/environments/test.rb +36 -0
- data/lti2_tc/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/lti2_tc/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/lti2_tc/test/dummy/config/initializers/inflections.rb +16 -0
- data/lti2_tc/test/dummy/config/initializers/mime_types.rb +5 -0
- data/lti2_tc/test/dummy/config/initializers/secret_token.rb +12 -0
- data/lti2_tc/test/dummy/config/initializers/session_store.rb +3 -0
- data/lti2_tc/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/lti2_tc/test/dummy/config/locales/en.yml +23 -0
- data/lti2_tc/test/dummy/config/routes.rb +4 -0
- data/lti2_tc/test/dummy/db/database.yml +39 -0
- data/lti2_tc/test/dummy/db/migrate/20131121225051_create_lti2_tc_registries.lti2_tc.rb +55 -0
- data/lti2_tc/test/dummy/db/schema.rb +68 -0
- data/lti2_tc/test/dummy/public/404.html +58 -0
- data/lti2_tc/test/dummy/public/422.html +58 -0
- data/lti2_tc/test/dummy/public/500.html +57 -0
- data/lti2_tc/test/dummy/public/favicon.ico +0 -0
- data/lti2_tc/test/fixtures/lti2_tc/registries.yml +7 -0
- data/lti2_tc/test/helpers/lti2_tc/deployment_requests_helper_test.rb +6 -0
- data/lti2_tc/test/helpers/lti2_tc/tool_consumer_profiles_helper_test.rb +6 -0
- data/lti2_tc/test/helpers/lti2_tc/tool_proxies_controller_helper_test.rb +6 -0
- data/lti2_tc/test/helpers/lti2_tc/tool_settings_controller_helper_test.rb +6 -0
- data/lti2_tc/test/helpers/lti2_tc/tools_controller_helper_test.rb +6 -0
- data/lti2_tc/test/integration/navigation_test.rb +10 -0
- data/lti2_tc/test/lti2_tc_test.rb +7 -0
- data/lti2_tc/test/models/lti2_tc/registries_test.rb +9 -0
- data/lti2_tc/test/test_helper.rb +15 -0
- metadata +93 -1
@@ -0,0 +1,361 @@
|
|
1
|
+
require_dependency 'lti2_tc/application_controller'
|
2
|
+
|
3
|
+
module Lti2Tc
|
4
|
+
class ToolsController < Lti2Tc::ApplicationController
|
5
|
+
include OAuth::OAuthProxy
|
6
|
+
include Lti2Commons::Utils
|
7
|
+
|
8
|
+
LTI2TC_SESSION_MAP = 'lti2_tc_session_map'
|
9
|
+
|
10
|
+
CORRELATION_ID = 'VND-IMS-CORRELATION-ID'
|
11
|
+
DISPOSITION = 'VND-IMS-DISPOSITION'
|
12
|
+
|
13
|
+
DISPOSITION_COMMIT = 'commit'
|
14
|
+
DISPOSITION_ABORT = 'abort'
|
15
|
+
|
16
|
+
|
17
|
+
def create
|
18
|
+
rack_parameters = OAuthRequest.collect_rack_parameters request
|
19
|
+
|
20
|
+
(tool_proxy_wrapper, status, error_msg) = process_tool_proxy(request)
|
21
|
+
if error_msg.present?
|
22
|
+
( render :json => { :errors => [error_msg] }, :status => status ) and return
|
23
|
+
end
|
24
|
+
|
25
|
+
end_registration_id = request.headers[CORRELATION_ID]
|
26
|
+
|
27
|
+
disposition = (tool_proxy_wrapper.root.has_key? 'tool_proxy_guid') ? 'reregister' : 'register'
|
28
|
+
if disposition == 'register'
|
29
|
+
reg_key = rack_parameters[:oauth_consumer_key]
|
30
|
+
@deployment_request = Lti2Tc::DeploymentRequest.where(:reg_key => reg_key).first
|
31
|
+
else
|
32
|
+
reg_key = tool_proxy_wrapper.root['tool_proxy_guid']
|
33
|
+
tool = Lti2Tc::Tool.where(:key => reg_key).first
|
34
|
+
@deployment_request = Lti2Tc::DeploymentRequest.where(:tool_proxy_guid => reg_key).first
|
35
|
+
end
|
36
|
+
|
37
|
+
# prompt for disposition
|
38
|
+
session_map = {}
|
39
|
+
session[LTI2TC_SESSION_MAP] = session_map
|
40
|
+
session_map['deployment_request_id'] = @deployment_request.id
|
41
|
+
@deployment_request.disposition = disposition
|
42
|
+
@deployment_request.end_registration_id = end_registration_id
|
43
|
+
@deployment_request.tool_proxy_json = tool_proxy_wrapper.root.to_json
|
44
|
+
@deployment_request.save
|
45
|
+
|
46
|
+
if disposition == 'reregister'
|
47
|
+
#tool = Tool.where(:key => reg_key).last
|
48
|
+
#tool.new_deployment_request_id = @deployment_request.id
|
49
|
+
#tool.save
|
50
|
+
(render :nothing => true, :status => 201) and return
|
51
|
+
end
|
52
|
+
|
53
|
+
secret = @deployment_request.reg_password
|
54
|
+
begin
|
55
|
+
oauth_validation_using_secret secret
|
56
|
+
rescue
|
57
|
+
(render :json => {:errors => ['Invalid signature']}, :status => 401) and return
|
58
|
+
end
|
59
|
+
|
60
|
+
# generate guid for tool_proxy
|
61
|
+
tool_proxy_guid = UUID.generate
|
62
|
+
tool_proxy_wrapper.root['tool_proxy_guid'] = tool_proxy_guid
|
63
|
+
tool_proxy_wrapper.substitute_text_in_all_nodes '{', '}', {'tool_proxy_guid' => tool_proxy_guid}
|
64
|
+
tool_consumer_registry = Rails.application.config.tool_consumer_registry
|
65
|
+
|
66
|
+
product_name = tool_proxy_wrapper.first_at('tool_profile.product_instance.product_info.product_name.default_value')
|
67
|
+
|
68
|
+
@tool = Tool.new
|
69
|
+
@tool.is_enabled = false
|
70
|
+
|
71
|
+
@tool.tool_proxy = JSON.pretty_generate tool_proxy_wrapper.root
|
72
|
+
@tool.product_name = product_name
|
73
|
+
@tool.description = tool_proxy_wrapper.first_at('tool_profile.product_instance.product_info.description.default_value')
|
74
|
+
@tool.key = tool_proxy_guid
|
75
|
+
@tool.secret = tool_proxy_wrapper.first_at('security_contract.shared_secret')
|
76
|
+
@tool.status = 'registered'
|
77
|
+
@tool.end_registration_id = end_registration_id
|
78
|
+
|
79
|
+
# TEMPORARY: enable tool...FOR DEMOS
|
80
|
+
# @tool.is_enabled = true
|
81
|
+
|
82
|
+
@tool.save
|
83
|
+
|
84
|
+
resource_nodes = tool_proxy_wrapper.first_at('tool_profile.resource_handler')
|
85
|
+
|
86
|
+
# course 2(SMPL101), 11 & 12 DEP from conformance test
|
87
|
+
target_courses = [2, 5, 6]
|
88
|
+
for resource_node in resource_nodes
|
89
|
+
target_courses.each do |course_id|
|
90
|
+
# create resource-relative jsonpath
|
91
|
+
resource_json_obj = JsonWrapper.new resource_node
|
92
|
+
resource = Resource.new
|
93
|
+
resource.tool = @tool
|
94
|
+
resource.resource_type = resource_json_obj.first_at('resource_type.code')
|
95
|
+
resource.resource_name = resource_json_obj.first_at('resource_name.default_value')
|
96
|
+
resource.description = resource_json_obj.first_at('description.default_value')
|
97
|
+
resource.save
|
98
|
+
|
99
|
+
# TEMPORARY: auto-create one link for SMPL101 (#2)
|
100
|
+
link = Lti2Tc::Link.new
|
101
|
+
link.course_id = course_id
|
102
|
+
link.resource = resource
|
103
|
+
link.resource_link_label = resource.resource_name
|
104
|
+
link_parameter_str = "{"
|
105
|
+
if ["Book", "BookSelection", "InteractiveResource"].include? resource.resource_name
|
106
|
+
link_parameter_str += "\"vbid\":\"L-999-74180\""
|
107
|
+
end
|
108
|
+
if resource.resource_name == "BookSelection"
|
109
|
+
link_parameter_str += ",\"book_location\":\"outline\/3\""
|
110
|
+
end
|
111
|
+
link_parameter_str += "}"
|
112
|
+
link.link_parameters = link_parameter_str
|
113
|
+
|
114
|
+
# and a grade_item for resource iResource only
|
115
|
+
if resource.resource_name == "InteractiveResource"
|
116
|
+
grade_item = GradeItem.new
|
117
|
+
grade_item.course_id = link.course_id
|
118
|
+
grade_item.label = "IRTestGrade"
|
119
|
+
grade_item.save
|
120
|
+
|
121
|
+
link.grade_item_id = grade_item.id
|
122
|
+
end
|
123
|
+
|
124
|
+
link.is_enabled = true
|
125
|
+
link.save
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# create links for conformance test
|
130
|
+
tc_profile_url = tool_proxy_wrapper.first_at('tool_consumer_profile')
|
131
|
+
tc_profile_guid = tc_profile_url.split('/').last if tc_profile_url =~ /\//
|
132
|
+
|
133
|
+
tool_proxy_guid = tool_proxy_wrapper.first_at('tool_proxy_guid')
|
134
|
+
tool_proxy_id = "#{tool_consumer_registry.tc_deployment_url}/tools/#{tool_proxy_guid}"
|
135
|
+
tool_proxy_wrapper.root['@id'] = tool_proxy_id
|
136
|
+
@tool.tool_proxy = JSON.pretty_generate tool_proxy_wrapper.root
|
137
|
+
|
138
|
+
capture_and_excise_settings(tool_proxy_wrapper.root, @tool)
|
139
|
+
|
140
|
+
@tool.save
|
141
|
+
|
142
|
+
@deployment_request.tool_proxy_guid = tool_proxy_guid
|
143
|
+
@deployment_request.save
|
144
|
+
|
145
|
+
#@deployment_request.delete
|
146
|
+
|
147
|
+
|
148
|
+
tool_proxy_response = {
|
149
|
+
"@context" => "http://purl.imsglobal.org/ctx/lti/v2/ToolProxyId",
|
150
|
+
"@type" => "ToolProxy",
|
151
|
+
"@id" => tool_proxy_id,
|
152
|
+
"tool_proxy_guid" => tool_proxy_guid
|
153
|
+
}
|
154
|
+
|
155
|
+
content_type = 'application/vnd.ims.lti.v2.toolproxy.id+json'
|
156
|
+
logger.info( "Exit from Tool/create(POST)--status 201 content-type: #{content_type}" )
|
157
|
+
logger.info( JSON.dump( tool_proxy_response ) )
|
158
|
+
|
159
|
+
render :json => tool_proxy_response, :content_type => content_type, :status => '201'
|
160
|
+
end
|
161
|
+
|
162
|
+
def show
|
163
|
+
oauth_validation
|
164
|
+
|
165
|
+
id_parm = params[:id]
|
166
|
+
match = /^id=(\d+)/.match( id_parm )
|
167
|
+
if match.present?
|
168
|
+
id = match[1]
|
169
|
+
@tool = Lti2Tc::Tool.find_by_id( id )
|
170
|
+
else
|
171
|
+
@tool = Lti2Tc::Tool.where( :key => id_parm ).first
|
172
|
+
end
|
173
|
+
( render :text => "Unauthorized", :status => 401 unless @tool.present? ) and return
|
174
|
+
secret = @tool.secret
|
175
|
+
#oauth_validation_using_secret secret
|
176
|
+
|
177
|
+
tool_proxy_str = @tool.tool_proxy
|
178
|
+
tool_proxy = JSON.load( tool_proxy_str )
|
179
|
+
|
180
|
+
# merge in Tool Settings for ToolProxy level
|
181
|
+
tool_settings = Lti2Tc::ToolSetting.where( :scopeable_id => @tool.id )
|
182
|
+
tool_settings_custom = {}
|
183
|
+
tool_settings.each do |tool_setting|
|
184
|
+
tool_settings_custom[tool_setting.name] = tool_setting.value
|
185
|
+
end
|
186
|
+
if tool_settings_custom.length > 0
|
187
|
+
tool_settings_custom['@id'] = ""
|
188
|
+
tool_proxy[:custom] = tool_settings_custom
|
189
|
+
end
|
190
|
+
|
191
|
+
tool_proxy_pretty_str = JSON.pretty_generate( tool_proxy )
|
192
|
+
|
193
|
+
content_type = 'application/vnd.ims.lti.v2.toolproxy+json'
|
194
|
+
|
195
|
+
logger.info( "Exit from Tool/show(GET)--status: 200 content-type: #{content_type}" )
|
196
|
+
logger.info( JSON.dump( tool_proxy_pretty_str ) )
|
197
|
+
|
198
|
+
render :text => "<pre>#{tool_proxy_pretty_str}</pre>", :content_type => content_type
|
199
|
+
end
|
200
|
+
|
201
|
+
def reregister_continue
|
202
|
+
|
203
|
+
|
204
|
+
message_type = "reregistration"
|
205
|
+
|
206
|
+
tool_id = params[:tool_id]
|
207
|
+
@tool = Lti2Tc::Tool.find(tool_id)
|
208
|
+
new_deployment_request_id = @tool.new_deployment_request_id
|
209
|
+
@deployment_request = DeploymentRequest.find(new_deployment_request_id)
|
210
|
+
tool_proxy_wrapper = JsonWrapper.new(@deployment_request.tool_proxy_json)
|
211
|
+
|
212
|
+
@tool.end_registration_id = @deployment_request.end_registration_id
|
213
|
+
@tool.save
|
214
|
+
|
215
|
+
tool_proxy_guid = tool_proxy_wrapper.first_at('tool_proxy_guid')
|
216
|
+
tool_consumer_registry = Rails.application.config.tool_consumer_registry
|
217
|
+
tool_proxy_id = "#{tool_consumer_registry.tc_deployment_url}/tools/#{tool_proxy_guid}"
|
218
|
+
|
219
|
+
# Post EndRegistration
|
220
|
+
tool_proxy_service_hash = {}
|
221
|
+
content_type = 'application/vnd.ims.lti.v2.toolproxy.id+json'
|
222
|
+
reregistration_service = nil
|
223
|
+
reregistration_service_endpoint = nil
|
224
|
+
|
225
|
+
tool_proxy_wrapper.root['tool_profile']['service_offered'].each do |service|
|
226
|
+
if service['format'][0] == content_type
|
227
|
+
reregistration_service = service
|
228
|
+
end
|
229
|
+
if reregistration_service.nil?
|
230
|
+
return [nil, 500, 'No reregistration service defined']
|
231
|
+
end
|
232
|
+
reregistration_service_endpoint = reregistration_service['endpoint']
|
233
|
+
if reregistration_service_endpoint.nil?
|
234
|
+
return [nil, 500, 'No reregistration endpoint defined in reregistration service']
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
end_registration_request = {
|
239
|
+
"@context" => "http://purl.imsglobal.org/ctx/lti/v2/ToolProxyId",
|
240
|
+
"@type" => "ToolProxy",
|
241
|
+
"@id" => tool_proxy_id,
|
242
|
+
"tool_proxy_guid" => tool_proxy_guid
|
243
|
+
}
|
244
|
+
|
245
|
+
headers = {}
|
246
|
+
headers[CORRELATION_ID] = @tool.end_registration_id
|
247
|
+
headers[DISPOSITION] = DISPOSITION_COMMIT
|
248
|
+
|
249
|
+
#DEBUG ONLY
|
250
|
+
if reregistration_service_endpoint.include? 'http://localhost:5000'
|
251
|
+
reregistration_service_endpoint.sub!('http://localhost:5000', 'http://localhost:5100')
|
252
|
+
end
|
253
|
+
|
254
|
+
#response = HTTParty.post reregistration_service_endpoint, :body => end_registration_request.to_json, :headers => headers
|
255
|
+
signed_request = create_signed_request \
|
256
|
+
reregistration_service_endpoint,
|
257
|
+
'POST',
|
258
|
+
@tool.key,
|
259
|
+
@tool.secret,
|
260
|
+
{},
|
261
|
+
end_registration_request.to_json,
|
262
|
+
"application/vnd.ims.lti.v2.toolproxy.id+json"
|
263
|
+
|
264
|
+
puts "Register request: #{signed_request.signature_base_string}"
|
265
|
+
puts "Register secret: #{@tool.secret}"
|
266
|
+
response = invoke_service(signed_request, Rails.application.config.wire_log, "Reregister ToolProxy",
|
267
|
+
CORRELATION_ID => @tool.end_registration_id, DISPOSITION => DISPOSITION_COMMIT)
|
268
|
+
# handle response error
|
269
|
+
|
270
|
+
product_name = tool_proxy_wrapper.first_at('tool_profile.product_instance.product_info.product_name.default_value')
|
271
|
+
|
272
|
+
@tool.tool_proxy = JSON.pretty_generate tool_proxy_wrapper.root
|
273
|
+
@tool.product_name = product_name
|
274
|
+
@tool.description = tool_proxy_wrapper.first_at('tool_profile.product_instance.product_info.description.default_value')
|
275
|
+
@tool.key = tool_proxy_wrapper.first_at('tool_proxy_guid')
|
276
|
+
@tool.secret = tool_proxy_wrapper.first_at('security_contract.shared_secret')
|
277
|
+
@tool.new_deployment_request_id = nil
|
278
|
+
|
279
|
+
tool_proxy_wrapper.root['@id'] = tool_proxy_id
|
280
|
+
|
281
|
+
@tool.tool_proxy = JSON.pretty_generate tool_proxy_wrapper.root
|
282
|
+
|
283
|
+
capture_and_excise_settings(tool_proxy_wrapper.root, @tool)
|
284
|
+
|
285
|
+
@tool.save
|
286
|
+
|
287
|
+
redirect_to @tool.registration_return_url
|
288
|
+
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
# for this reference impl: tool proxy settings system-of-record is db not TP itself
|
293
|
+
def capture_and_excise_settings( tool_proxy, tool )
|
294
|
+
settings = tool_proxy['custom']
|
295
|
+
if settings.present?
|
296
|
+
Lti2Tc::ToolSetting.where( :scopeable_type => 'Tool', :tool_id => tool.id ).delete_all
|
297
|
+
|
298
|
+
settings.each_pair do |k,v|
|
299
|
+
ts = Lti2Tc::ToolSetting.create(
|
300
|
+
:scopeable_type => 'Tool',
|
301
|
+
:tool_id => tool.id,
|
302
|
+
:scopeable_id => tool.id,
|
303
|
+
:name => k,
|
304
|
+
:value => v
|
305
|
+
)
|
306
|
+
ts.save
|
307
|
+
end
|
308
|
+
|
309
|
+
tool_proxy.delete( 'custom' )
|
310
|
+
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def check_for_validity(tool_proxy_wrapper)
|
315
|
+
if tool_proxy_wrapper.first_at('security_contract.shared_secret').blank?
|
316
|
+
return 'Missing shared_secret'
|
317
|
+
end
|
318
|
+
|
319
|
+
# check that services are a subset of those offered
|
320
|
+
# first, grab guid from tc_profile_url
|
321
|
+
tc_profile_guid = tool_proxy_wrapper.root['tool_consumer_profile'].split('/').last
|
322
|
+
tcp_obj = ToolConsumerProfile.where( :tc_profile_guid => tc_profile_guid ).first
|
323
|
+
tcp_str = tcp_obj.tc_profile
|
324
|
+
tcp = JsonWrapper.new( tcp_str ).root
|
325
|
+
tcp_service_hash = {}
|
326
|
+
tcp['service_offered'].each { |service| tcp_service_hash[service['@id']] = service['action'] }
|
327
|
+
tool_proxy_wrapper.root['security_contract']['tool_service'].each do |tp_service_item|
|
328
|
+
if tcp_service_hash.keys.include?( tp_service_item['service'] )
|
329
|
+
tp_service_item['action'].each do |action|
|
330
|
+
unless tcp_service_hash[tp_service_item['service']].include?( action )
|
331
|
+
return "Service #{tp_service_item['service']} does not support #{action}"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
else
|
335
|
+
return "Service mismatch on #{tp_service_item['service']}"
|
336
|
+
end
|
337
|
+
end
|
338
|
+
nil
|
339
|
+
end
|
340
|
+
|
341
|
+
def process_tool_proxy(request)
|
342
|
+
json_str = request.body.read
|
343
|
+
|
344
|
+
begin
|
345
|
+
tool_proxy_wrapper = JsonWrapper.new(json_str)
|
346
|
+
rescue
|
347
|
+
return [ nil, 400, 'JSON validation failure' ]
|
348
|
+
end
|
349
|
+
|
350
|
+
error_msg = check_for_validity(tool_proxy_wrapper)
|
351
|
+
if error_msg.present?
|
352
|
+
return [ nil, 400, error_msg ]
|
353
|
+
end
|
354
|
+
|
355
|
+
logger.info("ToolProxy as received: ")
|
356
|
+
logger.info(JSON.pretty_generate(tool_proxy_wrapper.root))
|
357
|
+
|
358
|
+
[tool_proxy_wrapper, nil, nil]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
include Lti2Commons
|
2
|
+
include MessageSupport
|
3
|
+
include Signer
|
4
|
+
|
5
|
+
module Lti2Tc
|
6
|
+
|
7
|
+
class DeploymentRequest < ActiveRecord::Base
|
8
|
+
|
9
|
+
after_initialize :initialize_fields
|
10
|
+
|
11
|
+
def create_lti_message( base_url, current_user )
|
12
|
+
parameters = create_request_tool_deployment( base_url, current_user.to_s )
|
13
|
+
create_lti_message_body( partner_url, parameters,
|
14
|
+
Rails.application.config.wire_log, 'Request Tool Registration' )
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_request_tool_deployment( base_url, user_id, lti_message_type = 'ToolProxyRegistrationRequest' )
|
18
|
+
parameters = {
|
19
|
+
'lti_message_type' => lti_message_type,
|
20
|
+
'lti_version' => 'LTI-2p0',
|
21
|
+
'user_id' => "#{user_id}",
|
22
|
+
'roles' => 'urn:lti:sysrole:ims/lis/SysAdmin',
|
23
|
+
'tc_profile_url' => "#{base_url}/lti2_tc/tool_consumer_profiles/#{self.tc_profile_guid}",
|
24
|
+
'reg_key' => self.reg_key,
|
25
|
+
'reg_password' => self.reg_password,
|
26
|
+
'launch_presentation_return_url' => "#{base_url}/admin/tool_actions",
|
27
|
+
'launch_presentation_document_target' => 'window'
|
28
|
+
}
|
29
|
+
parameters
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def initialize_fields
|
35
|
+
unless persisted?
|
36
|
+
self.reg_key = UUID.generate
|
37
|
+
self.tc_profile_guid = UUID.generate
|
38
|
+
self.reg_password = SecureRandom.hex
|
39
|
+
self.status = 'prepared'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
include Lti2Commons
|
2
|
+
include MessageSupport
|
3
|
+
include Signer
|
4
|
+
|
5
|
+
module Lti2Tc
|
6
|
+
|
7
|
+
class Link < ActiveRecord::Base
|
8
|
+
belongs_to :course
|
9
|
+
belongs_to :resource
|
10
|
+
has_many :tool_settings, :as => :scopeable
|
11
|
+
|
12
|
+
attr_accessor :is_link_visible, :url, :toggle_label, :grade_item_label, :grade_result
|
13
|
+
|
14
|
+
def lti_launch( user, return_url )
|
15
|
+
enrollment = Enrollment.where( :admin_user_id => user.id, :course_id => course.id ).first
|
16
|
+
Lti2Tc::Lti2Launch.new( user, self, self.resource, self.course, enrollment, return_url ).launch()
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_ready_for_use
|
20
|
+
self.is_enabled and self.resource.tool.is_enabled
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Lti2Tc
|
2
|
+
class Tool < ActiveRecord::Base
|
3
|
+
has_many :resources
|
4
|
+
has_many :tool_settings, :as => :scopeable
|
5
|
+
|
6
|
+
attr_accessor :toggle_label, :new_tool_proxy_url
|
7
|
+
|
8
|
+
def get_tool_proxy
|
9
|
+
Lti2Commons::JsonWrapper.new( self.tool_proxy )
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|