panda_pal 3.0.1 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d38f3ee39fd2a646758d9c6e47e9c0fdb496ed5
4
- data.tar.gz: d15a3f38b606c3705ee397e1e8ff7446c518006b
3
+ metadata.gz: 142d69b7f513a07ebace023bd229a780b099f17d
4
+ data.tar.gz: 60bd6a9784c2e2a9265b2e7c6582759560892c66
5
5
  SHA512:
6
- metadata.gz: c0524f269d6725c879f19bb6b304f8e83fe94d551935b7e6d7b424e8f1aac2dd1b2022ee06607d73180f6017f43a9c55dfa160f8c77613e97d06062d1bd9be57
7
- data.tar.gz: 7d8437a68bdb6611df7375b1f4a2fd8e7e17eb03075bf4af379fb7222293e7d9ffd7195525aa38ccde8fdab9032348b6bbdb1d65743594f98d7b59a520c9a3e2
6
+ metadata.gz: c95b68006a09db2e5cb559bc653f93219d6fc3f2aff350e5c2daa942a2d85c6a4490c1a10020cd0b8b8901f91ce3d299977d9334b677014c8c1c5bda14389083
7
+ data.tar.gz: d7ddd1733b129b550d69b736f9201115e0667f06cb1b8e116115b890e108963597fecb05d9b962fe2926e030e4557682cdd49b09d4106bfd4239d66b90bdedab
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
14
14
  rdoc.rdoc_files.include('lib/**/*.rb')
15
15
  end
16
16
 
17
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
18
  load 'rails/tasks/engine.rake'
19
19
 
20
20
 
@@ -1,4 +1,5 @@
1
1
  module PandaPal
2
+
2
3
  class Organization < ActiveRecord::Base
3
4
  attribute :settings
4
5
  attr_encrypted :settings, marshal: true, key: :encryption_key
@@ -8,7 +9,7 @@ module PandaPal
8
9
  validates :name, uniqueness: { case_sensitive: false }, presence: true, format: { with: /\A[a-z0-9_]+\z/i }
9
10
  validates :canvas_account_id, presence: true
10
11
  validates :salesforce_id, presence: true, uniqueness: true
11
-
12
+ validate :validate_settings
12
13
  after_create :create_schema
13
14
  after_commit :destroy_schema, on: :destroy
14
15
 
@@ -37,5 +38,48 @@ module PandaPal
37
38
  def destroy_schema
38
39
  Apartment::Tenant.drop name
39
40
  end
