ims-lti 2.0.0.beta.4 → 2.0.0.beta.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed76063b4d873fb5c4a6eea89c1da7aab0ccef25
4
- data.tar.gz: a2bc4269ce259274dbae7efca5f8f5113a76c5ec
3
+ metadata.gz: 38d11793d219aeeb78b863805a6330f15fc7d14b
4
+ data.tar.gz: 602686761cd45823ea59a209708afbdd17e2045c
5
5
  SHA512:
6
- metadata.gz: c5584c164f6aa8dad8c913eedb46cf957e139278890b2dbae7c28494584f2583d3e754d7827fcd028e94a55900576eee53bc21456600bceec4f0cc86c800929c
7
- data.tar.gz: ae554d8cb1ede05cb8f79a04e9bc5d77c3a9ecdd86686588e795b4075d9c90c3575c4728384d96215530eca309f77ea18dad667f445206a48b63eddbe80540cb
6
+ metadata.gz: 4a026706243f8e3748fbb14233f81b14ad6a4aea839bf66ba77eb099249485ae1bb7f58767507a5b6f629a5a01f495d79804349688db3199218cb186225627fe
7
+ data.tar.gz: 5f636b4a4b7c8155d7ef37449272f8353e6033fe5cabefb3818686a4aca50952e0706a45f6fd9d52ede72b2ea3f48af5bacdac49765398cfec29a583c7ef5573
@@ -31,6 +31,10 @@ module IMS::LTI::Models
31
31
  subclass.inherit_attributes(self.attributes)
32
32
  end
33
33
 
34
+ def self.from_json(json)
35
+ new.from_json(json)
36
+ end
37
+
34
38
  def attributes
35
39
  attrs = {}
36
40
  self.class.attributes.each do |a|
@@ -67,7 +71,7 @@ module IMS::LTI::Models
67
71
  end
68
72
 
69
73
  def from_json(json)
70
- data = JSON.parse(json)
74
+ data = json.is_a?(String) ? JSON.parse(json) : json
71
75
  if data.is_a? Array
72
76
  data.map { |hash| self.class.new.from_json(hash.to_json) }
73
77
  else
@@ -1,6 +1,6 @@
1
1
  module IMS::LTI::Models
2
2
  class MessageHandler < LTIModel
3
- add_attributes :message_type, :path, :enabled_capability, :parameter
3
+ add_attributes :message_type, :path, :enabled_capability
4
4
  add_attribute :parameter, relation:'IMS::LTI::Models::Parameter'
5
5
  end
6
6
  end
@@ -1,8 +1,16 @@
1
1
  module IMS::LTI::Models::Messages
2
2
  class BasicLTILaunchRequest < IMS::LTI::Models::Messages::Message
3
3
 
4
- add_attributes :context_id, :context_type, :launch_presentation_return_url, :resource_link_id, :role_scope_mentor,
5
- :tool_consumer_instance_guid, :user_image
4
+ required_params :resource_link_id
5
+ recommended_params :context_id, :launch_presentation_return_url, :tool_consumer_instance_guid
6
+ optional_params :context_type, :role_scope_mentor, :user_image
7
+ deprecated_params :context_title, :context_label, :resource_link_title, :resource_link_description,
8
+ :lis_person_name_given, :lis_person_name_family, :lis_person_name_full,
9
+ :lis_person_contact_email_primary, :user_image, :lis_person_sourcedid,
10
+ :lis_course_offering_sourcedid, :lis_course_section_sourcedid,
11
+ :tool_consumer_info_product_family_code, :tool_consumer_info_product_family_version,
12
+ :tool_consumer_instance_name, :tool_consumer_instance_description, :tool_consumer_instance_url,
13
+ :tool_consumer_instance_contact_email
6
14
 
7
15
  MESSAGE_TYPE = 'basic-lti-launch-request'
8
16
 
@@ -1,60 +1,135 @@
1
1
  module IMS::LTI::Models::Messages
