lti_box_engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ed29d85473c8108733a7065619550a82516a9772
4
+ data.tar.gz: d675c633ca88b0f96566dc4eac7ee909eac61d49
5
+ SHA512:
6
+ metadata.gz: 40cc43a14e1bb6eb1370b3e00c4e045e36f01cc6f3c2a42b3dc00ef4bb01a45765250961c335416e745dfcd0b1f415e48f2ecb9c2fab986fadeb439e5a143133
7
+ data.tar.gz: 2cf411615056fc78f45bb7dd5252f79404cf63b670498f714df306b309f5184b11c523f21865847adf22a9d1606e69ab910faaf551969add0936ae9d24a03891
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = LtiBoxEngine
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'LtiBoxEngine'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/test_app/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
25
+ require 'rspec/core/rake_task'
26
+ RSpec::Core::RakeTask.new(:spec)
27
+ task :default => :spec
28
+
29
+ desc 'Run the test dummy rails app'
30
+ task :run_engine do
31
+ exec 'cd spec/test_app && bundle exec rails s'
32
+ end
33
+
34
+ desc 'Run a pry console'
35
+ task :console do
36
+ require 'pry'
37
+ require '#{name}'
38
+ ARGV.clear
39
+ Pry.start
40
+ end
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,17 @@
1
+ @import "bootstrap";
2
+
3
+ body {
4
+ padding-top: 20px;
5
+ background-color: #eee;
6
+ }
7
+
8
+ .content {
9
+ max-width: 330px;
10
+ padding: 15px;
11
+ margin: 0 auto;
12
+ text-align: center;
13
+ }
14
+
15
+ #box-select {
16
+ margin: 20px auto;
17
+ }
@@ -0,0 +1,33 @@
1
+ module LtiBoxEngine
2
+ class ApplicationController < ActionController::Base
3
+ before_action :set_default_headers
4
+ before_filter :cors_preflight_check
5
+ after_filter :cors_set_access_control_headers
6
+
7
+ def set_default_headers
8
+ response.headers['X-Frame-Options'] = 'ALLOWALL'
9
+ end
10
+
11
+ # For all responses in this controller, return the CORS access control headers.
12
+ def cors_set_access_control_headers
13
+ headers['Access-Control-Allow-Origin'] = '*'
14
+ headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
15
+ headers['Access-Control-Request-Method'] = '*'
16
+ headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
17
+ headers['Access-Control-Max-Age'] = "1728000"
18
+ end
19
+
20
+ # If this is a preflight OPTIONS request, then short-circuit the
21
+ # request, return only the necessary headers and return an empty
22
+ # text/plain.
23
+ def cors_preflight_check
24
+ if request.method == :options
25
+ headers['Access-Control-Allow-Origin'] = '*'
26
+ headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
27
+ headers['Access-Control-Allow-Headers'] = '*'
28
+ headers['Access-Control-Max-Age'] = '1728000'
29
+ render :text => '', :content_type => 'text/plain'
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,80 @@
1
+ require_dependency "lti_box_engine/application_controller"
2
+ require "ims/lti"
3
+ require "oauth/request_proxy/rack_request"
4
+
5
+ module LtiBoxEngine
6
+ class LtiController < ApplicationController
7
+
8
+ def index
9
+ @client = Client.new
10
+ @tp = @client.authorize!(request, params)
11
+ if @tp
12
+ if @tp.accepts_content?
13
+ @lti_launch = LtiLaunch.create_from_tp(@tp)
14
+ if @tp.accepts_file?
15
+ @link_type = "direct"
16
+ else
17
+ @link_type = "shared"
18
+ end
19
+ else
20
+ # launched via navigation
21
+ redirect_to "https://www.box.com/embed_widget/files/0/f/0"
22
+ end
23
+ else
24
+ # handle invalid auth
25
+ @message = @client.error_message
26
+ render :error
27
+ end
28
+ end
29
+
30
+ def embed
31
+ item = params[:item]
32
+ lti_launch = LtiLaunch.where(id: params[:lti_launch_id]).first
33
+ launch_params = lti_launch.payload
34
+
35
+ tp = IMS::LTI::ToolProvider.new(nil, nil, launch_params)
36
+ tp.extend IMS::LTI::Extensions::Content::ToolProvider
37
+
38
+ if tp.accepts_content?
39
+ if tp.accepts_file?(item['name']) && item['type'] != 'folder'
40
+ redirect_url = tp.file_content_return_url(item['url'], item['name'])
41
+ render json: { redirect_url: redirect_url } and return
42
+ elsif tp.accepts_url?
43
+ # The URL will be to a folder. We need to modify it to load the embed widget
44
+ redirect_url = tp.url_content_return_url(Client.box_url_to_box_embed_url(item['url']), item['name'], item['name'])
45
+ render json: { redirect_url: redirect_url } and return
46
+ else
47
+ render text: 'Unsupported content type', status: 500
48
+ end
49
+ else
50
+ render text: 'Unable to embed content', status: 500
51
+ end
52
+ end
53
+
54
+ def xml_config
55
+ host = "#{request.protocol}#{request.host_with_port}"
56
+ url = "#{host}#{root_path}"
57
+ title = "Box"
58
+ tool_id = "lti_box_engine"
59
+ tc = IMS::LTI::ToolConfig.new(:title => title, :launch_url => url)
60
+ tc.extend IMS::LTI::Extensions::Canvas::ToolConfig
61
+ tc.description = "Embed files from Box.net"
62
+ tc.canvas_privacy_anonymous!
63
+ tc.canvas_domain!(request.host)
64
+ tc.canvas_icon_url!("#{host}/assets/lti_box_engine/icon.png")
65
+ tc.canvas_text!(title)
66
+ tc.set_ext_param('canvas.instructure.com', :tool_id, tool_id)
67
+ tc.canvas_homework_submission!(enabled: true)
68
+ tc.canvas_editor_button!(enabled: true)
69
+ tc.canvas_resource_selection!(enabled: true)
70
+ tc.canvas_course_navigation!(enabled: true)
71
+ tc.canvas_user_navigation!(enabled: true)
72
+ tc.canvas_selector_dimensions!(430, 200)
73
+ render xml: tc.to_xml
74
+ end
75
+
76
+ def health_check
77
+ head 200
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,8 @@
1
+ require_dependency "lti_box_engine/application_controller"
2
+
3
+ module LtiBoxEngine
4
+ class TestController < ApplicationController
5
+ def backdoor
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ module LtiBoxEngine
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module LtiBoxEngine
2
+ module LtiHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module LtiBoxEngine
2
+ module TestHelper
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ module LtiBoxEngine
2
+ class LtiLaunch < ActiveRecord::Base
3
+ serialize :payload, Hash
4
+
5
+ class << self
6
+ def valid_nonce?(nonce, min=60)
7
+ nonce_ts = Time.now - (min * 60 * 60)
8
+ where(nonce: nonce).where("request_oauth_timestamp >= ?", nonce_ts).count == 0
9
+ end
10
+
11
+ def cleanup!(num_days=3)
12
+ where("request_oauth_timestamp <= ?", Time.now - num_days.days).destroy_all
13
+ end
14
+
15
+ def create_from_tp(tp)
16
+ create({
17
+ nonce: tp.request_oauth_nonce,
18
+ request_oauth_timestamp: Time.at(tp.request_oauth_timestamp.to_i),
19
+ payload: tp.to_params
20
+ })
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Box</title>
5
+ <%= stylesheet_link_tag "lti_box_engine/application", media: "all" %>
6
+ <%= javascript_include_tag "lti_box_engine/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <div class="container">
12
+ <div class="content">
13
+ <%= yield %>
14
+ </div>
15
+ </div>
16
+
17
+ </body>
18
+ </html>
@@ -0,0 +1,10 @@
1
+ <div class="container">
2
+ <h4 class="page-header">Embed Code Generated</h4>
3
+ <p>
4
+ You're not in a system that supports auto-inserting content,
5
+ so you'll need to copy and past the following code by hand
6
+ in order to insert it into your content.
7
+ </p>
8
+
9
+ <textarea class="form-control" rows="4"><iframe title="<%= @title %>" width="<%= @width %>" height="<%= @height %>" src="<%= @url %>" /></textarea>
10
+ </div>
@@ -0,0 +1 @@
1
+ <%= @message %>
@@ -0,0 +1,34 @@
1
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
2
+ <script type="text/javascript" src="https://app.box.com/js/static/select.js"></script>
3
+
4
+ <div id="message">Click the button below to select your content</div>
5
+
6
+ <div id="box-select"
7
+ data-link-type="<%= @link_type %>"
8
+ data-multiselect="false"
9
+ data-client-id="zfwxjp79195xz6to7uxlo0hsoehkgryq"></div>
10
+
11
+ <script type="text/javascript">
12
+ $(document).ready(function() {
13
+ var boxSelect = new BoxSelect();
14
+
15
+ // Register a success callback handler
16
+ boxSelect.success(function(response) {
17
+ var item = response[0];
18
+ $.post('<%= lti_embed_path %>', { item: item, lti_launch_id: <%= @lti_launch.id %> }).then(
19
+ function(data) { // success
20
+ console.log(data.redirect_url);
21
+ window.location = data.redirect_url;
22
+ },
23
+ function(jqXHR) { // error
24
+ $('#message').addClass('alert alert-danger').html(jqXHR.responseText);
25
+ }
26
+ );
27
+ });
28
+
29
+ // Register a cancel callback handler
30
+ boxSelect.cancel(function() {
31
+ $('#message').removeClass('alert alert-danger').html("Click the button below to select your content");
32
+ });
33
+ });
34
+ </script>
@@ -0,0 +1,4 @@
1
+ <p>Form to access root page via POST. Used for tests.</p>
2
+ <%= form_tag root_path do %>
3
+ <button type="submit" id="submit">Submit</button>
4
+ <% end %>
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ LtiBoxEngine::Engine.routes.draw do
2
+ post "embed" => "lti#embed", as: :lti_embed
3
+ match "launch" => "lti#launch", as: :launch, via: [:get, :post]
4
+ get "config(.xml)" => "lti#xml_config", as: :lti_xml_config
5
+ get "health_check" => "lti#health_check"
6
+ match "/" => "lti#index", via: [:get, :post]
7
+ match "/picker" => "lti#picker", via: [:get, :post]
8
+ root "lti#index"
9
+ get "lti/index"
10
+ get "test/backdoor"
11
+ end
@@ -0,0 +1,11 @@
1
+ class CreateLtiBoxEngineLtiLaunches < ActiveRecord::Migration
2
+ def change
3
+ create_table :lti_box_engine_lti_launches do |t|
4
+ t.string :nonce
5
+ t.text :payload
6
+ t.timestamp :request_oauth_timestamp
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require "lti_box_engine/engine"
2
+ require "lti_box_engine/client"
3
+ require "bootstrap-sass"
4
+
5
+ # Enable oauth 10 support
6
+ OAUTH_10_SUPPORT = true
7
+
8
+ module LtiBoxEngine
9
+ end
@@ -0,0 +1,49 @@
1
+ require 'ims/lti'
2
+
3
+ module LtiBoxEngine
4
+ class Client
5
+
6
+ $oauth_creds = { "key" => "secret" }
7
+
8
+ attr_accessor :error_message
9
+
10
+ def initialize
11
+ @error_message = nil
12
+ end
13
+
14
+ def register_error(message)
15
+ @error_message = message
16
+ end
17
+
18
+ def self.box_url_to_box_embed_url(url)
19
+ embed_id = url.strip.split('/').last
20
+ "https://app.box.com/embed_widget/s/#{embed_id}?view=list&sort=name&direction=ASC&theme=blue"
21
+ end
22
+
23
+ def authorize!(request, opts = {})
24
+ @error_message = nil
25
+ key = opts['oauth_consumer_key']
26
+ tp = IMS::LTI::ToolProvider.new(key, $oauth_creds[key], opts)
27
+
28
+ if !tp.valid_request?(request)
29
+ register_error("The OAuth signature was invalid")
30
+ return nil
31
+ end
32
+
33
+ if Time.now.utc.to_i - tp.request_oauth_timestamp.to_i > 60*60
34
+ register_error("Your request is too old.")
35
+ return nil
36
+ end
37
+
38
+ if !LtiLaunch.valid_nonce?(tp.request_oauth_nonce, 60)
39
+ register_error("Nonce has already been used.")
40
+ return nil
41
+ end
42
+
43
+ tp.extend IMS::LTI::Extensions::Content::ToolProvider
44
+
45
+ return tp
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ module LtiBoxEngine
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace LtiBoxEngine
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module LtiBoxEngine
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ task "assets:precompile" do
2
+ #Copy assets to a non-fingerprinted version
3
+ fingerprint = /\-[0-9a-f]{32}\./
4
+ for file in Dir["public/assets/lti_box_engine/**/*"]
5
+ next unless file =~ fingerprint && !file.end_with?('.css', '.css.gz', '.js', '.js.gz')
6
+ nondigest = file.sub fingerprint, '.'
7
+ FileUtils.cp file, nondigest, verbose: true
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :lti_box_engine do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lti_box_engine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brad Humphrey
8
+ - Eric Berry
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 4.0.4
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 4.0.4
28
+ - !ruby/object:Gem::Dependency
29
+ name: sass-rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '3.2'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '3.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bootstrap-sass
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: 3.1.0
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 3.1.0
56
+ - !ruby/object:Gem::Dependency
57
+ name: ims-lti
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: sqlite3
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rspec-rails
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: capybara
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: poltergeist
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Box.net LTI Application as a mountable Rails engine
127
+ email:
128
+ - brad@instructure.com
129
+ - ericb@instructure.com
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - MIT-LICENSE
135
+ - README.rdoc
136
+ - Rakefile
137
+ - app/assets/images/lti_box_engine/icon.png
138
+ - app/assets/javascripts/lti_box_engine/application.js
139
+ - app/assets/javascripts/lti_box_engine/lti.js
140
+ - app/assets/javascripts/lti_box_engine/test.js
141
+ - app/assets/stylesheets/lti_box_engine/application.scss
142
+ - app/controllers/lti_box_engine/application_controller.rb
143
+ - app/controllers/lti_box_engine/lti_controller.rb
144
+ - app/controllers/lti_box_engine/test_controller.rb
145
+ - app/helpers/lti_box_engine/application_helper.rb
146
+ - app/helpers/lti_box_engine/lti_helper.rb
147
+ - app/helpers/lti_box_engine/test_helper.rb
148
+ - app/models/lti_box_engine/lti_launch.rb
149
+ - app/views/layouts/lti_box_engine/application.html.erb
150
+ - app/views/lti_box_engine/lti/embed.html.erb
151
+ - app/views/lti_box_engine/lti/error.html.erb
152
+ - app/views/lti_box_engine/lti/index.html.erb
153
+ - app/views/lti_box_engine/test/backdoor.html.erb
154
+ - config/routes.rb
155
+ - db/migrate/20140401155717_create_lti_box_engine_lti_launches.rb
156
+ - lib/lti_box_engine.rb
157
+ - lib/lti_box_engine/client.rb
158
+ - lib/lti_box_engine/engine.rb
159
+ - lib/lti_box_engine/version.rb
160
+ - lib/tasks/assets.rake
161
+ - lib/tasks/lti_box_engine_tasks.rake
162
+ homepage: https://github.com/instructure/lti-box-engine
163
+ licenses: []
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - '>='
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 2.2.1
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Box.net LTI Application
185
+ test_files: []
186
+ has_rdoc: