scimitar 1.8.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scimitar/active_record_backed_resources_controller.rb +20 -94
  3. data/app/controllers/scimitar/application_controller.rb +13 -41
  4. data/app/controllers/scimitar/schemas_controller.rb +0 -5
  5. data/app/models/scimitar/complex_types/address.rb +6 -0
  6. data/app/models/scimitar/engine_configuration.rb +5 -13
  7. data/app/models/scimitar/error_response.rb +0 -12
  8. data/app/models/scimitar/lists/query_parser.rb +10 -25
  9. data/app/models/scimitar/resource_invalid_error.rb +1 -1
  10. data/app/models/scimitar/resources/base.rb +4 -17
  11. data/app/models/scimitar/resources/mixin.rb +42 -539
  12. data/app/models/scimitar/schema/address.rb +0 -1
  13. data/app/models/scimitar/schema/attribute.rb +5 -14
  14. data/app/models/scimitar/schema/base.rb +1 -1
  15. data/app/models/scimitar/schema/vdtp.rb +1 -1
  16. data/app/models/scimitar/service_provider_configuration.rb +3 -14
  17. data/config/initializers/scimitar.rb +3 -28
  18. data/lib/scimitar/support/hash_with_indifferent_case_insensitive_access.rb +10 -140
  19. data/lib/scimitar/version.rb +2 -2
  20. data/lib/scimitar.rb +2 -7
  21. data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
  22. data/spec/apps/dummy/app/models/mock_group.rb +1 -1
  23. data/spec/apps/dummy/app/models/mock_user.rb +8 -36
  24. data/spec/apps/dummy/config/application.rb +1 -0
  25. data/spec/apps/dummy/config/environments/test.rb +28 -5
  26. data/spec/apps/dummy/config/initializers/scimitar.rb +10 -61
  27. data/spec/apps/dummy/config/routes.rb +7 -28
  28. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -10
  29. data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
  30. data/spec/apps/dummy/db/schema.rb +4 -11
  31. data/spec/controllers/scimitar/application_controller_spec.rb +3 -126
  32. data/spec/controllers/scimitar/resource_types_controller_spec.rb +2 -2
  33. data/spec/controllers/scimitar/schemas_controller_spec.rb +2 -10
  34. data/spec/models/scimitar/complex_types/address_spec.rb +4 -3
  35. data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
  36. data/spec/models/scimitar/lists/query_parser_spec.rb +9 -76
  37. data/spec/models/scimitar/resources/base_spec.rb +70 -216
  38. data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
  39. data/spec/models/scimitar/resources/mixin_spec.rb +129 -1447
  40. data/spec/models/scimitar/schema/attribute_spec.rb +3 -22
  41. data/spec/models/scimitar/schema/base_spec.rb +1 -1
  42. data/spec/models/scimitar/schema/user_spec.rb +0 -10
  43. data/spec/requests/active_record_backed_resources_controller_spec.rb +68 -787
  44. data/spec/requests/application_controller_spec.rb +3 -16
  45. data/spec/spec_helper.rb +0 -8
  46. data/spec/support/hash_with_indifferent_case_insensitive_access_spec.rb +0 -108
  47. metadata +14 -25
  48. data/LICENSE.txt +0 -21
  49. data/README.md +0 -710
  50. data/lib/scimitar/support/utilities.rb +0 -51
  51. data/spec/apps/dummy/app/controllers/custom_create_mock_users_controller.rb +0 -25
  52. data/spec/apps/dummy/app/controllers/custom_replace_mock_users_controller.rb +0 -25
  53. data/spec/apps/dummy/app/controllers/custom_save_mock_users_controller.rb +0 -24
  54. data/spec/apps/dummy/app/controllers/custom_update_mock_users_controller.rb +0 -25
@@ -10,7 +10,6 @@ module Scimitar
10
10
  def self.scim_attributes