41
+
42
+ def validate_settings
43
+ record = self
44
+ if PandaPal.lti_options && PandaPal.lti_options[:settings_structure]
45
+ validate_level(record, PandaPal.lti_options[:settings_structure], record.settings, [])
46
+ end
47
+ end
48
+ def validate_level(record, expectation, reality, previous_keys)
49
+ # Verify that the data elements at this level conform to requirements.
50
+ if expectation
51
+ expectation.each do |key, value|
52
+ is_required = expectation[key].try(:delete, :is_required)
53
+ data_type = expectation[key].try(:delete, :data_type)
54
+ value = reality.is_a?(Hash) ? reality.dig(key) : reality
55
+
56
+ if is_required && !value
57
+ record.errors[:settings] << "PandaPal::Organization.settings requires key [:#{previous_keys.push(key).join("][:")}]. It was not found."
58
+ end
59
+ if data_type && value
60
+ if value.class.to_s != data_type
61
+ record.errors[:settings] << "PandaPal::Organization.settings expected key [:#{previous_keys.push(key).join("][:")}] to be #{data_type} but it was instead #{value.class}."
62
+ end
63
+ end
64
+ end
65
+ end
66
+ # Verify that anything that is in the real settings has an expectation.
67
+ if reality
68
+ if reality.is_a? Hash
69
+ reality.each do |key, value|
70
+ was_expected = expectation.has_key?(key)
71
+ if !was_expected
72
+ record.errors[:settings] << "PandaPal::Organization.settings had unexpected key: #{key}. If settings have expanded please update your lti_options accordingly."
73
+ end
74
+ end
75
+ end
76
+ end
77
+ # Recursively check out any children settings as well.
78
+ if expectation
79
+ expectation.each do |key, value|
80
+ validate_level(record, expectation[key], (reality.is_a?(Hash) ? reality.dig(key) : nil), previous_keys.deep_dup.push(key))
81
+ end
82
+ end
83
+ end
40
84
  end
41
85
  end
@@ -1,4 +1,8 @@
1
1
  class RemoveOldOrganizationSettings < ActiveRecord::Migration[5.1]
2
+ def current_tenant
3
+ @current_tenant ||= PandaPal::Organization.find_by_name(Apartment::Tenant.current)
4
+ end
5
+
2
6
  def up
3
7
  # migrations run for public and local tenants. However, PandaPal::Organization
4
8
  # is going to always go to public tenant. So don't do this active record
@@ -1,3 +1,3 @@
1
1
  module PandaPal
2
- VERSION = "3.0.1"
2
+ VERSION = "3.0.3"
3
3
  end
data/panda_pal.gemspec CHANGED
@@ -21,8 +21,6 @@ Gem::Specification.new do |s|
21
21
  s.add_dependency 'ims-lti', '~> 2.1.0'
22
22
  s.add_dependency 'browser', '2.5.0'
23
23
  s.add_dependency 'attr_encrypted', '~> 3.0.0'
24
-
25
24
  s.add_development_dependency 'rspec-rails'
26
25
  s.add_development_dependency 'factory_girl_rails'
27
- s.add_development_dependency 'test_after_commit'
28
26
  end
@@ -19,8 +19,5 @@ module Dummy
19
19
  # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
20
20
  # config.i18n.default_locale = :de
21
21
 
22
- # Do not swallow errors in after_commit/after_rollback callbacks.
23
- config.active_record.raise_in_transactional_callbacks = true
24
22
  end
25
23
  end
26
-
@@ -5,20 +5,20 @@
5
5
  # gem 'sqlite3'
6
6
  #
7
7
  default: &default
8
- adapter: sqlite3
8
+ adapter: postgresql
9
9
  pool: 5
10
10
  timeout: 5000
11
11
 
12
12
  development:
13
13
  <<: *default
14
- database: db/development.sqlite3
14
+ database: panda_pal_development
15
15
 
16
16
  # Warning: The database defined as "test" will be erased and
17
17
  # re-generated from your development database when you run "rake".
18
18
  # Do not set this db to the same as development or production.
19
19
  test:
20
20
  <<: *default
21
- database: db/test.sqlite3
21
+ database: panda_pal_test
22
22
 
23
23
  production:
24
24
  <<: *default
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -11,45 +10,30 @@
11
10
  #
12
11
  # It's strongly recommended that you check this file into your version control system.
13
12
 
14
- ActiveRecord::Schema.define(version: 20160415162154) do
15
-
16
- create_table "delayed_jobs", force: :cascade do |t|
17
- t.integer "priority", default: 0, null: false
18
- t.integer "attempts", default: 0, null: false
19
- t.text "handler", null: false
20
- t.text "last_error"
21
- t.datetime "run_at"
22
- t.datetime "locked_at"
23
- t.datetime "failed_at"
24
- t.string "locked_by"
25
- t.string "queue"
26
- t.string "tenant"
27
- t.datetime "created_at"
28
- t.datetime "updated_at"
29
- end
30
-
31
- add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority"
13
+ ActiveRecord::Schema.define(version: 30171205194657) do
32
14
 
33
15
  create_table "panda_pal_organizations", force: :cascade do |t|
34
- t.string "name"
35
- t.string "key"
36
- t.string "secret"
37
- t.string "canvas_account_id"
38
- t.text "settings"
39
- t.datetime "created_at", null: false
40
- t.datetime "updated_at", null: false
16
+ t.string "name"
17
+ t.string "key"
18
+ t.string "secret"
19
+ t.string "canvas_account_id"
20
+ t.datetime "created_at", null: false
21
+ t.datetime "updated_at", null: false
22
+ t.string "salesforce_id"
23
+ t.text "encrypted_settings"
24
+ t.string "encrypted_settings_iv"
25
+ t.index ["key"], name: "index_panda_pal_organizations_on_key", unique: true
26
+ t.index ["name"], name: "index_panda_pal_organizations_on_name", unique: true
41
27
  end
42
28
 
43
- add_index "panda_pal_organizations", ["key"], name: "index_panda_pal_organizations_on_key", unique: true
44
- add_index "panda_pal_organizations", ["name"], name: "index_panda_pal_organizations_on_name", unique: true
45
-
46
29
  create_table "panda_pal_sessions", force: :cascade do |t|
47
- t.string "session_key"
48
- t.text "data"
49
- t.datetime "created_at", null: false
50
- t.datetime "updated_at", null: false
30
+ t.string "session_key"
31
+ t.text "data"
32
+ t.datetime "created_at", null: false
33
+ t.datetime "updated_at", null: false
34
+ t.integer "panda_pal_organization_id"
35
+ t.index ["panda_pal_organization_id"], name: "index_panda_pal_sessions_on_panda_pal_organization_id"
36
+ t.index ["session_key"], name: "index_panda_pal_sessions_on_session_key", unique: true
51
37
  end
52
38
 
53
- add_index "panda_pal_sessions", ["session_key"], name: "index_panda_pal_sessions_on_session_key", unique: true
54
-
55
39
  end
@@ -3,18 +3,44 @@ require 'rails_helper'
3
3
  module PandaPal
4
4
  RSpec.describe Organization, type: :model do
5
5
 
6
+ def set_test_settings_structure
7
+ PandaPal.lti_options = {
8
+ title: 'Test App',
9
+ settings_structure: YAML.load("
10
+ canvas:
11
+ is_required: true
12
+ data_type: Hash
13
+ api_token:
14
+ is_required: true
15
+ data_type: String
16
+ base_url:
17
+ is_required: true
18
+ data_type: String
19
+ reports:
20
+ is_required: true
21
+ data_type: Hash
22
+ active_term_allowance:
23
+ submissions_report_time_length:
24
+ is_required: true
25
+ data_type: ActiveSupport::Duration
26
+ recheck_wait:
27
+ data_type: ActiveSupport::Duration
28
+ max_recheck_time:
29
+ is_required: true
30
+ ").deep_symbolize_keys
31
+ }
32
+ end
33
+
6
34
  it 'creates a schema upon creation' do
7
35
  expect(Apartment::Tenant).to receive(:create)
8
36
  create :panda_pal_organization
9
37
  end
10
38
 
11
39
  it 'deletes a schema upon deletion' do
12
- TestAfterCommit.with_commits(true) do
13
- expect(Apartment::Tenant).to receive(:create)
14
- expect(Apartment::Tenant).to receive(:drop)
15
- org = create :panda_pal_organization
16
- org.destroy
17
- end
40
+ expect(Apartment::Tenant).to receive(:create)
41
+ expect(Apartment::Tenant).to receive(:drop)
42
+ org = create :panda_pal_organization
43
+ org.destroy
18
44
  end
19
45
 
20
46
  it 'does not allow the name to be changed after creation' do
@@ -33,5 +59,65 @@ module PandaPal
33
59
  org2 = build :panda_pal_organization, salesforce_id: 'salesforce'
34
60
  expect(org2.valid?).to be_falsey
35
61
  end
62
+
63
+ context 'settings validation' do
64
+ let!(:org) { create :panda_pal_organization }
65
+
66
+ it 'does not perform any validations if settings is not defined' do
67
+ PandaPal.lti_options = {}
68
+ expect_any_instance_of(PandaPal::Organization).not_to receive(:validate_level)
69
+ expect(org.valid?).to be_truthy
70
+ end
71
+
72
+ it 'does not perform any validations if options is not defined' do
73
+ PandaPal.lti_options = nil
74
+ expect_any_instance_of(PandaPal::Organization).not_to receive(:validate_level)
75
+ expect(org.valid?).to be_truthy
76
+ end
77
+
78
+ it 'does perform validations if settings_structure is defined' do
79
+ set_test_settings_structure
80
+ org.valid?
81
+ expect(org.valid?).to be_falsey
82
+ end
83
+
84
+ it 'will fail if a required setting is not present' do
85
+ set_test_settings_structure
86
+ expect(org.valid?).to be_falsey
87
+ errors = org.errors.messages[:settings]
88
+ expect(errors[0]).to eq("PandaPal::Organization.settings requires key [:canvas]. It was not found.")
89
+ end
90
+
91
+ it 'will fail if a setting is supplied but data_type is wrong' do
92
+ set_test_settings_structure
93
+ org.settings = {canvas: "Dog"}
94
+ expect(org.valid?).to be_falsey
95
+ errors = org.errors.messages[:settings]
96
+ expect(errors[0]).to eq("PandaPal::Organization.settings expected key [:canvas] to be Hash but it was instead String.")
97
+ end
98
+
99
+ it 'will fail if a required subsetting is missing' do
100
+ set_test_settings_structure
101
+ org.settings = {canvas: {base_url: 'http://'}, reports: {}}
102
+ expect(org.valid?).to be_falsey
103
+ errors = org.errors.messages[:settings]
104
+ expect(errors[0]).to eq("PandaPal::Organization.settings requires key [:canvas][:api_token]. It was not found.")
105
+ end
106
+
107
+ it 'will fail if extra options are specified' do
108
+ set_test_settings_structure
109
+ org.settings = {canvas: {base_url: 'http://'}, reports: {}, unknown_option: "WHAT IS THIS?"}
110
+ expect(org.valid?).to be_falsey
111
+ errors = org.errors.messages[:settings]
112
+ expect(errors[0]).to eq("PandaPal::Organization.settings had unexpected key: unknown_option. If settings have expanded please update your lti_options accordingly.")
113
+ end
114
+
115
+ it 'will pass if all structure is maintained' do
116
+ set_test_settings_structure
117
+ org.settings = {canvas: {base_url: 'http://', api_token: 'TEST'}, reports: {submissions_report_time_length: 30.minutes, max_recheck_time: 10.hours}}
118
+ expect(org.valid?).to be_truthy
119
+ end
120
+
121
+ end
36
122
  end
37
123
  end
data/spec/spec_helper.rb CHANGED
@@ -3,13 +3,17 @@ require File.expand_path("../dummy/config/environment.rb", __FILE__)
3
3
  require 'rspec/rails'
4
4
  require 'rspec/autorun'
5
5
  require 'nokogiri'
6
- require 'delayed_job_active_record'
7
6
  require 'factory_girl_rails'
8
- require 'test_after_commit'
9
7
 
10
- Delayed::Worker.delay_jobs = false
8
+ ActiveRecord::Migration.maintain_test_schema!
9
+ ActiveRecord::Schema.verbose = false
10
+ load 'dummy/db/schema.rb' # db agnostic
11
+
11
12
  RSpec.configure do |config|
12
13
  config.include FactoryGirl::Syntax::Methods
14
+ FactoryGirl.definition_file_paths = [File.expand_path('../factories', __FILE__)]
15
+ FactoryGirl.find_definitions
16
+
13
17
  # rspec-expectations config goes here. You can use an alternate
14
18
  # assertion/expectation library such as wrong or the stdlib/minitest
15
19
  # assertions if you prefer.
@@ -33,6 +37,13 @@ RSpec.configure do |config|
33
37
  mocks.verify_partial_doubles = true
34
38
  end
35
39
 
40
+ config.before(:each) do
41
+ PandaPal.lti_options = {
42
+ title: 'Test App',
43
+ settings_structure: {}
44
+ }
45
+ end
46
+
36
47
  # The settings below are suggested to provide a good initial experience
37
48
  # with RSpec, but feel free to customize to your heart's content.
38
49
  =begin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panda_pal
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Young
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-12-21 00:00:00.000000000 Z
12
+ date: 2018-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -123,20 +123,6 @@ dependencies:
123
123
  - - ">="
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: test_after_commit
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: '0'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- version: '0'
140
126
  description:
141
127
  email:
142
128
  - byoung@instructure.com
@@ -206,9 +192,6 @@ files:
206
192
  - spec/dummy/config/locales/en.yml
207
193
  - spec/dummy/config/routes.rb
208
194
  - spec/dummy/config/secrets.yml
209
- - spec/dummy/db/migrate/20160415162152_create_panda_pal_organizations.panda_pal.rb
210
- - spec/dummy/db/migrate/20160415162153_create_delayed_jobs.panda_pal.rb
211
- - spec/dummy/db/migrate/20160415162154_create_panda_pal_sessions.panda_pal.rb
212
195
  - spec/dummy/db/schema.rb
213
196
  - spec/dummy/public/404.html
214
197
  - spec/dummy/public/422.html
@@ -240,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
240
223
  version: '0'
241
224
  requirements: []
242
225
  rubyforge_project:
243
- rubygems_version: 2.5.2
226
+ rubygems_version: 2.2.2
244
227
  signing_key:
245
228
  specification_version: 4
246
229
  summary: LTI mountable engine
@@ -273,9 +256,6 @@ test_files:
273
256
  - spec/dummy/config/routes.rb
274
257
  - spec/dummy/config/secrets.yml
275
258
  - spec/dummy/config.ru
276
- - spec/dummy/db/migrate/20160415162152_create_panda_pal_organizations.panda_pal.rb
277
- - spec/dummy/db/migrate/20160415162153_create_delayed_jobs.panda_pal.rb
278
- - spec/dummy/db/migrate/20160415162154_create_panda_pal_sessions.panda_pal.rb
279
259
  - spec/dummy/db/schema.rb
280
260
  - spec/dummy/public/404.html
281
261
  - spec/dummy/public/422.html
@@ -289,3 +269,4 @@ test_files:
289
269
  - spec/models/panda_pal/session_spec.rb
290
270
  - spec/rails_helper.rb
291
271
  - spec/spec_helper.rb
272
+ has_rdoc:
@@ -1,16 +0,0 @@
1
- # This migration comes from panda_pal (originally 20160412205931)
2
- class CreatePandaPalOrganizations < ActiveRecord::Migration
3
- def change
4
- create_table :panda_pal_organizations do |t|
5
- t.string :name
6
- t.string :key
7
- t.string :secret
8
- t.string :canvas_account_id
9
- t.text :settings
10
-
11
- t.timestamps null: false
12
- end
13
- add_index :panda_pal_organizations, :name, unique: true
14
- add_index :panda_pal_organizations, :key, unique: true
15
- end
16
- end
@@ -1,24 +0,0 @@
1
- # This migration comes from panda_pal (originally 20160413132229)
2
- class CreateDelayedJobs < ActiveRecord::Migration
3
- def self.up
4
- create_table :delayed_jobs, force: true do |table|
5
- table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
6
- table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
7
- table.text :handler, null: false # YAML-encoded string of the object that will do work
8
- table.text :last_error # reason for last failure (See Note below)
9
- table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
10
- table.datetime :locked_at # Set when a client is working on this object
11
- table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
12
- table.string :locked_by # Who is working on this object (if locked)
13
- table.string :queue # The name of the queue this job is in
14
- table.string :tenant
15
- table.timestamps null: true
16
- end
17
-
18
- add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
19
- end
20
-
21
- def self.down
22
- drop_table :delayed_jobs
23
- end
24
- end
@@ -1,12 +0,0 @@
1
- # This migration comes from panda_pal (originally 20160413135653)
2
- class CreatePandaPalSessions < ActiveRecord::Migration
3
- def change
4
- create_table :panda_pal_sessions do |t|
5
- t.string :session_key
6
- t.text :data
7
-
8
- t.timestamps null: false
9
- end
10
- add_index :panda_pal_sessions, :session_key, unique: true
11
- end
12
- end