ims-lti 2.0.0.beta.18 → 2.0.0.beta.19

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: 469b57f391256431763f04ca1187ae5a7769367a
4
- data.tar.gz: 0be379c6ea503a5503b9319aaaec4a0cc3c89f38
3
+ metadata.gz: abb31c30499a793de7682bdd02c9e1e8a71f1500
4
+ data.tar.gz: a4ed57fa69bf00c8128ec2986d47d9d3ef2c7c7b
5
5
  SHA512:
6
- metadata.gz: e16ab1448cc60ae4a895d0d21eb5f9d9a09ac65efcf211c50a84adb01fbbb43105b261e15da74fe9e9fe69b7e1a7d84f18306c5f4fe8073b527c897059e151da
7
- data.tar.gz: f5b3797ab367c341275611dfc31434673cc73c94916036d02471fe570e499f5e5cfdc343b7252da33777c72b6e4ede92d452a1977bfefd2de25aaa6a856c280b
6
+ metadata.gz: 473cafa07eada8291040ecc68b7b5ee5815914f72522576fdd442fbce7ed91bbbfed19d150a55f9178aaef3564d9ec53dce72c4a48214102b7c079c5cc2eeb6e
7
+ data.tar.gz: 70e79ca8a862600a05508314b99a281a4800600038f4e106d92bf1aebc140df14ccf1d4d6011fc2aea8ad5e6ff3b2228ffab29cef6268762a4cdf8a074be1300
@@ -3,11 +3,14 @@ require 'securerandom'
3
3
  require 'simple_oauth'
4
4
  require 'faraday'
5
5
  require 'faraday_middleware'
6
+ require 'builder'
7
+ require 'rexml/document'
6
8
 
7
9
  module IMS
8
10
  module LTI
9
11
  require_relative 'lti/models'
10
12
  require_relative 'lti/converters'
11
13
  require_relative 'lti/services'
14
+ require_relative 'lti/errors'
12
15
  end
13
16
  end
@@ -0,0 +1,5 @@
1
+ module IMS::LTI
2
+ module Errors
3
+ require_relative 'errors/invalid_lti_config_error'
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module IMS::LTI::Errors
2
+ class InvalidLTIConfigError < StandardError
3
+ end
4
+ end
@@ -10,7 +10,7 @@ module IMS::LTI::Models::Messages
10
10
  :lis_course_offering_sourcedid, :lis_course_section_sourcedid,
11
11
  :tool_consumer_info_product_family_code, :tool_consumer_info_product_family_version,
12
12
  :tool_consumer_instance_name, :tool_consumer_instance_description, :tool_consumer_instance_url,
13
- :tool_consumer_instance_contact_email
13
+ :tool_consumer_instance_contact_email, :tool_consumer_info_version
14
14
 
15
15
  MESSAGE_TYPE = 'basic-lti-launch-request'
16
16
 
@@ -1,5 +1,6 @@
1
1
  module IMS::LTI
2
2
  module Services
3
3
  require_relative 'services/tool_proxy_registration_service'
4
+ require_relative 'services/tool_config'
4
5
  end
5
6
  end
@@ -1,10 +1,12 @@
1
- class ServiceDefinition
2
- attr_reader :name, :formats, :paramater_variables
1
+ module IMS::LTI::Services
2
+ class ServiceDefinition
3
+ attr_reader :name, :formats, :paramater_variables
3
4
 
4
- def initialize(name, formats, parameter_variables = [])
5
- @name = name
6
- @formats = formats
7
- @parameter_variables = parameter_variables
8
- end
5
+ def initialize(name, formats, parameter_variables = [])
6
+ @name = name
7
+ @formats = formats
8
+ @parameter_variables = parameter_variables
9
+ end
9
10
 
10
- end
11
+ end
12
+ end
@@ -1,30 +1,32 @@
1
- class ServiceLookup
1
+ module IMS::LTI::Services
2
+ class ServiceLookup
2
3
 
3
- TOOL_SETTING_SERVICE = ServiceDefinition.new(
4
- 'ToolSettingsContainer Service',
5
- %w(application/vnd.ims.lti.v2.toolsettings+json application/vnd.ims.lti.v2.toolsettings.simple+json),
6
- %w(LtiLink.custom.url ToolProxyBinding.custom.url ToolProxy.custom.url)
7
- )
4
+ TOOL_SETTING_SERVICE = ServiceDefinition.new(
5
+ 'ToolSettingsContainer Service',
6
+ %w(application/vnd.ims.lti.v2.toolsettings+json application/vnd.ims.lti.v2.toolsettings.simple+json),
7
+ %w(LtiLink.custom.url ToolProxyBinding.custom.url ToolProxy.custom.url)
8
+ )
8
9
 
