coalescing_panda 5.0.0 → 5.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/coalescing_panda/manifest.js +3 -0
  3. data/app/controllers/coalescing_panda/lti_controller.rb +1 -1
  4. data/app/controllers/coalescing_panda/oauth2_controller.rb +2 -0
  5. data/app/models/coalescing_panda/json_with_indifferent_access.rb +13 -0
  6. data/app/models/coalescing_panda/persistent_session.rb +2 -1
  7. data/db/migrate/20131114150001_create_coalescing_panda_canvas_api_auths.rb +1 -1
  8. data/db/migrate/20131118211442_create_coalescing_panda_lti_accounts.rb +1 -1
  9. data/db/migrate/20131119165343_create_coalescing_panda_lti_nonces.rb +1 -1
  10. data/db/migrate/20140904223159_create_coalescing_panda_sessions.rb +1 -1
  11. data/db/migrate/20141119225319_create_coalescing_panda_terms.rb +1 -1
  12. data/db/migrate/20141119225721_create_coalescing_panda_courses.rb +1 -1
  13. data/db/migrate/20141120151432_create_coalescing_panda_sections.rb +1 -1
  14. data/db/migrate/20141120151940_create_coalescing_panda_assignments.rb +1 -1
  15. data/db/migrate/20141120152458_create_coalescing_panda_users.rb +1 -1
  16. data/db/migrate/20141120152546_create_coalescing_panda_submissions.rb +1 -1
  17. data/db/migrate/20141120153135_create_coalescing_panda_enrollments.rb +1 -1
  18. data/db/migrate/20141121174846_create_coalescing_panda_canvas_batches.rb +1 -1
  19. data/db/migrate/20141124160857_create_delayed_jobs.rb +1 -1
  20. data/db/migrate/20141208221740_add_submission_types_to_assignments.rb +1 -1
  21. data/db/migrate/20150106175418_add_group_category_id_to_assignment.rb +1 -1
  22. data/db/migrate/20150106180131_add_published_to_assignments.rb +1 -1
  23. data/db/migrate/20150107205405_create_coalescing_panda_groups.rb +1 -1
  24. data/db/migrate/20150107205413_create_coalescing_panda_group_memberships.rb +1 -1
  25. data/db/migrate/20150210180516_add_context_to_canvas_batch.rb +1 -1
  26. data/db/migrate/20150506183335_create_coalescing_panda_assignment_groups.rb +1 -1
  27. data/db/migrate/20150506192717_add_assignment_group_id_to_assignments.rb +1 -1
  28. data/db/migrate/20150526144713_add_account_to_canvas_batches.rb +1 -1
  29. data/db/migrate/20150602205257_add_option_to_canvas_batches.rb +1 -1
  30. data/db/migrate/20150708192717_add_group_moderator_to_group_memberships.rb +1 -1
  31. data/db/migrate/20150709192717_add_leader_id_to_groups.rb +1 -1
  32. data/db/migrate/20150714205405_create_coalescing_panda_group_categories.rb +1 -1
  33. data/db/migrate/20150811140030_add_fields_to_users.rb +1 -1
  34. data/db/migrate/20151209155923_add_refresh_settings_to_canvas_api_auth.rb +1 -1
  35. data/db/migrate/20160830183155_create_coalescing_panda_oauth_states.rb +1 -1
  36. data/db/migrate/20200528224505_create_coalescing_panda_persistent_session.rb +1 -1
  37. data/lib/coalescing_panda/controller_helpers.rb +40 -23
  38. data/lib/coalescing_panda/engine.rb +15 -41
  39. data/lib/coalescing_panda/misc_helper.rb +13 -0
  40. data/lib/coalescing_panda/secure_headers.rb +84 -0
  41. data/lib/coalescing_panda/version.rb +1 -1
  42. metadata +18 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d645cd8c2b844e464a37181c7810119004db0d11f74fb1293e97d7230412e8b3
