lti2 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/lti2/version.rb +1 -1
  3. data/lti2_tc/Gemfile +14 -0
  4. data/lti2_tc/Gemfile.lock +94 -0
  5. data/lti2_tc/MIT-LICENSE +20 -0
  6. data/lti2_tc/README.rdoc +3 -0
  7. data/lti2_tc/Rakefile +34 -0
  8. data/lti2_tc/app/assets/javascripts/lti2_tc/application.js +13 -0
  9. data/lti2_tc/app/assets/stylesheets/lti2_tc/application.css +13 -0
  10. data/lti2_tc/app/controllers/lti2_tc/application_controller.rb +13 -0
  11. data/lti2_tc/app/controllers/lti2_tc/deployment_requests_controller.rb +9 -0
  12. data/lti2_tc/app/controllers/lti2_tc/tool_consumer_profiles_controller.rb +23 -0
  13. data/lti2_tc/app/controllers/lti2_tc/tool_proxies_controller.rb +8 -0
  14. data/lti2_tc/app/controllers/lti2_tc/tool_settings_controller.rb +215 -0
  15. data/lti2_tc/app/controllers/lti2_tc/tools_controller.rb +361 -0
  16. data/lti2_tc/app/models/lti2_tc/deployment_request.rb +43 -0
  17. data/lti2_tc/app/models/lti2_tc/link.rb +24 -0
  18. data/lti2_tc/app/models/lti2_tc/registry.rb +4 -0
  19. data/lti2_tc/app/models/lti2_tc/resource.rb +6 -0
  20. data/lti2_tc/app/models/lti2_tc/tool.rb +12 -0
  21. data/lti2_tc/app/models/lti2_tc/tool_consumer_profile.rb +4 -0
  22. data/lti2_tc/app/models/lti2_tc/tool_consumer_registry.rb +24 -0
  23. data/lti2_tc/app/models/lti2_tc/tool_registration.rb +83 -0
  24. data/lti2_tc/app/models/lti2_tc/tool_setting.rb +61 -0
  25. data/lti2_tc/app/services/lti2_tc/authorizer.rb +36 -0
  26. data/lti2_tc/app/services/lti2_tc/lti2_launch.rb +259 -0
  27. data/lti2_tc/app/views/layouts/lti2_tc/application.html.erb +14 -0
  28. data/lti2_tc/app/views/lti2_tc/deployment_requests/show.html.erb +2 -0
  29. data/lti2_tc/app/views/lti2_tc/tool_consumer_profiles/index.html.erb +2 -0
  30. data/lti2_tc/app/views/lti2_tc/tool_consumer_profiles/show.html.erb +2 -0
  31. data/lti2_tc/app/views/lti2_tc/tool_proxies_controller/index.html.erb +2 -0
  32. data/lti2_tc/app/views/lti2_tc/tool_settings_controller/show.html.erb +2 -0
  33. data/lti2_tc/app/views/lti2_tc/tool_settings_controller/update.html.erb +2 -0
  34. data/lti2_tc/app/views/lti2_tc/tools_controller/create.html.erb +2 -0
  35. data/lti2_tc/app/views/lti2_tc/tools_controller/show.html.erb +2 -0
  36. data/lti2_tc/bin/rails +8 -0
  37. data/lti2_tc/config/routes.rb +20 -0
  38. data/lti2_tc/db/migrate/20140826141858_create_lti2_tool_consumer_tables.rb +94 -0
  39. data/lti2_tc/db/migrate/20140826150753_create_lti2_tc_resources.rb +37 -0
  40. data/lti2_tc/db/migrate/20141027193548_insert_tool_guid.rb +5 -0
  41. data/lti2_tc/lib/lti2_tc.rb +4 -0
  42. data/lti2_tc/lib/lti2_tc/engine.rb +5 -0
  43. data/lti2_tc/lib/lti2_tc/version.rb +3 -0
  44. data/lti2_tc/lib/tasks/lti2_tc_tasks.rake +4 -0
  45. data/lti2_tc/lti2_tc.gemspec +27 -0
  46. data/lti2_tc/test/controllers/lti2_tc/deployment_requests_controller_test.rb +11 -0
  47. data/lti2_tc/test/controllers/lti2_tc/tool_consumer_profiles_controller_test.rb +16 -0
  48. data/lti2_tc/test/controllers/lti2_tc/tool_proxies_controller_controller_test.rb +11 -0
  49. data/lti2_tc/test/controllers/lti2_tc/tool_settings_controller_controller_test.rb +16 -0
  50. data/lti2_tc/test/controllers/lti2_tc/tools_controller_controller_test.rb +16 -0
  51. data/lti2_tc/test/dummy/README.rdoc +28 -0
  52. data/lti2_tc/test/dummy/Rakefile +6 -0
  53. data/lti2_tc/test/dummy/app/assets/javascripts/application.js +13 -0
  54. data/lti2_tc/test/dummy/app/assets/stylesheets/application.css +13 -0
  55. data/lti2_tc/test/dummy/app/controllers/application_controller.rb +5 -0
  56. data/lti2_tc/test/dummy/app/helpers/application_helper.rb +2 -0
  57. data/lti2_tc/test/dummy/app/views/layouts/application.html.erb +14 -0
  58. data/lti2_tc/test/dummy/bin/bundle +3 -0
  59. data/lti2_tc/test/dummy/bin/rails +4 -0
  60. data/lti2_tc/test/dummy/bin/rake +4 -0
  61. data/lti2_tc/test/dummy/config.ru +4 -0
  62. data/lti2_tc/test/dummy/config/application.rb +23 -0
  63. data/lti2_tc/test/dummy/config/boot.rb +5 -0
  64. data/lti2_tc/test/dummy/config/database.yml +39 -0
  65. data/lti2_tc/test/dummy/config/environment.rb +5 -0
  66. data/lti2_tc/test/dummy/config/environments/development.rb +29 -0
  67. data/lti2_tc/test/dummy/config/environments/production.rb +80 -0
  68. data/lti2_tc/test/dummy/config/environments/test.rb +36 -0
  69. data/lti2_tc/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  70. data/lti2_tc/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  71. data/lti2_tc/test/dummy/config/initializers/inflections.rb +16 -0
  72. data/lti2_tc/test/dummy/config/initializers/mime_types.rb +5 -0
  73. data/lti2_tc/test/dummy/config/initializers/secret_token.rb +12 -0
  74. data/lti2_tc/test/dummy/config/initializers/session_store.rb +3 -0
  75. data/lti2_tc/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  76. data/lti2_tc/test/dummy/config/locales/en.yml +23 -0
  77. data/lti2_tc/test/dummy/config/routes.rb +4 -0
  78. data/lti2_tc/test/dummy/db/database.yml +39 -0
  79. data/lti2_tc/test/dummy/db/migrate/20131121225051_create_lti2_tc_registries.lti2_tc.rb +55 -0
  80. data/lti2_tc/test/dummy/db/schema.rb +68 -0
  81. data/lti2_tc/test/dummy/public/404.html +58 -0
  82. data/lti2_tc/test/dummy/public/422.html +58 -0
  83. data/lti2_tc/test/dummy/public/500.html +57 -0
  84. data/lti2_tc/test/dummy/public/favicon.ico +0 -0
  85. data/lti2_tc/test/fixtures/lti2_tc/registries.yml +7 -0
  86. data/lti2_tc/test/helpers/lti2_tc/deployment_requests_helper_test.rb +6 -0
  87. data/lti2_tc/test/helpers/lti2_tc/tool_consumer_profiles_helper_test.rb +6 -0
  88. data/lti2_tc/test/helpers/lti2_tc/tool_proxies_controller_helper_test.rb +6 -0
  89. data/lti2_tc/test/helpers/lti2_tc/tool_settings_controller_helper_test.rb +6 -0
  90. data/lti2_tc/test/helpers/lti2_tc/tools_controller_helper_test.rb +6 -0
  91. data/lti2_tc/test/integration/navigation_test.rb +10 -0
  92. data/lti2_tc/test/lti2_tc_test.rb +7 -0
  93. data/lti2_tc/test/models/lti2_tc/registries_test.rb +9 -0
  94. data/lti2_tc/test/test_helper.rb +15 -0
  95. metadata +93 -1