11
11
  @scim_attributes ||= [
12
12
  Attribute.new(name: 'type', type: 'string'),
13
- Attribute.new(name: 'primary', type: 'boolean'),
14
13
  Attribute.new(name: 'formatted', type: 'string'),
15
14
  Attribute.new(name: 'streetAddress', type: 'string'),
16
15
  Attribute.new(name: 'locality', type: 'string'),
@@ -93,23 +93,14 @@ module Scimitar
93
93
  end
94
94
 
95
95
  def valid_simple_type?(value)
96
- if multiValued
97
- valid = value.is_a?(Array) && value.all? { |v| simple_type?(v) }
98
- errors.add(self.name, "or one of its elements has the wrong type. It has to be an array of #{self.type}s.") unless valid
99
- else
100
- valid = simple_type?(value)
101
- errors.add(self.name, "has the wrong type. It has to be a(n) #{self.type}.") unless valid
102
- end
96
+ valid = (type == 'string' && value.is_a?(String)) ||
97
+ (type == 'boolean' && (value.is_a?(TrueClass) || value.is_a?(FalseClass))) ||
98
+ (type == 'integer' && (value.is_a?(Integer))) ||
99
+ (type == 'dateTime' && valid_date_time?(value))
100
+ errors.add(self.name, "has the wrong type. It has to be a(n) #{self.type}.") unless valid
103
101
  valid
104
102
  end
105
103
 
106
- def simple_type?(value)
107
- (type == 'string' && value.is_a?(String)) ||
108
- (type == 'boolean' && (value.is_a?(TrueClass) || value.is_a?(FalseClass))) ||
109
- (type == 'integer' && (value.is_a?(Integer))) ||
110
- (type == 'dateTime' && valid_date_time?(value))
111
- end
112
-
113
104
  def valid_date_time?(value)
114
105
  !!Time.iso8601(value)
115
106
  rescue ArgumentError
@@ -13,7 +13,7 @@ module Scimitar
13
13
 
14
14
  # Converts the schema to its json representation that will be returned by /SCHEMAS end-point of a SCIM service provider.
15
15
  def as_json(options = {})
16
- @meta.location ||= Scimitar::Engine.routes.url_helpers.scim_schemas_path(name: id)
16
+ @meta.location = Scimitar::Engine.routes.url_helpers.scim_schemas_path(name: id)
17
17
  original = super
18
18
  original.merge('attributes' => original.delete('scim_attributes'))
19
19
  end
@@ -7,7 +7,7 @@ module Scimitar
7
7
  class Vdtp < Base
8
8
  def self.scim_attributes
9
9
  @scim_attributes ||= [
10
- Attribute.new(name: 'value', type: 'string', required: Scimitar.engine_configuration.optional_value_fields_required),
10
+ Attribute.new(name: 'value', type: 'string', required: true),
11
11
  Attribute.new(name: 'display', type: 'string', mutability: 'readOnly'),
12
12
  Attribute.new(name: 'type', type: 'string'),
13
13
  Attribute.new(name: 'primary', type: 'boolean'),
@@ -9,22 +9,11 @@ module Scimitar
9
9
  class ServiceProviderConfiguration
10
10
  include ActiveModel::Model
11
11
 
12
- attr_accessor(
13
- :uses_defaults,
14
- :patch,
15
- :bulk,
16
- :filter,
17
- :changePassword,
18
- :sort,
19
- :etag,
20
- :authenticationSchemes,
21
- :schemas,
22
- :meta,
23
- )
12
+ attr_accessor :patch, :bulk, :filter, :changePassword,
13
+ :sort, :etag, :authenticationSchemes,
14
+ :schemas, :meta
24
15
 
25
16
  def initialize(attributes = {})
26
- @uses_defaults = attributes.empty?
27
-
28
17
  defaults = {
29
18
  bulk: Supportable.unsupported,
30
19
  changePassword: Supportable.unsupported,
@@ -38,10 +38,9 @@ Rails.application.config.to_prepare do # (required for >= Rails 7 / Zeitwerk)
38
38
  Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
39
39
 
40
40
  # If you have filters you want to run for any Scimitar action/route, you
41
- # can define them here. You can also override any shared controller methods
42
- # here. For example, you might use a before-action to set up some
43
- # multi-tenancy related state, skip Rails CSRF token verification, or
44
- # customise how Scimitar generates URLs:
41
+ # can define them here. For example, you might use a before-action to set
42
+ # up some multi-tenancy related state, or skip Rails CSRF token
43
+ # verification. For example:
45
44
  #
46
45
  # application_controller_mixin: Module.new do
47
46
  # def self.included(base)
@@ -55,10 +54,6 @@ Rails.application.config.to_prepare do # (required for >= Rails 7 / Zeitwerk)
55
54
  # prepend_before_action :setup_some_kind_of_multi_tenancy_data
56
55
  # end
57
56
  # end
58
- #
59
- # def scim_schemas_url(options)
60
- # super(custom_param: 'value', **options)
61
- # end
62
57
  # end, # ...other configuration entries might follow...
63
58
 
64
59
  # If you want to support username/password authentication:
@@ -86,26 +81,6 @@ Rails.application.config.to_prepare do # (required for >= Rails 7 / Zeitwerk)
86
81
  # Note that both basic and token authentication can be declared, with the
87
82
  # parameters in the inbound HTTP request determining which is invoked.
88
83
 
89
- # Scimitar rescues certain error cases and exceptions, in order to return a
90
- # JSON response to the API caller. If you want exceptions to also be
91
- # reported to a third party system such as sentry.io or raygun.com, you can
92
- # configure a Proc to do so. It is passed a Ruby exception subclass object.
93
- # For example, a minimal sentry.io reporter might do this:
94
- #
95
- # exception_reporter: Proc.new do | exception |
96
- # Sentry.capture_exception(exception)
97
- # end
98
- #
99
- # You will still need to configure your reporting system according to its
100
- # documentation (e.g. via a Rails "config/initializers/<foo>.rb" file).
101
-
102
- # Scimilar treats "VDTP" (Value, Display, Type, Primary) attribute values,
103
- # used for e.g. e-mail addresses or phone numbers, as required by default.
104
- # If you encounter a service which calls these with e.g. "null" value data,
105
- # you can configure all values to be optional. You'll need to deal with
106
- # whatever that means for you receiving system in your model code.
107
- #
108
- # optional_value_fields_required: false
109
84
  })
110
85
 
111
86
  end
@@ -23,8 +23,8 @@ class Hash
23
23
  #
24
24
  def self.deep_indifferent_case_insensitive_access(object)
25
25
  if object.is_a?(Hash)
26
- new_hash = Scimitar::Support::HashWithIndifferentCaseInsensitiveAccess.new
27
- object.each do | key, value |
26
+ new_hash = Scimitar::Support::HashWithIndifferentCaseInsensitiveAccess.new(object)
27
+ new_hash.each do | key, value |
28
28
  new_hash[key] = deep_indifferent_case_insensitive_access(value)
29
29
  end
30
30
  new_hash
@@ -49,164 +49,34 @@ module Scimitar
49
49
  # in a case-insensitive fashion too.
50
50
  #
51
51
  # During enumeration, Hash keys will always be returned in whatever case
52
- # they were originally set. Just as with
53
- # ActiveSupport::HashWithIndifferentAccess, though, the type of the keys is
54
- # always returned as a String, even if originally set as a Symbol - only
55
- # the upper/lower case nature of the original key is preserved.
56
- #
57
- # If a key is written more than once with the same effective meaning in a
58
- # to-string, to-downcase form, then whatever case was used *first* wins;
59
- # e.g. if you did hash['User'] = 23, then hash['USER'] = 42, the result
60
- # would be {"User" => 42}.
61
- #
62
- # It's important to remember that Hash#merge is shallow and replaces values
63
- # found at existing keys in the target ("this") hash with values in the
64
- # inbound Hash. If that new value that is itself a Hash, this *replaces*
65
- # the value. For example:
66
- #
67
- # * Original: <tt>'Foo' => { 'Bar' => 42 }</tt>
68
- # * Merge: <tt>'FOO' => { 'BAR' => 24 }</tt>
69
- #
70
- # ...results in "this" target hash's key +Foo+ being addressed in the merge
71
- # by inbound key +FOO+, so the case doesn't change. But the value for +Foo+
72
- # is _replaced_ by the merging-in Hash completely:
73
- #
74
- # * Result: <tt>'Foo' => { 'BAR' => 24 }</tt>
75
- #
76
- # ...and of course we might've replaced with a totally different type, such
77
- # as +true+:
78
- #
79
- # * Original: <tt>'Foo' => { 'Bar' => 42 }</tt>
80
- # * Merge: <tt>'FOO' => true</tt>
81
- # * Result: <tt>'Foo' => true</tt>
82
- #
83
- # If you're intending to merge nested Hashes, then use ActiveSupport's
84
- # #deep_merge or an equivalent. This will have the expected outcome, where
85
- # the hash with 'BAR' is _merged_ into the existing value and, therefore,
86
- # the original 'Bar' key case is preserved:
87
- #
88
- # * Original: <tt>'Foo' => { 'Bar' => 42 }</tt>
89
- # * Deep merge: <tt>'FOO' => { 'BAR' => 24 }</tt>
90
- # * Result: <tt>'Foo' => { 'Bar' => 24 }</tt>
52
+ # they were originally set.
91
53
  #
92
54
  class HashWithIndifferentCaseInsensitiveAccess < ActiveSupport::HashWithIndifferentAccess
93
55
  def with_indifferent_case_insensitive_access
94
56
  self
95
57
  end
96
58
 
97
- def initialize(constructor = nil)
98
- @scimitar_hash_with_indifferent_case_insensitive_access_key_map = {}
99
- super
100
- end
101
-
102
- # It's vital that the attribute map is carried over when one of these
103
- # objects is duplicated. Duplication of this ivar state does *not* happen
104
- # when 'dup' is called on our superclass, so we have to do that manually.
105
- #
106
- def dup
107
- duplicate = super
108
- duplicate.instance_variable_set(
109
- '@scimitar_hash_with_indifferent_case_insensitive_access_key_map',
110
- @scimitar_hash_with_indifferent_case_insensitive_access_key_map
111
- )
112
-
113
- return duplicate
114
- end
115
-
116
- # Override the individual key writer.
117
- #
118
- def []=(key, value)
119
- string_key = scimitar_hash_with_indifferent_case_insensitive_access_string(key)
120
- indifferent_key = scimitar_hash_with_indifferent_case_insensitive_access_downcase(string_key)
121
- converted_value = convert_value(value, conversion: :assignment)
122
-
123
- # Note '||=', as there might have been a prior use of the "same" key in
124
- # a different case. The earliest one is preserved since the actual Hash
125
- # underneath all this is already using that variant of the key.
126
- #
127
- key_for_writing = (
128
- @scimitar_hash_with_indifferent_case_insensitive_access_key_map[indifferent_key] ||= string_key
129
- )
130
-
131
- regular_writer(key_for_writing, converted_value)
132
- end
133
-
134
- # Override #merge to express it in terms of #merge! (also overridden), so
135
- # that merged hashes can have their keys treated indifferently too.
136
- #
137
- def merge(*other_hashes, &block)
138
- dup.merge!(*other_hashes, &block)
139
- end
140
-
141
- # Modifies-self version of #merge, overriding Hash#merge!.
142
- #
143
- def merge!(*hashes_to_merge_to_self, &block)
144
- if block_given?
145
- hashes_to_merge_to_self.each do |hash_to_merge_to_self|
146
- hash_to_merge_to_self.each_pair do |key, value|
147
- value = block.call(key, self[key], value) if self.key?(key)
148
- self[key] = value
149
- end
150
- end
151
- else
152
- hashes_to_merge_to_self.each do |hash_to_merge_to_self|
153
- hash_to_merge_to_self.each_pair do |key, value|
154
- self[key] = value
155
- end
156
- end
157
- end
158
-
159
- self
160
- end
161
-
162
- # =======================================================================
163
- # PRIVATE INSTANCE METHODS
164
- # =======================================================================
165
- #
166
59
  private
167
60
 
168
61
  if Symbol.method_defined?(:name)
169
- def scimitar_hash_with_indifferent_case_insensitive_access_string(key)
170
- key.kind_of?(Symbol) ? key.name : key
62
+ def convert_key(key)
63
+ key.kind_of?(Symbol) ? key.name.downcase : key.downcase
171
64
  end
172
65
  else
173
- def scimitar_hash_with_indifferent_case_insensitive_access_string(key)
174
- key.kind_of?(Symbol) ? key.to_s : key
175
- end
176
- end
177
-
178
- def scimitar_hash_with_indifferent_case_insensitive_access_downcase(key)
179
- key.kind_of?(String) ? key.downcase : key
180
- end
181
-
182
- def convert_key(key)
183
- string_key = scimitar_hash_with_indifferent_case_insensitive_access_string(key)
184
- indifferent_key = scimitar_hash_with_indifferent_case_insensitive_access_downcase(string_key)
185
-
186
- @scimitar_hash_with_indifferent_case_insensitive_access_key_map[indifferent_key] || string_key
187
- end
188
-
189
- def convert_value(value, conversion: nil)
190
- if value.is_a?(Hash)
191
- if conversion == :to_hash
192
- value.to_hash
193
- else
194
- value.with_indifferent_case_insensitive_access
195
- end
196
- else
197
- super
66
+ def convert_key(key)
67
+ key.kind_of?(Symbol) ? key.to_s.downcase : key.downcase
198
68
  end
199
69
  end
200
70
 
201
71
  def update_with_single_argument(other_hash, block)
202
- if other_hash.is_a?(HashWithIndifferentCaseInsensitiveAccess)
72
+ if other_hash.is_a? HashWithIndifferentCaseInsensitiveAccess
203
73
  regular_update(other_hash, &block)
204
74
  else
205
75
  other_hash.to_hash.each_pair do |key, value|
206
76
  if block && key?(key)
207
- value = block.call(self.convert_key(key), self[key], value)
77
+ value = block.call(convert_key(key), self[key], value)
208
78
  end
209
- self.[]=(key, value)
79
+ regular_writer(convert_key(key), convert_value(value))
210
80
  end
211
81
  end
212
82
  end
@@ -3,11 +3,11 @@ module Scimitar
3
3
  # Gem version. If this changes, be sure to re-run "bundle install" or
4
4
  # "bundle update".
5
5
  #
6
- VERSION = '1.8.2'
6
+ VERSION = '2.0.0'
7
7
 
8
8
  # Date for VERSION. If this changes, be sure to re-run "bundle install"
9
9
  # or "bundle update".
10
10
  #
11
- DATE = '2024-03-27'
11
+ DATE = '2022-03-04'
12
12
 
13
13
  end
data/lib/scimitar.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  require 'scimitar/version'
2
2
  require 'scimitar/support/hash_with_indifferent_case_insensitive_access'
3
- require 'scimitar/support/utilities'
4
3
  require 'scimitar/engine'
5
4
 
6
5
  module Scimitar
7
6
  def self.service_provider_configuration=(custom_configuration)
8
- if @service_provider_configuration.nil? || ! custom_configuration.uses_defaults
9
- @service_provider_configuration = custom_configuration
10
- end
7
+ @service_provider_configuration = custom_configuration
11
8
  end
12
9
 
13
10
  def self.service_provider_configuration(location:)
@@ -17,9 +14,7 @@ module Scimitar
17
14
  end
18
15
 
19
16
  def self.engine_configuration=(custom_configuration)
20
- if @engine_configuration.nil? || ! custom_configuration.uses_defaults
21
- @engine_configuration = custom_configuration
22
- end
17
+ @engine_configuration = custom_configuration
23
18
  end
24
19
 
25
20
  def self.engine_configuration
@@ -1,4 +1,4 @@
1
- class MockGroupsController < Scimitar::ActiveRecordBackedResourcesController
1
+ class MockUsersController < Scimitar::ActiveRecordBackedResourcesController
2
2
 
3
3
  protected
4
4
 
@@ -58,7 +58,7 @@ class MockGroup < ActiveRecord::Base
58
58
 
59
59
  case type.downcase
60
60
  when 'user'
61
- MockUser.find_by_primary_key(id)
61
+ MockUser.find_by_id(id)
62
62
  when 'group'
63
63
  MockGroup.find_by_id(id)
64
64
  else
@@ -1,24 +1,18 @@
1
1
  class MockUser < ActiveRecord::Base
2
2
 
3
- self.primary_key = :primary_key
4
-
5
3
  # ===========================================================================
6
4
  # TEST ATTRIBUTES - see db/migrate/20210304014602_create_mock_users.rb etc.
7
5
  # ===========================================================================
8
6
 
9
7
  READWRITE_ATTRS = %w{
10
- primary_key
8
+ id
11
9
  scim_uid
12
10
  username
13
- password
14
11
  first_name
15
12
  last_name
16
13
  work_email_address
17
14
  home_email_address
18
15
  work_phone_number
19
- organization
20
- department
21
- mock_groups
22
16
  }
23
17
 
24
18
  has_and_belongs_to_many :mock_groups
@@ -44,10 +38,9 @@ class MockUser < ActiveRecord::Base
44
38
 
45
39
  def self.scim_attributes_map
46
40
  return {
47
- id: :primary_key,
41
+ id: :id,
48
42
  externalId: :scim_uid,
49
43
  userName: :username,
50
- password: :password,
51
44
  name: {
52
45
  givenName: :first_name,
53
46
  familyName: :last_name
@@ -89,23 +82,7 @@ class MockUser < ActiveRecord::Base
89
82
  }
90
83
  }
91
84
  ],