4
- data.tar.gz: e2741818208ab1301551d47c9063d20ee9bbb0a58e6db63b164cc068b0c2c76a
3
+ metadata.gz: 92bed66c0757318a64fada41a45e598216c1daefdd7b43c8adf0a58c9d5259af
4
+ data.tar.gz: d99684f401684ffdcb93ae63fe7ea49ba6ae4303db2e68ac43709e934b31ebeb
5
5
  SHA512:
6
- metadata.gz: 6430b3b457aa5776cd8590228794fcb77537824dbec08356ae9a512bf268e357e9a0f7e0db900ffa33d1f261964b393443719aa4a407b61970b26b19e7f65ce7
7
- data.tar.gz: 3a4853c0b20ffc72041e5157f5a0813a8c5e30c27648b23193fc9d94652adaeda01ded2ef829e6e70617d6a02a7e89841cd5615474d0c866242fc435ba0d3eca
6
+ metadata.gz: 8d1289c6a483a650b1e54a669ad2968cd1d3935e4ef3a67de130775cacfeab78a810ab7a736edb7b5a63b1960633f98fb8d813ceb0e3b6dd1e59d50448fa9697
7
+ data.tar.gz: a8b9d22ffc7262a1385e156915e382ef43bc0d3e68d9077032676c92b9e9dd466084289c143079e977ee20d82e7259a05496ed452798aaf3ae3306f9efe006b7
@@ -0,0 +1,3 @@
1
+ //= link_tree ../../images
2
+ //= link_directory ../../javascripts/coalescing_panda/ .js
3
+ //= link_directory ../../stylesheets/coalescing_panda/ .css
@@ -17,7 +17,7 @@ module CoalescingPanda
17
17
  lti_nav[:account][:text] = params[:account_navigation_label] if params[:account_navigation_label].present?
18
18
  platform = 'canvas.instructure.com'
19
19
  host = "#{request.scheme}://#{request.host_with_port}"
20
- tc = IMS::LTI::Services::ToolConfig.new(:title => lti_options[:title], :launch_url => ("#{host}#{lti_options[:launch_route]}") || 'ABC')
20
+ tc = IMS::LTI::ToolConfig.new(:title => lti_options[:title], :launch_url => ("#{host}#{lti_options[:launch_route]}") || 'ABC')
21
21
  tc.set_ext_param(platform, :domain, request.host)
22
22
  tc.set_ext_param(platform, :privacy_level, 'public')
23
23
  tc.set_custom_param(:custom_canvas_role, '$Canvas.membership.roles')
@@ -7,6 +7,8 @@ module CoalescingPanda
7
7
  end
8
8
 
9
9
  def redirect
10
+ use_secure_headers_override(:allow_inline_scripts)
11
+
10
12
  if !params[:error] && retrieve_oauth_state
11
13
  lti_account = LtiAccount.find_by_key(@oauth_state.data[:key])
12
14
  client_id = lti_account.oauth2_client_id
@@ -0,0 +1,13 @@
1
+ module CoalescingPanda
2
+ class JSONWithIndifferentAccess
3
+ def self.load(str)
4
+ return nil unless str.present?
5
+ parsed = JSON.parse(str)
6
+ parsed.is_a?(Hash) ? HashWithIndifferentAccess.new(parsed) : parsed
7
+ end
8
+
9
+ def self.dump(obj)
10
+ JSON.dump(obj)
11
+ end
12
+ end
13
+ end
@@ -1,10 +1,11 @@
1
1
  module CoalescingPanda
2
2
  class PersistentSession < ActiveRecord::Base
3
- serialize :data, Hash
3
+ serialize :data, JSONWithIndifferentAccess
4
4
  belongs_to :coalescing_panda_lti_account, :class_name => 'CoalescingPanda::LtiAccount'
5
5
  validates :coalescing_panda_lti_account_id, presence: true
6
6
 
7
7
  after_initialize do
8
+ self.data ||= {}
8
9
  self.session_key ||= SecureRandom.urlsafe_base64(60)
