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 +4 -4
- data/README.md +15 -9
- data/lib/rack/lti/config.rb +4 -1
- data/lib/rack/lti/middleware.rb +42 -35
- data/lib/rack/lti/version.rb +1 -1
- data/rack-lti.gemspec +2 -2
- data/test/config_test.rb +2 -1
- data/test/lti_test.rb +1 -1
- data/test/middleware_test.rb +31 -7
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 537b86b974404190e61290b5055b113080e7aa71
|
4
|
+
data.tar.gz: 7f6fd669ce3c9c836fc8385c709496a937ed7bb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
31
|
-
consumer_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: ->(
|
42
|
-
|
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: ->(
|
80
|
-
|
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
|
125
|
-
for the current user, find the current user, etc.
|
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.
|
data/lib/rack/lti/config.rb
CHANGED
@@ -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
|
-
|
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
|
}
|
data/lib/rack/lti/middleware.rb
CHANGED
@@ -3,58 +3,65 @@ require 'oauth/request_proxy/rack_request'
|
|
3
3
|
require 'rack/lti/config'
|
4
4
|
|
5
5
|
module Rack::LTI
|
6
|
-
|
7
|
-
|
6
|
+
class Middleware
|
7
|
+
attr_reader :app, :config
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def initialize(app, options = {}, &block)
|
10
|
+
@app = app
|
11
|
+
@config = Config.new(options, &block)
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
def call(env)
|
15
|
+
request = Rack::Request.new(env)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
23
|
-
|
22
|
+
end
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
37
|
+
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
46
|
-
[
|
47
|
-
|
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
|
-
|
51
|
-
|
57
|
+
end
|
58
|
+
end
|
52
59
|
|
53
|
-
|
54
|
-
|
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
|
-
|
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
|
-
|
85
|
+
end
|
79
86
|
end
|
data/lib/rack/lti/version.rb
CHANGED
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', '~>
|
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.
|
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::
|
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
data/test/middleware_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'minitest/autorun'
|
|
2
2
|
require 'rack'
|
3
3
|
require 'rack/lti/middleware'
|
4
4
|
|
5
|
-
class MiddlewareTest < Minitest::
|
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
|
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
|
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
|
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-
|
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:
|
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:
|
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.
|
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.
|
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.
|
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.
|