9
- TOOL_CONSUMER_PROFILE_SERVICE = ServiceDefinition.new(
10
- 'ToolConsumerProfile Service',
11
- %w(application/vnd.ims.lti.v2.toolconsumerprofile+json),
12
- []
13
- )
10
+ TOOL_CONSUMER_PROFILE_SERVICE = ServiceDefinition.new(
11
+ 'ToolConsumerProfile Service',
12
+ %w(application/vnd.ims.lti.v2.toolconsumerprofile+json),
13
+ []
14
+ )
14
15
 
15
- TOOL_PROXY_SERVICE = ServiceDefinition.new(
16
- 'ToolProxy Service',
17
- %w(application/vnd.ims.lti.v2.toolproxy+json),
18
- []
19
- )
16
+ TOOL_PROXY_SERVICE = ServiceDefinition.new(
17
+ 'ToolProxy Service',
18
+ %w(application/vnd.ims.lti.v2.toolproxy+json),
19
+ []
20
+ )
20
21
 
21
- def self.services
22
- [TOOL_SETTING_SERVICE, TOOL_CONSUMER_PROFILE_SERVICE, TOOL_PROXY_SERVICE]
23
- end
22
+ def self.services
23
+ [TOOL_SETTING_SERVICE, TOOL_CONSUMER_PROFILE_SERVICE, TOOL_PROXY_SERVICE]
24
+ end
24
25
 
25
- def self.lookup(format)
26
- services.select { |service| service.formats.include? format }
27
- end
26
+ def self.lookup(format)
27
+ services.select { |service| service.formats.include? format }
28
+ end
28
29
 
29
30
 
