scimitar 1.5.2 → 2.0.0

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scimitar/active_record_backed_resources_controller.rb +6 -27
  3. data/app/controllers/scimitar/application_controller.rb +9 -29
  4. data/app/models/scimitar/engine_configuration.rb +3 -7
  5. data/app/models/scimitar/error_response.rb +0 -12
  6. data/app/models/scimitar/errors.rb +1 -1
  7. data/app/models/scimitar/lists/query_parser.rb +4 -14
  8. data/app/models/scimitar/resources/base.rb +1 -1
  9. data/app/models/scimitar/resources/mixin.rb +4 -113
  10. data/app/models/scimitar/schema/address.rb +0 -1
  11. data/app/models/scimitar/schema/attribute.rb +1 -1
  12. data/app/models/scimitar/schema/base.rb +3 -1
  13. data/app/models/scimitar/schema/vdtp.rb +1 -1
  14. data/config/initializers/scimitar.rb +70 -86
  15. data/lib/scimitar/version.rb +2 -2
  16. data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
  17. data/spec/apps/dummy/app/models/mock_group.rb +1 -1
  18. data/spec/apps/dummy/app/models/mock_user.rb +8 -19
  19. data/spec/apps/dummy/config/application.rb +1 -0
  20. data/spec/apps/dummy/config/environments/test.rb +28 -5
  21. data/spec/apps/dummy/config/initializers/scimitar.rb +9 -44
  22. data/spec/apps/dummy/config/routes.rb +0 -4
  23. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -9
  24. data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
  25. data/spec/apps/dummy/db/schema.rb +4 -10
  26. data/spec/controllers/scimitar/application_controller_spec.rb +1 -70
  27. data/spec/controllers/scimitar/schemas_controller_spec.rb +2 -2
  28. data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
  29. data/spec/models/scimitar/lists/query_parser_spec.rb +9 -9
  30. data/spec/models/scimitar/resources/base_spec.rb +66 -161
  31. data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
  32. data/spec/models/scimitar/resources/mixin_spec.rb +43 -757
  33. data/spec/models/scimitar/resources/user_spec.rb +4 -4
  34. data/spec/models/scimitar/schema/attribute_spec.rb +3 -0
  35. data/spec/models/scimitar/schema/base_spec.rb +1 -1
  36. data/spec/models/scimitar/schema/user_spec.rb +0 -10
  37. data/spec/requests/active_record_backed_resources_controller_spec.rb +40 -309
  38. data/spec/requests/application_controller_spec.rb +3 -17
  39. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b55b1f0a0a700b57690cb05fc02241cf47f60a4ad8c92946a32366c90ee56d8c
4
- data.tar.gz: a7143dcd7d1381250e66529c70288659a2018fb26fc16639c14ba796acc805d5
3
+ metadata.gz: 95a2166cc921a400959f9d8d4398f6bf8ecb772f8d7a0a0a73950892e85d808a
4
+ data.tar.gz: cdf5aab3812f10f69c96304e738a150f4208850267527b66d36eeb99548d7b1f
5
5
  SHA512:
6
- metadata.gz: fb740b528770a918fc3237cabdc953affcde23fa7787cc9e9383a6d71b104e2d6325c2829545d367983a3bb64435179a0523b6d785d8e6d3eb7b2bfdb6c82748
7
- data.tar.gz: 9f73bcafefbd7de57f258d1dc1c18e020b8dd7bca6330f7b288e308168daf7cb698051a9f2d4eaee9717139978df4e7a9fe854ba269ab94b2b46f1030d2ab9db
6
+ metadata.gz: f0925517599b107e44fd93db9be142aebe608892c2c5069c50d22b353c51238290710474b062a002fdb010be3d783c4dea3b314f72f47b4aca3c2385a8fc1377
7
+ data.tar.gz: eef6eebfc64bb2d4adabfca110f26e3a6c9e227f47387da6fb384925899ddf0ae260cf68176f24040a6bb356cf34f6576c920bd44264d4a1fee415aeadc237e6
@@ -21,8 +21,6 @@ module Scimitar
21
21
 
22
22
  rescue_from ActiveRecord::RecordNotFound, with: :handle_resource_not_found # See Scimitar::ApplicationController
23
23
 
