panda_pal 5.9.7 → 5.9.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 799fa888cac92c1bdd0f8db04306a6ca3eac462f8cf545fa28aa1fee2cd8d2e2
4
- data.tar.gz: c52ec2f608302a2c646634691bbe05730455fcec5716493e400f3c2066be2830
3
+ metadata.gz: 2b12b3b77cb30daf1aef73f0e798f1e6e4087ed55f26749252815ac7f6e79d36
4
+ data.tar.gz: 0f2d3408e91d3df0a20d16d6b35a302aa319c0dc2c1fb33dae38baf859d3dc5f
5
5
  SHA512:
6
- metadata.gz: 9c76429c86e9a999aaa90d953175988b86c5af85de9c8021608cd34d911af3bc299f31fe22729c9b91a622749fd2665801de21e34a1076bf11f0be9ec2690090
7
- data.tar.gz: 3c0a7d8aab01ebcdc6eb70fcf89a6936cf138fb661634194417ac55961645e0654d65bf2a9264dac7b53652a6eb67afdc1edf0bc83d7611ac7f5781b337cf79d
6
+ metadata.gz: 8b9d7af482b7a0a6db6a8403f7f23380e7939b7bc09a5312e8af255a4caf8ac8a7e011f08f65949c42aaa31c0e28977d37b04ec5e64090d36cb8f49ad6efafd2
7
+ data.tar.gz: e93bc45ce0ae92dadece7844a14c259baae692a4b10c112699af1f3129c26ca706da9ef75c0d26547f69b9b991604e6bc7897c39b42416472cc3758914c03e90
@@ -6,15 +6,26 @@ module PandaPal
6
6
  self.session_key ||= SecureRandom.urlsafe_base64(60)
7
7
  end
8
8
 
9
+ def cache(key, &blk)
10
+ panda_pal_session[:cache] ||= {}
11
+ panda_pal_session[:cache][key] ||= blk.call
12
+ end
13
+
14
+ def launch_params
15
+ data[:launch_params] || {}
16
+ end
17
+
9
18
  def lti_platform
10
19
  return nil unless data[:lti_platform].present?
11
20
 
12
21
  @lti_platform ||= Platform.from_serialized(data[:lti_platform])
13
22
  end
14
23
 
15
- def custom_lti_params
16
- launch_params = data[:launch_params] || {}
24
+ def lti_launch_placement
25
+ launch_params['https://www.instructure.com/placement'] || launch_params[:launch_type]
26
+ end
17
27
 
28
+ def custom_lti_params
18
29
  # LT 1.3
19
30
  custom_params = launch_params["https://purl.imsglobal.org/spec/lti/claim/custom"]
20
31
  return custom_params if custom_params.present?
@@ -29,6 +40,113 @@ module PandaPal
29
40
  custom_params.with_indifferent_access
30
41
  end
31
42
 