9
10
  end
10
11
 
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaCanvasApiAuths < ActiveRecord::Migration
1
+ class CreateCoalescingPandaCanvasApiAuths < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_canvas_api_auths do |t|
4
4
  t.string :user_id
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaLtiAccounts < ActiveRecord::Migration
1
+ class CreateCoalescingPandaLtiAccounts < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_lti_accounts do |t|
4
4
  t.string :name
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaLtiNonces < ActiveRecord::Migration
1
+ class CreateCoalescingPandaLtiNonces < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_lti_nonces do |t|
4
4
  t.belongs_to :coalescing_panda_lti_account
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaSessions < ActiveRecord::Migration
1
+ class CreateCoalescingPandaSessions < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_sessions do |t|
4
4
  t.string :token
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaTerms < ActiveRecord::Migration
1
+ class CreateCoalescingPandaTerms < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_terms do |t|
4
4
  t.belongs_to :coalescing_panda_lti_account, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaCourses < ActiveRecord::Migration
1
+ class CreateCoalescingPandaCourses < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_courses do |t|
4
4
  t.belongs_to :coalescing_panda_lti_account, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaSections < ActiveRecord::Migration
1
+ class CreateCoalescingPandaSections < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_sections do |t|
4
4
  t.belongs_to :coalescing_panda_course, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaAssignments < ActiveRecord::Migration
1
+ class CreateCoalescingPandaAssignments < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_assignments do |t|
4
4
  t.belongs_to :coalescing_panda_course, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaUsers < ActiveRecord::Migration
1
+ class CreateCoalescingPandaUsers < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_users do |t|
4
4
  t.belongs_to :coalescing_panda_lti_account, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaSubmissions < ActiveRecord::Migration
1
+ class CreateCoalescingPandaSubmissions < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_submissions do |t|
4
4
  t.belongs_to :coalescing_panda_user, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaEnrollments < ActiveRecord::Migration
1
+ class CreateCoalescingPandaEnrollments < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_enrollments do |t|
4
4
  t.belongs_to :coalescing_panda_user, null: false
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaCanvasBatches < ActiveRecord::Migration
1
+ class CreateCoalescingPandaCanvasBatches < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_canvas_batches do |t|
4
4
  t.float :percent_complete, default: 0.0
@@ -1,4 +1,4 @@
1
- class CreateDelayedJobs < ActiveRecord::Migration
1
+ class CreateDelayedJobs < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def self.up
3
3
  create_table :delayed_jobs, :force => true do |table|
4
4
  table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
@@ -1,4 +1,4 @@
1
- class AddSubmissionTypesToAssignments < ActiveRecord::Migration
1
+ class AddSubmissionTypesToAssignments < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_assignments, :submission_types, :text
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddGroupCategoryIdToAssignment < ActiveRecord::Migration
1
+ class AddGroupCategoryIdToAssignment < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_assignments, :group_category_id, :integer
4
4
  add_column :coalescing_panda_assignments, :grade_group_students_individually, :boolean
@@ -1,4 +1,4 @@
1
- class AddPublishedToAssignments < ActiveRecord::Migration
1
+ class AddPublishedToAssignments < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_assignments, :published, :boolean
4
4
  end
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaGroups < ActiveRecord::Migration
1
+ class CreateCoalescingPandaGroups < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_groups do |t|
4
4
  t.belongs_to :context, polymorphic: true
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaGroupMemberships < ActiveRecord::Migration
1
+ class CreateCoalescingPandaGroupMemberships < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_group_memberships do |t|
4
4
  t.belongs_to :coalescing_panda_group
@@ -1,4 +1,4 @@
1
- class AddContextToCanvasBatch < ActiveRecord::Migration
1
+ class AddContextToCanvasBatch < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_canvas_batches, :context_id, :integer
4
4
  add_column :coalescing_panda_canvas_batches, :context_type, :string
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaAssignmentGroups < ActiveRecord::Migration
1
+ class CreateCoalescingPandaAssignmentGroups < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_assignment_groups do |t|
4
4
  t.belongs_to :coalescing_panda_course, null: false