24
- before_action :obtain_id_column_name_from_attribute_map
25
-
26
24
  # GET (list)
27
25
  #
28
26
  def index
@@ -39,13 +37,12 @@ module Scimitar
39
37
  pagination_info = scim_pagination_info(query.count())
40
38
 
41
39
  page_of_results = query
42
- .order(@id_column => :asc)
43
40
  .offset(pagination_info.offset)
44
41
  .limit(pagination_info.limit)
45
42
  .to_a()
46
43
 
47
44
  super(pagination_info, page_of_results) do | record |
48
- record_to_scim(record)
45
+ record.to_scim(location: url_for(action: :show, id: record.id))
49
46
  end
50
47
  end
51
48
 
@@ -54,7 +51,7 @@ module Scimitar
54
51
  def show
55
52
  super do |record_id|
56
53
  record = self.find_record(record_id)
57
- record_to_scim(record)
54
+ record.to_scim(location: url_for(action: :show, id: record_id))
58
55
  end
59
56
  end
60
57
 
@@ -66,7 +63,7 @@ module Scimitar
66
63
  record = self.storage_class().new
67
64
  record.from_scim!(scim_hash: scim_resource.as_json())
68
65
  self.save!(record)
69
- record_to_scim(record)
66
+ record.to_scim(location: url_for(action: :show, id: record.id))
70
67
  end
71
68
  end
72
69
  end
@@ -79,7 +76,7 @@ module Scimitar
79
76
  record = self.find_record(record_id)
80
77
  record.from_scim!(scim_hash: scim_resource.as_json())
81
78
  self.save!(record)
82
- record_to_scim(record)
79
+ record.to_scim(location: url_for(action: :show, id: record.id))
83
80
  end
84
81
  end
85
82
  end
@@ -92,7 +89,7 @@ module Scimitar
92
89
  record = self.find_record(record_id)
93
90
  record.from_scim_patch!(patch_hash: patch_hash)
94
91
  self.save!(record)
95
- record_to_scim(record)
92
+ record.to_scim(location: url_for(action: :show, id: record.id))
96
93
  end
97
94
  end
98
95
  end
@@ -140,14 +137,7 @@ module Scimitar
140
137
  # +record_id+:: Record ID (SCIM schema 'id' value - "our" ID).
141
138
  #
142
139
  def find_record(record_id)
143
- self.storage_scope().find_by!(@id_column => record_id)
144
- end
145
-
146
- # DRY up controller actions - pass a record; returns the SCIM
147
- # representation, with a "show" location specified via #url_for.
148
- #
149
- def record_to_scim(record)
150
- record.to_scim(location: url_for(action: :show, id: record.send(@id_column)))
140
+ self.storage_scope().find(record_id)
151
141
  end
152
142
 
153
143
  # Save a record, dealing with validation exceptions by raising SCIM
@@ -186,16 +176,5 @@ module Scimitar
186
176
  end
187
177
  end
188
178
 
189
- # Called via +before_action+ - stores in @id_column the name of whatever
190
- # model column is used to store the record ID, via
191
- # Scimitar::Resources::Mixin::scim_attributes_map.
192
- #
193
- # Default is <tt>:id</tt>.
194
- #
195
- def obtain_id_column_name_from_attribute_map
196
- attrs = storage_class().scim_attributes_map() || {}
197
- @id_column = attrs[:id] || :id
198
- end
199
-
200
179
  end
201
180
  end
@@ -25,12 +25,10 @@ module Scimitar
25
25
  #
26
26
  # ...to "globally" invoke this handler if you wish.
27
27
  #
28
+ # +_exception+:: Exception instance (currently unused).
28
29
  #
29
- # +exception+:: Exception instance, used for a configured error reporter
30
- # via #handle_scim_error (if present).
31
- #
32
- def handle_resource_not_found(exception)
33
- handle_scim_error(NotFoundError.new(params[:id]), exception)
30
+ def handle_resource_not_found(_exception)
31
+ handle_scim_error(NotFoundError.new(params[:id]))
34
32
  end
35
33
 
36
34
  # This base controller uses:
@@ -40,22 +38,9 @@ module Scimitar
40
38
  # ...to "globally" invoke this handler for all Scimitar errors (including
41
39
  # subclasses).
42
40
  #
