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

Sign up to get free protection for your applications and to get access to all the features.
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