43
+ def get_lti_cust_param(key)
44
+ nkey = key.to_s.gsub(/^custom_/, '')
45
+
46
+ launch_params.dig("https://purl.imsglobal.org/spec/lti/claim/custom", nkey) || launch_params[nkey] || launch_params["custom_#{nkey}"]
47
+ end
48
+
49
+ def canvas_role_labels
50
+ labels = get_lti_cust_param('custom_canvas_role')
51
+ labels.is_a?(String) ? labels.split(',') : []
52
+ end
53
+
54
+ def canvas_account_role_labels(account = 'self')
55
+ account = 'self' if account.to_s == "root"
56
+ account = account.canvas_id if account.respond_to?(:canvas_id)
57
+
58
+ if "::Admin".safe_constantize && ::Admin < ::ActiveRecord::Base
59
+ account = current_organization.canvas_account_id if account == 'self'
60
+ adm_query = ::Admin.where(canvas_account_id: account, workflow_state: "active")
61
+ adm_query.pluck(:role_name)
62
+ else
63
+ Rails.cache.fetch([self.class.name, "AccountAdminLinks", account, canvas_user_id], expires_in: 1.hour) do
64
+ admin_entries = canvas_sync_client.account_admins(account, user_id: [canvas_user_id])
65
+ admin_entries = admin_entries.select{|ent| ent[:workflow_state] == 'active' }
66
+ admin_entries.map{|ent| ent[:role] }
67
+ end
68
+ end
69
+ end
70
+
71
+ def lti_roles
72
+ @lti_roles ||= RoleStore.new(launch_params["https://purl.imsglobal.org/spec/lti/claim/roles"] || launch_params['ext_roles'] || '')
73
+ end
74
+
75
+ def canvas_site_admin?
76
+ lti_roles.system_roles.include?("sys_admin")
77
+ end
78
+
79
+ class RoleStore
80
+ ContextTypeURN = 'urn:lti:context-type:ims/lis/'.freeze
81
+
82
+ ROLE_TYPES = [
83
+ { type: "system", urn: "urn:lti:sysrole:ims/lis/", url: "http://purl.imsglobal.org/vocab/lis/v2/system/person#" },
84
+ { type: "institution", urn: "urn:lti:instrole:ims/lis/", url: "http://purl.imsglobal.org/vocab/lis/v2/institution/person#" },
85
+ { type: "context", urn: "urn:lti:role:ims/lis/", url: "http://purl.imsglobal.org/vocab/lis/v2/membership#" },
86
+ ]
87
+
88
+ attr_accessor :roles, :context_types, :other_roles
89
+
90
+ def initialize(roles = '')
91
+ roles = roles.split(',') if roles.is_a?(String)
92
+ @roles = roles || []
93
+
94
+ @context_types = []
95
+ @other_roles = []
96
+ @parsed_roles = HashWithIndifferentAccess.new
97
+
98
+ map_roles
99
+ end
100
+
101
+ def system_roles; @parsed_roles[:system] || []; end
102
+ def institution_roles; @parsed_roles[:institution] || []; end
103
+ def context_roles; @parsed_roles[:context] || []; end
104
+
105
+ def to_h
106
+ {
107
+ 'roles' => roles,
108
+ 'context_type' => context_types,
109
+ 'system_roles' => system_roles,
110
+ 'institution_roles' => institution_roles,
111
+ 'context_roles' => context_roles
112
+ }
113
+ end
114
+
115
+ protected
116
+
117
+ def map_roles
118
+ roles.each do |role|
119
+ if role.downcase.include?(ContextTypeURN)
120
+ context_types << clean_role(ContextTypeURN, role)
121
+ elsif (simple_role, type = match_role(role)).present?
122
+ (@parsed_roles[type[:type]] ||= []) << simple_role
123
+ else
124
+ other_roles << role
125
+ end
126
+ end
127
+ end
128
+
129
+ def match_role(role)
130
+ ROLE_TYPES.each do |rt|
131
+ # LIS V1
132
+ if role.downcase.start_with?(rt[:urn])
133
+ return clean_role(ContextTypeURN, role), rt
134
+ end
135
+
136
+ # LIS V2
137
+ if role.downcase.start_with?(rt[:url])
138
+ return role.split('#')[1].underscore, rt
139
+ end
140
+ end
141
+
142
+ nil
143
+ end
144
+
145
+ def clean_role(urn_prefix, role)
146
+ role.gsub(/#{Regexp.quote(urn_prefix)}/i, '').gsub('/', '').underscore
147
+ end
148
+ end
149
+
32
150
  class DataSerializer
33
151
  def self.load(str)
34
152
  return {} unless str.present?
@@ -2,8 +2,10 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>PandaPal</title>
5
- <%= stylesheet_link_tag "panda_pal/application", media: "all" %>
6
- <%= javascript_include_tag "panda_pal/application" %>
5
+ <% if defined? Sprockets%>
6
+ <%= stylesheet_link_tag "panda_pal/application", media: "all" %>
7
+ <%= javascript_include_tag "panda_pal/application" %>
8
+ <% end %>
7
9
  <%= csrf_meta_tags %>
8
10
  </head>
9
11
  <body>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PandaPal::Concerns
4
+ module AbilityHelper
5
+ extend ActiveSupport::Concern
6
+
7
+ # @return PandaPal::Session
8
+ def panda_pal_session
9
+ @panda_pal_session ||= begin
10
+ raise "Ability class needs to set @panda_pal_session or @controller to use this feature" unless @controller.present?
11
+ @controller.current_session
12
+ end
13
+ end
14
+
15
+ def rails_session
16
+ @rails_session ||= begin
17
+ raise "Ability class needs to set @rails_session or @controller to use this feature" unless @controller.present?
18
+ @controller.session
19
+ end
20
+ end
21
+
22
+ def is_lti_launch?
23
+ panda_pal_session.present?
24
+ end
25
+
26
+ def launch_params
27
+ @launch_params ||= panda_pal_session[:launch_params] || {}
28
+ end
29
+
30
+ def canvas_site_admin?
31
+ panda_pal_session.canvas_site_admin?
32
+ end
33
+ end
34
+ end
@@ -210,6 +210,7 @@ module PandaPal
210
210
  OAUTH_10_SUPPORT = true
211
211
  ActiveSupport.on_load(:action_controller) do
212
212
  include PandaPal::Helpers::ControllerHelper
213
+ include PandaPal::Concerns::AbilityHelper
213
214
  end
214
215
  end
215
216
 
@@ -1,3 +1,3 @@
1
1
  module PandaPal
2
- VERSION = "5.9.7"
2
+ VERSION = "5.9.8"
3
3
  end
data/lib/panda_pal.rb CHANGED
@@ -4,6 +4,8 @@ require 'panda_pal/helpers'
4
4
  require 'oauth/request_proxy/rack_request'
5
5
  require 'oauth/request_proxy/action_dispatch_request'
6
6
 
7
+ Dir[File.dirname(__FILE__) + "/panda_pal/concerns/**/*.rb"].each { |file| require file }
8
+
7
9
  module PandaPal
8
10
  class LtiNavigationInUse < StandardError;end
9
11
  class NotMounted < StandardError;end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panda_pal
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.9.7
4
+ version: 5.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure CustomDev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-21 00:00:00.000000000 Z
11
+ date: 2024-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -282,7 +282,7 @@ dependencies:
282
282
  - - '='
283
283
  - !ruby/object:Gem::Version
284
284
  version: 2.7.1
285
- description:
285
+ description:
286
286
  email:
287
287
  - pseng@instructure.com
288
288
  executables: []
@@ -333,6 +333,7 @@ files:
333
333
  - db/migrate/20171205194657_remove_old_organization_settings.rb
334
334
  - db/migrate/20220721095653_create_panda_pal_api_calls.rb
335
335
  - lib/panda_pal.rb
336
+ - lib/panda_pal/concerns/ability_helper.rb
336
337
  - lib/panda_pal/engine.rb
337
338
  - lib/panda_pal/helpers.rb
338
339
  - lib/panda_pal/helpers/console_helpers.rb
@@ -393,7 +394,7 @@ homepage: http://instructure.com
393
394
  licenses:
394
395
  - MIT
395
396
  metadata: {}
396
- post_install_message:
397
+ post_install_message:
397
398
  rdoc_options: []
398
399
  require_paths:
399
400
  - lib
@@ -408,52 +409,52 @@ required_rubygems_version: !ruby/object:Gem::Requirement
408
409
  - !ruby/object:Gem::Version
409
410
  version: '0'
410
411
  requirements: []
411
- rubygems_version: 3.1.6
412
- signing_key:
412
+ rubygems_version: 3.5.4
413
+ signing_key:
413
414
  specification_version: 4
414
415
  summary: LTI mountable engine
415
416
  test_files:
416
- - spec/rails_helper.rb
417
- - spec/models/panda_pal/api_call_spec.rb
418
- - spec/models/panda_pal/organization_spec.rb
419
- - spec/models/panda_pal/session_spec.rb
420
- - spec/models/panda_pal/organization/settings_validation_spec.rb
421
- - spec/models/panda_pal/organization/task_scheduling_spec.rb
422
417
  - spec/controllers/panda_pal/api_call_controller_spec.rb
423
- - spec/spec_helper.rb
424
- - spec/dummy/db/schema.rb
425
- - spec/dummy/public/422.html
426
- - spec/dummy/public/favicon.ico
427
- - spec/dummy/public/404.html
428
- - spec/dummy/public/500.html
418
+ - spec/dummy/README.rdoc
429
419
  - spec/dummy/Rakefile
430
- - spec/dummy/app/views/layouts/application.html.erb
420
+ - spec/dummy/app/assets/javascripts/application.js
421
+ - spec/dummy/app/assets/stylesheets/application.css
431
422
  - spec/dummy/app/controllers/application_controller.rb
432
423
  - spec/dummy/app/helpers/application_helper.rb
433
- - spec/dummy/app/assets/stylesheets/application.css
434
- - spec/dummy/app/assets/javascripts/application.js
435
- - spec/dummy/config/secrets.yml
424
+ - spec/dummy/app/views/layouts/application.html.erb
425
+ - spec/dummy/bin/bundle
426
+ - spec/dummy/bin/rails
427
+ - spec/dummy/bin/rake
428
+ - spec/dummy/bin/setup
436
429
  - spec/dummy/config/application.rb
437
- - spec/dummy/config/initializers/session_store.rb
438
- - spec/dummy/config/initializers/wrap_parameters.rb
439
- - spec/dummy/config/initializers/inflections.rb
440
- - spec/dummy/config/initializers/filter_parameter_logging.rb
441
- - spec/dummy/config/initializers/mime_types.rb
442
- - spec/dummy/config/initializers/backtrace_silencers.rb
443
- - spec/dummy/config/initializers/cookies_serializer.rb
444
- - spec/dummy/config/environments/development.rb
445
- - spec/dummy/config/environments/test.rb
446
- - spec/dummy/config/environments/production.rb
447
- - spec/dummy/config/database.yml
448
430
  - spec/dummy/config/boot.rb
449
- - spec/dummy/config/routes.rb
431
+ - spec/dummy/config/database.yml
450
432
  - spec/dummy/config/environment.rb
433
+ - spec/dummy/config/environments/development.rb
434
+ - spec/dummy/config/environments/production.rb
435
+ - spec/dummy/config/environments/test.rb
436
+ - spec/dummy/config/initializers/backtrace_silencers.rb
437
+ - spec/dummy/config/initializers/cookies_serializer.rb
438
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
439
+ - spec/dummy/config/initializers/inflections.rb
440
+ - spec/dummy/config/initializers/mime_types.rb
441
+ - spec/dummy/config/initializers/session_store.rb
442
+ - spec/dummy/config/initializers/wrap_parameters.rb
451
443
  - spec/dummy/config/locales/en.yml
452
- - spec/dummy/README.rdoc
444
+ - spec/dummy/config/routes.rb
445
+ - spec/dummy/config/secrets.yml
453
446
  - spec/dummy/config.ru
454
- - spec/dummy/bin/bundle
455
- - spec/dummy/bin/rake
456
- - spec/dummy/bin/setup
457
- - spec/dummy/bin/rails
447
+ - spec/dummy/db/schema.rb
448
+ - spec/dummy/public/404.html
449
+ - spec/dummy/public/422.html
450
+ - spec/dummy/public/500.html
451
+ - spec/dummy/public/favicon.ico
458
452
  - spec/factories/panda_pal_organizations.rb
459
453
  - spec/factories/panda_pal_sessions.rb
454
+ - spec/models/panda_pal/api_call_spec.rb
455
+ - spec/models/panda_pal/organization/settings_validation_spec.rb
456
+ - spec/models/panda_pal/organization/task_scheduling_spec.rb
457
+ - spec/models/panda_pal/organization_spec.rb
458
+ - spec/models/panda_pal/session_spec.rb
459
+ - spec/rails_helper.rb
460
+ - spec/spec_helper.rb