scimitar 1.8.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) 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 -14
  11. data/app/models/scimitar/resources/mixin.rb +13 -140
  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/version.rb +2 -2
  19. data/lib/scimitar.rb +2 -7
  20. data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
  21. data/spec/apps/dummy/app/models/mock_group.rb +1 -1
  22. data/spec/apps/dummy/app/models/mock_user.rb +8 -36
  23. data/spec/apps/dummy/config/application.rb +1 -0
  24. data/spec/apps/dummy/config/environments/test.rb +28 -5
  25. data/spec/apps/dummy/config/initializers/scimitar.rb +10 -61
  26. data/spec/apps/dummy/config/routes.rb +7 -28
  27. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -10
  28. data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
  29. data/spec/apps/dummy/db/schema.rb +4 -11
  30. data/spec/controllers/scimitar/application_controller_spec.rb +3 -126
  31. data/spec/controllers/scimitar/resource_types_controller_spec.rb +2 -2
  32. data/spec/controllers/scimitar/schemas_controller_spec.rb +2 -10
  33. data/spec/models/scimitar/complex_types/address_spec.rb +4 -3
  34. data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
  35. data/spec/models/scimitar/lists/query_parser_spec.rb +9 -76
  36. data/spec/models/scimitar/resources/base_spec.rb +70 -208
  37. data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
  38. data/spec/models/scimitar/resources/mixin_spec.rb +43 -790
  39. data/spec/models/scimitar/schema/attribute_spec.rb +3 -22
  40. data/spec/models/scimitar/schema/base_spec.rb +1 -1
  41. data/spec/models/scimitar/schema/user_spec.rb +0 -10
  42. data/spec/requests/active_record_backed_resources_controller_spec.rb +66 -709
  43. data/spec/requests/application_controller_spec.rb +3 -16
  44. data/spec/spec_helper.rb +0 -8
  45. metadata +14 -25
  46. data/LICENSE.txt +0 -21
  47. data/README.md +0 -710
  48. data/lib/scimitar/support/utilities.rb +0 -51
  49. data/spec/apps/dummy/app/controllers/custom_create_mock_users_controller.rb +0 -25
  50. data/spec/apps/dummy/app/controllers/custom_replace_mock_users_controller.rb +0 -25
  51. data/spec/apps/dummy/app/controllers/custom_save_mock_users_controller.rb +0 -24
  52. data/spec/apps/dummy/app/controllers/custom_update_mock_users_controller.rb +0 -25
@@ -220,8 +220,13 @@ module Scimitar
220
220
  # allow for different client searching "styles", given ambiguities in RFC
221
221
  # 7644 filter examples).
222
222
  #
223
- # Each value is a hash of queryable SCIM attribute options, described
224
- # below - for example:
223
+ # Each value is a Hash with Symbol keys ':column', naming just one simple
224
+ # column for a mapping; ':columns', with an Array of column names that you
225
+ # want to map using 'OR' for a single search on the corresponding SCIM
226
+ # attribute; or ':ignore' with value 'true', which means that a fitler on
227
+ # the matching attribute is ignored rather than resulting in an "invalid
228
+ # filter" exception - beware possibilities for surprised clients getting a
229
+ # broader result set than expected. Example:
225
230
  #
226
231
  # def self.scim_queryable_attributes
227
232
  # return {
@@ -229,27 +234,10 @@ module Scimitar
229
234
  # 'name.familyName' => { column: :last_name },
230
235
  # 'emails' => { columns: [ :work_email_address, :home_email_address ] },
231
236
  # 'emails.value' => { columns: [ :work_email_address, :home_email_address ] },
232
- # 'emails.type' => { ignore: true },
233
- # 'groups.value' => { column: Group.arel_table[:id] }
237
+ # 'emails.type' => { ignore: true }
234
238
  # }
235
239
  # end
236
240
  #
