lti2 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/lti2/version.rb +1 -1
- data/lti2_tp/Gemfile +14 -0
- data/lti2_tp/Gemfile.lock +94 -0
- data/lti2_tp/MIT-LICENSE +20 -0
- data/lti2_tp/README.md +77 -0
- data/lti2_tp/README.rdoc +3 -0
- data/lti2_tp/Rakefile +31 -0
- data/lti2_tp/app/assets/javascripts/lti2_tp/application.js +13 -0
- data/lti2_tp/app/assets/stylesheets/lti2_tp/application.css +13 -0
- data/lti2_tp/app/controllers/lti2_tp/application_controller.rb +4 -0
- data/lti2_tp/app/controllers/lti2_tp/registrations_controller.rb +200 -0
- data/lti2_tp/app/models/lti2_tp/context.rb +55 -0
- data/lti2_tp/app/models/lti2_tp/registration.rb +180 -0
- data/lti2_tp/app/models/lti2_tp/registry.rb +5 -0
- data/lti2_tp/app/models/lti2_tp/tool.rb +27 -0
- data/lti2_tp/app/models/lti2_tp/tool_deployment.rb +5 -0
- data/lti2_tp/app/models/lti2_tp/tool_provider_registry.rb +21 -0
- data/lti2_tp/app/views/layouts/lti2_tp/application.html.erb +14 -0
- data/lti2_tp/bin/rails +8 -0
- data/lti2_tp/config/initializers/lti2_tp.rb +11 -0
- data/lti2_tp/config/routes.rb +9 -0
- data/lti2_tp/db/migrate/20140826151614_create_lti2_tp_resources.rb +67 -0
- data/lti2_tp/lib/lti2_tp.rb +4 -0
- data/lti2_tp/lib/lti2_tp/engine.rb +5 -0
- data/lti2_tp/lib/lti2_tp/version.rb +3 -0
- data/lti2_tp/lib/tasks/lti2_tp_tasks.rake +4 -0
- data/lti2_tp/lti2_tp.gemspec +27 -0
- data/lti2_tp/test/dummy/README.rdoc +28 -0
- data/lti2_tp/test/dummy/Rakefile +6 -0
- data/lti2_tp/test/dummy/app/assets/javascripts/application.js +13 -0
- data/lti2_tp/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/lti2_tp/test/dummy/app/controllers/application_controller.rb +5 -0
- data/lti2_tp/test/dummy/app/helpers/application_helper.rb +2 -0
- data/lti2_tp/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/lti2_tp/test/dummy/bin/bundle +3 -0
- data/lti2_tp/test/dummy/bin/rails +4 -0
- data/lti2_tp/test/dummy/bin/rake +4 -0
- data/lti2_tp/test/dummy/config.ru +4 -0
- data/lti2_tp/test/dummy/config/application.rb +23 -0
- data/lti2_tp/test/dummy/config/boot.rb +5 -0
- data/lti2_tp/test/dummy/config/database.yml +25 -0
- data/lti2_tp/test/dummy/config/environment.rb +5 -0
- data/lti2_tp/test/dummy/config/environments/development.rb +29 -0
- data/lti2_tp/test/dummy/config/environments/production.rb +80 -0
- data/lti2_tp/test/dummy/config/environments/test.rb +36 -0
- data/lti2_tp/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/lti2_tp/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/lti2_tp/test/dummy/config/initializers/inflections.rb +16 -0
- data/lti2_tp/test/dummy/config/initializers/mime_types.rb +5 -0
- data/lti2_tp/test/dummy/config/initializers/secret_token.rb +12 -0
- data/lti2_tp/test/dummy/config/initializers/session_store.rb +3 -0
- data/lti2_tp/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/lti2_tp/test/dummy/config/locales/en.yml +23 -0
- data/lti2_tp/test/dummy/config/routes.rb +4 -0
- data/lti2_tp/test/dummy/db/schema.rb +63 -0
- data/lti2_tp/test/dummy/public/404.html +58 -0
- data/lti2_tp/test/dummy/public/422.html +58 -0
- data/lti2_tp/test/dummy/public/500.html +57 -0
- data/lti2_tp/test/dummy/public/favicon.ico +0 -0
- data/lti2_tp/test/integration/navigation_test.rb +10 -0
- data/lti2_tp/test/lti2_tp_test.rb +7 -0
- data/lti2_tp/test/test_helper.rb +15 -0
- metadata +62 -1
@@ -0,0 +1,55 @@
|
|
1
|
+
module Lti2Tp
|
2
|
+
class Context < ActiveRecord::Base
|
3
|
+
|
4
|
+
SESSION_LTI2_CONTEXT_ID = 'lti2_tc_profile.key'
|
5
|
+
|
6
|
+
class Holder
|
7
|
+
attr_accessor :lti2_context
|
8
|
+
def initialize( id=nil )
|
9
|
+
unless id.nil?
|
10
|
+
@lti2_context = Lti2Tp::Context.find_all_by_id([id]).first
|
11
|
+
end
|
12
|
+
if id.nil? || @lti2_context.blank?
|
13
|
+
@lti2_context = Lti2Tp::Context.create()
|
14
|
+
end
|
15
|
+
begin
|
16
|
+
@context_hash = JSON.load( @lti2_context.content )
|
17
|
+
rescue
|
18
|
+
@context_hash = nil
|
19
|
+
end
|
20
|
+
@context_hash ||= {}
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def [] name
|
25
|
+
@context_hash[name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def []= name, value
|
29
|
+
@context_hash[name] = value
|
30
|
+
@lti2_context.content = JSON.dump( @context_hash )
|
31
|
+
@lti2_context.save
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear name
|
35
|
+
@context_hash.delete( name )
|
36
|
+
@lti2_context.content = JSON.dump( @context_hash )
|
37
|
+
@lti2_context.save
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get_holder( session )
|
42
|
+
# lazy create for holder
|
43
|
+
if session.has_key?( SESSION_LTI2_CONTEXT_ID )
|
44
|
+
result = Lti2Tp::Context::Holder.new( session[SESSION_LTI2_CONTEXT_ID] )
|
45
|
+
end
|
46
|
+
if result.blank?
|
47
|
+
result = Lti2Tp::Context::Holder.new()
|
48
|
+
end
|
49
|
+
# reassert in class new run in same browser session
|
50
|
+
session[SESSION_LTI2_CONTEXT_ID] = result.lti2_context.id
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
module Lti2Tp
|
2
|
+
class Registration < ActiveRecord::Base
|
3
|
+
|
4
|
+
CORRELATION_ID = 'VND-IMS-CORRELATION-ID'
|
5
|
+
DISPOSITION = 'VND-IMS-DISPOSITION'
|
6
|
+
|
7
|
+
HTTP_CORRELATION_ID = 'HTTP_VND_IMS_CORRELATION_ID'
|
8
|
+
HTTP_DISPOSITION = 'HTTP_VND_IMS_DISPOSITION'
|
9
|
+
|
10
|
+
def create_tool_proxy tool_consumer_profile, tool_proxy_guid, disposition
|
11
|
+
tool_provider_registry = Rails.application.config.tool_provider_registry
|
12
|
+
tool_proxy = {}
|
13
|
+
# clone from provided TCP
|
14
|
+
tool_proxy['@context'] = tool_consumer_profile['@context'].clone
|
15
|
+
tool_proxy['@type'] = 'ToolProxy'
|
16
|
+
tool_proxy['@id'] = "ToolProxyProposal_at_#{Time.now.utc.iso8601}"
|
17
|
+
|
18
|
+
tool_proxy['lti_version'] = 'LTI-2p0'
|
19
|
+
tool_proxy['tool_proxy_guid'] = tool_proxy_guid if disposition == 'reregister'
|
20
|
+
|
21
|
+
tool_proxy['tool_consumer_profile'] = self.tc_profile_url
|
22
|
+
tool_proxy['tool_profile'] = JSON.load( tool_profile_json )
|
23
|
+
tool_proxy['security_contract'] = resolve_security_contract( tool_consumer_profile )
|
24
|
+
|
25
|
+
tool_proxy_wrapper = JsonWrapper.new( tool_proxy )
|
26
|
+
tool_proxy_wrapper.root
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_tool_consumer_profile()
|
30
|
+
tcp_response = invoke_unsigned_service(self.tc_profile_url, 'get', {}, {}, nil, Rails.application.config.wire_log, "Get Tool Consumer Profile")
|
31
|
+
JSON.load( tcp_response.body )
|
32
|
+
end
|
33
|
+
|
34
|
+
def prepare_tool_proxy disposition, tool_proxy_guid
|
35
|
+
tool_consumer_profile = JSON.load( self.tool_consumer_profile_json )
|
36
|
+
tool_proxy = create_tool_proxy(tool_consumer_profile, tool_proxy_guid, disposition)
|
37
|
+
if tool_proxy
|
38
|
+
self.end_registration_id = UUID.generate
|
39
|
+
if disposition == 'register'
|
40
|
+
self.tool_proxy_json = tool_proxy.to_json
|
41
|
+
else
|
42
|
+
self.proposed_tool_proxy_json = tool_proxy.to_json
|
43
|
+
end
|
44
|
+
self.save!
|
45
|
+
|
46
|
+
service_offered = nil
|
47
|
+
tool_consumer_profile['service_offered'].select do |entry|
|
48
|
+
if match_services( entry['@id'] , ':ToolProxy.collection' )
|
49
|
+
service_offered = entry
|
50
|
+
break
|
51
|
+
end
|
52
|
+
end
|
53
|
+
if service_offered.nil?
|
54
|
+
status = create_status(false, nil, "No matching service definition")
|
55
|
+
return_url = self.launch_presentation_return_url + '?status=failure'
|
56
|
+
(redirect_to return_url) and return
|
57
|
+
end
|
58
|
+
|
59
|
+
(tool_proxy_response, err_code, err_msg) = register_tool_proxy service_offered, "post", disposition
|
60
|
+
unless err_code == 201
|
61
|
+
status = create_status(false, nil, "#{err_code}-#{err_msg}")
|
62
|
+
return status
|
63
|
+
end
|
64
|
+
if disposition.blank? || disposition == 'register'
|
65
|
+
# get guid from the response returned by the TC
|
66
|
+
tool_proxy['tool_proxy_guid'] = tool_proxy_response['tool_proxy_guid']
|
67
|
+
|
68
|
+
|
69
|
+
# substitute tool_proxy_guid now in the Proxy where needed
|
70
|
+
tool_proxy_wrapper = JsonWrapper.new( tool_proxy )
|
71
|
+
tool_proxy_wrapper.substitute_text_in_all_nodes( '{', '}', { 'tool_proxy_guid' => tool_proxy['tool_proxy_guid'] } )
|
72
|
+
|
73
|
+
self.tool_proxy_json = tool_proxy.to_json
|
74
|
+
self.status = disposition
|
75
|
+
self.save!
|
76
|
+
|
77
|
+
status = create_status(true, tool_proxy_wrapper.first_at('tool_proxy_guid'))
|
78
|
+
else
|
79
|
+
status = create_status(true)
|
80
|
+
end
|
81
|
+
else
|
82
|
+
status = create_status(false, nil, "Can't access ToolProxy")
|
83
|
+
end
|
84
|
+
|
85
|
+
status
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_status(is_success, tool_guid=nil, message=nil)
|
89
|
+
status = "?"
|
90
|
+
if is_success
|
91
|
+
status += 'status=success&'
|
92
|
+
status += "tool_guid=#{tool_guid}&" if tool_guid.present?
|
93
|
+
else
|
94
|
+
status += 'status=failure&'
|
95
|
+
encoded_message = Rack::Utils.escape( message )
|
96
|
+
status += "lti_errormsg=#{encoded_message}<i_errorlog=#{encoded_message}&"
|
97
|
+
end
|
98
|
+
status
|
99
|
+
end
|
100
|
+
|
101
|
+
def is_status_failure? status
|
102
|
+
status.include? "status=failure&"
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def match_services( test_service, model_service )
|
108
|
+
service_name_pattern = /.*\W(\w+?\.\w+)$/
|
109
|
+
m = service_name_pattern.match( test_service )
|
110
|
+
if m.present?
|
111
|
+
test_word = m[1]
|
112
|
+
m = service_name_pattern.match( model_service )
|
113
|
+
if m.present?
|
114
|
+
model_word = m[1]
|
115
|
+
return test_word == model_word
|
116
|
+
end
|
117
|
+
end
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
|
121
|
+
def register_tool_proxy service_offered, method, disposition
|
122
|
+
if disposition == 'register'
|
123
|
+
data = self.tool_proxy_json
|
124
|
+
label = 'Register'
|
125
|
+
else
|
126
|
+
data = self.proposed_tool_proxy_json
|
127
|
+
label = 'ReRegister'
|
128
|
+
end
|
129
|
+
|
130
|
+
data = JSON.pretty_generate(JSON.load(data))
|
131
|
+
|
132
|
+
# data = CGI::escape(data)
|
133
|
+
signed_request = create_signed_request \
|
134
|
+
service_offered['endpoint'],
|
135
|
+
method,
|
136
|
+
self.reg_key,
|
137
|
+
self.reg_password,
|
138
|
+
{},
|
139
|
+
data,
|
140
|
+
"application/vnd.ims.lti.v2.toolproxy+json"
|
141
|
+
|
142
|
+
puts "Register request: #{signed_request.signature_base_string}"
|
143
|
+
puts "Register secret: #{self.reg_password}"
|
144
|
+
headers = {}
|
145
|
+
(headers[CORRELATION_ID] = self.end_registration_id) if disposition == 'reregister'
|
146
|
+
response = invoke_service(signed_request, Rails.application.config.wire_log, "#{label} ToolProxy with ToolConsumer",
|
147
|
+
headers)
|
148
|
+
if response.code.between?( 200, 202 )
|
149
|
+
response_body = response.body
|
150
|
+
response_content = JSON.load( response_body ) unless response_body.strip.empty?
|
151
|
+
else
|
152
|
+
response_content = nil
|
153
|
+
end
|
154
|
+
[ response_content, response.code, response.message ]
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def resolve_security_contract tool_consumer_profile
|
159
|
+
security_contract = {}
|
160
|
+
|
161
|
+
security_contract['shared_secret'] = SecureRandom.hex
|
162
|
+
security_contract['tool_service'] = []
|
163
|
+
|
164
|
+
services_offered = tool_consumer_profile['service_offered']
|
165
|
+
services_offered.each { |service_offered|
|
166
|
+
tool_service = {}
|
167
|
+
tool_service['@type'] = 'RestServiceProfile'
|
168
|
+
tool_service['service'] = service_offered['@id']
|
169
|
+
tool_service['action'] = service_offered['action']
|
170
|
+
|
171
|
+
# following may be wrong...check on proper construction of RestService
|
172
|
+
# tool_service['format'] = service_offered['format']
|
173
|
+
security_contract['tool_service'] << tool_service
|
174
|
+
}
|
175
|
+
|
176
|
+
security_contract
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Lti2Tp
|
2
|
+
class Tool < ActiveRecord::Base
|
3
|
+
|
4
|
+
def get_tool_profile( tool_options=nil )
|
5
|
+
tool_provider_registry = Rails.application.config.tool_provider_registry
|
6
|
+
tool_profile = Lti2Commons::JsonWrapper.new( self.tool_profile_template )
|
7
|
+
tool_profile.substitute_text_in_all_nodes( '{', '}', tool_provider_registry.registry )
|
8
|
+
|
9
|
+
# only if tool_options, provided prune day available resource_handlers
|
10
|
+
if tool_options
|
11
|
+
resource_handlers = tool_profile.first_at('resource_handler')
|
12
|
+
resource_handlers_to_delete = []
|
13
|
+
resource_handlers.each { |resource_handler|
|
14
|
+
resource_handler_wrapper = Lti2Commons::JsonWrapper.new( resource_handler )
|
15
|
+
unless tool_options.include? resource_handler_wrapper.first_at('resource_name.default_value')
|
16
|
+
resource_handlers_to_delete << resource_handler
|
17
|
+
end
|
18
|
+
}
|
19
|
+
resource_handlers_to_delete.each { |rh|
|
20
|
+
resource_handlers.delete( rh )
|
21
|
+
}
|
22
|
+
end
|
23
|
+
tool_profile.root
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Lti2Tp
|
2
|
+
|
3
|
+
class ToolProviderRegistry
|
4
|
+
|
5
|
+
attr_reader :security_contract_template, :tp_deployment_url, :relaxed_oauth_check, :result_template,
|
6
|
+
:tool_provider_name, :registry
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
registry_entries = Registry.all()
|
10
|
+
@registry = {}
|
11
|
+
registry_entries.each { |entry| @registry[entry.name] = entry.content unless entry.name == 'content' }
|
12
|
+
|
13
|
+
@tp_deployment_url = registry['tp_deployment_url']
|
14
|
+
@relaxed_oauth_check = registry['relaxed_oauth_check']
|
15
|
+
@result_template = registry['result_template']
|
16
|
+
@tool_provider_name = registry['tool_provider_name']
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Lti2Tp</title>
|
5
|
+
<%= stylesheet_link_tag "lti2_tp/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "lti2_tp/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
data/lti2_tp/bin/rails
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
|
3
|
+
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/lti2_tp/engine', __FILE__)
|
6
|
+
|
7
|
+
require 'rails/all'
|
8
|
+
require 'rails/engine/commands'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
include Lti2Commons
|
2
|
+
include WireLogSupport
|
3
|
+
|
4
|
+
NONCE_TIME_TO_LIVE = 300 # seconds
|
5
|
+
Rails.application.config.nonce_cache = Cache.new :ttl => NONCE_TIME_TO_LIVE
|
6
|
+
|
7
|
+
if ActiveRecord::Base.connection.table_exists? 'lti2_tp_registries'
|
8
|
+
Rails.application.config.tool_provider_registry = Lti2Tp::ToolProviderRegistry.new
|
9
|
+
end
|
10
|
+
|
11
|
+
Rails.application.config.wire_log = WireLog.new "ToolProvider", File.expand_path("../tc_sample_app/public/wirelog.html")
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class CreateLti2TpResources < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
create_table :lti2_tp_registrations do |t|
|
4
|
+
t.integer :tool_id
|
5
|
+
t.integer :tenant_id
|
6
|
+
t.string :tenant_name
|
7
|
+
t.string :tenant_basename
|
8
|
+
t.string :user_id
|
9
|
+
t.string :reg_key
|
10
|
+
t.string :reg_password
|
11
|
+
t.string :tc_profile_url
|
12
|
+
t.string :launch_presentation_return_url
|
13
|
+
t.string :status
|
14
|
+
t.string :message_type
|
15
|
+
t.string :lti_version
|
16
|
+
t.string :end_registration_id
|
17
|
+
t.text :tool_consumer_profile_json
|
18
|
+
t.text :tool_profile_json
|
19
|
+
t.text :tool_proxy_json
|
20
|
+
t.text :proposed_tool_proxy_json
|
21
|
+
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
execute('ALTER TABLE lti2_tp_registrations CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
|
25
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `tenant_name` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
26
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `tenant_basename` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
27
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `user_id` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
28
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `reg_key` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
29
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `reg_password` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
30
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `tc_profile_url` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
31
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `launch_presentation_return_url` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
32
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `status` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
33
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `message_type` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
34
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `lti_version` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
35
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `end_registration_id` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
36
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `tool_consumer_profile_json` TEXT CHARACTER SET utf8mb4 NULL;")
|
37
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `tool_profile_json` TEXT CHARACTER SET utf8mb4 NULL;")
|
38
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `tool_proxy_json` TEXT CHARACTER SET utf8mb4 NULL;")
|
39
|
+
execute("ALTER TABLE lti2_tp_registrations MODIFY `proposed_tool_proxy_json` TEXT CHARACTER SET utf8mb4 NULL;")
|
40
|
+
|
41
|
+
create_table :lti2_tp_registries do |t|
|
42
|
+
t.string :name
|
43
|
+
t.text :content
|
44
|
+
|
45
|
+
t.timestamps
|
46
|
+
end
|
47
|
+
execute('ALTER TABLE lti2_tp_registries CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
|
48
|
+
execute("ALTER TABLE lti2_tp_registries MODIFY `name` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
49
|
+
execute("ALTER TABLE lti2_tp_registries MODIFY `content` TEXT CHARACTER SET utf8mb4 NULL;")
|
50
|
+
|
51
|
+
create_table :lti2_tp_tools do |t|
|
52
|
+
t.string :tool_name
|
53
|
+
t.text :tool_profile_template
|
54
|
+
|
55
|
+
t.timestamps
|
56
|
+
end
|
57
|
+
execute('ALTER TABLE lti2_tp_tools CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
|
58
|
+
execute("ALTER TABLE lti2_tp_tools MODIFY `tool_name` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;")
|
59
|
+
execute("ALTER TABLE lti2_tp_tools MODIFY `tool_profile_template` TEXT CHARACTER SET utf8mb4 NULL;")
|
60
|
+
end
|
61
|
+
|
62
|
+
def down
|
63
|
+
drop_table :lti2_tp_registrations
|
64
|
+
drop_table :lti2_tp_registries
|
65
|
+
drop_table :lti2_tp_tools
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
$:.push File.expand_path( '../lib', __FILE__ )
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require 'lti2_tp/version'
|
5
|
+
|
6
|
+
# Describe your gem and declare its dependencies:
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
|
9
|
+
s.name = 'lti2_tp'
|
10
|
+
s.version = Lti2Tp::VERSION
|
11
|
+
s.authors = ['John Tibbetts']
|
12
|
+
s.email = ['john.tibbetts@ingramcontent.com']
|
13
|
+
s.homepage = 'http://vitalsource.com'
|
14
|
+
s.summary = 'LTI2 Tool Provider'
|
15
|
+
s.description = 'LTI2 Tool Provider'
|
16
|
+
|
17
|
+
s.files = Dir[ '{app,config,db,lib}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.rdoc' ]
|
18
|
+
s.test_files = Dir[ 'test/**/*' ]
|
19
|
+
|
20
|
+
s.required_ruby_version = '~> 2.0.0'
|
21
|
+
|
22
|
+
s.add_dependency 'rails', '~> 4.1.1'
|
23
|
+
s.add_dependency 'mysql2', '~> 0.3.13'
|
24
|
+
|
25
|
+
s.add_development_dependency 'sqlite3'
|
26
|
+
|
27
|
+
end
|