@@ -1,4 +1,4 @@
1
- class AddAssignmentGroupIdToAssignments < ActiveRecord::Migration
1
+ class AddAssignmentGroupIdToAssignments < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_assignments, :coalescing_panda_assignment_group_id, :integer
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddAccountToCanvasBatches < ActiveRecord::Migration
1
+ class AddAccountToCanvasBatches < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_canvas_batches, :coalescing_panda_lti_account_id, :integer, index: true
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddOptionToCanvasBatches < ActiveRecord::Migration
1
+ class AddOptionToCanvasBatches < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_canvas_batches, :options, :text
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddGroupModeratorToGroupMemberships < ActiveRecord::Migration
1
+ class AddGroupModeratorToGroupMemberships < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_group_memberships, :moderator, :boolean
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddLeaderIdToGroups < ActiveRecord::Migration
1
+ class AddLeaderIdToGroups < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_groups, :leader_id, :integer
4
4
  add_foreign_key :coalescing_panda_groups, :coalescing_panda_users, column: :leader_id, primary_key: "id"
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaGroupCategories < ActiveRecord::Migration
1
+ class CreateCoalescingPandaGroupCategories < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_group_categories do |t|
4
4
  t.belongs_to :context, polymorphic: true
@@ -1,4 +1,4 @@
1
- class AddFieldsToUsers < ActiveRecord::Migration
1
+ class AddFieldsToUsers < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_users, :login_id, :string
4
4
  end
@@ -1,4 +1,4 @@
1
- class AddRefreshSettingsToCanvasApiAuth < ActiveRecord::Migration
1
+ class AddRefreshSettingsToCanvasApiAuth < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  add_column :coalescing_panda_canvas_api_auths, :refresh_token, :string
4
4
  add_column :coalescing_panda_canvas_api_auths, :expires_at, :datetime
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaOauthStates < ActiveRecord::Migration
1
+ class CreateCoalescingPandaOauthStates < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_oauth_states do |t|
4
4
  t.string :state_key
@@ -1,4 +1,4 @@
1
- class CreateCoalescingPandaPersistentSession < ActiveRecord::Migration
1
+ class CreateCoalescingPandaPersistentSession < CoalescingPanda::MiscHelper::MigrationClass
2
2
  def change
3
3
  create_table :coalescing_panda_persistent_sessions do |t|
4
4
  t.string :session_key
@@ -2,15 +2,32 @@ require 'browser'
2
2
 
3
3
  module CoalescingPanda
4
4
  module ControllerHelpers
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ alias_method :rails_session, :session
9
+
10
+ helper_method :encrypted_session_key, :current_session_data, :current_session
11
+ append_after_action :save_session, if: -> { @current_session && session_changed? }
12
+ end
13
+
14
+ class_methods do
15
+ def use_native_sessions
16
+ after_action do
17
+ rails_session['persistent_session_key'] = current_session.session_key if @current_session.present?
18
+ end
19
+ end
20
+ end
21
+
5
22
  def current_session
6
- @current_session ||= CoalescingPanda::PersistentSession.find_by(session_key: session_key) if session_key
7
- @current_session ||= CoalescingPanda::PersistentSession.create_from_launch(params, current_lti_account.id)
23
+ @current_session ||= (CoalescingPanda::PersistentSession.find_by(session_key: session_key) if session_key)
24
+ @current_session ||= (CoalescingPanda::PersistentSession.create_from_launch(params, current_lti_account.id) if current_lti_account.present?)
8
25
  @current_session
9
26
  end
10
27
 
11
28
  def current_lti_account
12
- @account ||= CoalescingPanda::LtiAccount.find_by!(key: organization_key) if organization_key
13
- @account ||= CoalescingPanda::LtiAccount.find_by(id: organization_id) if organization_id
29
+ @account ||= (CoalescingPanda::LtiAccount.find_by!(key: organization_key) if organization_key)
30
+ @account ||= (CoalescingPanda::LtiAccount.find_by(id: organization_id) if organization_id)
14
31
  @account
