panda_pal 5.0.0.beta.2 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +11 -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: 581c5acd9f7a7ade63f59c20f00f2dcbe7ee4e77670a6e5b98e3b29491f2edc9
|
4
|
+
data.tar.gz: d42d100b86c391585fa5f45d23368711487c78eff96916aa9868ba1e22f868c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ec8c2b412e14dcfc0398fbb496d68d62aec0b897a3f30b5471df867d32b3db8279bd774c0b620a074b204cbbcf5f51c4edb80cfc92285205849f77c11d68122
|
7
|
+
data.tar.gz: 397d0cfccec6719e1ca201925fd7b5d23e87dff5a4170169c9f7aafd741a2956c8540abcf19dcbbff672faa3e85c54d0e81bc73d033a5e7d5f1ba21d5437577e
|
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
|