92
- active: :is_active,
93
-
94
- # Custom extension schema - see configuration in
95
- # "spec/apps/dummy/config/initializers/scimitar.rb".
96
- #
97
- organization: :organization,
98
- department: :department,
99
- userGroups: [
100
- {
101
- list: :mock_groups,
102
- find_with: ->(value) { MockGroup.find(value["value"]) },
103
- using: {
104
- value: :id,
105
- display: :display_name
106
- }
107
- }
108
- ]
85
+ active: :is_active
109
86
  }
110
87
  end
111
88
 
@@ -115,16 +92,11 @@ class MockUser < ActiveRecord::Base
115
92
 
116
93
  def self.scim_queryable_attributes
117
94
  return {
118
- 'id' => { column: :primary_key },
119
- 'externalId' => { column: :scim_uid },
120
- 'meta.lastModified' => { column: :updated_at },
121
- 'name.givenName' => { column: :first_name },
122
- 'name.familyName' => { column: :last_name },
123
- 'groups' => { column: MockGroup.arel_table[:id] },
124
- 'groups.value' => { column: MockGroup.arel_table[:id] },
125
- 'emails' => { columns: [ :work_email_address, :home_email_address ] },
126
- 'emails.value' => { columns: [ :work_email_address, :home_email_address ] },
127
- 'emails.type' => { ignore: true } # We can't filter on that; it'll just search all e-mails
95
+ 'name.givenName' => { column: :first_name },
96
+ 'name.familyName' => { column: :last_name },
97
+ 'emails' => { columns: [ :work_email_address, :home_email_address ] },
98
+ 'emails.value' => { columns: [ :work_email_address, :home_email_address ] },
99
+ 'emails.type' => { ignore: true } # We can't filter on that; it'll just search all e-mails
128
100
  }
