panda_pal 5.0.0.beta.3 → 5.2.1
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 +204 -107
- data/app/controllers/panda_pal/lti_controller.rb +0 -18
- data/app/controllers/panda_pal/lti_v1_p0_controller.rb +34 -0
- data/app/controllers/panda_pal/lti_v1_p3_controller.rb +98 -0
- data/app/lib/lti_xml/base_platform.rb +4 -4
- data/app/lib/panda_pal/launch_url_helpers.rb +69 -0
- data/app/lib/panda_pal/lti_jwt_validator.rb +88 -0
- data/app/lib/panda_pal/misc_helper.rb +13 -0
- data/app/models/panda_pal/organization.rb +21 -47
- data/app/models/panda_pal/organization_concerns/settings_validation.rb +127 -0
- data/app/models/panda_pal/organization_concerns/task_scheduling.rb +204 -0
- data/app/models/panda_pal/platform.rb +40 -0
- data/app/views/panda_pal/lti_v1_p3/login.html.erb +1 -0
- data/app/views/panda_pal/partials/_auto_submit_form.html.erb +9 -0
- data/config/dev_lti_key.key +27 -0
- data/config/routes.rb +12 -2
- data/db/migrate/20160412205931_create_panda_pal_organizations.rb +1 -1
- data/db/migrate/20160413135653_create_panda_pal_sessions.rb +1 -1
- data/db/migrate/20160425130344_add_panda_pal_organization_to_session.rb +1 -1
- data/db/migrate/20170106165533_add_salesforce_id_to_organizations.rb +1 -1
- data/db/migrate/20171205183457_encrypt_organization_settings.rb +1 -1
- data/db/migrate/20171205194657_remove_old_organization_settings.rb +8 -3
- data/lib/panda_pal.rb +28 -15
- data/lib/panda_pal/engine.rb +8 -39
- data/lib/panda_pal/helpers.rb +1 -0
- data/lib/panda_pal/helpers/controller_helper.rb +137 -90
- data/lib/panda_pal/helpers/route_helper.rb +8 -8
- data/lib/panda_pal/helpers/secure_headers.rb +79 -0
- data/lib/panda_pal/version.rb +1 -1
- data/panda_pal.gemspec +6 -2
- data/spec/dummy/config/application.rb +7 -1
- data/spec/dummy/config/environments/development.rb +0 -14
- data/spec/dummy/config/environments/production.rb +0 -11
- data/spec/models/panda_pal/organization/settings_validation_spec.rb +175 -0
- data/spec/models/panda_pal/organization/task_scheduling_spec.rb +144 -0
- data/spec/models/panda_pal/organization_spec.rb +0 -89
- data/spec/spec_helper.rb +4 -0
- metadata +66 -12
- data/app/views/panda_pal/lti/iframe_cookie_authorize.html.erb +0 -19
- data/app/views/panda_pal/lti/iframe_cookie_fix.html.erb +0 -12
- data/spec/dummy/config/initializers/assets.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88fe8cce75e1f511b08e025ca0f00ab9cb224e9ab9c91f4a6f36fbbef6031f26
|
4
|
+
data.tar.gz: 9b23a25becc266908e081985943a9b51a5b856b7b52c8c948e007ad638ce90a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b82a6629e5d87d9420263eff1a57c477c9e1786fd91312354d8de41c0eba1e83968e4bf954691cb17eb09e6e5fc1f73284f08c76574ec459329ec5c5093d9c2
|
7
|
+
data.tar.gz: 86c997d27d7de28fd3be87bd9343c06ec5cfbf35a1559b2f131f068315b883449b58049b23ccba31e99524a32cef3132ff12ac50777a098821c17bbbe445a2e6
|
data/README.md
CHANGED
@@ -11,7 +11,12 @@ PandaPal.lti_properties = {oauth_compliant: 'true'}
|
|
11
11
|
PandaPal.lti_environments = { domain: ENV['PROD_DOMAIN'], beta_domain: ENV['BETA_DOMAIN'], test_domain: ENV['TEST_DOMAIN'] }
|
12
12
|
PandaPal.lti_custom_params = { custom_canvas_role: '$Canvas.membership.roles' }
|
13
13
|
# :user_navigation, :course_navigation for user context and course context endpoints respectively
|
14
|
-
PandaPal::stage_navigation(:account_navigation, {
|
14
|
+
PandaPal::stage_navigation(:account_navigation, {
|
15
|
+
enabled: true,
|
16
|
+
# url: :account_index, # Optional if using lti_nav
|
17
|
+
text: 'Teacher Reports',
|
18
|
+
visibility: 'admins',
|
19
|
+
})
|
15
20
|
```
|
16
21
|
|
17
22
|
Configuration data for an installation can be set by creating a `PandaPal::Organization` record. Due to the nature of the data segregation, once created, the name of the organization should not be changed (and will raise a validation error).
|
@@ -28,16 +33,50 @@ Use one of these 6 options in `PandaPal.lti_options` hash.
|
|
28
33
|
5. Leave this property off, and you will get the dynamic host with the root path ('http://appdomain.com/') by default.
|
29
34
|
6. If you really do not want this property use the option `launch_url: false` for it to be left off.
|
30
35
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
### Task Scheduling
|
37
|
+
`PandaPal` includes an integration with `sidekiq-scheduler`. You can define tasks on an Organization class Stub like so:
|
38
|
+
```ruby
|
39
|
+
# <your_app>/app/models/panda_pal/organization.rb
|
40
|
+
require File.expand_path('../../app/models/panda_pal/organization.rb', PandaPal::Engine.called_from)
|
41
|
+
|
42
|
+
module PandaPal
|
43
|
+
class Organization
|
44
|
+
# Will invoke CanvasSyncStarterWorker.perform_async() according to the cron schedule
|
45
|
+
scheduled_task '0 15 05 * * *', :identifier, worker: CanvasSyncStarterWorker
|
46
|
+
|
47
|
+
# Will invoke the method 'organization_method' on the Organization
|
48
|
+
scheduled_task '0 15 05 * * *', :organization_method_and_identifier
|
39
49
|
|
40
|
-
|
50
|
+
# If you need to invoke the same method on multiple schedules
|
51
|
+
scheduled_task '0 15 05 * * *', :identifier, worker: :organization_method
|
52
|
+
|
53
|
+
# You can also use a block
|
54
|
+
scheduled_task '0 15 05 * * *', :identifier do
|
55
|
+
# Do Stuff
|
56
|
+
end
|
57
|
+
|
58
|
+
# You can use a Proc (called in the context of the Organization) to determine the schedule
|
59
|
+
scheduled_task -> { settings[:cron] }, :identifier
|
60
|
+
|
61
|
+
# You can specify a timezone. If a TZ is not coded and settings[:timezone] is present, it will be appended automatically
|
62
|
+
scheduled_task '0 15 05 * * * America/Denver', :identifier, worker: :organization_method
|
63
|
+
|
64
|
+
# Setting settings[:task_schedules][:identifier] will override the code cron schedule. Setting it to false will disable the Task
|
65
|
+
# :identifer values _must_ be unique, but can be nil, in which case they will be determined by where (lineno etc) scheduled_task is called
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
### Organization Attributes
|
71
|
+
`id`: Primary Key
|
72
|
+
`name`: Name of the organization. Used to on requests to select the tenant
|
73
|
+
`key`: Key field from CanvasLMS
|
74
|
+
`secret`: Secret field from CanvasLMS
|
75
|
+
`canvas_account_id`: ID of the corresponding Canvas account.
|
76
|
+
`settings`: Hash of settings for this Organization
|
77
|
+
`salesforce_id`: ID of this organization in Salesforce
|
78
|
+
|
79
|
+
XML for an installation can be generated by visiting `/lti/config` in your application.
|
41
80
|
|
42
81
|
### Routing
|
43
82
|
|
@@ -46,7 +85,7 @@ The following routes should be added to the routes.rb file of the implementing L
|
|
46
85
|
```ruby
|
47
86
|
# config/routes.rb
|
48
87
|
mount PandaPal::Engine, at: '/lti'
|
49
|
-
lti_nav account_navigation: 'accounts#launch'
|
88
|
+
lti_nav account_navigation: 'accounts#launch' # Use lti_nav to provide a custom Launch implementation, otherwise use the url: param of stage_navigation to let PandaPal handle launch.
|
50
89
|
root to: 'panda_pal/lti#launch'
|
51
90
|
```
|
52
91
|
|
@@ -81,9 +120,10 @@ It is also possible to switch tenants by implementing `around_action :switch_ten
|
|
81
120
|
However, it should be noted that calling `switch_tenant` must be used in an `around_action` hook (or given a block), and is only intended to be used for LTI launches, and not subsequent requests.
|
82
121
|
|
83
122
|
### Rake tasks and jobs
|
84
|
-
|
123
|
+
**Delayed Job Support has been removed. This allows each project to assess it's need to handle background jobs.**
|
124
|
+
|
85
125
|
The Apartment Gem makes it so background jobs need to be run within the current tenant. If using sidekiq, there is a gem that
|
86
|
-
does this automatically called apartment-sidkiq
|
126
|
+
does this automatically called `apartment-sidkiq`. If Delayed Jobs, see how it's done in version 1 of PandaPal.
|
87
127
|
|
88
128
|
For rake tasks, the current tenant will be set to `public`, and thus special handling must be taken when running the task or queueing jobs as part of it.
|
89
129
|
|
@@ -125,25 +165,52 @@ Controllers will automatically have access to a number of methods that can be he
|
|
125
165
|
* `save_session` - Saves the session given by `current_session` to the database.
|
126
166
|
|
127
167
|
## Sessions and `current_session`
|
128
|
-
|
129
|
-
|
168
|
+
Because of the ever-increasing security around `<iframe>`s and cookies, a custom session implementation has been rolled into `PandaPal`.
|
169
|
+
The implementation is mostly passive, but requires some changes and caveats as opposed to the native Rails implementation.
|
130
170
|
|
131
|
-
|
171
|
+
The current session object can be accessed from any controller using `current_session`. This object isn't the actual data container (as `session` _is_ in Rails).
|
172
|
+
Session data can be accessed and modified using `current_session.data[:key]` or `current_session_data[:key]`.
|
132
173
|
|
133
|
-
|
134
|
-
|
135
|
-
params[:session_key] || session_key_header || flash[:session_key] || session[:session_key]
|
136
|
-
end
|
174
|
+
Because cookies are unreliable, it becomes the responsibility of the LTI developer to ensure that a custom "cookie" is passed to the frontend with each response
|
175
|
+
and returned to the backend with each request, otherwise the backend won't be able to access the current session. There are a few ways to do this.
|
137
176
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
177
|
+
Generally, the method for passing the session "cookie" to the frontend looks something like:
|
178
|
+
```html
|
179
|
+
<meta name="session_key" content="<%= current_session.session_key %>">
|
180
|
+
```
|
181
|
+
|
182
|
+
### Returning to the backend
|
183
|
+
The `session_key` can be passed to the backend in multiple ways:
|
184
|
+
1. (Recommended) Via the `Authorization` Header (usually defining it as a default in your AJAX/XHR/`fetch` library):
|
185
|
+
```http
|
186
|
+
Authorization: token=SESSION_KEY_HERE
|
187
|
+
```
|
188
|
+
2. Via a `session_key` parameter in a `POST` request (Useful for native HTML `<form>`s).
|
189
|
+
3. (Used for Dev, but not highly discouraged in Prod) via a `GET`/URL Query parameter: `?session_key=SESSION_KEY_HERE`.
|
190
|
+
|
191
|
+
The `session_key` does not contain any secrets itself, so it is safe to pass to the frontend, but it is encouraged to keep it away from the
|
192
|
+
end-user as much as possible because it should not be shared.
|
193
|
+
|
194
|
+
### Redirecting and Multi-Page Applications
|
195
|
+
Special instructions must be followed when using `link_to` or `redirect_to` to ensure that the Session is passed correctly:
|
196
|
+
|
197
|
+
Add a `session_token:` (notice the use of _`_token`_ as opposed to _`_key`_!) parameter when using `link_to` or `redirect_to`:
|
198
|
+
```ruby
|
199
|
+
link_to "Link Name", somewhere_else_path(session_token: link_nonce)
|
200
|
+
redirect_to somewhere_else_path(session_token: link_nonce)
|
201
|
+
```
|
202
|
+
You can also use the `redirect_with_session_to` helper, which will automatically add `organization_id:` and `session_token:` params:
|
203
|
+
```ruby
|
204
|
+
redirect_with_session_to :somewhere_else_path, other_param: 1
|
143
205
|
```
|
206
|
+
For each request (not each call), `link_nonce` generates a nonce and stores it in the Session. The generated value can be used
|
207
|
+
for at-most-one future request. This means that browser back-forward navigation **will not work** (if it actually ever worked for
|
208
|
+
iframe-based LTIs in the first place).
|
144
209
|
|
145
210
|
### Persisting the session
|
146
|
-
|
211
|
+
The session is automatically saved using an `after_action` callback. This callback is poised to run last, but if that causes issues
|
212
|
+
(eg some other callback running afterwards and needing to modify the session), `skip_after_action :auto_save_session` can be used
|
213
|
+
and a custom implementation can be supplemented.
|
147
214
|
|
148
215
|
### Session cleanup
|
149
216
|
Over time, the sessions table will become bloated with sessions that are no longer active.
|
@@ -151,11 +218,6 @@ As such, `rake panda_pal:clean_sessions` should be run periodically to clean up
|
|
151
218
|
|
152
219
|
## Organizations and `current_organization`
|
153
220
|
Similar to `current_session`, `current_organization` can be returned with a number of methods, shown below
|
154
|
-
```ruby
|
155
|
-
def organization_key
|
156
|
-
params[:oauth_consumer_key] || params[:organization_id] || current_session_data[:organization_key] || session[:organization_key]
|
157
|
-
end
|
158
|
-
```
|
159
221
|
|
160
222
|
## Security
|
161
223
|
|
@@ -179,56 +241,62 @@ It can be overridden on a action-by-action basis by using `skip_before_action`.
|
|
179
241
|
skip_before_action :forbid_access_if_lacking_session, only: :launch
|
180
242
|
```
|
181
243
|
|
182
|
-
###
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
ENV['SECRET_KEY_BASE']. For production environments, config/secrets.yml should not have a plain-text secret,
|
192
|
-
it should be referencing an ENV variable. Make sure your secret is not plain-text committed to a repository!
|
193
|
-
|
194
|
-
The secret key is used to encrypt / decrypt the settings hash as necessary.
|
195
|
-
|
196
|
-
Before upgrading to version 3, you should confirm that the secret key is set to a consistent value (if the
|
197
|
-
value is lost your settings will be hosed).
|
198
|
-
|
199
|
-
You should also rollback any local encryption you have done on the settings hash. The settings hash
|
200
|
-
should just be plainly visible when you upgrade to V3. Otherwise the panda_pal migrations will
|
201
|
-
probably fail.
|
202
|
-
|
203
|
-
Once you have upgraded your gem, you will need to run migrations. Before doing that, I would store off your
|
204
|
-
unencrypted settings (just in case).
|
205
|
-
|
206
|
-
`rake db:migrate`
|
207
|
-
|
208
|
-
If all goes well, you should be set! Log into console, and verify that you can still access settings:
|
209
|
-
|
210
|
-
`PandaPal::Organization.first.settings`
|
211
|
-
|
212
|
-
should show unencrypted settings in your console.
|
213
|
-
|
214
|
-
If anything goes wrong, you should be able to rollback the change:
|
215
|
-
|
216
|
-
`rake db:rollback STEP=2`
|
217
|
-
|
218
|
-
If you need to give up on the change, just make sure to change your gem version for panda_pal to be < 3.
|
244
|
+
### Secure Headers
|
245
|
+
PandaPal bundles the `secure_headers` Gem and provides a default config. The PandaPal default works for really basic apps, but you may need to provide
|
246
|
+
a custom configuration. This can be done by creating a `secure_headers.rb` initializer in you App like so:
|
247
|
+
```ruby
|
248
|
+
SecureHeaders::Configuration.default do |config|
|
249
|
+
PandaPal::SecureHeaders.apply_defaults(config) # Optional, but recommended
|
250
|
+
# ...
|
251
|
+
end
|
252
|
+
```
|
219
253
|
|
220
|
-
|
254
|
+
## Validating settings in your LTI.
|
221
255
|
|
222
256
|
You can specify a structure that you would like to have enforced for your settings.
|
223
257
|
|
224
|
-
In your panda_pal initializer (i.e. config/initializers/panda_pal.rb or config/initializers/lti.rb)
|
258
|
+
In your panda_pal initializer (i.e. `config/initializers/panda_pal.rb` or `config/initializers/lti.rb`)
|
225
259
|
|
226
260
|
You can specify options that can include a structure for your settings. If specified, PandaPal will
|
227
261
|
enforce this structure on any new / updated organizations.
|
228
262
|
|
263
|
+
```ruby
|
264
|
+
PandaPal.lti_options = {
|
265
|
+
title: 'LBS Gradebook',
|
266
|
+
settings_structure: {
|
267
|
+
allow_additional: true, # Allow additional properties that aren't included in the :properties Hash.
|
268
|
+
allow_additional: { type: 'String' }, # You can also set :allow_additional to a settings specification that will be used to validate each additional setting
|
269
|
+
validate: ->(value, spec, **kwargs) {
|
270
|
+
# kwargs currently includes:
|
271
|
+
# :errors => [An array to push errors to]
|
272
|
+
# :path => [An array representation of the current path in the settings object]
|
273
|
+
|
274
|
+
# To add errors, you may:
|
275
|
+
# Push strings to the kwargs[:errors] Array:
|
276
|
+
kwargs[:errors] << "Your error message at <path>" unless value < 10
|
277
|
+
# Or return a string or string array:
|
278
|
+
value.valid? ? nil : "Your error message at <path>" # <path> will be replaced with the actual path that the error occurred at
|
279
|
+
},
|
280
|
+
properties: {
|
281
|
+
canvas_api_token: { type: 'String', required: true, },
|
282
|
+
catalog: { # :validate, :allow_additional, :properties keys are all supported at this level as well
|
283
|
+
type: 'Hash',
|
284
|
+
required: false,
|
285
|
+
validate: -> (*args) {},
|
286
|
+
allow_additional: false,
|
287
|
+
properties: {
|
288
|
+
|
289
|
+
},
|
290
|
+
}
|
291
|
+
}
|
292
|
+
},
|
293
|
+
}
|
294
|
+
```
|
295
|
+
|
296
|
+
#### Legacy Settings Structure:
|
229
297
|
Here is an example options specification:
|
230
298
|
|
231
|
-
```
|
299
|
+
```ruby
|
232
300
|
PandaPal.lti_options = {
|
233
301
|
title: 'LBS Gradebook',
|
234
302
|
settings_structure: YAML.load("
|
@@ -271,9 +339,41 @@ This is determined by `PandaPal.lti_options[:platform]`.
|
|
271
339
|
Set this to `platform: 'canvas.instructure.com'` (default)
|
272
340
|
OR `platform: 'bridgeapp.com'`
|
273
341
|
|
274
|
-
|
342
|
+
## Development:
|
343
|
+
### Running Specs:
|
344
|
+
Initialize the Specs DB:
|
345
|
+
`cd spec/dummy; bundle exec rake db:drop; bundle exec rake db:create; bundle exec rake db:schema:load`
|
346
|
+
Then `bundle exec rspec`
|
347
|
+
|
348
|
+
## Safari Support
|
349
|
+
Safari is weird (it blocks cookies in `<iframe>`s unless the site has set a cookie _outside_ of an `<iframe>` first), and you'll run into
|
350
|
+
issues with Rails-native Sessions and CSRF because of that.
|
275
351
|
|
276
|
-
|
352
|
+
This means that safari will likely refuse to send info about your rails session
|
353
|
+
back to the LTI, and the application will start up a new session each time the
|
354
|
+
browser navigates. This likely means a new session each time the LTI launches.
|
355
|
+
|
356
|
+
### PandaPal 5
|
357
|
+
It has been a constant struggle to force safari to store and allow
|
358
|
+
access to a rails session while the application is embedded in Canvas.
|
359
|
+
|
360
|
+
As of PandaPal 5, a session cookie is no longer required by panda_pal.
|
361
|
+
|
362
|
+
See the Section on [Sessions and `current_session`](#sessions-and-current_session)
|
363
|
+
|
364
|
+
You will want to watch out for a few scenarios:
|
365
|
+
1) Make sure you are using `redirect_with_session_to` if you need to redirect
|
366
|
+
and have your PandaPal session_key persisted server side.
|
367
|
+
2) Use the `Authorization` header with `token={session_key}` to send your
|
368
|
+
PandaPal session info into api calls.
|
369
|
+
3) If you use `link_to` and navigate in your LTI (apps that are not single page)
|
370
|
+
make sure you include the `link_nonce` like so:
|
371
|
+
```ruby
|
372
|
+
link_to "Link Name", somewhere_else_path(session_token: link_nonce)
|
373
|
+
```
|
374
|
+
|
375
|
+
### Previous Safari Instructions
|
376
|
+
Safari is weird and you'll potentially run into issues getting `POST` requests to properly validate CSRF if you don't do the following:
|
277
377
|
|
278
378
|
- Make sure you have both a `launch` controller and your normal controllers. The `launch` controller should call `before_action :validate_launch!` and then redirect
|
279
379
|
to your other controller.
|
@@ -281,49 +381,47 @@ Safari is weird, and you'll potentially run into issues getting `POST` requests
|
|
281
381
|
|
282
382
|
This will allow `PandaPal` to apply an iframe cookie fix that will allow CSRF validation to work.
|
283
383
|
|
384
|
+
## Migrating Major Versions
|
284
385
|
|
285
|
-
###
|
386
|
+
### Upgrading to version 3
|
286
387
|
|
287
|
-
|
288
|
-
|
388
|
+
Before upgrading save existing settings somewhere safe in case you need to
|
389
|
+
restore them for whatever reason.
|
289
390
|
|
290
|
-
|
391
|
+
panda_pal v3 introduces an encrypted settings hash. This should provide more security in the case where a
|
392
|
+
customer may have gained access to Organization information in the database. Settings cannot be decrypted
|
393
|
+
without knowing the secret decryption key. For panda_pal, we are relying on the secret_key_base to be set
|
394
|
+
(`typically in config/secrets.yml`), if that is not available we are falling back to directly use
|
395
|
+
`ENV['SECRET_KEY_BASE']`. For production environments, `config/secrets.yml` should not have a plain-text secret,
|
396
|
+
it should be referencing an ENV variable. Make sure your secret is not plain-text committed to a repository!
|
291
397
|
|
292
|
-
|
293
|
-
back to the LTI, and the application will start up a new session each time the
|
294
|
-
browser navigates. This likely means a new session each time the LTI launches.
|
398
|
+
The secret key is used to encrypt / decrypt the settings hash as necessary.
|
295
399
|
|
296
|
-
|
400
|
+
Before upgrading to version 3, you should confirm that the secret key is set to a consistent value (if the
|
401
|
+
value is lost your settings will be hosed).
|
297
402
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
PandaPal session info into api calls.
|
403
|
+
You should also rollback any local encryption you have done on the settings hash. The settings hash
|
404
|
+
should just be plainly visible when you upgrade to V3. Otherwise the panda_pal migrations will
|
405
|
+
probably fail.
|
302
406
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
407
|
+
Once you have upgraded your gem, you will need to run migrations. Before doing that, I would store off your
|
408
|
+
unencrypted settings (just in case).
|
409
|
+
|
410
|
+
`rake db:migrate`
|
411
|
+
|
412
|
+
If all goes well, you should be set! Log into console, and verify that you can still access settings:
|
413
|
+
|
414
|
+
`PandaPal::Organization.first.settings`
|
310
415
|
|
311
|
-
|
416
|
+
should show unencrypted settings in your console.
|
417
|
+
|
418
|
+
If anything goes wrong, you should be able to rollback the change:
|
312
419
|
|
313
|
-
|
314
|
-
attempts to set that up.
|
420
|
+
`rake db:rollback STEP=2`
|
315
421
|
|
316
|
-
|
317
|
-
2) LTI will attempt to POST message from iframe to top window (canvas) telling
|
318
|
-
canvas to relaunch in full screen so we aren't inhibited by safari.
|
319
|
-
3) LTI will setup session and cookies in full-screen mode. Session will be saved
|
320
|
-
in browser.
|
321
|
-
4) LTI will redirect to an authorization page, that will require user to give
|
322
|
-
access to the session store to our application.
|
323
|
-
5) Once the user gives access to the session store, we will reload the LTI
|
324
|
-
and the cookie should now be persistent.
|
422
|
+
If you need to give up on the change, just make sure to change your gem version for panda_pal to be < 3.
|
325
423
|
|
326
|
-
|
424
|
+
### Upgrading from PandaPal 4 to 5:
|
327
425
|
|
328
426
|
If your tool is setup according to a pretty standard pattern (see pace_plans,
|
329
427
|
canvas_group_enrollment, etc), you shouldn't have to do anything to upgrade.
|
@@ -333,7 +431,7 @@ using "redirect_with_session_to".
|
|
333
431
|
|
334
432
|
Here is an example launch / account controller setup, assuming an account launch.
|
335
433
|
|
336
|
-
```
|
434
|
+
```ruby
|
337
435
|
class LaunchController < ApplicationController
|
338
436
|
# We don't verify CSRF on launch because the LTI launch is done via a POST
|
339
437
|
# request, and Canvas wouldn't know anything about the CSRF
|
@@ -360,4 +458,3 @@ class AccountController < ApplicationController
|
|
360
458
|
end
|
361
459
|
end
|
362
460
|
```
|
363
|
-
|
@@ -2,23 +2,5 @@ require_dependency "panda_pal/application_controller"
|
|
2
2
|
|
3
3
|
module PandaPal
|
4
4
|
class LtiController < ApplicationController
|
5
|
-
def tool_config
|
6
|
-
if PandaPal.lti_environments.empty?
|
7
|
-
render plain: 'Domains must be set in lti_environments'
|
8
|
-
return
|
9
|
-
end
|
10
|
-
platform = PandaPal.lti_options.delete(:platform) || 'canvas.instructure.com'
|
11
|
-
request_url = "#{request.scheme}://#{request.host_with_port}"
|
12
|
-
case platform
|
13
|
-
when 'canvas.instructure.com'
|
14
|
-
xml_config = LtiXml::CanvasPlatform.new(platform, request_url, main_app)
|
15
|
-
when 'bridgeapp.com'
|
16
|
-
xml_config = LtiXml::BridgePlatform.new(platform, request_url, main_app)
|
17
|
-
else
|
18
|
-
render plain: 'platform must be set under lti_options'
|
19
|
-
return
|
20
|
-
end
|
21
|
-
render xml: xml_config.xml
|
22
|
-
end
|
23
5
|
end
|
24
6
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_dependency "panda_pal/application_controller"
|
2
|
+
|
3
|
+
module PandaPal
|
4
|
+
class LtiV1P0Controller < ApplicationController
|
5
|
+
def launch
|
6
|
+
current_session_data.merge!({
|
7
|
+
lti_version: 'v1p0',
|
8
|
+
lti_launch_placement: params[:launch_type],
|
9
|
+
launch_params: params.to_unsafe_h,
|
10
|
+
})
|
11
|
+
|
12
|
+
redirect_with_session_to(:"#{LaunchUrlHelpers.launch_route(params[:launch_type])}_url", route_context: main_app)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tool_config
|
16
|
+
if PandaPal.lti_environments.empty?
|
17
|
+
render plain: 'Domains must be set in lti_environments'
|
18
|
+
return
|
19
|
+
end
|
20
|
+
platform = PandaPal.lti_options.delete(:platform) || 'canvas.instructure.com'
|
21
|
+
request_url = "#{request.scheme}://#{request.host_with_port}"
|
22
|
+
case platform
|
23
|
+
when 'canvas.instructure.com'
|
24
|
+
xml_config = LtiXml::CanvasPlatform.new(platform, request_url, main_app)
|
25
|
+
when 'bridgeapp.com'
|
26
|
+
xml_config = LtiXml::BridgePlatform.new(platform, request_url, main_app)
|
27
|
+
else
|
28
|
+
render plain: 'platform must be set under lti_options'
|
29
|
+
return
|
30
|
+
end
|
31
|
+
render xml: xml_config.xml
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|