rack-lti 0.0.2 → 0.1.0

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: fb5033988f314beec36f2ec28a42b36e90771687
4
- data.tar.gz: 99c197e05ab5d504c5162b298b52851b953344a7
3
+ metadata.gz: 537b86b974404190e61290b5055b113080e7aa71
4
+ data.tar.gz: 7f6fd669ce3c9c836fc8385c709496a937ed7bb8
5
5
  SHA512:
6
- metadata.gz: 7c6d14c8b63847b9f10844ecb371f9518e786e39a7079638c4fd120639bcde24d66dcd30eef5e7de03e1088edc4d1bace15229e3aeaf9e0d175fb86943dff73b
7
- data.tar.gz: 5c136b52efd1d4301c0cfd038e348e32d10af591db4d5479017c31cf0f41fd0fcee826ec2c7b3be441b192ac16914c0cd66710bceb1ed0016a4461738e2c2c43
6
+ metadata.gz: f0ad5da56b771dfa481665eaf4f5bb86ac89975c54bf9ee39d049f0297d9dc94207b3d66b629e035cb5a23d04d42513737e7ac09abdf046e59b87fbe2d1fa56e
7
+ data.tar.gz: d8347cd911f9e5c91aed61287030878cae2d98abe07da13a2aa4162028bc1a7f2ce21ef7ff9caee62e395af35bfd419f139ac9632ad05911e506f1b3ce4f0f03
data/README.md CHANGED
@@ -27,19 +27,21 @@ Add Rack::LTI to your `config/application.rb`:
27
27
  ```ruby
28
28
  class Application < Rails::Application
29
29
  config.middleware.use Rack::LTI,
30
- consumer_key: ->(key, consumer_id) { key == 'key_value' },
31
- consumer_secret: ->(secret) { secret == 'top_secret' }
30
+ consumer_key: ->(key, consumer_id) { 'key' },
31
+ consumer_secret: ->(key, consumer_id) { 'secret' }
32
32
 
33
33
  app_path: '/',
34
34
  config_path: '/lti/config.xml',
35
35
  launch_path: '/lti/launch',
36
+ redirect: true,
36
37
 
37
38
  title: 'My LTI App',
38
39
  description: 'My LTI App description',
39
40
 
40
41
  nonce_validator: ->(nonce) { !FakeNonceStore.include?(nonce) },
41
- success: ->(params, session) {
42
- params['launch_params'] = params unless session.nil?
42
+ success: ->(lti_params, request, response) {
43
+ request.session['launch_params'] = lti_params
44
+ response.headers['X-Custom-Header'] = 'value'
43
45
  },
44
46
  time_limit: 60*60,
45
47
 
@@ -71,13 +73,15 @@ class Application < Sinatra::Base
71
73
  app_path: '/',
72
74
  config_path: '/lti/config.xml',
73
75
  launch_path: '/lti/launch',
76
+ redirect: true,
74
77
 
75
78
  title: 'My LTI App',
76
79
  description: 'My LTI App description',
77
80
 
78
81
  nonce_validator: ->(nonce) { !FakeNonceStore.include?(nonce) },
79
- success: ->(params, session) {
80
- params['launch_params'] = params unless session.nil?
82
+ success: ->(lti_params, request, response) {
83
+ request.session['launch_params'] = lti_params
84
+ response.headers['X-Custom-Header'] = 'value'
81
85
  },
82
86
  time_limit: 60*60,
83
87
 
@@ -114,6 +118,8 @@ values are:
114
118
  '/lti/config.xml'.
115
119
  * `launch_path` The path to receive LTI launch requests at. Defaults to
116
120
  '/lti/launch'.
121
+ * `redirect` If true, redirect to the `app_path`. If false, pass the launch
122
+ request through to the application. If false, app_path is not used.
117
123
  * `title` The title of your LTI application.
118
124
  * `description` The description of your LTI application.
119
125
  * `nonce_validator` A lambda used to validate the current request's nonce.
@@ -121,9 +127,9 @@ values are:
121
127
  * `time_limit` The time limit, in seconds, to consider requests valid within.
122
128
  If not passed, the default is 3600 seconds (one hour).
123
129
  * `success` A lambda called on successful launch. It is passed the launch
124
- params as a hash and the session if present. Can be used to cache params
125
- for the current user, find the current user, etc. If not given, the launch
126
- params are stored in the 'launch_params' key of the session.
130
+ params as a hash, the Rack Request, and the Rack Response. Can be used to
131
+ cache params for the current user, find the current user, etc. By default,
132
+ the launch params are stored in the 'launch_params' key of the session.
127
133
  * `extensions` A hash of extension information to include with the config.
128
134
  Format is platform -> option -> properties. See usage examples above for
129
135
  more detail.
@@ -8,7 +8,10 @@ module Rack::LTI
8
8
  description: 'An LTI Application.',
9
9
  launch_path: '/lti/launch',
10
10
  nonce_validator: true,
11
- success: ->(params, session) { session['launch_params'] = params if session },
11
+ redirect: true,
12
+ success: ->(lti, req, res) {
13
+ req.session['launch_params'] = lti if req.env['rack.session']
14
+ },
12
15
  time_limit: 60*60,
13
16
  title: 'LTI App'
14
17
  }
@@ -3,58 +3,65 @@ require 'oauth/request_proxy/rack_request'
3
3
  require 'rack/lti/config'
4
4
 
5
5
  module Rack::LTI
6
- class Middleware
7
- attr_reader :app, :config
6
+ class Middleware
7
+ attr_reader :app, :config
8
8
 
9
- def initialize(app, options = {}, &block)
10
- @app = app
11
- @config = Config.new(options, &block)
12
- end
9
+ def initialize(app, options = {}, &block)
10
+ @app = app
11
+ @config = Config.new(options, &block)
12
+ end
13
13
 
14
- def call(env)
15
- request = Rack::Request.new(env)
14
+ def call(env)
15
+ request = Rack::Request.new(env)
16
16
 
17
- if routes.has_key?(request.path)
18
- env['rack.lti'] = true
19
- send(routes[request.path], request, env)
17
+ if routes.has_key?(request.path)
18
+ env['rack.lti'] = true
19
+ send(routes[request.path], request, env)
20
20
  else
21
21
  @app.call(env)
22
- end
23
- end
22
+ end
23
+ end
24
24
 
25
- def routes
26
- {
27
- @config.config_path => :config_action,
28
- @config.launch_path => :launch_action
29
- }
30
- end
25
+ def routes
26
+ {
27
+ @config.config_path => :config_action,
28
+ @config.launch_path => :launch_action
29
+ }
30
+ end
31
31
 
32
32
  private
33
33
 
34
- def config_action(request, env)
34
+ def config_action(request, env)
35
35
  response = [@config.to_xml(launch_url: request.url.sub(@config.config_path, @config.launch_path))]
36
36
  [200, { 'Content-Type' => 'application/xml', 'Content-Length' => response[0].length.to_s }, response]
37
- end
37
+ end
38
38
 
39
- def launch_action(request, env)
40
- provider = IMS::LTI::ToolProvider.new(@config.consumer_key(*request.params.values_at('oauth_consumer_key', 'tool_consumer_instance_guid')),
41
- @config.consumer_secret(*request.params.values_at('oauth_consumer_key', 'tool_consumer_instance_guid')),
42
- request.params)
39
+ def launch_action(request, env)
40
+ provider = IMS::LTI::ToolProvider.new(@config.consumer_key(*request.params.values_at('oauth_consumer_key', 'tool_consumer_instance_guid')),
41
+ @config.consumer_secret(*request.params.values_at('oauth_consumer_key', 'tool_consumer_instance_guid')),
42
+ request.params)
43
43
 
44
- if valid?(provider, request)
45
- @config.success.call(provider.to_params, env['rack.session'])
46
- [301, { 'Content-Length' => '0', 'Content-Type' => 'text/html', 'Location' => @config.app_path }, []]
47
- else
44
+ if valid?(provider, request)
45
+ req = Rack::Request.new(env)
46
+ res = Rack::Response.new([], 302, { 'Content-Length' => '0',
47
+ 'Content-Type' => 'text/html', 'Location' => @config.app_path })
48
+ @config.success.call(provider.to_params, req, res)
49
+ if @config.redirect
50
+ res.finish
51
+ else
52
+ @app.call(env)
53
+ end
54
+ else
48
55
  response = 'Invalid launch.'
49
56
  [403, { 'Content-Type' => 'text/plain', 'Content-Length' => response.length.to_s }, [response]]
50
- end
51
- end
57
+ end
58
+ end
52
59
 
53
- def valid?(provider, request)
54
- valid_request?(provider, request) &&
60
+ def valid?(provider, request)
61
+ valid_request?(provider, request) &&
55
62
  valid_nonce?(request.params['oauth_nonce']) &&
56
63
  valid_timestamp?(request.params['oauth_timestamp'].to_i)
57
- end
64
+ end
58
65
 
59
66
  def valid_request?(provider, request)
60
67
  @config.public? ? true : provider.valid_request?(request)
@@ -75,5 +82,5 @@ module Rack::LTI
75
82
  (Time.now.to_i - @config.time_limit) <= timestamp
76
83
  end
77
84
  end
78
- end
85
+ end
79
86
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module LTI
3
- VERSION = '0.0.2'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
data/rack-lti.gemspec CHANGED
@@ -25,9 +25,9 @@ Gem::Specification.new do |spec|
25
25
  spec.require_paths = ['lib']
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1.3'
28
- spec.add_development_dependency 'minitest', '~> 4.7.0'
28
+ spec.add_development_dependency 'minitest', '~> 5.0.6'
29
29
  spec.add_development_dependency 'rake'
30
30
 
31
- spec.add_dependency 'ims-lti', '~> 1.1.2'
31
+ spec.add_dependency 'ims-lti', '~> 1.1.3'
32
32
  spec.add_dependency 'rack'
33
33
  end
data/test/config_test.rb CHANGED
@@ -2,7 +2,7 @@ require 'minitest/autorun'
2
2
  require 'rexml/document'
3
3
  require 'rack/lti/config'
4
4
 
5
- class ConfigTest < Minitest::Unit::TestCase
5
+ class ConfigTest < Minitest::Test
6
6
  def setup
7
7
  @config = Rack::LTI::Config.new
8
8
  end
@@ -33,6 +33,7 @@ class ConfigTest < Minitest::Unit::TestCase
33
33
  assert_equal true, @config.nonce_validator
34
34
  assert_equal 3600, @config.time_limit
35
35
  assert_equal 'LTI App', @config.title
36
+ assert_equal true, @config.redirect
36
37
  assert_instance_of Proc, @config.success
37
38
  end
38
39
 
data/test/lti_test.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'minitest/autorun'
2
2
  require 'rack-lti'
3
3
 
4
- class LtiTest < Minitest::Unit::TestCase
4
+ class LtiTest < Minitest::Test
5
5
  def setup
6
6
  @app = ->(env) { [200, [], ['Hi']] }
7
7
  end
@@ -2,7 +2,7 @@ require 'minitest/autorun'
2
2
  require 'rack'
3
3
  require 'rack/lti/middleware'
4
4
 
5
- class MiddlewareTest < Minitest::Unit::TestCase
5
+ class MiddlewareTest < Minitest::Test
6
6
  def setup
7
7
  @app = ->(env) { [200, {}, ['hi']] }
8
8
  @lti_app = Rack::LTI::Middleware.new(@app)
@@ -59,11 +59,12 @@ class MiddlewareTest < Minitest::Unit::TestCase
59
59
 
60
60
  def test_call_passes_the_nonce_to_the_given_proc
61
61
  assertion = MiniTest::Mock.new
62
- assertion.expect(:call, true)
63
- @lti_app.config.nonce_validator = ->(nonce) { assertion.call }
62
+ assertion.expect(:call, true, [@params['oauth_nonce']])
63
+ @lti_app.config.nonce_validator = ->(nonce) { assertion.call(nonce) }
64
64
 
65
65
  @lti_app.stub(:valid_request?, true) do
66
- @lti_app.call(Rack::MockRequest.env_for('/lti/launch'))
66
+ @lti_app.call(Rack::MockRequest.env_for('/lti/launch',
67
+ method: 'post', params: @params))
67
68
  assertion.verify
68
69
  end
69
70
  end
@@ -105,17 +106,41 @@ class MiddlewareTest < Minitest::Unit::TestCase
105
106
  env = Rack::MockRequest.env_for('/lti/launch', method: 'post',
106
107
  params: @params)
107
108
  response = @lti_app.call(env)
108
- assert_equal 301, response[0]
109
+ assert_equal 302, response[0]
109
110
  assert_equal @lti_app.config[:app_path], response[1]['Location']
110
111
  end
111
112
  end
112
113
 
114
+ def test_passes_request_through_if_redirect_is_false
115
+ @lti_app.config[:redirect] = false
116
+ @lti_app.stub(:valid_request?, true) do
117
+ env = Rack::MockRequest.env_for('/lti/launch', method: 'post',
118
+ params: @params)
119
+ response = @lti_app.call(env)
120
+ assert_equal 200, response[0]
121
+ assert_equal %w{hi}, response[2]
122
+ end
123
+ end
124
+
125
+ def test_call_passes_params_request_and_response_to_success_proc
126
+ @lti_app.config.success = ->(lti, req, res) {
127
+ assert_equal @params.sort, lti.sort
128
+ assert_instance_of Rack::Request, req
129
+ assert_instance_of Rack::Response, res
130
+ }
131
+ @lti_app.stub(:valid_request?, true) do
132
+ env = Rack::MockRequest.env_for('/lti/launch', method: 'post',
133
+ params: @params)
134
+ @lti_app.call(env)
135
+ end
136
+ end
137
+
113
138
  def test_call_succeeds_if_sessions_are_not_used
114
139
  @lti_app.stub(:valid_request?, true) do
115
140
  env = Rack::MockRequest.env_for('/lti/launch', method: 'post',
116
141
  params: @params)
117
142
  response = @lti_app.call(env)
118
- assert_equal 301, response[0]
143
+ assert_equal 302, response[0]
119
144
  end
120
145
  end
121
146
 
@@ -149,5 +174,4 @@ class MiddlewareTest < Minitest::Unit::TestCase
149
174
  @lti_app.call(env)
150
175
  end
151
176
  end
152
-
153
177
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-lti
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Pendleton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-10 00:00:00.000000000 Z
11
+ date: 2013-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: 4.7.0
33
+ version: 5.0.6
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: 4.7.0
40
+ version: 5.0.6
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 1.1.2
61
+ version: 1.1.3
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 1.1.2
68
+ version: 1.1.3
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rack
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  version: '0'
128
128
  requirements: []
129
129
  rubyforge_project:
130
- rubygems_version: 2.0.0
130
+ rubygems_version: 2.0.3
131
131
  signing_key:
132
132
  specification_version: 4
133
133
  summary: Middleware for handling LTI launches inside your Rack app.