15
32
  end
16
33
 
@@ -83,42 +100,42 @@ module CoalescingPanda
83
100
  end
84
101
 
85
102
  def check_refresh_token
86
- return unless session['uri'] && session['user_id'] && session['oauth_consumer_key']
87
- uri = BearcatUri.new(session['uri'])
88
- api_auth = CanvasApiAuth.find_by(user_id: session['user_id'], api_domain: uri.api_domain)
89
- @lti_account = LtiAccount.find_by(key: session['oauth_consumer_key'])
103
+ return unless current_session_data['uri'] && current_session_data['user_id'] && current_session_data['oauth_consumer_key']
104
+ uri = BearcatUri.new(current_session_data['uri'])
105
+ api_auth = CanvasApiAuth.find_by(user_id: current_session_data['user_id'], api_domain: uri.api_domain)
106
+ @lti_account = LtiAccount.find_by(key: current_session_data['oauth_consumer_key'])
90
107
  return if @lti_account.nil? || api_auth.nil? # Not all tools use oauth
91
108
 
92
109
  refresh_token(uri, api_auth) if api_auth.expired?
93
110
  rescue Footrest::HttpError::BadRequest
94
- render_oauth2_page uri, session['user_id']
111
+ render_oauth2_page uri, current_session_data['user_id']
95
112
  end
96
113
 
97
114
  def set_session(launch_presentation_return_url)
98
- session['user_id'] = params['user_id']
99
- session['uri'] = launch_presentation_return_url
100
- session['lis_person_sourcedid'] = params['lis_person_sourcedid']
101
- session['oauth_consumer_key'] = params['oauth_consumer_key']
102
- session['custom_canvas_account_id'] = params['custom_canvas_account_id']
115
+ current_session_data['user_id'] = params['user_id']
116
+ current_session_data['uri'] = launch_presentation_return_url
117
+ current_session_data['lis_person_sourcedid'] = params['lis_person_sourcedid']
118
+ current_session_data['oauth_consumer_key'] = params['oauth_consumer_key']
119
+ current_session_data['custom_canvas_account_id'] = params['custom_canvas_account_id']
103
120
  end
104
121
 
105
122
  def have_session?
106
- if params['tool_consumer_instance_guid'] && session['user_id'] != params['user_id']
123
+ if params['tool_consumer_instance_guid'] && current_session_data['user_id'] != params['user_id']
107
124
  reset_session
108
125
  logger.info("resetting session params")
109
- session['user_id'] = params['user_id']
126
+ current_session_data['user_id'] = params['user_id']
110
127
  end
111
128
 
112
- if (session['user_id'] && session['uri'])
113
- uri = BearcatUri.new(session['uri'])
114
- api_auth = CanvasApiAuth.find_by('user_id = ? and api_domain = ?', session['user_id'], uri.api_domain)
129
+ if (current_session_data['user_id'] && current_session_data['uri'])
130
+ uri = BearcatUri.new(current_session_data['uri'])
131
+ api_auth = CanvasApiAuth.find_by('user_id = ? and api_domain = ?', current_session_data['user_id'], uri.api_domain)
115
132
  if api_auth && !api_auth.expired?
116
133
  @client = Bearcat::Client.new(token: api_auth.api_token, prefix: uri.prefix)
117
134
  @client.user_profile 'self'
118
135
  end
119
136
  end
120
137
 
121
- @lti_account = LtiAccount.find_by_key(session['oauth_consumer_key']) if session['oauth_consumer_key']
138
+ @lti_account = LtiAccount.find_by_key(current_session_data['oauth_consumer_key']) if current_session_data['oauth_consumer_key']
122
139
 
123
140
  !!@client
124
141
  rescue Footrest::HttpError::Unauthorized