43
- # Mandatory parameters are:
44
- #
45
41
  # +error_response+:: Scimitar::ErrorResponse (or subclass) instance.
46
42
  #
47
- # Optional parameters are:
48
- #
49
- # *exception+:: If a Ruby exception was the reason this method is being
50
- # called, pass it here. Any configured exception reporting
51
- # mechanism will be invokved with the given parameter.
52
- # Otherwise, the +error_response+ value is reported.
53
- #
54
- def handle_scim_error(error_response, exception = error_response)
55
- unless Scimitar.engine_configuration.exception_reporter.nil?
56
- Scimitar.engine_configuration.exception_reporter.call(exception)
57
- end
58
-
43
+ def handle_scim_error(error_response)
59
44
  render json: error_response, status: error_response.status
60
45
  end
61
46
 
@@ -70,7 +55,7 @@ module Scimitar
70
55
  # +exception+:: Exception instance.
71
56
  #
72
57
  def handle_bad_json_error(exception)
73
- handle_scim_error(ErrorResponse.new(status: 400, detail: "Invalid JSON - #{exception.message}"), exception)
58
+ handle_scim_error(ErrorResponse.new(status: 400, detail: "Invalid JSON - #{exception.message}"))
74
59
  end
75
60
 
76
61
  # This base controller uses:
@@ -83,7 +68,7 @@ module Scimitar
83
68
  #
84
69
  def handle_unexpected_error(exception)
85
70
  Rails.logger.error("#{exception.message}\n#{exception.backtrace}")
86
- handle_scim_error(ErrorResponse.new(status: 500, detail: exception.message), exception)
71
+ handle_scim_error(ErrorResponse.new(status: 500, detail: exception.message))
87
72
  end
88
73
 
89
74
  # =========================================================================
@@ -97,17 +82,12 @@ module Scimitar
97
82
  # request and subclass processing.
98
83
  #
99
84
  def require_scim
100
- scim_mime_type = Mime::Type.lookup_by_extension(:scim).to_s
101
-
102
- if request.media_type.nil? || request.media_type.empty?
103
- request.format = :scim
104
- request.headers['CONTENT_TYPE'] = scim_mime_type
105
- elsif request.media_type.downcase == scim_mime_type
85
+ if request.content_type&.downcase == Mime::Type.lookup_by_extension(:scim).to_s
106
86
  request.format = :scim
107
87
  elsif request.format == :scim
108
- request.headers['CONTENT_TYPE'] = scim_mime_type
88
+ request.headers['CONTENT_TYPE'] = Mime::Type.lookup_by_extension(:scim).to_s
109
89
  else
110
- handle_scim_error(ErrorResponse.new(status: 406, detail: "Only #{scim_mime_type} type is accepted."))
90
+ handle_scim_error(ErrorResponse.new(status: 406, detail: "Only #{Mime::Type.lookup_by_extension(:scim)} type is accepted."))
111
91
  end
112
92
  end
113
93
 
@@ -9,17 +9,13 @@ module Scimitar
9
9
 
10
10
  attr_accessor :basic_authenticator,
11
11
  :token_authenticator,
12
- :application_controller_mixin,
13
- :exception_reporter,
14
- :optional_value_fields_required
12
+ :application_controller_mixin
15
13
 
16
14
  def initialize(attributes = {})
17
15
 
18
- # Set defaults that may be overridden by the initializer.
16
+ # No defaults yet - reserved for future use.
19
17
  #
20
- defaults = {
21
- optional_value_fields_required: true
22
- }
18
+ defaults = {}
23
19
 
24
20
  super(defaults.merge(attributes))
25
21
  end
@@ -16,17 +16,5 @@ module Scimitar
16
16
  data['scimType'] = scimType if scimType
17
17
  data
18
18
  end
19
-
20
- # Originally Scimitar used attribute "detail" for exception text; it was
21
- # only for JSON responses at the time, but in hindsight was a bad choice.
22
- # It should have been "message" given inheritance from StandardError, which
23
- # then works properly with e.g. error reporting services.
24
- #
25
- # The "detail" attribute is still present, for backwards compatibility with
26
- # any client code that might be using this class.
27
- #
28
- def message
29
- self.detail
30
- end
31
19
  end
32
20
  end
@@ -1,6 +1,6 @@
1
1
  module Scimitar