2
- class Message < IMS::LTI::Models::LTIModel
2
+ class Message
3
+ class << self
4
+
5
+ def required_params(param, *params)
6
+ add_params(param, *params)
7
+ end
8
+
9
+ def recommended_params(param, *params)
10
+ add_params(param, *params)
11
+ end
12
+
13
+ def optional_params(param, *params)
14
+ add_params(param, *params)
15
+ end
16
+
17
+ def deprecated_params(param, *params)
18
+ add_params(param, *params)
19
+ end
20
+
21
+ private
22
+
23
+ def add_params(param, *params)
24
+ params.unshift(param)
25
+ @parameters ||= []
26
+ @parameters += params
27
+ attr_accessor(params.shift, *params)
28
+ end
29
+
30
+ def parameters
31
+ @parameters ||= []
32
+ end
33
+
34
+ end
35
+
3
36
  LAUNCH_TARGET_IFRAME = 'iframe'
4
37
  LAUNCH_TARGET_WINDOW = 'window'
5
38
 
6
39
  EXTENSION_PREFIX = 'ext_'
7
40
  CUSTOM_PREFIX = 'custom_'
8
41
 
9
- add_attributes :lti_message_type, :lti_version, :user_id, :roles, :launch_presentation_local,
10
- :launch_presentation_document_target, :launch_presentation_css_url, :launch_presentation_width,
11
- :launch_presentation_height
42
+ OAUTH_KEYS = :oauth_callback, :oauth_consumer_key, :oauth_nonce, :oauth_signature, :oauth_signature_method,
43
+ :oauth_timestamp, :oauth_token, :oauth_verifier, :oauth_version
44
+
45
+ attr_accessor :launch_url, *OAUTH_KEYS
46
+
47
+ required_params :lti_message_type, :lti_version
48
+ recommended_params :user_id, :roles, :launch_presentation_document_target, :launch_presentation_width, :launch_presentation_height
49
+ optional_params :launch_presentation_local, :launch_presentation_css_url
50
+
12
51
 
13
52
  def initialize(attrs = {})
14
53
  @custom_params = {}
15
54
  @ext_params = {}
16
- attributes = {}
17
55
 
18
- attrs.each do |k,v|
56
+ attrs.each do |k, v|
19
57
  str_key = k.to_s
20
58
  if str_key.start_with?(EXTENSION_PREFIX)
21
- @ext_params[str_key.sub(EXTENSION_PREFIX, '')] = v
59
+ @ext_params[str_key] = v
22
60
  elsif str_key.start_with?(CUSTOM_PREFIX)
23
- @custom_params[str_key.sub(CUSTOM_PREFIX, '')] = v
61
+ @custom_params[str_key] = v
62
+ elsif !v.nil? && self.respond_to?(k.to_sym)
63
+ instance_variable_set("@#{k}", v)
24
64
  else
25
- attributes[k] = v
65
+ warn "Unknown parameter #{k}"
26
66
  end
27
67
  end
68
+ end
28
69
 
29
- super(attributes)
70
+ def add_custom_params(params)
71
+ params.each { |k,v| k.to_s.start_with?('custom_') ? @custom_params[k.to_s] = v : @custom_params["custom_#{k.to_s}"] = v }
72
+ end
73
+
74
+ def get_custom_params
75
+ @custom_params.inject({}) { |hash, (k,v)| hash[k.gsub(/\Acustom_/, '')] = v ; hash }
30
76
  end
31
77
 
32
78
  def post_params
33
- get_custom_params.merge(get_ext_params).merge(attributes)
79
+ @custom_params.merge(@ext_params).merge(parameters)
34
80
  end
35
81
 
36
- def get_ext_params
37
- params = {}
38
- @ext_params.each { |k, v| params["#{EXTENSION_PREFIX}#{k}"] = v }
39
- params
82
+ def signed_post_params(secret)
83
+ params = post_params
84
+ header = SimpleOAuth::Header.new(:post, launch_url, params, consumer_key: oauth_consumer_key, consumer_secret: secret)
85
+ header.signed_attributes.merge(params)
40
86
  end
41
87
 