@@ -129,8 +146,8 @@ module CoalescingPanda
129
146
  authorized = false
130
147
  if (@lti_account = params['oauth_consumer_key'] && LtiAccount.find_by_key(params['oauth_consumer_key']))
131
148
  sanitized_params = sanitize_params
132
- authenticator = IMS::LTI::Services::MessageAuthenticator.new(request.original_url, sanitized_params, @lti_account.secret)
133
- authorized = authenticator.valid_signature?
149
+ @tp = IMS::LTI::ToolProvider.new(@lti_account.key, @lti_account.secret, sanitized_params)
150
+ authorized = @tp.valid_request?(request)
134
151
  end
135
152
  logger.info 'not authorized on tp valid request' unless authorized
136
153
  authorized = authorized && (roles.count == 0 || (roles & lti_roles).count > 0)
@@ -198,7 +215,7 @@ module CoalescingPanda
198
215
  if params[:encrypted_session_key]
199
216
  return msg_encryptor.decrypt_and_verify(params[:encrypted_session_key])
200
217
  end
201
- params[:session_key] || session_key_header
218
+ params[:session_key] || session_key_header || rails_session['persistent_session_key']
202
219
  end
203
220
 
204
221
  def session_key_header
@@ -1,4 +1,5 @@
1
1
  require 'secure_headers'
2
+ require_relative './secure_headers'
2
3
 
3
4
  module CoalescingPanda
4
5
  class Engine < ::Rails::Engine
@@ -25,6 +26,10 @@ module CoalescingPanda
25
26
  end
26
27
  end
27
28
 
29
+ initializer 'coalescing_panda.assets' do |app|
30
+ app.config.assets.precompile << 'coalescing_panda/manifest.js'
31
+ end
32
+
28
33
  initializer 'cloaescing_panda.route_helper' do |route|
29
34
  ActionDispatch::Routing::Mapper.send :include, CoalescingPanda::RouteHelpers
30
35
  end
@@ -38,52 +43,21 @@ module CoalescingPanda
38
43
  end
39
44
 
40
45
  initializer :secure_headers do |app|
41
- connect_src = %w('self')
42
- script_src = %w('self')
43
-
44
- if Rails.env.development?
45
- # Allow webpack-dev-server to work
46
- connect_src << "http://localhost:3035"
47
- connect_src << "ws://localhost:3035"
48
-
49
- # Allow stuff like rack-mini-profiler to work in development:
50
- # https://github.com/MiniProfiler/rack-mini-profiler/issues/327
51
- # DON'T ENABLE THIS FOR PRODUCTION!
52
- script_src << "'unsafe-eval'"
53
- elsif CoalescingPanda.lti_options.has_key?(:allow_unsafe_eval) && CoalescingPanda.lti_options[:allow_unsafe_eval] == true
54
- # For when code is returned from server and injected into dom. Need to have unsafe-eval or it won't work.
55
- script_src << "'unsafe-eval'"
56
- end
57
-
58
- SecureHeaders::Configuration.default do |config|
59
- # The default cookie headers aren't compatible with PandaPal cookies currently
60
- config.cookies = { samesite: { none: true } }
61
-
62
- if Rails.env.production?
63
- config.cookies[:secure] = true
46
+ begin
47
+ ::SecureHeaders::Configuration.default do |config|
48
+ CoalescingPanda::SecureHeaders.apply_defaults(config)
64
49
  end