2
2
  module Errors
3
- def add_errors_from_hash(errors_hash, prefix: nil)
3
+ def add_errors_from_hash(errors_hash:, prefix: nil)
4
4
  errors_hash.each_pair do |key, value|
5
5
  new_key = prefix.nil? ? key : "#{prefix}.#{key}".to_sym
6
6
  if value.is_a?(Array)
@@ -78,7 +78,7 @@ module Scimitar
78
78
  # method's return value here.
79
79
  #
80
80
  def initialize(attribute_map)
81
- @attribute_map = attribute_map.with_indifferent_case_insensitive_access()
81
+ @attribute_map = attribute_map
82
82
  end
83
83
 
84
84
  # Parse SCIM filter query into RPN stack
@@ -605,16 +605,6 @@ module Scimitar
605
605
 
606
606
  raise Scimitar::FilterError unless all_supported
607
607
 
608
- unless case_sensitive
609
- lc_scim_attribute = scim_attribute.downcase()
610
-
611
- case_sensitive = (
612
- lc_scim_attribute == 'id' ||
613
- lc_scim_attribute == 'externalid' ||
614
- lc_scim_attribute.start_with?('meta.')
615
- )
616
- end
617
-
618
608
  column_names.each.with_index do | column_name, index |
619
609
  arel_column = arel_table[column_name]
620
610
  arel_operation = case scim_operator
@@ -643,7 +633,7 @@ module Scimitar
643
633
  when 'pr'
644
634
  arel_table.grouping(arel_column.not_eq_all(['', nil]))
645
635
  else
646
- raise Scimitar::FilterError.new("Unsupported operator: '#{scim_operator}'")
636
+ raise Scimitar::FilterError
647
637
  end
648
638
 
649
639
  if index == 0
@@ -666,10 +656,10 @@ module Scimitar
666
656
  # +scim_attribute+:: SCIM attribute from a filter string.
667
657
  #
668
658
  def activerecord_columns(scim_attribute)
669
- raise Scimitar::FilterError.new("No scim_attribute provided") if scim_attribute.blank?
659
+ raise Scimitar::FilterError if scim_attribute.blank?
670
660
 
671
661
  mapped_attribute = self.attribute_map()[scim_attribute]
672
- raise Scimitar::FilterError.new("Unable to find domain attribute from SCIM attribute: '#{scim_attribute}'") if mapped_attribute.blank?
662
+ raise Scimitar::FilterError if mapped_attribute.blank?
673
663
 
674
664
  if mapped_attribute[:ignore]
675
665
  return []
@@ -138,7 +138,7 @@ module Scimitar
138
138
  end
139
139
 
140
140
  def as_json(options = {})
141
- self.meta = Meta.new unless self.meta && self.meta.is_a?(Meta)
141
+ self.meta = Meta.new unless self.meta
142
142
  meta.resourceType = self.class.resource_type_id
143
143
  original_hash = super(options).except('errors')
144
144
  original_hash.merge!('schemas' => self.class.schemas.map(&:id))
@@ -443,30 +443,9 @@ module Scimitar
443
443
  ci_scim_hash = { 'root' => ci_scim_hash }.with_indifferent_case_insensitive_access()
444
444
  end
445
445
 
446
- # Handle extension schema. Contributed by @bettysteger and
447
- # @MorrisFreeman via:
448
- #
449
- # https://github.com/RIPAGlobal/scimitar/issues/48
450
- # https://github.com/RIPAGlobal/scimitar/pull/49
451
- #
452
- # Note the ":" separating the schema ID (URN) from the attribute.
453
- # The nature of JSON rendering / other payloads might lead you to
454
- # expect a "." as with any complex types, but that's not the case;
455
- # see https://tools.ietf.org/html/rfc7644#section-3.10, or
456
- # https://tools.ietf.org/html/rfc7644#section-3.5.2 of which in
457
- # particular, https://tools.ietf.org/html/rfc7644#page-35.
458
- #
459
- paths = []
460
- self.class.scim_resource_type.extended_schemas.each do |schema|
461
- path_str.downcase.split(schema.id.downcase + ':').drop(1).each do |path|
462
- paths += [schema.id] + path.split('.')
463
- end
464
- end
465
- paths = path_str.split('.') if paths.empty?
466
-
467
446
  self.from_patch_backend!(
468
447
  nature: nature,
469
- path: paths,
448
+ path: (path_str || '').split('.'),
470
449
  value: value,
471
450
  altering_hash: ci_scim_hash
472
451
  )