30
- end
31
+ end
32
+ end
@@ -0,0 +1,225 @@
1
+ module IMS::LTI::Services
2
+ # Class used to represent an LTI configuration
3
+ #
4
+ # It can create and read the Common Cartridge XML representation of LTI links
5
+ # as described here: http://www.imsglobal.org/LTI/v1p1pd/ltiIMGv1p1pd.html#_Toc309649689
6
+ #
7
+ # == Usage
8
+ # To generate an XML configuration:
9
+ #
10
+ # # Create a config object and set some options
11
+ # tc = IMS::LTI::Services::ToolConfig.new(:title => "Example Sinatra Tool Provider", :launch_url => url)
12
+ # tc.description = "This example LTI Tool Provider supports LIS Outcome pass-back."
13
+ #
14
+ # # generate the XML
15
+ # tc.to_xml
16
+ #
17
+ # Or to create a config object from an XML String:
18
+ #
19
+ # tc = IMS::LTI::Services::ToolConfig.create_from_xml(xml)
20
+ class ToolConfig
21
+ attr_reader :custom_params, :extensions
22
+
23
+ attr_accessor :title, :description, :launch_url, :secure_launch_url,
24
+ :icon, :secure_icon, :cartridge_bundle, :cartridge_icon,
25
+ :vendor_code, :vendor_name, :vendor_description, :vendor_url,
26
+ :vendor_contact_email, :vendor_contact_name
27
+
28
+ # Create a new ToolConfig with the given options
29
+ #
30
+ # @param opts [Hash] The initial options for the ToolConfig
31
+ def initialize(opts={})
32
+ @custom_params = opts.delete("custom_params") || {}
33
+ @extensions = opts.delete("extensions") || {}
34
+
35
+ opts.each_pair do |key, val|
36
+ self.send("#{key}=", val) if self.respond_to?("#{key}=")
37
+ end
38
+ end
39
+
40
+ # Create a ToolConfig from the given XML
41
+ #
42
+ # @param xml [String]
43
+ def self.create_from_xml(xml)
44
+ tc = ToolConfig.new
45
+ tc.process_xml(xml)
46
+
47
+ tc
48
+ end
49
+
50
+ def set_custom_param(key, val)
51
+ @custom_params[key] = val
52
+ end
53
+
54
+ def get_custom_param(key)
55
+ @custom_params[key]
56
+ end
57
+
58
+ # Set the extension parameters for a specific vendor
59
+ #
60
+ # @param ext_key [String] The identifier for the vendor-specific parameters
61
+ # @param ext_params [Hash] The parameters, this is allowed to be two-levels deep
62
+ def set_ext_params(ext_key, ext_params)
63
+ raise ArgumentError unless ext_params.is_a?(Hash)
64
+ @extensions[ext_key] = ext_params
65
+ end
66
+
67
+ def get_ext_params(ext_key)
68
+ @extensions[ext_key]
69
+ end
70
+
71
+ def set_ext_param(ext_key, param_key, val)
72
+ @extensions[ext_key] ||= {}
73
+ @extensions[ext_key][param_key] = val
74
+ end
75
+
76
+ def get_ext_param(ext_key, param_key)
77
+ @extensions[ext_key] && @extensions[ext_key][param_key]
78
+ end
79
+
80
+ # Namespaces used for parsing configuration XML
81
+ LTI_NAMESPACES = {
82
+ "xmlns" => 'http://www.imsglobal.org/xsd/imslticc_v1p0',
83
+ "blti" => 'http://www.imsglobal.org/xsd/imsbasiclti_v1p0',
84
+ "lticm" => 'http://www.imsglobal.org/xsd/imslticm_v1p0',
85
+ "lticp" => 'http://www.imsglobal.org/xsd/imslticp_v1p0',
86
+ }
87
+
88
+ # Parse tool configuration data out of the Common Cartridge LTI link XML
89
+ def process_xml(xml)
90
+ doc = REXML::Document.new xml
91
+ if root = REXML::XPath.first(doc, 'xmlns:cartridge_basiclti_link')
92
+ @title = get_node_text(root, 'blti:title')
93
+ @description = get_node_text(root, 'blti:description')
94
+ @launch_url = get_node_text(root, 'blti:launch_url')
95
+ @secure_launch_url = get_node_text(root, 'blti:secure_launch_url')
96
+ @icon = get_node_text(root, 'blti:icon')
97
+ @secure_icon = get_node_text(root, 'blti:secure_icon')
98
+ @cartridge_bundle = get_node_att(root, 'xmlns:cartridge_bundle', 'identifierref')
99
+ @cartridge_icon = get_node_att(root, 'xmlns:cartridge_icon', 'identifierref')
100
+
101
+ if vendor = REXML::XPath.first(root, 'blti:vendor')
102
+ @vendor_code = get_node_text(vendor, 'lticp:code')
103
+ @vendor_description = get_node_text(vendor, 'lticp:description')
104
+ @vendor_name = get_node_text(vendor, 'lticp:name')
105
+ @vendor_url = get_node_text(vendor, 'lticp:url')
106
+ @vendor_contact_email = get_node_text(vendor, '//lticp:contact/lticp:email')
107
+ @vendor_contact_name = get_node_text(vendor, '//lticp:contact/lticp:name')
108
+ end
109
+
110
+ if custom = REXML::XPath.first(root, 'blti:custom', LTI_NAMESPACES)
111
+ set_properties(@custom_params, custom)
112
+ end
113
+
114
+ REXML::XPath.each(root, 'blti:extensions', LTI_NAMESPACES) do |vendor_ext_node|
115
+ platform = vendor_ext_node.attributes['platform']
116
+ properties = {}
117
+ set_properties(properties, vendor_ext_node)
118
+ REXML::XPath.each(vendor_ext_node, 'lticm:options', LTI_NAMESPACES) do |options_node|
119
+ opt_name = options_node.attributes['name']
120
+ options = {}
121
+ set_properties(options, options_node)
122
+ properties[opt_name] = options
123
+ end
124
+
125
+ self.set_ext_params(platform, properties)
126
+ end
127
+
128
+ end
129
+ end
130
+
131
+ # Generate XML from the current settings
132
+ def to_xml(opts = {})
133
+ raise IMS::LTI::Errors::InvalidLTIConfigError, "A launch url is required for an LTI configuration." unless self.launch_url || self.secure_launch_url
134
+
135
+ builder = Builder::XmlMarkup.new(:indent => opts[:indent] || 0)
136
+ builder.instruct!
137
+ builder.cartridge_basiclti_link("xmlns" => "http://www.imsglobal.org/xsd/imslticc_v1p0",
138
+ "xmlns:blti" => 'http://www.imsglobal.org/xsd/imsbasiclti_v1p0',
139
+ "xmlns:lticm" => 'http://www.imsglobal.org/xsd/imslticm_v1p0',
140
+ "xmlns:lticp" => 'http://www.imsglobal.org/xsd/imslticp_v1p0',
141
+ "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
142
+ "xsi:schemaLocation" => "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0p1.xsd http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd"
143
+ ) do |blti_node|
144
+
145
+ %w{title description launch_url secure_launch_url icon secure_icon}.each do |key|
146
+ blti_node.blti key.to_sym, self.send(key) if self.send(key)
147
+ end
148
+
149
+ vendor_keys = %w{name code description url}
150
+ if vendor_keys.any? { |k| self.send("vendor_#{k}") } || vendor_contact_email
151
+ blti_node.blti :vendor do |v_node|
152
+ vendor_keys.each do |key|
153
+ v_node.lticp key.to_sym, self.send("vendor_#{key}") if self.send("vendor_#{key}")
154
+ end
155
+ if vendor_contact_email
156
+ v_node.lticp :contact do |c_node|
157
+ c_node.lticp :name, vendor_contact_name
158
+ c_node.lticp :email, vendor_contact_email
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ if !@custom_params.empty?
165
+ blti_node.tag!("blti:custom") do |custom_node|
166
+ @custom_params.keys.sort.each do |key|
167
+ val = @custom_params[key]
168
+ custom_node.lticm :property, val, 'name' => key
169
+ end
170
+ end
171
+ end
172
+
173
+ if !@extensions.empty?
174
+ @extensions.keys.sort.each do |ext_platform|
175
+ ext_params = @extensions[ext_platform]
176
+ blti_node.blti(:extensions, :platform => ext_platform) do |ext_node|
177
+ ext_params.keys.sort.each do |key|
178
+ val = ext_params[key]
179
+ if val.is_a?(Hash)
180
+ ext_node.lticm(:options, :name => key) do |type_node|
181
+ val.keys.sort.each do |p_key|
182
+ p_val = val[p_key]
183
+ type_node.lticm :property, p_val, 'name' => p_key
184
+ end
185
+ end
186
+ else
187
+ ext_node.lticm :property, val, 'name' => key
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ blti_node.cartridge_bundle(:identifierref => @cartridge_bundle) if @cartridge_bundle
195
+ blti_node.cartridge_icon(:identifierref => @cartridge_icon) if @cartridge_icon
196
+
197
+ end
198
+ end
199
+
200
+ private
201
+
202
+ def get_node_text(node, path)
203
+ if val = REXML::XPath.first(node, path, LTI_NAMESPACES)
204
+ val.text
205
+ else
206
+ nil
207
+ end
208
+ end
209
+
210
+ def get_node_att(node, path, att)
211
+ if val = REXML::XPath.first(node, path, LTI_NAMESPACES)
212
+ val.attributes[att]
213
+ else
214
+ nil
215
+ end
216
+ end
217
+
218
+ def set_properties(hash, node)
219
+ REXML::XPath.each(node, 'lticm:property', LTI_NAMESPACES) do |prop|
220
+ hash[prop.attributes['name']] = prop.text
221
+ end
222
+ end
223
+
224
+ end
225
+ 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.18
4
+ version: 2.0.0.beta.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-12 00:00:00.000000000 Z
11
+ date: 2015-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_oauth
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: builder
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +121,8 @@ files:
107
121
  - lib/ims/lti.rb
108
122
  - lib/ims/lti/converters.rb
109
123
  - lib/ims/lti/converters/time_json_converter.rb
124
+ - lib/ims/lti/errors.rb
125
+ - lib/ims/lti/errors/invalid_lti_config_error.rb
110
126
  - lib/ims/lti/models.rb
111
127
  - lib/ims/lti/models/base_url_choice.rb
112
128
  - lib/ims/lti/models/base_url_selector.rb
@@ -141,6 +157,7 @@ files:
141
157
  - lib/ims/lti/services.rb
142
158
  - lib/ims/lti/services/service_definition.rb
143
159
  - lib/ims/lti/services/service_lookup.rb
160
+ - lib/ims/lti/services/tool_config.rb
144
161
  - lib/ims/lti/services/tool_proxy_registration_service.rb
145
162
  - lib/ims/lti/version.rb
146
163
  homepage: http://github.com/instructure/ims-lti