129
101
  end
130
102
 
@@ -12,6 +12,7 @@ require 'scimitar'
12
12
 
13
13
  module Dummy
14
14
  class Application < Rails::Application
15
+ config.load_defaults 7.0
15
16
  end
16
17
  end
17
18
 
@@ -1,15 +1,38 @@
1
+ require 'active_support/core_ext/integer/time'
2
+
1
3
  Rails.application.configure do
2
4
  config.cache_classes = true
3
5
  config.eager_load = false
4
- config.serve_static_files = true
5
- config.static_cache_control = 'public, max-age=3600'
6
- config.consider_all_requests_local = true
7
6
 
8
- config.action_dispatch.show_exceptions = false
7
+ # Configure public file server for tests with Cache-Control for performance.
8
+ config.public_file_server.enabled = true
9
+ config.public_file_server.headers = {
10
+ 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
11
+ }
9
12
 
13
+ # Show full error reports and disable caching.
14
+ config.consider_all_requests_local = true
10
15
  config.action_controller.perform_caching = false
16
+ config.cache_store = :null_store
17
+
18
+ # Raise exceptions instead of rendering exception templates.
19
+ config.action_dispatch.show_exceptions = false
20
+
21
+ # Disable request forgery protection in test environment.
11
22
  config.action_controller.allow_forgery_protection = false