@@ -637,19 +616,7 @@ module Scimitar
637
616
  attrs_map_or_leaf_value.each do | scim_attribute, sub_attrs_map_or_leaf_value |
638
617
  next if scim_attribute&.to_s&.downcase == 'id' && path.empty?
639
618
 
640
- # Handle extension schema. Contributed by @bettysteger and
641
- # @MorrisFreeman via:
642
- #
643
- # https://github.com/RIPAGlobal/scimitar/issues/48
644
- # https://github.com/RIPAGlobal/scimitar/pull/49
645
- #
646
- attribute_tree = []
647
- resource_class.extended_schemas.each do |schema|
648
- attribute_tree << schema.id and break if schema.scim_attributes.any? { |attribute| attribute.name == scim_attribute.to_s }
649
- end
650
- attribute_tree << scim_attribute.to_s
651
-
652
- 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)
653
620
 
654
621
  self.from_scim_backend!(
655
622
  attrs_map_or_leaf_value: sub_attrs_map_or_leaf_value,
@@ -934,86 +901,10 @@ module Scimitar
934
901
  else
935
902
  altering_hash[path_component] = value
936
903
  end
937
-
938
904
  when 'replace'
939
- if path_component == 'root'
940
- altering_hash[path_component].merge!(value)
941
- else
942
- altering_hash[path_component] = value
943
- end
944
-
945
- # The array check handles payloads seen from e.g. Microsoft for
946
- # remove-user-from-group, where contrary to examples in the RFC
947
- # which would imply "payload removes all users", there is the
948
- # clear intent to remove just one.
949
- #
950
- # https://tools.ietf.org/html/rfc7644#section-3.5.2.2
951
- # https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#update-group-remove-members
952
- #
953
- # Since remove-all in the face of remove-one is destructive, we
954
- # do a special check here to see if there's an array value for
955
- # the array path that the payload yielded. If so, we can match
956
- # each value against array items and remove just those items.
957
- #
958
- # There is an additional special case to handle a bad example
959
- # from Salesforce:
960
- #
961
- # https://help.salesforce.com/s/articleView?id=sf.identity_scim_manage_groups.htm&type=5
962
- #
905
+ altering_hash[path_component] = value
963
906
  when 'remove'
964
- if altering_hash[path_component].is_a?(Array) && value.present?
965
-
966
- # Handle bad Salesforce example. That might be simply a
967
- # documentation error, but just in case...
968
- #
969
- value = value.values.first if (
970
- path_component&.downcase == 'members' &&
971
- value.is_a?(Hash) &&
972
- value.keys.size == 1 &&
973
- value.keys.first&.downcase == 'members'
974
- )
975
-
976
- # The Microsoft example provides an array of values, but we
977
- # may as well cope with a value specified 'flat'. Promote
978
- # such a thing to an Array to simplify the following code.
979
- #
980
- value = [value] unless value.is_a?(Array)
981
-
982
- # For each value item, delete matching array entries. The
983
- # concept of "matching" is:
984
- #
985
- # * For simple non-Hash values (if possible) just delete on
986
- # an exact match
987
- #
988
- # * For Hash-based values, only delete if all 'patch' keys
989
- # are present in the resource and all values thus match.
990
- #
991
- # Special case to ignore '$ref' from the Microsoft payload.
992
- #
993
- # Note coercion to strings to account for SCIM vs the usual
994
- # tricky case of underlying implementations with (say)
995
- # integer primary keys, which all end up as strings anyway.
996
- #
997
- value.each do | value_item |
998
- altering_hash[path_component].delete_if do | item |
999
- if item.is_a?(Hash) && value_item.is_a?(Hash)
1000
- matched_all = true
1001
- value_item.each do | value_key, value_value |
1002
- next if value_key == '$ref'
1003
- if ! item.key?(value_key) || item[value_key]&.to_s != value_value&.to_s
1004
- matched_all = false
1005
- end
1006
- end
1007
- matched_all
1008
- else
1009
- item&.to_s == value_item&.to_s
1010
- end
1011
- end
1012
- end
1013
- else
1014
- altering_hash.delete(path_component)
1015
- end
1016
-
907
+ altering_hash.delete(path_component)
1017
908
  end
1018
909
  end
1019
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'),
@@ -88,7 +88,7 @@ module Scimitar
88
88
  end
89
89
  value.class.schema.valid?(value)
90
90
  return true if value.errors.empty?
91
- add_errors_from_hash(value.errors.to_hash, prefix: self.name)
91
+ add_errors_from_hash(errors_hash: value.errors.to_hash, prefix: self.name)
92
92
  false
93
93
  end
94
94
 
@@ -26,7 +26,9 @@ module Scimitar
26
26
  #
27
27
  def self.valid?(resource)
28
28
  cloned_scim_attributes.each do |scim_attribute|
29
- resource.add_errors_from_hash(scim_attribute.errors.to_hash) unless scim_attribute.valid?(resource.send(scim_attribute.name))
29
+ unless scim_attribute.valid?(resource.send(scim_attribute.name))
30
+ resource.add_errors_from_hash(errors_hash: scim_attribute.errors.to_hash)
31
+ end
30
32
  end
31
33
  end
32
34
 
@@ -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'),
@@ -2,101 +2,85 @@
2
2
  #
3
3
  # For supporting information and rationale, please see README.md.
4
4
 
5
- # =============================================================================
6
- # SERVICE PROVIDER CONFIGURATION
7
- # =============================================================================
8
- #
9
- # This is a Ruby abstraction over a SCIM entity that declares the capabilities
10
- # supported by a particular implementation.
11
- #
12
- # Typically this is used to declare parts of the standard unsupported, if you
13
- # don't need them and don't want to provide subclass support.
14
- #
15
- Scimitar.service_provider_configuration = Scimitar::ServiceProviderConfiguration.new({
5
+ Rails.application.config.to_prepare do # (required for >= Rails 7 / Zeitwerk)
16
6
 
17
- # See https://tools.ietf.org/html/rfc7643#section-8.5 for properties.
7
+ # ===========================================================================
8
+ # SERVICE PROVIDER CONFIGURATION
9
+ # ===========================================================================
18
10
  #
19
- # See Gem source file 'app/models/scimitar/service_provider_configuration.rb'
20
- # for defaults. Define Hash keys here that override defaults; e.g. to declare
21
- # that filters are not supported so that calling clients shouldn't use them:
11
+ # This is a Ruby abstraction over a SCIM entity that declares the
12
+ # capabilities supported by a particular implementation.
22
13
  #
23
- # filter: Scimitar::Supported.unsupported
14
+ # Typically this is used to declare parts of the standard unsupported, if you
15
+ # don't need them and don't want to provide subclass support.
16
+ #
17
+ Scimitar.service_provider_configuration = Scimitar::ServiceProviderConfiguration.new({
24
18
 
25
- })
19
+ # See https://tools.ietf.org/html/rfc7643#section-8.5 for properties.
20
+ #
21
+ # See Gem file 'app/models/scimitar/service_provider_configuration.rb'
22
+ # for defaults. Define Hash keys here that override defaults; e.g. to
23
+ # declare that filters are not supported so that calling clients shouldn't
24
+ # use them:
25
+ #
26
+ # filter: Scimitar::Supported.unsupported
26
27
 
27
- # =============================================================================
28
- # ENGINE CONFIGURATION
29
- # =============================================================================
30
- #
31
- # This is where you provide callbacks for things like authorisation or mixins
32
- # that get included into all Scimitar-derived controllers (for things like
33
- # before-actions that apply to all Scimitar controller-based routes).
34
- #
35
- Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
28
+ })
36
29
 
37
- # If you have filters you want to run for any Scimitar action/route, you can
38
- # define them here. For example, you might use a before-action to set up some
39
- # multi-tenancy related state, or skip Rails CSRF token verification/
40
- #
41
- # For example:
42
- #
43
- # application_controller_mixin: Module.new do
44
- # def self.included(base)
45
- # base.class_eval do
30
+ # ===========================================================================
31
+ # ENGINE CONFIGURATION
32
+ # ===========================================================================
46
33
  #
47
- # # Anything here is written just as you'd write it at the top of
48
- # # one of your controller classes, but it gets included in all
49
- # # Scimitar classes too.
34
+ # This is where you provide callbacks for things like authorisation or mixins
35
+ # that get included into all Scimitar-derived controllers (for things like
36
+ # before-actions that apply to all Scimitar controller-based routes).
50
37
  #
51
- # skip_before_action :verify_authenticity_token
52
- # prepend_before_action :setup_some_kind_of_multi_tenancy_data
53
- # end
54
- # end
55
- # end, # ...other configuration entries might follow...
38
+ Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
56
39
 
57
- # If you want to support username/password authentication:
58
- #
59
- # basic_authenticator: Proc.new do | username, password |
60
- # # Check username/password and return 'true' if valid, else 'false'.
61
- # end, # ...other configuration entries might follow...
62
- #
63
- # The 'username' and 'password' parameters come from Rails:
64
- #
65
- # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html
66
- # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html#method-i-authenticate_with_http_basic
40
+ # If you have filters you want to run for any Scimitar action/route, you
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:
44
+ #
45
+ # application_controller_mixin: Module.new do
46
+ # def self.included(base)
47
+ # base.class_eval do
48
+ #
49
+ # # Anything here is written just as you'd write it at the top of
50
+ # # one of your controller classes, but it gets included in all
51
+ # # Scimitar classes too.
52
+ #
53
+ # skip_before_action :verify_authenticity_token
54
+ # prepend_before_action :setup_some_kind_of_multi_tenancy_data
55
+ # end
56
+ # end
57
+ # end, # ...other configuration entries might follow...
67
58
 
68
- # If you want to support HTTP bearer token (OAuth-style) authentication:
69
- #
70
- # token_authenticator: Proc.new do | token, options |
71
- # # Check token and return 'true' if valid, else 'false'.
72
- # end, # ...other configuration entries might follow...
73
- #
74
- # The 'token' and 'options' parameters come from Rails:
75
- #
76
- # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
77
- # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token/ControllerMethods.html#method-i-authenticate_with_http_token
78
- #
79
- # Note that both basic and token authentication can be declared, with the
80
- # parameters in the inbound HTTP request determining which is invoked.
59
+ # If you want to support username/password authentication:
60
+ #
61
+ # basic_authenticator: Proc.new do | username, password |
62
+ # # Check username/password and return 'true' if valid, else 'false'.
63
+ # end, # ...other configuration entries might follow...
64
+ #
65
+ # The 'username' and 'password' parameters come from Rails:
66
+ #
67
+ # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html
68
+ # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html#method-i-authenticate_with_http_basic
81
69
 
82
- # Scimitar rescues certain error cases and exceptions, in order to return a
83
- # JSON response to the API caller. If you want exceptions to also be
84
- # reported to a third party system such as sentry.io or raygun.com, you can
85
- # configure a Proc to do so. It is passed a Ruby exception subclass object.
86
- # For example, a minimal sentry.io reporter might do this:
87
- #
88
- # exception_reporter: Proc.new do | exception |
89
- # Sentry.capture_exception(exception)
90
- # end
91
- #
92
- # You will still need to configure your reporting system according to its
93
- # documentation (e.g. via a Rails "config/initializers/<foo>.rb" file).
70
+ # If you want to support HTTP bearer token (OAuth-style) authentication:
71
+ #
72
+ # token_authenticator: Proc.new do | token, options |
73
+ # # Check token and return 'true' if valid, else 'false'.
74
+ # end, # ...other configuration entries might follow...
75
+ #
76
+ # The 'token' and 'options' parameters come from Rails:
77
+ #
78
+ # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
79
+ # https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token/ControllerMethods.html#method-i-authenticate_with_http_token
80
+ #
81
+ # Note that both basic and token authentication can be declared, with the
82
+ # parameters in the inbound HTTP request determining which is invoked.
94
83
 
95
- # Scimilar treats "VDTP" (Value, Display, Type, Primary) attribute values,
96
- # used for e.g. e-mail addresses or phone numbers, as required by default.
97
- # If you encounter a service which calls these with e.g. "null" value data,
98
- # you can configure all values to be optional. You'll need to deal with
99
- # whatever that means for you receiving system in your model code.
100
- #
101
- # optional_value_fields_required: false
102
- })
84
+ })
85
+
86
+ end