coalescing_panda 0.0.11 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/coalescing_panda/lti_controller.rb +9 -2
- data/lib/coalescing_panda/controller_helpers.rb +52 -41
- data/lib/coalescing_panda/engine.rb +13 -3
- data/lib/coalescing_panda/route_helpers.rb +1 -1
- data/lib/coalescing_panda/version.rb +1 -1
- data/lib/coalescing_panda.rb +2 -2
- data/spec/controllers/coalescing_panda/lti_controller_spec.rb +3 -1
- data/spec/dummy/config/initializers/lti_initializer.rb +1 -0
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/db/schema.rb +17 -1
- metadata +22 -4
@@ -11,7 +11,6 @@ module CoalescingPanda
|
|
11
11
|
tc = IMS::LTI::ToolConfig.new(:title => lti_options[:title], :launch_url => (lti_options[:launch_url])|| 'ABC')
|
12
12
|
tc.set_ext_param(platform, :domain, request.host)
|
13
13
|
tc.set_ext_param(platform, :privacy_level, 'public')
|
14
|
-
|
15
14
|
if(lti_options.has_key?(:custom_fields))
|
16
15
|
tc.set_ext_param(platform, :custom_fields, lti_options[:custom_fields])
|
17
16
|
|
@@ -21,7 +20,7 @@ module CoalescingPanda
|
|
21
20
|
end
|
22
21
|
|
23
22
|
lti_nav.each do |k, v|
|
24
|
-
tc.set_ext_param(platform,
|
23
|
+
tc.set_ext_param(platform, setting_name(k.to_s), ext_params(v) )
|
25
24
|
end
|
26
25
|
|
27
26
|
#strip the launch url
|
@@ -30,6 +29,14 @@ module CoalescingPanda
|
|
30
29
|
end
|
31
30
|
|
32
31
|
private
|
32
|
+
|
33
|
+
def setting_name(name)
|
34
|
+
tail = ''
|
35
|
+
if(name == 'course' || name == 'account')
|
36
|
+
tail = '_navigation' unless name.include? "_navigation"
|
37
|
+
end
|
38
|
+
(name+tail).to_sym
|
39
|
+
end
|
33
40
|
|
34
41
|
def ext_params(options)
|
35
42
|
url = options.delete(:url)
|
@@ -1,26 +1,28 @@
|
|
1
1
|
module CoalescingPanda
|
2
2
|
module ControllerHelpers
|
3
3
|
|
4
|
-
def canvas_oauth2
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
def canvas_oauth2(*roles)
|
5
|
+
if lti_authorize!(*roles)
|
6
|
+
user_id = params['user_id']
|
7
|
+
uri = URI.parse(params['launch_presentation_return_url'])
|
8
|
+
api_domain = uri.host
|
9
|
+
api_domain = "#{api_domain}:#{uri.port.to_s}" if uri.port
|
10
|
+
scheme = uri.scheme + '://'
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
if token = CanvasApiAuth.where('user_id = ? and api_domain = ?', user_id, api_domain).pluck(:api_token).first
|
13
|
+
@client = Bearcat::Client.new(token: token, prefix: scheme+api_domain)
|
14
|
+
elsif @lti_account = params['oauth_consumer_key'] && LtiAccount.find_by_key(params['oauth_consumer_key'])
|
15
|
+
client_id = @lti_account.oauth2_client_id
|
16
|
+
client = Bearcat::Client.new(prefix: scheme+api_domain)
|
17
|
+
@lti_params = params.to_hash
|
18
|
+
@canvas_url = client.auth_redirect_url(client_id,
|
19
|
+
coalescing_panda.oauth2_redirect_url({key: params['oauth_consumer_key'],
|
20
|
+
user_id: user_id, api_domain: api_domain}))
|
21
|
+
#delete the added params so the original oauth sig still works
|
22
|
+
@lti_params.delete('action')
|
23
|
+
@lti_params.delete('controller')
|
24
|
+
render 'coalescing_panda/oauth2/oauth2'
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -30,34 +32,43 @@ module CoalescingPanda
|
|
30
32
|
@tp = IMS::LTI::ToolProvider.new(@lti_account.key, @lti_account.secret, params)
|
31
33
|
authorized = @tp.valid_request?(request)
|
32
34
|
end
|
33
|
-
authorized = authorized && (roles == 0 || (roles & lti_roles).count > 0)
|
34
|
-
authorized = authorized && @lti_account.validate_nonce(params['oauth_nonce'], DateTime.strptime(params['oauth_timestamp'],'%s'))
|
35
|
+
authorized = authorized && (roles.count == 0 || (roles & lti_roles).count > 0)
|
36
|
+
authorized = authorized && @lti_account.validate_nonce(params['oauth_nonce'], DateTime.strptime(params['oauth_timestamp'], '%s'))
|
35
37
|
if !authorized
|
36
38
|
render :text => 'Invalid Credentials, please contact your Administrator.', :status => :unauthorized
|
37
39
|
end
|
40
|
+
authorized
|
41
|
+
end
|
42
|
+
|
43
|
+
def lti_editor_button_response(return_type, return_params)
|
44
|
+
valid_return_types = [:image_url, :iframe, :url]
|
45
|
+
raise "invalid editor button return type #{return_type}" unless valid_return_types.include?(return_type)
|
46
|
+
return_params[:return_type] = return_type.to_s
|
47
|
+
return_url = "#{params['launch_presentation_return_url']}?#{return_params.to_query}"
|
48
|
+
redirect_to return_url
|
38
49
|
end
|
39
50
|
|
40
51
|
def lti_roles
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
52
|
+
@lti_roles ||= params['roles'].split(',').map { |role|
|
53
|
+
case role.downcase.strip
|
54
|
+
when 'admin'
|
55
|
+
:admin
|
56
|
+
when 'urn:lti:instrole:ims/lis/administrator'
|
57
|
+
:admin
|
58
|
+
when 'learner'
|
59
|
+
:student
|
60
|
+
when 'instructor'
|
61
|
+
:teacher
|
62
|
+
when 'urn:lti:role:ims/lis/teachingassistant'
|
63
|
+
:ta
|
64
|
+
when 'contentdeveloper'
|
65
|
+
:designer
|
66
|
+
when 'urn:lti:instrole:ims/lis/observer'
|
67
|
+
:observer
|
68
|
+
else
|
69
|
+
:none
|
70
|
+
end
|
71
|
+
}.uniq
|
61
72
|
end
|
62
73
|
|
63
74
|
def canvas_environment
|
@@ -3,6 +3,14 @@ module CoalescingPanda
|
|
3
3
|
config.autoload_once_paths += Dir["#{config.root}/lib/**/"]
|
4
4
|
isolate_namespace CoalescingPanda
|
5
5
|
|
6
|
+
initializer :append_migrations do |app|
|
7
|
+
unless app.root.to_s.match root.to_s
|
8
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
9
|
+
app.config.paths["db/migrate"] << expanded_path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
initializer 'coalescing_panda.app_controller' do |app|
|
7
15
|
OAUTH_10_SUPPORT = true
|
8
16
|
ActiveSupport.on_load(:action_controller) do
|
@@ -14,11 +22,13 @@ module CoalescingPanda
|
|
14
22
|
ActionDispatch::Routing::Mapper.send :include, CoalescingPanda::RouteHelpers
|
15
23
|
end
|
16
24
|
|
17
|
-
initializer 'coalescing_panda.route_options' do |app|
|
18
|
-
ActiveSupport.on_load(:
|
25
|
+
initializer 'coalescing_panda.route_options', :after => :disable_dependency_loading do |app|
|
26
|
+
ActiveSupport.on_load(:action_controller) do
|
27
|
+
#force the routes to load
|
28
|
+
Rails.application.reload_routes!
|
19
29
|
CoalescingPanda::propagate_lti_navigation
|
20
30
|
end
|
21
31
|
end
|
22
|
-
|
32
|
+
|
23
33
|
end
|
24
34
|
end
|
@@ -3,7 +3,7 @@ module CoalescingPanda
|
|
3
3
|
def lti_nav(nav, *rest, &block)
|
4
4
|
base_path = Rails.application.routes.named_routes[:coalescing_panda].path.spec
|
5
5
|
raise LtiNavigationInUse.new('CoalescingPanda must be mounted before defining lti_nav routes') if base_path.blank?
|
6
|
-
valid_options = [:course, :user, :account, :
|
6
|
+
valid_options = [:course, :user, :account, :editor_button, :external_tool]
|
7
7
|
if rest.empty? && nav.is_a?(Hash)
|
8
8
|
options = nav
|
9
9
|
nav, to = options.find {|name, _value| valid_options.include? name}
|
data/lib/coalescing_panda.rb
CHANGED
@@ -9,7 +9,7 @@ module CoalescingPanda
|
|
9
9
|
|
10
10
|
@@lti_navigation = {}
|
11
11
|
@@staged_navigation = {}
|
12
|
-
@@lti_options
|
12
|
+
@@lti_options = {}
|
13
13
|
|
14
14
|
def self.lti_options= lti_options
|
15
15
|
@@lti_options = lti_options
|
@@ -20,7 +20,7 @@ module CoalescingPanda
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.register_navigation(navigation)
|
23
|
-
@@lti_navigation[navigation]
|
23
|
+
@@lti_navigation[navigation] ||= {}
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.stage_navigation(navigation, options)
|
@@ -16,11 +16,13 @@ describe CoalescingPanda::LtiController do
|
|
16
16
|
|
17
17
|
it 'generates lti nav config' do
|
18
18
|
controller.main_app.stub(:test_action_url) {'foo'}
|
19
|
-
CoalescingPanda.
|
19
|
+
CoalescingPanda.stage_navigation(:account, {
|
20
20
|
url: 'test_action',
|
21
21
|
text: 'My Title',
|
22
22
|
enabled: false
|
23
23
|
})
|
24
|
+
CoalescingPanda.register_navigation(:account)
|
25
|
+
CoalescingPanda.propagate_lti_navigation
|
24
26
|
get(:lti_config)
|
25
27
|
xml = Nokogiri::XML(response.body)
|
26
28
|
account_nav = xml.at_xpath('//lticm:options[@name="account_navigation"]')
|
@@ -0,0 +1 @@
|
|
1
|
+
CoalescingPanda.lti_options= {title:'LTI Tool'}
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20131119165343) do
|
15
15
|
|
16
16
|
create_table "coalescing_panda_canvas_api_auths", force: true do |t|
|
17
17
|
t.string "user_id"
|
@@ -21,4 +21,20 @@ ActiveRecord::Schema.define(version: 20131114150001) do
|
|
21
21
|
t.datetime "updated_at"
|
22
22
|
end
|
23
23
|
|
24
|
+
create_table "coalescing_panda_lti_accounts", force: true do |t|
|
25
|
+
t.string "name"
|
26
|
+
t.string "key"
|
27
|
+
t.string "secret"
|
28
|
+
t.string "oauth2_client_id"
|
29
|
+
t.string "oauth2_client_key"
|
30
|
+
t.datetime "created_at"
|
31
|
+
t.datetime "updated_at"
|
32
|
+
end
|
33
|
+
|
34
|
+
create_table "coalescing_panda_lti_nonces", force: true do |t|
|
35
|
+
t.integer "coalescing_panda_lti_account_id"
|
36
|
+
t.string "nonce"
|
37
|
+
t.datetime "timestamp"
|
38
|
+
end
|
39
|
+
|
24
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coalescing_panda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-01-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: '0.
|
37
|
+
version: '0.6'
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: '0.
|
45
|
+
version: '0.6'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: ims-lti
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,6 +171,22 @@ dependencies:
|
|
171
171
|
- - ! '>='
|
172
172
|
- !ruby/object:Gem::Version
|
173
173
|
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: debugger
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
174
190
|
description:
|
175
191
|
email:
|
176
192
|
- nathanm@instructure.com
|
@@ -224,6 +240,7 @@ files:
|
|
224
240
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
225
241
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
226
242
|
- spec/dummy/config/initializers/inflections.rb
|
243
|
+
- spec/dummy/config/initializers/lti_initializer.rb
|
227
244
|
- spec/dummy/config/initializers/mime_types.rb
|
228
245
|
- spec/dummy/config/initializers/secret_token.rb
|
229
246
|
- spec/dummy/config/initializers/session_store.rb
|
@@ -285,6 +302,7 @@ test_files:
|
|
285
302
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
286
303
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
287
304
|
- spec/dummy/config/initializers/inflections.rb
|
305
|
+
- spec/dummy/config/initializers/lti_initializer.rb
|
288
306
|
- spec/dummy/config/initializers/mime_types.rb
|
289
307
|
- spec/dummy/config/initializers/secret_token.rb
|
290
308
|
- spec/dummy/config/initializers/session_store.rb
|