12
23
 
13
- config.active_support.test_order = :random
24
+ # Print deprecation notices to the stderr.
14
25
  config.active_support.deprecation = :stderr
26
+
27
+ # Raise exceptions for disallowed deprecations.
28
+ config.active_support.disallowed_deprecation = :raise
29
+
30
+ # Tell Active Support which deprecation messages to disallow.
31
+ config.active_support.disallowed_deprecation_warnings = []
32
+
33
+ # Raises error for missing translations.
34
+ config.i18n.raise_on_missing_translations = true
35
+
36
+ # Annotate rendered view with file names.
37
+ # config.action_view.annotate_rendered_view_with_filenames = true
15
38
  end
@@ -1,67 +1,16 @@
1
1
  # Test app configuration.
2
2
  #
3
- # Note that as a result of https://github.com/RIPAGlobal/scimitar/issues/48,
4
- # tests include a custom extension of the core User schema. A shortcoming of
5
- # some of the code from which Scimitar was originally built is that those
6
- # extensions are done with class-level ivars, so it is largely impossible (or
7
- # at least, impractical in tests) to avoid polluting the core class itself
8
- # with the extension.
9
- #
10
- # All related schema tests are written with this in mind.
11
- #
12
- # Further, https://github.com/RIPAGlobal/scimitar/pull/54 fixed warning
13
- # messages in a way that worked on Rails 6+ but, for V1 Scimitar, it would
14
- # break existing working setups that didn't use the +to_prepare+ wrapper. Their
15
- # application configuration would be written *first* but then *overwritten* by
16
- # the default +to_prepare+ block in Scimitar itself, since that runs later. The
17
- # file below does *not* use +to_prepare+ in order to test the workaround that
18
- # was produced; it should work on all Ruby versions as-is.
19
- #
20
- Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
21
-
22
- application_controller_mixin: Module.new do
23
- def self.included(base)
24
- base.class_eval do
25
- def test_hook; end
26
- before_action :test_hook
3
+ Rails.application.config.to_prepare do
4
+ Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
5
+
6
+ application_controller_mixin: Module.new do
7
+ def self.included(base)
8
+ base.class_eval do
9
+ def test_hook; end
10
+ before_action :test_hook
11
+ end
27
12
  end