42
- def get_custom_params
43
- params = {}
44
- @custom_params.each { |k, v| params["#{CUSTOM_PREFIX}#{k}"] = v }
45
- params
88
+ def valid_signature?(secret)
89
+ params = OAUTH_KEYS.inject({}) do |hash, k|
90
+ value = instance_variable_get("@#{k}")
91
+ hash[k] = value if value
92
+ hash
93
+ end
94
+ options, parsed_params = parse_params(params)
95
+ signature = parsed_params.delete(:oauth_signature)
96
+ consumer_key = oauth_consumer_key
97
+ header = SimpleOAuth::Header.new(:post, launch_url, parsed_params, options.merge({consumer_key: consumer_key, consumer_secret: secret}))
98
+ header.valid?(signature: signature)
46
99
  end
47
100
 
48
101
  def method_missing(meth, *args, &block)
49
102
  if match = /^(custom|ext)_([^=$]*)/.match(meth)
50
103
  param_type, key = match.captures
51
104
  param_hash = instance_variable_get("@#{param_type}_params".to_sym)
52
- meth =~ /=$/ ? param_hash[key] = args[0] : param_hash[key]
105
+ meth =~ /=$/ ? param_hash[match.to_s] = args[0] : param_hash[match.to_s]
53
106
  else
54
107
  super
55
108
  end
56
109
  end
57
110
 
58
111
  private
112
+
113
+ def parameters
114
+
115
+ self.class.instance_variable_get("@parameters").inject({}) do |h, param|
116
+ value = instance_variable_get("@#{param.to_s}")
117
+ h[param.to_s] = value unless value.nil?
118
+ h
119
+ end
120
+ end
121
+
122
+ def parse_params(params)
123
+ params.inject([{}, {}]) do |array, (k, v)|
124
+ attr = k.to_s.sub('oauth_', '').to_sym
125
+ if SimpleOAuth::Header::ATTRIBUTE_KEYS.include?(attr)
126
+ array[0][attr] = v
127
+ else
128
+ array[1][k] = v
129
+ end
130
+ array
131
+ end
132
+ end
133
+
59
134
  end
60
135
  end
@@ -1,6 +1,7 @@
1
1
  module IMS::LTI::Models::Messages
2
2
  class RegistrationRequest < Message
3
- add_attributes :reg_key, :reg_password, :tc_profile_url, :launch_presentation_return_url
3
+
4
+ required_params :reg_key, :reg_password, :tc_profile_url, :launch_presentation_return_url
4
5
 
5
6
  MESSAGE_TYPE = 'ToolProxyRegistrationRequest'
6
7
 
@@ -1,5 +1,28 @@
1
1
  module IMS::LTI::Models
2
2
  class Parameter < LTIModel
3
+
3
4
  add_attributes :name, :variable, :fixed
5
+
6
+ def fixed?
7
+ !fixed.nil? && fixed.to_s.strip != ''
8
+ end
9
+
10
+ def self.process_params(parameters, lookup_hash)
11
+ [*parameters].inject({}) do |hash, param|
12
+ hash[param.name] = param.fixed? ? param.fixed : expand_variable(lookup_hash[param.variable]) || '$' + param.variable
13
+ hash
14
+ end
15
+ end
16
+
17
+ def ==(obj)
18
+ self.fixed? == obj.fixed? && self.name == obj.name && self.fixed == obj.fixed
19
+ end
20
+
21
+ private
22
+
23
+ def self.expand_variable(value)
24
+ value.respond_to?(:call) ? value.call : value
25
+ end
26
+
4
27
  end
5
28
  end
@@ -4,6 +4,9 @@ module IMS::LTI::Models
4
4
  CONTEXT = "http://purl.imsglobal.org/ctx/lti/v2/ToolConsumerProfile"
5
5
  TYPE = "ToolConsumerProfile"
6
6
 
7
+ MESSAGING_CAPABILITIES = %w(basic-lti-launch-request)
8
+ OUTCOMES_CAPABILITIES = %w(Result.autocreate)
9
+
7
10
  add_attributes :lti_version, :guid, :capability_offered
8
11
  add_attribute :id, json_key:'@id'
9
12
  add_attribute :type, json_key:'@type'