65
-
66
- # Need to allow LTI iframes
67
- config.x_frame_options = "ALLOWALL"
68
-
69
- config.x_content_type_options = "nosniff"
70
- config.x_xss_protection = "1; mode=block"
71
- config.referrer_policy = %w(origin-when-cross-origin strict-origin-when-cross-origin)
72
-
73
- config.csp = {
74
- default_src: %w('self'),
75
- script_src: script_src,
76
- # Certain CSS-in-JS libraries inline the CSS, so we need to use unsafe-inline for them
77
- style_src: %w('self' 'unsafe-inline' blob: https://fonts.googleapis.com),
78
- font_src: %w('self' data: https://fonts.gstatic.com),
79
- connect_src: connect_src,
80
- }
50
+ rescue ::SecureHeaders::Configuration::AlreadyConfiguredError
51
+ # The App already applied settings
81
52
  end
82
53
 
83
- SecureHeaders::Configuration.override(:safari_override) do |config|
54
+ ::SecureHeaders::Configuration.override(:safari_override) do |config|
84
55
  config.cookies = SecureHeaders::OPT_OUT
85
56
  end
86
- end
87
57
 
58
+ ::SecureHeaders::Configuration.override(:allow_inline_scripts) do |config|
59
+ config.csp[:script_src] << "'unsafe-inline'"
60
+ end
61
+ end
88
62
  end
89
63
  end
@@ -0,0 +1,13 @@
1
+ module CoalescingPanda
2
+ module MiscHelper
3
+ MigrationClass = Rails.version < '5.0' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
4
+
5
+ def self.to_boolean(v)
6
+ if Rails.version < '5.0'
7
+ ActiveRecord::Type::Boolean.new.type_cast_from_user("0")
8
+ else
9
+ ActiveRecord::Type::Boolean.new.deserialize('0')
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,84 @@
1
+ module CoalescingPanda
2
+ module SecureHeaders
3
+ def self.apply_defaults(config)
4
+ @config = config
5
+ # The default cookie headers aren't compatable with CoalescingPanda cookies currenntly
6
+ config.cookies = { samesite: { none: true } }
7
+
8
+ if Rails.env.production?
9
+ config.cookies[:secure] = true
10
+ end
11
+
12
+ # Need to allow LTI iframes
13
+ config.x_frame_options = "ALLOWALL"
14
+
15
+ config.x_content_type_options = "nosniff"
16
+ config.x_xss_protection = "1; mode=block"
17
+ config.referrer_policy = %w(origin-when-cross-origin strict-origin-when-cross-origin)
18
+
19
+ config.csp ||= {}
20
+
21
+ csp_entry(:default_src, %w['self'])
22
+ csp_entry(:connect_src, %w['self'])
23
+ csp_entry(:script_src, %w['self'])
24
+
25
+ if Rails.env.development?
26
+ # Allow webpack-dev-server to work
27
+ csp_entry(:connect_src, "http://localhost:3035")
28
+ csp_entry(:connect_src, "ws://localhost:3035")
29
+
30
+ # Allow stuff like rack-mini-profiler to work in development:
31
+ # https://github.com/MiniProfiler/rack-mini-profiler/issues/327
32
+ # DON'T ENABLE THIS FOR PRODUCTION!
33
+ csp_entry(:script_src, "'unsafe-eval'")
34
+
35
+ # Detect and permit Scout APM in Dev
36
+ if MiscHelper.to_boolean(ENV['SCOUT_DEV_TRACE'])
37
+ csp_entry(:default_src, 'https://scoutapm.com')
38
+ csp_entry(:default_src, 'https://apm.scoutapp.com')
39
+
40
+ csp_entry(:script_src, "'unsafe-inline'")
41
+ csp_entry(:script_src, 'https://scoutapm.com')
42
+ csp_entry(:script_src, 'https://apm.scoutapp.com')
43
+
44
+ csp_entry(:connect_src, 'https://apm.scoutapp.com')
45
+
46
+ csp_entry(:style_src, 'https://scoutapm.com')
47
+ csp_entry(:style_src, 'https://apm.scoutapp.com')
48
+ end
49
+ end
50
+
51
+ if CoalescingPanda.lti_options.has_key?(:allow_unsafe_eval) && CoalescingPanda.lti_options[:allow_unsafe_eval] == true
52
+ # For when code is returned from server and injected into dom. Need to have unsafe-eval or it won't work.
53
+ csp_entry(:script_src, "'unsafe-eval'")
54
+ end
55
+
56
+ # Detect and permit Sentry
57
+ if defined?(Raven) && Raven.configuration.server.present?
58
+ csp_entry(:connect_src, Raven.configuration.server)
59
+
60
+ # Report CSP Violations to Sentry
61
+ unless config.csp[:report_uri].present?
62
+ cfg = Raven.configuration
63
+ config.csp[:report_uri] = ["#{cfg.scheme}://#{cfg.host}/api/#{cfg.project_id}/security/?sentry_key=#{cfg.public_key}"] unless config.csp[:report_uri].present?
64
+ end
65
+ end
66
+
67
+ # Certain CSS-in-JS libraries inline the CSS, so we need to use unsafe-inline for them
68
+ csp_entry(:style_src, %w('self' 'unsafe-inline' blob: https://fonts.googleapis.com))
69
+ csp_entry(:font_src, %w('self' data: https://fonts.gstatic.com))
70
+
71
+ @config = nil
72
+
73
+ config
74
+ end
75
+
76
+ private
77
+
78
+ def self.csp_entry(key, *values)
79
+ values = values.flatten
80
+ @config.csp[key] ||= []
81
+ @config.csp[key] |= values
82
+ end
83
+ end
84
+ end
@@ -1,3 +1,3 @@
1
1
  module CoalescingPanda
2
- VERSION = '5.0.0'
2
+ VERSION = '5.0.6'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coalescing_panda
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Mills
@@ -10,20 +10,20 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-06-04 00:00:00.000000000 Z
13
+ date: 2020-08-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - "~>"
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: 4.2.1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - "~>"
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: 4.2.1
29
29
  - !ruby/object:Gem::Dependency
@@ -72,16 +72,22 @@ dependencies:
72
72
  name: ims-lti
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - ">="
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: 1.2.0
78
+ - - "<"
76
79
  - !ruby/object:Gem::Version
77
- version: 2.1.0
80
+ version: '2.0'
78
81
  type: :runtime
79
82
  prerelease: false
80
83
  version_requirements: !ruby/object:Gem::Requirement
81
84
  requirements:
82
- - - ">="
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: 1.2.0
88
+ - - "<"
83
89
  - !ruby/object:Gem::Version
84
- version: 2.1.0
90
+ version: '2.0'
85
91
  - !ruby/object:Gem::Dependency
86
92
  name: haml-rails
87
93
  requirement: !ruby/object:Gem::Requirement
@@ -400,6 +406,7 @@ extensions: []
400
406
  extra_rdoc_files: []
401
407
  files:
402
408
  - Rakefile
409
+ - app/assets/config/coalescing_panda/manifest.js
403
410
  - app/assets/images/bootstrap/glyphicons-halflings-white.png
404
411
  - app/assets/images/bootstrap/glyphicons-halflings.png
405
412
  - app/assets/javascripts/coalescing_panda/application.js
@@ -422,6 +429,7 @@ files:
422
429
  - app/models/coalescing_panda/group.rb
423
430
  - app/models/coalescing_panda/group_category.rb
424
431
  - app/models/coalescing_panda/group_membership.rb
432
+ - app/models/coalescing_panda/json_with_indifferent_access.rb
425
433
  - app/models/coalescing_panda/lti_account.rb
426
434
  - app/models/coalescing_panda/lti_nonce.rb
427
435
  - app/models/coalescing_panda/oauth_state.rb
@@ -479,7 +487,9 @@ files:
479
487
  - lib/coalescing_panda/bearcat_uri.rb
480
488
  - lib/coalescing_panda/controller_helpers.rb
481
489
  - lib/coalescing_panda/engine.rb
490
+ - lib/coalescing_panda/misc_helper.rb
482
491
  - lib/coalescing_panda/route_helpers.rb
492
+ - lib/coalescing_panda/secure_headers.rb
483
493
  - lib/coalescing_panda/version.rb
484
494
  - lib/tasks/coalescing_panda_tasks.rake
485
495
  - spec/controllers/coalescing_panda/canvas_batches_controller_spec.rb