28
13
  end
29
14
 
30
- def scim_schemas_url(options)
31
- super(test: 1, **options)
32
- end
33
-
34
- def scim_resource_type_url(options)
35
- super(test: 1, **options)
36
- end
37
- end
38
-
39
- })
40
-
41
- module ScimSchemaExtensions
42
- module User
43
- class Enterprise < Scimitar::Schema::Base
44
- def initialize(options = {})
45
- super(
46
- name: 'ExtendedUser',
47
- description: 'Enterprise extension for a User',
48
- id: self.class.id,
49
- scim_attributes: self.class.scim_attributes
50
- )
51
- end
52
-
53
- def self.id
54
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'
55
- end
56
-
57
- def self.scim_attributes
58
- [
59
- Scimitar::Schema::Attribute.new(name: 'organization', type: 'string'),
60
- Scimitar::Schema::Attribute.new(name: 'department', type: 'string')
61
- ]
62
- end
63
- end
64
- end
15
+ })
65
16
  end
66
-
67
- Scimitar::Resources::User.extend_schema ScimSchemaExtensions::User::Enterprise
@@ -6,38 +6,17 @@
6
6
  Rails.application.routes.draw do
7
7
  mount Scimitar::Engine, at: '/'
8
8
 
9
- get 'Users', to: 'mock_users#index'
10
- get 'Users/:id', to: 'mock_users#show'
11
- post 'Users', to: 'mock_users#create'
12
- put 'Users/:id', to: 'mock_users#replace'
13
- patch 'Users/:id', to: 'mock_users#update'
14
- delete 'Users/:id', to: 'mock_users#destroy'
9
+ get 'Users', to: 'mock_users#index'
10
+ get 'Users/:id', to: 'mock_users#show'
11
+ post 'Users', to: 'mock_users#create'
12
+ put 'Users/:id', to: 'mock_users#replace'
13
+ patch 'Users/:id', to: 'mock_users#update'
14
+ delete 'Users/:id', to: 'mock_users#destroy'
15
15
 