@@ -1,6 +1,5 @@
1
1
  module IMS::LTI
2
2
  module Services
3
- require_relative 'services/message_service'
4
3
  require_relative 'services/tool_proxy_registration_service'
5
4
  end
6
5
  end
@@ -17,7 +17,7 @@ module IMS::LTI::Services
17
17
  end
18
18
 
19
19
  def register_tool_proxy(tool_proxy)
20
- service = tool_consumer_profile.services_offered.find{|s| s.formats.include?('application/vnd.ims.lti.v2.toolproxy+json') && s.actions.include?('POST')}
20
+ service = tool_consumer_profile.services_offered.find { |s| s.formats.include?('application/vnd.ims.lti.v2.toolproxy+json') && s.actions.include?('POST') }
21
21
 
22
22
  conn = Faraday.new do |conn|
23
23
  conn.request :oauth, {:consumer_key => @registration_request.reg_key, :consumer_secret => @registration_request.reg_password}
@@ -35,5 +35,32 @@ module IMS::LTI::Services
35
35
  end
36
36
  end
37
37
 
38
+
39
+ def remove_invalid_capabilities!(message_handler)
40
+ {
41
+ invalid_capabilities: remove_capabilites!(message_handler),
42
+ invalid_parameters: remove_params!(message_handler)
43
+ }
44
+ end
45
+
46
+ private
47
+
48
+ def remove_params!(message_handler)
49
+ orig_parameters = message_handler.parameter || []
50
+ parameters = orig_parameters.select {|p| p.fixed? || tool_consumer_profile.capability_offered.include?(p.variable)}
51
+ message_handler.parameter = parameters
52
+ orig_parameters - parameters
53
+ end
54
+
55
+ def remove_capabilites!(message_handler)
56
+ orig_capabilities = message_handler.enabled_capability || []
57
+ capabilites = orig_capabilities & tool_consumer_profile.capability_offered
58
+ capabilites.reject! { |cap| IMS::LTI::Models::ToolConsumerProfile::MESSAGING_CAPABILITIES.include? cap }
59
+ message_handler.enabled_capability = capabilites
60
+ orig_capabilities - capabilites
61
+ end
62
+
63
+
64
+
38
65
  end
39
66
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ims-lti
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta.4
4
+ version: 2.0.0.beta.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-06 00:00:00.000000000 Z
11
+ date: 2014-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_oauth
@@ -137,7 +137,6 @@ files:
137
137
  - lib/ims/lti/models/tool_proxy.rb
138
138
  - lib/ims/lti/models/vendor.rb
139
139
  - lib/ims/lti/services.rb
140
- - lib/ims/lti/services/message_service.rb
141
140
  - lib/ims/lti/services/tool_proxy_registration_service.rb
142
141
  - lib/ims/lti/version.rb
143
142
  homepage: http://github.com/instructure/ims-lti
@@ -1,37 +0,0 @@
1
- module IMS::LTI::Services
2
- class MessageService
3
-
4
- def initialize(key, secret)
5
- @credentials = {consumer_key: key, consumer_secret: secret}
6
- end
7
-
8
- def signed_params(url, message)
9
- params = message.post_params
10
- header = SimpleOAuth::Header.new(:post, url, params, @credentials)
11
- params = header.signed_attributes.merge(params)
12
- params
13
- end
14
-
15
- def valid_signature?(url, params)
16
- options, parsed_params = parse_params(params)
17
- signature = parsed_params.delete(:oauth_signature)
18
- header = SimpleOAuth::Header.new(:post, url, parsed_params, options.merge(@credentials))
19
- header.valid?(signature: signature)
20
- end
21
-
22
- private
23
-
24
- def parse_params(params)
25
- params.inject([{}, {}]) do |array, (k, v)|
26
- attr = k.to_s.sub('oauth_', '').to_sym
27
- if SimpleOAuth::Header::ATTRIBUTE_KEYS.include?(attr)
28
- array[0][attr] = v
29
- else
30
- array[1][k] = v
31
- end
32
- array
33
- end
34
- end
35
-
36
- end
37
- end