@@ -0,0 +1,4 @@
1
+ module Lti2Tc
2
+ class ToolConsumerProfile < ActiveRecord::Base
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ module Lti2Tc
2
+ class ToolConsumerRegistry
3
+
4
+ attr_reader :tool_consumer_profile, :tc_deployment_url, :relaxed_oauth_check, :result_template,
5
+ :tool_consumer_name, :registry, :tool_consumer_profile_wrapper
6
+
7
+ def initialize
8
+ registry_entries = Registry.all
9
+ @registry = {}
10
+ registry_entries.each { |entry| @registry[entry.name] = entry.content unless entry.name == 'content' }
11
+
12
+ @tc_deployment_url = registry['tc_deployment_url']
13
+ @relaxed_oauth_check = registry['relaxed_oauth_check']
14
+ @result_template = registry['result_template']
15
+ @tool_consumer_name = registry['tool_consumer_name']
16
+
17
+ # gets tcp root and returns as a json_object (optimizes successive accesses to tcp)
18
+ tcp = Lti2Commons::JsonWrapper.new registry['tool_consumer_profile_template']
19
+ tcp.substitute_text_in_all_nodes '{', '}', registry
20
+ @tool_consumer_profile_wrapper = tcp
21
+ @tool_consumer_profile = tcp.root
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,83 @@
1
+ module Lti2Tc
2
+ class ToolRegistration
3
+ def self.remap_tool_consumer_profile( tool_consumer_profile_wrapper, tc_profile_guid )
4
+ tool_consumer_profile_wrapper.substitute_text_in_all_nodes(
5
+ '{', '}', { 'tool_consumer_profile_guid' => tc_profile_guid }
6
+ )
7
+ tool_consumer_profile_wrapper.root['guid'] = tc_profile_guid
8
+ JSON.pretty_generate( tool_consumer_profile_wrapper.root )
9
+ end
10
+
11
+ def self.register_tool( user, deployment_request, tool_consumer_profile_wrapper, tc_deployment_url )
12
+ unless deployment_request.status == 'prepared'
13
+ if deployment_request.status == 'submitted'
14
+ raise 'This deployment request has already been send to the Tool Provider'
15
+ elsif deployment_request.status == 'registered'
16
+ raise 'This deployment request has already been provisioned. Consider a Reregistration request.'
17
+ else
18
+ raise 'Invalid status for deployment request'
19
+ end
20
+ end
21
+ deployment_request.status = 'submitted'
22
+ deployment_request.save
23
+
24
+ tool_consumer_profile = Lti2Tc::ToolConsumerProfile.new
25
+ tool_consumer_profile.tc_profile = remap_tool_consumer_profile(
26
+ tool_consumer_profile_wrapper, deployment_request.tc_profile_guid
27
+ )
28
+ tool_consumer_profile.tc_profile_guid = deployment_request.tc_profile_guid
29
+ tool_consumer_profile.save
30
+
31
+ html_body = deployment_request.create_lti_message( tc_deployment_url, user.id )
32
+
33
+ html_body
34
+ end
35
+
36
+ def self.reregister_tool( user, deployment_request, tool, tool_consumer_profile,
37
+ tool_consumer_profile_wrapper, tc_deployment_url, launch_presentation_return_url )
38
+
39
+ tool_proxy = tool.get_tool_proxy
40
+ tp_base_url = tool_proxy.select('tool_profile.base_url_choice',
41
+ "selector.applies_to", "MessageHandler", 'default_base_url')
42
+ singleton_messages = tool_proxy.first_at( 'tool_profile.message' )
43
+ service_endpoint = nil
44
+ singleton_messages.each { |singleton_message|
45
+ message_types = singleton_message['message_type']
46
+ if message_types.include? 'ToolProxyReregistrationRequest'
47
+ service_endpoint = singleton_message['path']
48
+ break
49
+ end
50
+ }
51
+ raise 'No message handler found for ToolProxyRegistrationRequest' unless service_endpoint
52
+
53
+ # deployment_request = DeploymentRequest.new
54
+ deployment_request.status = 'reregistering'
55
+ deployment_request.save
56
+
57
+ # tool_consumer_profile = ToolConsumerProfile.new
58
+ current_tcp = Lti2Tc::ToolConsumerProfile.where(:tc_profile_guid => deployment_request.tc_profile_guid).first
59
+ tool_consumer_profile = current_tcp if current_tcp.present?
60
+ tool_consumer_profile.tc_profile = remap_tool_consumer_profile(
61
+ tool_consumer_profile_wrapper, deployment_request.tc_profile_guid
62
+ )
63
+ tool_consumer_profile.tc_profile_guid = deployment_request.tc_profile_guid
64
+ tool_consumer_profile.save
65
+
66
+ # convert parameters
67
+ parameters = {}
68
+ tc_base_url = tc_deployment_url
69
+ parameters['tc_profile_url'] = "#{tc_base_url}/lti2_tc/tool_consumer_profiles/#{tool_consumer_profile.tc_profile_guid}"
70
+ parameters['launch_presentation_return_url'] = launch_presentation_return_url
71
+ parameters['lti_message_type'] = 'ToolProxyReregistrationRequest'
72
+
73
+ key = tool_proxy.first_at( 'tool_proxy_guid' )
74
+ secret = tool_proxy.first_at( 'security_contract.shared_secret' )
75
+
76
+ signed_request = Signer::create_signed_request( service_endpoint, 'post', key, secret, parameters )
77
+ puts "TC Signed Request: #{signed_request.signature_base_string}"
78
+ body = MessageSupport::create_lti_message_body( service_endpoint, parameters,
79
+ Rails.application.config.wire_log, 'Reregister Tool' )
80
+ body
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,61 @@
1
+ module Lti2Tc
2
+ class ToolSetting < ActiveRecord::Base
3
+ belongs_to :scopeable, :polymorphic => true
4
+
5
+ COLLECTION_TYPES = [ :Tool, :Context, :Ltilink ]
6
+
7
+ def self.collection_index( collection_type )
8
+ COLLECTION_TYPES.find_index( collection_type.to_sym )
9
+ end
10
+
11
+ def self.create_uri( tool_id, scopeable_type, scopeable_id=nil )
12
+ tool_consumer_registry = Rails.application.config.tool_consumer_registry
13
+ result = "#{tool_consumer_registry.tc_deployment_url}/lti2_tc/tool_settings/#{tool_id}"
14
+ if scopeable_type == 'Context'
15
+ result << "/context/#{scopeable_id}"
16
+ elsif scopeable_type == 'Ltilink'
17
+ result << "/ltilink/#{scopeable_id}"
18
+ end
19
+ result
20
+ end
21
+
22
+ def self.create_reachable_uris( tool_id, scopeable_type, scopeable_id=nil )
23
+ result = {}
24
+ start_index = self.collection_index( scopeable_type )
25
+ (start_index...0).each do |index|
26
+ case index
27
+ when 0
28
+ result[:Tool] = self.create_uri( tool_id, 'Tool' )
29
+ when 1
30
+ result[:Context] = self.create_uri( tool_id, 'Context', scopeable_id )
31
+ when 2
32
+ result[:Ltilink] = self.create_uri( tool_id, 'Ltilink', scopeable_id )
33
+ link = Lti2Tc::Link.find( scopeable_id )
34
+ # for next iteration
35
+ scopeable_id = link.course.id
36
+ end
37
+ end
38
+ result
39
+ end
40
+
41
+ def self.parse_uri( path )
42
+ m = /^\/lti2_tc\/tool_settings\/(.*)\/context\/(.*)$/.match(path)
43
+ if m.present?
44
+ return [ 'Context', m[1], m[2].to_i ]
45
+ end
46
+ m = /^\/lti2_tc\/tool_settings\/(.*)\/ltilink\/(.*)$/.match(path)
47
+ if m.present?
48
+ return [ 'Ltilink', m[1], m[2].to_i ]
49
+ end
50
+ m = /^\/lti2_tc\/tool_settings\/(.*)$/.match(path)
51
+ if m.present?
52
+ return [ 'Tool', m[1], nil ]
53
+ end
54
+ return [ nil, nil, nil ]
55
+ end
56
+
57
+ def to_uri
58
+ ToolSetting.create_uri( self.tool_id, self.scopeable_type, self.scopeable_id )
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,36 @@
1
+ include Lti2Commons
2
+ include Signer
3
+ include MessageSupport
4
+ include OAuth::OAuthProxy
5
+
6
+ module Lti2Tc
7
+ class Authorizer
8
+ def self.pre_process_tenant request
9
+ rack_parameters = OAuthRequest.collect_rack_parameters request
10
+ key = rack_parameters[:oauth_consumer_key]
11
+ @tool = Lti2Tc::Tool.where( :key => key ).first
12
+ secret = @tool.secret
13
+ self.validate( request, secret )
14
+ end
15
+
16
+ def self.validate( request, secret )
17
+ # OAuth check here
18
+ tool_consumer_registry = Rails.application.config.tool_consumer_registry
19
+ unless tool_consumer_registry.relaxed_oauth_check == 'true'
20
+ request_wrapper = OAuthRequest.create_from_rack_request( request )
21
+ begin
22
+ request_wrapper.verify_signature?( secret, Rails.application.config.nonce_cache, false )
23
+ @oauth_error = false
24
+ return
25
+ rescue
26
+ # puts "Secret: #{secret}"
27
+ puts "TP Signed Request: #{request_wrapper.signature_base_string}"
28
+ @oauth_error = true
29
+ end
30
+
31
+ puts "request_wrapper: #{request_wrapper.request['parameters'].inspect}"
32
+ end
33
+ @oauth_error
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,259 @@
1
+ module Lti2Tc
2
+
3
+ class Lti2Launch
4
+
5
+ def initialize( user, link, resource, course, enrollment, return_url, &substitute_final )
6
+ @user = user
7
+ @link = link
8
+ @resource = resource
9
+ @course = course
10
+ @enrollment = enrollment
11
+ @return_url = return_url
12
+ @tool_proxy = resource.tool.get_tool_proxy
13
+ @substitute_final = substitute_final
14
+ end
15
+
16
+ def launch( open_in_external_window=true )
17
+ tool = @resource.tool
18
+ tool_name = @tool_proxy.first_at('tool_profile.product_instance.product_info.product_name.default_value')
19
+ raise "Tool #{tool_name} is currently disabled" unless tool.is_enabled
20
+
21
+ base_url = @tool_proxy.select('tool_profile.base_url_choice', 'selector.applies_to',
22
+ 'MessageHandler', 'default_base_url' )
23
+ resource_type = @resource.resource_type
24
+ resource_handler_node = @tool_proxy.search( 'tool_profile.resource_handler',
25
+ { 'resource_type' => { 'code' => resource_type } }, '@' )
26
+ resource_handler = JsonWrapper.new resource_handler_node
27
+ message = resource_handler.search( '@..message', { 'message_type' => 'basic-lti-launch-request' }, '@' )
28
+ path = message['path']
29
+ m = /(.*)\?(.*)/.match( path )
30
+ if m.present?
31
+ final_qs = '?'
32
+ parmstr = CGI.unescapeHTML( m[2] )
33
+ parm_hash = Rack::Utils::parse_query( parmstr )
34
+ parm_hash.each_pair do |k,v|
35
+ final_qs += "#{k}="
36
+ final_qs += Rack::Utils.escape( v )
37
+ final_qs += '&'
38
+ end
39
+ # conformance issue: remove trailing ampersand
40
+ final_qs = final_qs[0..final_qs.length-2] if final_qs[-1] == '&'
41
+ final_path = m[1] + final_qs
42
+ else
43
+ final_path = path
44
+ end
45
+
46
+ tp_parameters = message['parameter']
47
+ service_endpoint = base_url + final_path
48
+
49
+ if @enrollment
50
+ role = @enrollment.role
51
+ else
52
+ role = @user.role
53
+ end
54
+
55
+ tool_consumer_registry = Rails.application.config.tool_consumer_registry
56
+ tcp_wrapper = tool_consumer_registry.tool_consumer_profile_wrapper
57
+ parameters = {
58
+ 'lti_version' => @tool_proxy.first_at('lti_version'),
59
+ 'lti_message_type' => 'basic-lti-launch-request',
60
+ 'resource_link_id' => @link.id.to_s,
61
+ 'user_id' => @user.id.to_s,
62
+ 'roles' => role,
63
+ 'launch_presentation_return_url' => "#{tool_consumer_registry.tc_deployment_url}#{@return_url}",
64
+ 'launch_presentation_document_target' => 'window',
65
+
66
+ # optional
67
+ 'context_id' => @course.id.to_s,
68
+ 'launch_presentation_locale' => 'en_US',
69
+
70
+ # for conformance
71
+ 'context_label' => @course.course_label,
72
+ 'context_title' => @course.course_title,
73
+ 'lis_course_section_sourcedid' => @course.id.to_s,
74
+ 'tool_consumer_info_product_family_code' => "#{tcp_wrapper.first_at("product_instance.product_info.product_family.code")}",
75
+ 'tool_consumer_info_version' => "#{tcp_wrapper.first_at("product_instance.product_info.product_version")}",
76
+ }
77
+
78
+ if @link.is_name_permission
79
+ parameters['lis_person_sourcedid'] = @user.id.to_s
80
+ parameters['lis_person_name_given'] = @user.first_name
81
+ parameters['lis_person_name_family'] = @user.last_name
82
+ parameters['lis_person_name_full'] = "#{@user.first_name} #{@user.last_name}"
83
+ end
84
+
85
+ if @link.is_email_permission
86
+ parameters['lis_person_contact_email_primary'] = @user.email
87
+ end
88
+
89
+ if role =~ /Mentor$/
90
+ parameters['role_scope_mentor'] = url_encode_users(@user.mentor)
91
+ end
92
+
93
+ # add parameters from ToolProxy
94
+ for parameter in tp_parameters
95
+ name = parameter['name']
96
+ if parameter.has_key? 'fixed'
97
+ value = parameter['fixed']
98
+ elsif parameter.has_key? 'variable'
99
+ value = parameter['variable']
100
+ else
101
+ value = '[link-to-resolve]'
102
+ end
103
+ parameters[name] = value
104
+ end
105
+
106
+ # add parameters from Link
107
+ link_parameter_json = @link.link_parameters
108
+ if link_parameter_json
109
+ link_parameters = JSON.parse( link_parameter_json )
110
+ parameters.merge!( link_parameters )
111
+ end
112
+
113
+ # add parameters from Settings levels
114
+ settings = Lti2Tc::ToolSetting.where( :tool_id => tool.id, :scopeable_type => 'Tool' )
115
+ settings.each { |setting| parameters[setting.name] = setting.value }
116
+
117
+ settings = Lti2Tc::ToolSetting.where( :tool_id => tool.id, :scopeable_id => @course.id, :scopeable_type => 'Context' )
118
+ settings.each { |setting| parameters[setting.name] = setting.value }
119
+
120
+ settings = Lti2Tc::ToolSetting.where( :tool_id => tool.id, :scopeable_id => @link.id, :scopeable_type => 'Ltilink' )
121
+ settings.each { |setting| parameters[setting.name] = setting.value }
122
+
123
+ # auto-create result (if required) and add to reference to parameters
124
+ capabilities = resource_handler.first_at('message[0].enabled_capability')
125
+ if capabilities and capabilities.include? 'Result.autocreate'
126
+ if @link.grade_item_id
127
+ grade_result = GradeResult.where( :link_id => @link.id, :admin_user_id => @user.id ).first
128
+ # TEST ONLY
129
+ # grade_result.delete if grade_result
130
+ # grade_result = nil
131
+
132
+ unless grade_result
133
+ grade_result = GradeResult.new
134
+ grade_result.link_id = @link.id
135
+ grade_result.admin_user_id = @user.id
136
+ grade_result.save
137
+ else
138
+ # note that a nil grade_result still let's us through
139
+ unless grade_result.result.nil?
140
+ raise 'Grade result associated with this tool launch has already been filled in'
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ # perform variable substitution on all parameters
147
+ resolver = Lti2Commons::SubstitutionSupport::Resolver.new
148
+ resolver.add_resolver( 'User', @user.method(:user_resolver) )
149
+ resolver.add_resolver( 'Person', @user.method(:person_resolver) )
150
+ # now already resolved
151
+ #@course = Course.find( parameters['context_id'] )
152
+ resolver.add_resolver( 'CourseOffering', @course.method(:course_resolver) )
153
+ resolver.add_resolver( 'Result', grade_result.method(:grade_result_resolver) ) if grade_result
154
+
155
+ # This one is a bit deceptive. A TCP is usually associated with a @tool_proxy.
156
+ resolver.add_resolver( 'ToolConsumerProfile', self.method(:tool_consumer_profile_resolver) )
157
+
158
+ # Settings resolvers
159
+ resolver.add_resolver( 'ToolProxy', self.method(:tool_proxy_resolver) )
160
+ resolver.add_resolver( 'ToolProxyBinding', self.method(:tool_proxy_binding_resolver) )
161
+ resolver.add_resolver( 'LtiLink', self.method(:lti_link_resolver) )
162
+
163
+ # and resolve and normalize
164
+ final_parameters = {}
165
+ parameters.each { |k,v|
166
+ resolved_value = resolver.resolve( v )
167
+ if known_lti2_parameters.include? k or deprecated_lti_parameters.include? k
168
+ final_parameters[k] = resolved_value
169
+ else
170
+ name = 'custom_' + k
171
+ lti1_name = slugify( name )
172
+ unless name == lti1_name
173
+ final_parameters[lti1_name] = resolved_value
174
+ end
175
+ final_parameters[name] = resolved_value
176
+ end
177
+
178
+ }
179
+
180
+ subst_final_map = @substitute_final.nil? ? final_parameters : @substitute_final.call( final_parameters )
181
+
182
+ key = @resource.tool.key
183
+ secret = @resource.tool.secret
184
+
185
+ signed_request = Signer::create_signed_request( service_endpoint, 'post', key, secret, subst_final_map )
186
+ puts "TC Signed Request: #{signed_request.signature_base_string}"
187
+ puts "before"
188
+ puts Rails.application.config.wire_log.inspect
189
+ puts "after"
190
+ body = MessageSupport::create_lti_message_body( service_endpoint, subst_final_map,
191
+ Rails.application.config.wire_log, 'Lti Launch', open_in_external_window )
192
+ puts body
193
+ body
194
+ end
195
+
196
+ def deprecated_lti_parameters
197
+ [ 'context_title', 'context_label', 'resource_link_title', 'resource_link_description',
198
+ 'lis_person_name_given', 'lis_person_name_family', 'lis_person_name_full', 'lis_person_contact_email_primary',
199
+ 'user_image', 'lis_person_sourcedid', 'lis_course_offering_sourcedid', 'lis_course_section_sourcedid',
200
+ 'tool_consumer_info_product_family_code', 'tool_consumer_info_version',
201
+ 'tool_consumer_instance_name', 'tool_consumer_instance_description', 'tool_consumer_instance_url',
202
+ 'tool_consumer_instance_contact_email' ]
203
+ end
204
+
205
+ def known_lti2_parameters
206
+ [ 'lti_message_type', 'lti_version', 'user_id', 'roles', 'resource_link_id',
207
+ 'context_id', 'context_type',
208
+ 'launch_presentation_locale', 'launch_presentation_document_target', 'launch_presentation_css_url',
209
+ 'launch_presentation_width', 'launch_presentation_height', 'launch_presentation_return_url',
210
+ 'role_scope_mentor' ]
211
+ end
212
+
213
+
214
+ def tool_consumer_profile_resolver( fieldname )
215
+ if fieldname == 'url'
216
+ @tool_proxy.first_at('tool_consumer_profile')
217
+ end
218
+ end
219
+
220
+ def tool_proxy_resolver( fieldname )
221
+ if fieldname == 'custom.url'
222
+ tool_guid = @resource.tool.key
223
+ ToolSetting.create_uri( tool_guid, 'Tool' )
224
+ end
225
+ end
226
+
227
+ def tool_proxy_binding_resolver( fieldname )
228
+ if fieldname == 'custom.url'
229
+ tool_guid = @resource.tool.key
230
+ ToolSetting.create_uri( tool_guid, 'Context', @course.id )
231
+ end
232
+ end
233
+
234
+ def lti_link_resolver( fieldname )
235
+ if fieldname == 'custom.url'
236
+ tool_guid = @resource.tool.key
237
+ ToolSetting.create_uri( tool_guid, 'Ltilink', @link.id )
238
+ end
239
+ end
240
+
241
+ def slugify name
242
+ result = ''
243
+ name.each_char { |c|
244
+ result << (c =~ /\w/ ? c.downcase : '_')
245
+ }
246
+ result
247
+ end
248
+
249
+ def url_encode_users( user_list_str )
250
+ user_list = []
251
+ unless user_list_str.nil?
252
+ users = user_list_str.split(',')
253
+ users.each { |user| user_list << URI.encode( user ) }
254
+ end
255
+ user_list.join(',')
256
+ end
257
+
258
+ end
259
+ end