237
- # Column references can be either a Symbol representing a column within
238
- # the resource model table, or an <tt>Arel::Attribute</tt> instance via
239
- # e.g. <tt>MyModel.arel_table[:my_column]</tt>.
240
- #
241
- # === Queryable SCIM attribute options
242
- #
243
- # +:column+:: Just one simple column for a mapping.
244
- #
245
- # +:columns+:: An Array of columns that you want to map using 'OR' for a
246
- # single search of the corresponding entity.
247
- #
248
- # +:ignore+:: When set to +true+, the matching attribute is ignored rather
249
- # than resulting in an "invalid filter" exception. Beware
250
- # possibilities for surprised clients getting a broader result
251
- # set than expected, since a constraint may have been ignored.
252
- #
253
241
  # Filtering is currently limited and searching within e.g. arrays of data
254
242
  # is not supported; only simple top-level keys can be mapped.
255
243
  #
@@ -418,11 +406,8 @@ module Scimitar
418
406
  def from_scim_patch!(patch_hash:)
419
407
  frozen_ci_patch_hash = patch_hash.with_indifferent_case_insensitive_access().freeze()
420
408
  ci_scim_hash = self.to_scim(location: '(unused)').as_json().with_indifferent_case_insensitive_access()
421
- operations = frozen_ci_patch_hash['operations']
422
-
423
- raise Scimitar::InvalidSyntaxError.new("Missing PATCH \"operations\"") unless operations
424
409
 
425
- operations.each do |operation|
410
+ frozen_ci_patch_hash['operations'].each do |operation|
426
411
  nature = operation['op' ]&.downcase
427
412
  path_str = operation['path' ]
428
413
  value = operation['value']
@@ -458,30 +443,9 @@ module Scimitar
458
443
  ci_scim_hash = { 'root' => ci_scim_hash }.with_indifferent_case_insensitive_access()
459
444
  end
460
445
 
461
- # Handle extension schema. Contributed by @bettysteger and
462
- # @MorrisFreeman via:
463
- #
464
- # https://github.com/RIPAGlobal/scimitar/issues/48
465
- # https://github.com/RIPAGlobal/scimitar/pull/49
466
- #
467
- # Note the ":" separating the schema ID (URN) from the attribute.
468
- # The nature of JSON rendering / other payloads might lead you to
469
- # expect a "." as with any complex types, but that's not the case;
470
- # see https://tools.ietf.org/html/rfc7644#section-3.10, or
471
- # https://tools.ietf.org/html/rfc7644#section-3.5.2 of which in
472
- # particular, https://tools.ietf.org/html/rfc7644#page-35.
473
- #
474
- paths = []
475
- self.class.scim_resource_type.extended_schemas.each do |schema|
476
- path_str.downcase.split(schema.id.downcase + ':').drop(1).each do |path|
477
- paths += [schema.id] + path.split('.')
478
- end
479
- end
480
- paths = path_str.split('.') if paths.empty?
481
-
482
446
  self.from_patch_backend!(
483
447
  nature: nature,
484
- path: paths,
448
+ path: (path_str || '').split('.'),
485
449
  value: value,
486
450
  altering_hash: ci_scim_hash
487
451
  )
@@ -652,19 +616,7 @@ module Scimitar
652
616
  attrs_map_or_leaf_value.each do | scim_attribute, sub_attrs_map_or_leaf_value |
653
617
  next if scim_attribute&.to_s&.downcase == 'id' && path.empty?
654
618
 
655
- # Handle extension schema. Contributed by @bettysteger and
656
- # @MorrisFreeman via:
657
- #
658
- # https://github.com/RIPAGlobal/scimitar/issues/48
659
- # https://github.com/RIPAGlobal/scimitar/pull/49
660
- #
661
- attribute_tree = []
662
- resource_class.extended_schemas.each do |schema|
663
- attribute_tree << schema.id and break if schema.scim_attributes.any? { |attribute| attribute.name == scim_attribute.to_s }
664
- end
665
- attribute_tree << scim_attribute.to_s
666
-
667
- sub_scim_hash_or_leaf_value = scim_hash_or_leaf_value&.dig(*attribute_tree)
619
+ sub_scim_hash_or_leaf_value = scim_hash_or_leaf_value&.dig(scim_attribute.to_s)
668
620
 
