scimitar 1.5.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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