16
- get 'Groups', to: 'mock_groups#index'
17
- get 'Groups/:id', to: 'mock_groups#show'
18
- patch 'Groups/:id', to: 'mock_groups#update'
19
-
20
- # For testing blocks passed to ActiveRecordBackedResourcesController#create,
21
- # #update, #replace and #destroy.
16
+ # For testing blocks passed to ActiveRecordBackedResourcesController#destroy
22
17
  #
23
- post 'CustomCreateUsers', to: 'custom_create_mock_users#create'
24
- patch 'CustomUpdateUsers/:id', to: 'custom_update_mock_users#update'
25
- put 'CustomReplaceUsers/:id', to: 'custom_replace_mock_users#replace'
26
18
  delete 'CustomDestroyUsers/:id', to: 'custom_destroy_mock_users#destroy'
27
19
 
28
- # Needed because the auto-render of most of the above includes a 'url_for'
29
- # call for a 'show' action, so we must include routes (implemented in the
30
- # base class) for the "show" endpoint.
31
- #
32
- get 'CustomCreateUsers/:id', to: 'custom_create_mock_users#show'
33
- get 'CustomUpdateUsers/:id', to: 'custom_update_mock_users#show'
34
- get 'CustomReplaceUsers/:id', to: 'custom_replace_mock_users#show'
35
-
36
- # For testing blocks passed to ActiveRecordBackedResourcesController#save!
37
- #
38
- post 'CustomSaveUsers', to: 'custom_save_mock_users#create'
39
- get 'CustomSaveUsers/:id', to: 'custom_save_mock_users#show'
40
-
41
20
  # For testing environment inside Scimitar::ApplicationController subclasses.
42
21
  #
43
22
  get 'CustomRequestVerifiers', to: 'custom_request_verifiers#index'
@@ -1,24 +1,15 @@
1
1
  class CreateMockUsers < ActiveRecord::Migration[6.1]
2
2
  def change
3
- create_table :mock_users, id: :uuid, primary_key: :primary_key do |t|
4
- t.timestamps
3
+ create_table :mock_users do |t|
5
4
 
6
- # Support part of the core schema
7
- #
8
5
  t.text :scim_uid
9
6
  t.text :username
10
- t.text :password
11
7
  t.text :first_name
12
8
  t.text :last_name
13
9
  t.text :work_email_address
14
10
  t.text :home_email_address
15
11
  t.text :work_phone_number
16
12
 
17
- # Support the custom extension schema - see configuration in
18
- # "spec/apps/dummy/config/initializers/scimitar.rb".
19
- #
20
- t.text :organization
21
- t.text :department
22
13
  end
23
14
  end
24
15
  end