669
621
  self.from_scim_backend!(
670
622
  attrs_map_or_leaf_value: sub_attrs_map_or_leaf_value,
@@ -949,89 +901,10 @@ module Scimitar
949
901
  else
950
902
  altering_hash[path_component] = value
951
903
  end
952
-
953
904
  when 'replace'
954
- if path_component == 'root'
955
- dot_pathed_value = value.inject({}) do |hash, (k, v)|
956
- hash.deep_merge!(::Scimitar::Support::Utilities.dot_path(k.split('.'), v))
957
- end
958
- altering_hash[path_component].deep_merge!(dot_pathed_value)
959
- else
960
- altering_hash[path_component] = value
961
- end
962
-
963
- # The array check handles payloads seen from e.g. Microsoft for
964
- # remove-user-from-group, where contrary to examples in the RFC
965
- # which would imply "payload removes all users", there is the
966
- # clear intent to remove just one.
967
- #
968
- # https://tools.ietf.org/html/rfc7644#section-3.5.2.2
969
- # https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#update-group-remove-members
970
- #
971
- # Since remove-all in the face of remove-one is destructive, we
972
- # do a special check here to see if there's an array value for
973
- # the array path that the payload yielded. If so, we can match
974
- # each value against array items and remove just those items.
975
- #
976
- # There is an additional special case to handle a bad example
977
- # from Salesforce:
978
- #
979
- # https://help.salesforce.com/s/articleView?id=sf.identity_scim_manage_groups.htm&type=5
980
- #
905
+ altering_hash[path_component] = value
981
906
  when 'remove'
982
- if altering_hash[path_component].is_a?(Array) && value.present?
983
-
984
- # Handle bad Salesforce example. That might be simply a
985
- # documentation error, but just in case...
986
- #
987
- value = value.values.first if (
988
- path_component&.downcase == 'members' &&
989
- value.is_a?(Hash) &&
990
- value.keys.size == 1 &&
991
- value.keys.first&.downcase == 'members'
992
- )
993
-
994
- # The Microsoft example provides an array of values, but we
995
- # may as well cope with a value specified 'flat'. Promote
996
- # such a thing to an Array to simplify the following code.
997
- #
998
- value = [value] unless value.is_a?(Array)
999
-
1000
- # For each value item, delete matching array entries. The
1001
- # concept of "matching" is:
1002
- #
1003
- # * For simple non-Hash values (if possible) just delete on
1004
- # an exact match
1005
- #
1006
- # * For Hash-based values, only delete if all 'patch' keys
1007
- # are present in the resource and all values thus match.
1008
- #
1009
- # Special case to ignore '$ref' from the Microsoft payload.
1010
- #
1011
- # Note coercion to strings to account for SCIM vs the usual
1012
- # tricky case of underlying implementations with (say)
1013
- # integer primary keys, which all end up as strings anyway.
1014
- #
1015
- value.each do | value_item |
1016
- altering_hash[path_component].delete_if do | item |
1017
- if item.is_a?(Hash) && value_item.is_a?(Hash)
1018
- matched_all = true
1019
- value_item.each do | value_key, value_value |
1020
- next if value_key == '$ref'
1021
- if ! item.key?(value_key) || item[value_key]&.to_s != value_value&.to_s
1022
- matched_all = false
1023
- end
1024
- end
1025
- matched_all
1026
- else
1027
- item&.to_s == value_item&.to_s
1028
- end
1029
- end
1030
- end
1031
- else
1032
- altering_hash.delete(path_component)
1033
- end
1034
-
907
+ altering_hash.delete(path_component)
1035
908
  end
1036
909
  end
1037
910
  end
@@ -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
@@ -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.1'
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-01-16'
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'