scimitar 1.10.0 → 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.
- checksums.yaml +4 -4
 - data/app/controllers/scimitar/active_record_backed_resources_controller.rb +23 -98
 - data/app/controllers/scimitar/application_controller.rb +13 -41
 - data/app/controllers/scimitar/resource_types_controller.rb +2 -0
 - data/app/controllers/scimitar/resources_controller.rb +2 -0
 - data/app/controllers/scimitar/schemas_controller.rb +3 -366
 - data/app/controllers/scimitar/service_provider_configurations_controller.rb +1 -0
 - data/app/models/scimitar/complex_types/address.rb +6 -0
 - data/app/models/scimitar/engine_configuration.rb +5 -15
 - data/app/models/scimitar/error_response.rb +0 -12
 - data/app/models/scimitar/lists/query_parser.rb +13 -113
 - data/app/models/scimitar/resource_invalid_error.rb +1 -1
 - data/app/models/scimitar/resources/base.rb +9 -53
 - data/app/models/scimitar/resources/mixin.rb +59 -646
 - data/app/models/scimitar/schema/address.rb +0 -1
 - data/app/models/scimitar/schema/attribute.rb +5 -14
 - data/app/models/scimitar/schema/base.rb +1 -1
 - data/app/models/scimitar/schema/name.rb +2 -2
 - data/app/models/scimitar/schema/user.rb +10 -10
 - data/app/models/scimitar/schema/vdtp.rb +1 -1
 - data/app/models/scimitar/service_provider_configuration.rb +3 -14
 - data/config/initializers/scimitar.rb +3 -69
 - data/lib/scimitar/engine.rb +12 -57
 - data/lib/scimitar/support/hash_with_indifferent_case_insensitive_access.rb +10 -140
 - data/lib/scimitar/version.rb +2 -2
 - data/lib/scimitar.rb +2 -7
 - data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
 - data/spec/apps/dummy/app/models/mock_group.rb +1 -1
 - data/spec/apps/dummy/app/models/mock_user.rb +9 -52
 - data/spec/apps/dummy/config/application.rb +1 -0
 - data/spec/apps/dummy/config/environments/test.rb +28 -5
 - data/spec/apps/dummy/config/initializers/scimitar.rb +10 -90
 - data/spec/apps/dummy/config/routes.rb +7 -28
 - data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -11
 - data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
 - data/spec/apps/dummy/db/schema.rb +4 -12
 - data/spec/controllers/scimitar/application_controller_spec.rb +3 -126
 - data/spec/controllers/scimitar/resource_types_controller_spec.rb +2 -2
 - data/spec/controllers/scimitar/schemas_controller_spec.rb +48 -344
 - data/spec/models/scimitar/complex_types/address_spec.rb +4 -3
 - data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
 - data/spec/models/scimitar/lists/query_parser_spec.rb +9 -146
 - data/spec/models/scimitar/resources/base_spec.rb +71 -217
 - data/spec/models/scimitar/resources/base_validation_spec.rb +5 -43
 - data/spec/models/scimitar/resources/mixin_spec.rb +129 -1508
 - data/spec/models/scimitar/schema/attribute_spec.rb +3 -22
 - data/spec/models/scimitar/schema/base_spec.rb +1 -1
 - data/spec/models/scimitar/schema/user_spec.rb +2 -12
 - data/spec/requests/active_record_backed_resources_controller_spec.rb +66 -1016
 - data/spec/requests/application_controller_spec.rb +3 -16
 - data/spec/requests/engine_spec.rb +0 -75
 - data/spec/spec_helper.rb +1 -9
 - data/spec/support/hash_with_indifferent_case_insensitive_access_spec.rb +0 -108
 - metadata +26 -37
 - data/LICENSE.txt +0 -21
 - data/README.md +0 -717
 - data/lib/scimitar/support/utilities.rb +0 -111
 - data/spec/apps/dummy/app/controllers/custom_create_mock_users_controller.rb +0 -25
 - data/spec/apps/dummy/app/controllers/custom_replace_mock_users_controller.rb +0 -25
 - data/spec/apps/dummy/app/controllers/custom_save_mock_users_controller.rb +0 -24
 - data/spec/apps/dummy/app/controllers/custom_update_mock_users_controller.rb +0 -25
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 95a2166cc921a400959f9d8d4398f6bf8ecb772f8d7a0a0a73950892e85d808a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: cdf5aab3812f10f69c96304e738a150f4208850267527b66d36eeb99548d7b1f
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: f0925517599b107e44fd93db9be142aebe608892c2c5069c50d22b353c51238290710474b062a002fdb010be3d783c4dea3b314f72f47b4aca3c2385a8fc1377
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: eef6eebfc64bb2d4adabfca110f26e3a6c9e227f47387da6fb384925899ddf0ae260cf68176f24040a6bb356cf34f6576c920bd44264d4a1fee415aeadc237e6
         
     | 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_dependency "scimitar/application_controller"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module Scimitar
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
              # An ActiveRecord-centric subclass of Scimitar::ResourcesController. See that
         
     | 
| 
         @@ -17,9 +19,7 @@ module Scimitar 
     | 
|
| 
       17 
19 
     | 
    
         
             
              #
         
     | 
| 
       18 
20 
     | 
    
         
             
              class ActiveRecordBackedResourcesController < ResourcesController
         
     | 
| 
       19 
21 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                rescue_from  
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                before_action :obtain_id_column_name_from_attribute_map
         
     | 
| 
      
 22 
     | 
    
         
            +
                rescue_from ActiveRecord::RecordNotFound, with: :handle_resource_not_found # See Scimitar::ApplicationController
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
                # GET (list)
         
     | 
| 
       25 
25 
     | 
    
         
             
                #
         
     | 
| 
         @@ -37,13 +37,12 @@ module Scimitar 
     | 
|
| 
       37 
37 
     | 
    
         
             
                  pagination_info = scim_pagination_info(query.count())
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                  page_of_results = query
         
     | 
| 
       40 
     | 
    
         
            -
                    .order(@id_column => :asc)
         
     | 
| 
       41 
40 
     | 
    
         
             
                    .offset(pagination_info.offset)
         
     | 
| 
       42 
41 
     | 
    
         
             
                    .limit(pagination_info.limit)
         
     | 
| 
       43 
42 
     | 
    
         
             
                    .to_a()
         
     | 
| 
       44 
43 
     | 
    
         | 
| 
       45 
44 
     | 
    
         
             
                  super(pagination_info, page_of_results) do | record |
         
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
      
 45 
     | 
    
         
            +
                    record.to_scim(location: url_for(action: :show, id: record.id))
         
     | 
| 
       47 
46 
     | 
    
         
             
                  end
         
     | 
| 
       48 
47 
     | 
    
         
             
                end
         
     | 
| 
       49 
48 
     | 
    
         | 
| 
         @@ -52,61 +51,45 @@ module Scimitar 
     | 
|
| 
       52 
51 
     | 
    
         
             
                def show
         
     | 
| 
       53 
52 
     | 
    
         
             
                  super do |record_id|
         
     | 
| 
       54 
53 
     | 
    
         
             
                    record = self.find_record(record_id)
         
     | 
| 
       55 
     | 
    
         
            -
                     
     | 
| 
      
 54 
     | 
    
         
            +
                    record.to_scim(location: url_for(action: :show, id: record_id))
         
     | 
| 
       56 
55 
     | 
    
         
             
                  end
         
     | 
| 
       57 
56 
     | 
    
         
             
                end
         
     | 
| 
       58 
57 
     | 
    
         | 
| 
       59 
58 
     | 
    
         
             
                # POST (create)
         
     | 
| 
       60 
59 
     | 
    
         
             
                #
         
     | 
| 
       61 
     | 
    
         
            -
                 
     | 
| 
       62 
     | 
    
         
            -
                # block, passing it the new ActiveRecord model instance to be saved. It
         
     | 
| 
       63 
     | 
    
         
            -
                # is up to the block to make any further changes and persist the record.
         
     | 
| 
       64 
     | 
    
         
            -
                #
         
     | 
| 
       65 
     | 
    
         
            -
                # Blocks are invoked from within a wrapping database transaction.
         
     | 
| 
       66 
     | 
    
         
            -
                # ActiveRecord::RecordInvalid exceptions are handled for you, rendering
         
     | 
| 
       67 
     | 
    
         
            -
                # an appropriate SCIM error.
         
     | 
| 
       68 
     | 
    
         
            -
                #
         
     | 
| 
       69 
     | 
    
         
            -
                def create(&block)
         
     | 
| 
      
 60 
     | 
    
         
            +
                def create
         
     | 
| 
       70 
61 
     | 
    
         
             
                  super do |scim_resource|
         
     | 
| 
       71 
62 
     | 
    
         
             
                    self.storage_class().transaction do
         
     | 
| 
       72 
63 
     | 
    
         
             
                      record = self.storage_class().new
         
     | 
| 
       73 
64 
     | 
    
         
             
                      record.from_scim!(scim_hash: scim_resource.as_json())
         
     | 
| 
       74 
     | 
    
         
            -
                      self.save!(record 
     | 
| 
       75 
     | 
    
         
            -
                       
     | 
| 
      
 65 
     | 
    
         
            +
                      self.save!(record)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      record.to_scim(location: url_for(action: :show, id: record.id))
         
     | 
| 
       76 
67 
     | 
    
         
             
                    end
         
     | 
| 
       77 
68 
     | 
    
         
             
                  end
         
     | 
| 
       78 
69 
     | 
    
         
             
                end
         
     | 
| 
       79 
70 
     | 
    
         | 
| 
       80 
71 
     | 
    
         
             
                # PUT (replace)
         
     | 
| 
       81 
72 
     | 
    
         
             
                #
         
     | 
| 
       82 
     | 
    
         
            -
                 
     | 
| 
       83 
     | 
    
         
            -
                # block, passing the updated record which the block must persist, with the
         
     | 
| 
       84 
     | 
    
         
            -
                # same rules as for #create.
         
     | 
| 
       85 
     | 
    
         
            -
                #
         
     | 
| 
       86 
     | 
    
         
            -
                def replace(&block)
         
     | 
| 
      
 73 
     | 
    
         
            +
                def replace
         
     | 
| 
       87 
74 
     | 
    
         
             
                  super do |record_id, scim_resource|
         
     | 
| 
       88 
75 
     | 
    
         
             
                    self.storage_class().transaction do
         
     | 
| 
       89 
76 
     | 
    
         
             
                      record = self.find_record(record_id)
         
     | 
| 
       90 
77 
     | 
    
         
             
                      record.from_scim!(scim_hash: scim_resource.as_json())
         
     | 
| 
       91 
     | 
    
         
            -
                      self.save!(record 
     | 
| 
       92 
     | 
    
         
            -
                       
     | 
| 
      
 78 
     | 
    
         
            +
                      self.save!(record)
         
     | 
| 
      
 79 
     | 
    
         
            +
                      record.to_scim(location: url_for(action: :show, id: record.id))
         
     | 
| 
       93 
80 
     | 
    
         
             
                    end
         
     | 
| 
       94 
81 
     | 
    
         
             
                  end
         
     | 
| 
       95 
82 
     | 
    
         
             
                end
         
     | 
| 
       96 
83 
     | 
    
         | 
| 
       97 
84 
     | 
    
         
             
                # PATCH (update)
         
     | 
| 
       98 
85 
     | 
    
         
             
                #
         
     | 
| 
       99 
     | 
    
         
            -
                 
     | 
| 
       100 
     | 
    
         
            -
                # block, passing the updated record which the block must persist, with the
         
     | 
| 
       101 
     | 
    
         
            -
                # same rules as for #create.
         
     | 
| 
       102 
     | 
    
         
            -
                #
         
     | 
| 
       103 
     | 
    
         
            -
                def update(&block)
         
     | 
| 
      
 86 
     | 
    
         
            +
                def update
         
     | 
| 
       104 
87 
     | 
    
         
             
                  super do |record_id, patch_hash|
         
     | 
| 
       105 
88 
     | 
    
         
             
                    self.storage_class().transaction do
         
     | 
| 
       106 
89 
     | 
    
         
             
                      record = self.find_record(record_id)
         
     | 
| 
       107 
90 
     | 
    
         
             
                      record.from_scim_patch!(patch_hash: patch_hash)
         
     | 
| 
       108 
     | 
    
         
            -
                      self.save!(record 
     | 
| 
       109 
     | 
    
         
            -
                       
     | 
| 
      
 91 
     | 
    
         
            +
                      self.save!(record)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      record.to_scim(location: url_for(action: :show, id: record.id))
         
     | 
| 
       110 
93 
     | 
    
         
             
                    end
         
     | 
| 
       111 
94 
     | 
    
         
             
                  end
         
     | 
| 
       112 
95 
     | 
    
         
             
                end
         
     | 
| 
         @@ -148,46 +131,19 @@ module Scimitar 
     | 
|
| 
       148 
131 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       149 
132 
     | 
    
         
             
                  end
         
     | 
| 
       150 
133 
     | 
    
         | 
| 
       151 
     | 
    
         
            -
                  # Return an Array of exceptions that #save! can rescue and handle with a
         
     | 
| 
       152 
     | 
    
         
            -
                  # SCIM error automatically.
         
     | 
| 
       153 
     | 
    
         
            -
                  #
         
     | 
| 
       154 
     | 
    
         
            -
                  def scimitar_rescuable_exceptions
         
     | 
| 
       155 
     | 
    
         
            -
                    [
         
     | 
| 
       156 
     | 
    
         
            -
                      ActiveRecord::RecordInvalid,
         
     | 
| 
       157 
     | 
    
         
            -
                      ActiveRecord::RecordNotSaved,
         
     | 
| 
       158 
     | 
    
         
            -
                      ActiveRecord::RecordNotUnique,
         
     | 
| 
       159 
     | 
    
         
            -
                    ]
         
     | 
| 
       160 
     | 
    
         
            -
                  end
         
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
134 
     | 
    
         
             
                  # Find a record by ID. Subclasses can override this if they need special
         
     | 
| 
       163 
135 
     | 
    
         
             
                  # lookup behaviour.
         
     | 
| 
       164 
136 
     | 
    
         
             
                  #
         
     | 
| 
       165 
137 
     | 
    
         
             
                  # +record_id+:: Record ID (SCIM schema 'id' value - "our" ID).
         
     | 
| 
       166 
138 
     | 
    
         
             
                  #
         
     | 
| 
       167 
139 
     | 
    
         
             
                  def find_record(record_id)
         
     | 
| 
       168 
     | 
    
         
            -
                    self.storage_scope(). 
     | 
| 
       169 
     | 
    
         
            -
                  end
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                  # DRY up controller actions - pass a record; returns the SCIM
         
     | 
| 
       172 
     | 
    
         
            -
                  # representation, with a "show" location specified via #url_for.
         
     | 
| 
       173 
     | 
    
         
            -
                  #
         
     | 
| 
       174 
     | 
    
         
            -
                  def record_to_scim(record)
         
     | 
| 
       175 
     | 
    
         
            -
                    record.to_scim(
         
     | 
| 
       176 
     | 
    
         
            -
                      location: url_for(action: :show, id: record.send(@id_column)),
         
     | 
| 
       177 
     | 
    
         
            -
                      include_attributes: params.fetch(:attributes, "").split(",")
         
     | 
| 
       178 
     | 
    
         
            -
                    )
         
     | 
| 
      
 140 
     | 
    
         
            +
                    self.storage_scope().find(record_id)
         
     | 
| 
       179 
141 
     | 
    
         
             
                  end
         
     | 
| 
       180 
142 
     | 
    
         | 
| 
       181 
143 
     | 
    
         
             
                  # Save a record, dealing with validation exceptions by raising SCIM
         
     | 
| 
       182 
144 
     | 
    
         
             
                  # errors.
         
     | 
| 
       183 
145 
     | 
    
         
             
                  #
         
     | 
| 
       184 
     | 
    
         
            -
                  # +record+:: ActiveRecord subclass to save.
         
     | 
| 
       185 
     | 
    
         
            -
                  #
         
     | 
| 
       186 
     | 
    
         
            -
                  # If you just let this superclass handle things, it'll call the standard
         
     | 
| 
       187 
     | 
    
         
            -
                  # +#save!+ method on the record. If you pass a block, then this block is
         
     | 
| 
       188 
     | 
    
         
            -
                  # invoked and passed the ActiveRecord model instance to be saved. You can
         
     | 
| 
       189 
     | 
    
         
            -
                  # then do things like calling a different method, using a service object
         
     | 
| 
       190 
     | 
    
         
            -
                  # of some kind, perform audit-related operations and so-on.
         
     | 
| 
      
 146 
     | 
    
         
            +
                  # +record+:: ActiveRecord subclass to save (via #save!).
         
     | 
| 
       191 
147 
     | 
    
         
             
                  #
         
     | 
| 
       192 
148 
     | 
    
         
             
                  # The return value is not used internally, making life easier for
         
     | 
| 
       193 
149 
     | 
    
         
             
                  # overriding subclasses to "do the right thing" / avoid mistakes (instead
         
     | 
| 
         @@ -195,31 +151,11 @@ module Scimitar 
     | 
|
| 
       195 
151 
     | 
    
         
             
                  # and relying upon this to generate correct response payloads - an early
         
     | 
| 
       196 
152 
     | 
    
         
             
                  # version of the gem did this and it caused a confusing subclass bug).
         
     | 
| 
       197 
153 
     | 
    
         
             
                  #
         
     | 
| 
       198 
     | 
    
         
            -
                  def save!(record 
     | 
| 
       199 
     | 
    
         
            -
                     
     | 
| 
       200 
     | 
    
         
            -
                      yield(record)
         
     | 
| 
       201 
     | 
    
         
            -
                    else
         
     | 
| 
       202 
     | 
    
         
            -
                      record.save!
         
     | 
| 
       203 
     | 
    
         
            -
                    end
         
     | 
| 
       204 
     | 
    
         
            -
                  rescue *self.scimitar_rescuable_exceptions() => exception
         
     | 
| 
       205 
     | 
    
         
            -
                    handle_on_save_exception(record, exception)
         
     | 
| 
       206 
     | 
    
         
            -
                  end
         
     | 
| 
      
 154 
     | 
    
         
            +
                  def save!(record)
         
     | 
| 
      
 155 
     | 
    
         
            +
                    record.save!
         
     | 
| 
       207 
156 
     | 
    
         | 
| 
       208 
     | 
    
         
            -
                   
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
                  # validation errors defined, but falls back to the provided exception's
         
     | 
| 
       211 
     | 
    
         
            -
                  # message otherwise.
         
     | 
| 
       212 
     | 
    
         
            -
                  #
         
     | 
| 
       213 
     | 
    
         
            -
                  # +record+::    The record that provoked the exception. Mandatory.
         
     | 
| 
       214 
     | 
    
         
            -
                  # +exception+:: The exception that was raised. If omitted, a default of
         
     | 
| 
       215 
     | 
    
         
            -
                  #               'Unknown', in English with no I18n, is used.
         
     | 
| 
       216 
     | 
    
         
            -
                  #
         
     | 
| 
       217 
     | 
    
         
            -
                  def handle_on_save_exception(record, exception = RuntimeError.new('Unknown'))
         
     | 
| 
       218 
     | 
    
         
            -
                    details = if record.errors.present?
         
     | 
| 
       219 
     | 
    
         
            -
                      record.errors.full_messages.join('; ')
         
     | 
| 
       220 
     | 
    
         
            -
                    else
         
     | 
| 
       221 
     | 
    
         
            -
                      exception.message
         
     | 
| 
       222 
     | 
    
         
            -
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
                  rescue ActiveRecord::RecordInvalid => exception
         
     | 
| 
      
 158 
     | 
    
         
            +
                    joined_errors = record.errors.full_messages.join('; ')
         
     | 
| 
       223 
159 
     | 
    
         | 
| 
       224 
160 
     | 
    
         
             
                    # https://tools.ietf.org/html/rfc7644#page-12
         
     | 
| 
       225 
161 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -229,27 +165,16 @@ module Scimitar 
     | 
|
| 
       229 
165 
     | 
    
         
             
                    #   status code 409 (Conflict) with a "scimType" error code of
         
     | 
| 
       230 
166 
     | 
    
         
             
                    #   "uniqueness"
         
     | 
| 
       231 
167 
     | 
    
         
             
                    #
         
     | 
| 
       232 
     | 
    
         
            -
                    if  
     | 
| 
      
 168 
     | 
    
         
            +
                    if record.errors.any? { | e | e.type == :taken }
         
     | 
| 
       233 
169 
     | 
    
         
             
                      raise Scimitar::ErrorResponse.new(
         
     | 
| 
       234 
170 
     | 
    
         
             
                        status:   409,
         
     | 
| 
       235 
171 
     | 
    
         
             
                        scimType: 'uniqueness',
         
     | 
| 
       236 
     | 
    
         
            -
                        detail:    
     | 
| 
      
 172 
     | 
    
         
            +
                        detail:   joined_errors
         
     | 
| 
       237 
173 
     | 
    
         
             
                      )
         
     | 
| 
       238 
174 
     | 
    
         
             
                    else
         
     | 
| 
       239 
     | 
    
         
            -
                      raise Scimitar::ResourceInvalidError.new( 
     | 
| 
      
 175 
     | 
    
         
            +
                      raise Scimitar::ResourceInvalidError.new(joined_errors)
         
     | 
| 
       240 
176 
     | 
    
         
             
                    end
         
     | 
| 
       241 
177 
     | 
    
         
             
                  end
         
     | 
| 
       242 
178 
     | 
    
         | 
| 
       243 
     | 
    
         
            -
                  # Called via +before_action+ - stores in @id_column the name of whatever
         
     | 
| 
       244 
     | 
    
         
            -
                  # model column is used to store the record ID, via
         
     | 
| 
       245 
     | 
    
         
            -
                  # Scimitar::Resources::Mixin::scim_attributes_map.
         
     | 
| 
       246 
     | 
    
         
            -
                  #
         
     | 
| 
       247 
     | 
    
         
            -
                  # Default is <tt>:id</tt>.
         
     | 
| 
       248 
     | 
    
         
            -
                  #
         
     | 
| 
       249 
     | 
    
         
            -
                  def obtain_id_column_name_from_attribute_map
         
     | 
| 
       250 
     | 
    
         
            -
                    attrs      = storage_class().scim_attributes_map() || {}
         
     | 
| 
       251 
     | 
    
         
            -
                    @id_column = attrs[:id] || :id
         
     | 
| 
       252 
     | 
    
         
            -
                  end
         
     | 
| 
       253 
     | 
    
         
            -
             
     | 
| 
       254 
179 
     | 
    
         
             
              end
         
     | 
| 
       255 
180 
     | 
    
         
             
            end
         
     | 
| 
         @@ -25,11 +25,10 @@ module Scimitar 
     | 
|
| 
       25 
25 
     | 
    
         
             
                  #
         
     | 
| 
       26 
26 
     | 
    
         
             
                  # ...to "globally" invoke this handler if you wish.
         
     | 
| 
       27 
27 
     | 
    
         
             
                  #
         
     | 
| 
       28 
     | 
    
         
            -
                  # + 
     | 
| 
       29 
     | 
    
         
            -
                  #               via #handle_scim_error (if present).
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # +_exception+:: Exception instance (currently unused).
         
     | 
| 
       30 
29 
     | 
    
         
             
                  #
         
     | 
| 
       31 
     | 
    
         
            -
                  def handle_resource_not_found( 
     | 
| 
       32 
     | 
    
         
            -
                    handle_scim_error(NotFoundError.new(params[:id]) 
     | 
| 
      
 30 
     | 
    
         
            +
                  def handle_resource_not_found(_exception)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    handle_scim_error(NotFoundError.new(params[:id]))
         
     | 
| 
       33 
32 
     | 
    
         
             
                  end
         
     | 
| 
       34 
33 
     | 
    
         | 
| 
       35 
34 
     | 
    
         
             
                  # This base controller uses:
         
     | 
| 
         @@ -39,22 +38,9 @@ module Scimitar 
     | 
|
| 
       39 
38 
     | 
    
         
             
                  # ...to "globally" invoke this handler for all Scimitar errors (including
         
     | 
| 
       40 
39 
     | 
    
         
             
                  # subclasses).
         
     | 
| 
       41 
40 
     | 
    
         
             
                  #
         
     | 
| 
       42 
     | 
    
         
            -
                  # Mandatory parameters are:
         
     | 
| 
       43 
     | 
    
         
            -
                  #
         
     | 
| 
       44 
41 
     | 
    
         
             
                  # +error_response+:: Scimitar::ErrorResponse (or subclass) instance.
         
     | 
| 
       45 
42 
     | 
    
         
             
                  #
         
     | 
| 
       46 
     | 
    
         
            -
                   
     | 
| 
       47 
     | 
    
         
            -
                  #
         
     | 
| 
       48 
     | 
    
         
            -
                  # *exception+:: If a Ruby exception was the reason this method is being
         
     | 
| 
       49 
     | 
    
         
            -
                  #               called, pass it here. Any configured exception reporting
         
     | 
| 
       50 
     | 
    
         
            -
                  #               mechanism will be invokved with the given parameter.
         
     | 
| 
       51 
     | 
    
         
            -
                  #               Otherwise, the +error_response+ value is reported.
         
     | 
| 
       52 
     | 
    
         
            -
                  #
         
     | 
| 
       53 
     | 
    
         
            -
                  def handle_scim_error(error_response, exception = error_response)
         
     | 
| 
       54 
     | 
    
         
            -
                    unless Scimitar.engine_configuration.exception_reporter.nil?
         
     | 
| 
       55 
     | 
    
         
            -
                      Scimitar.engine_configuration.exception_reporter.call(exception)
         
     | 
| 
       56 
     | 
    
         
            -
                    end
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def handle_scim_error(error_response)
         
     | 
| 
       58 
44 
     | 
    
         
             
                    render json: error_response, status: error_response.status
         
     | 
| 
       59 
45 
     | 
    
         
             
                  end
         
     | 
| 
       60 
46 
     | 
    
         | 
| 
         @@ -69,7 +55,7 @@ module Scimitar 
     | 
|
| 
       69 
55 
     | 
    
         
             
                  # +exception+:: Exception instance.
         
     | 
| 
       70 
56 
     | 
    
         
             
                  #
         
     | 
| 
       71 
57 
     | 
    
         
             
                  def handle_bad_json_error(exception)
         
     | 
| 
       72 
     | 
    
         
            -
                    handle_scim_error(ErrorResponse.new(status: 400, detail: "Invalid JSON - #{exception.message}") 
     | 
| 
      
 58 
     | 
    
         
            +
                    handle_scim_error(ErrorResponse.new(status: 400, detail: "Invalid JSON - #{exception.message}"))
         
     | 
| 
       73 
59 
     | 
    
         
             
                  end
         
     | 
| 
       74 
60 
     | 
    
         | 
| 
       75 
61 
     | 
    
         
             
                  # This base controller uses:
         
     | 
| 
         @@ -82,7 +68,7 @@ module Scimitar 
     | 
|
| 
       82 
68 
     | 
    
         
             
                  #
         
     | 
| 
       83 
69 
     | 
    
         
             
                  def handle_unexpected_error(exception)
         
     | 
| 
       84 
70 
     | 
    
         
             
                    Rails.logger.error("#{exception.message}\n#{exception.backtrace}")
         
     | 
| 
       85 
     | 
    
         
            -
                    handle_scim_error(ErrorResponse.new(status: 500, detail: exception.message) 
     | 
| 
      
 71 
     | 
    
         
            +
                    handle_scim_error(ErrorResponse.new(status: 500, detail: exception.message))
         
     | 
| 
       86 
72 
     | 
    
         
             
                  end
         
     | 
| 
       87 
73 
     | 
    
         | 
| 
       88 
74 
     | 
    
         
             
                # =========================================================================
         
     | 
| 
         @@ -96,17 +82,12 @@ module Scimitar 
     | 
|
| 
       96 
82 
     | 
    
         
             
                  # request and subclass processing.
         
     | 
| 
       97 
83 
     | 
    
         
             
                  #
         
     | 
| 
       98 
84 
     | 
    
         
             
                  def require_scim
         
     | 
| 
       99 
     | 
    
         
            -
                     
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                    if request.media_type.nil? || request.media_type.empty?
         
     | 
| 
       102 
     | 
    
         
            -
                      request.format = :scim
         
     | 
| 
       103 
     | 
    
         
            -
                      request.headers['CONTENT_TYPE'] = scim_mime_type
         
     | 
| 
       104 
     | 
    
         
            -
                    elsif request.media_type.downcase == scim_mime_type
         
     | 
| 
      
 85 
     | 
    
         
            +
                    if request.content_type&.downcase == Mime::Type.lookup_by_extension(:scim).to_s
         
     | 
| 
       105 
86 
     | 
    
         
             
                      request.format = :scim
         
     | 
| 
       106 
87 
     | 
    
         
             
                    elsif request.format == :scim
         
     | 
| 
       107 
     | 
    
         
            -
                      request.headers['CONTENT_TYPE'] =  
     | 
| 
      
 88 
     | 
    
         
            +
                      request.headers['CONTENT_TYPE'] = Mime::Type.lookup_by_extension(:scim).to_s
         
     | 
| 
       108 
89 
     | 
    
         
             
                    else
         
     | 
| 
       109 
     | 
    
         
            -
                      handle_scim_error(ErrorResponse.new(status: 406, detail: "Only #{ 
     | 
| 
      
 90 
     | 
    
         
            +
                      handle_scim_error(ErrorResponse.new(status: 406, detail: "Only #{Mime::Type.lookup_by_extension(:scim)} type is accepted."))
         
     | 
| 
       110 
91 
     | 
    
         
             
                    end
         
     | 
| 
       111 
92 
     | 
    
         
             
                  end
         
     | 
| 
       112 
93 
     | 
    
         | 
| 
         @@ -124,13 +105,8 @@ module Scimitar 
     | 
|
| 
       124 
105 
     | 
    
         
             
                    #
         
     | 
| 
       125 
106 
     | 
    
         
             
                    # https://stackoverflow.com/questions/10239970/what-is-the-delimiter-for-www-authenticate-for-multiple-schemes
         
     | 
| 
       126 
107 
     | 
    
         
             
                    #
         
     | 
| 
       127 
     | 
    
         
            -
                    response.set_header(' 
     | 
| 
       128 
     | 
    
         
            -
                    response.set_header(' 
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                    # No matter what a caller might request via headers, the only content
         
     | 
| 
       131 
     | 
    
         
            -
                    # type we can ever respond with is JSON-for-SCIM.
         
     | 
| 
       132 
     | 
    
         
            -
                    #
         
     | 
| 
       133 
     | 
    
         
            -
                    response.set_header('Content-Type', "#{Mime::Type.lookup_by_extension(:scim)}; charset=utf-8")
         
     | 
| 
      
 108 
     | 
    
         
            +
                    response.set_header('WWW_AUTHENTICATE', 'Basic' ) if Scimitar.engine_configuration.basic_authenticator.present?
         
     | 
| 
      
 109 
     | 
    
         
            +
                    response.set_header('WWW_AUTHENTICATE', 'Bearer') if Scimitar.engine_configuration.token_authenticator.present?
         
     | 
| 
       134 
110 
     | 
    
         
             
                  end
         
     | 
| 
       135 
111 
     | 
    
         | 
| 
       136 
112 
     | 
    
         
             
                  def authenticate
         
     | 
| 
         @@ -139,15 +115,11 @@ module Scimitar 
     | 
|
| 
       139 
115 
     | 
    
         | 
| 
       140 
116 
     | 
    
         
             
                  def authenticated?
         
     | 
| 
       141 
117 
     | 
    
         
             
                    result = if Scimitar.engine_configuration.basic_authenticator.present?
         
     | 
| 
       142 
     | 
    
         
            -
                      authenticate_with_http_basic 
     | 
| 
       143 
     | 
    
         
            -
                        instance_exec(username, password, &Scimitar.engine_configuration.basic_authenticator)
         
     | 
| 
       144 
     | 
    
         
            -
                      end
         
     | 
| 
      
 118 
     | 
    
         
            +
                      authenticate_with_http_basic(&Scimitar.engine_configuration.basic_authenticator)
         
     | 
| 
       145 
119 
     | 
    
         
             
                    end
         
     | 
| 
       146 
120 
     | 
    
         | 
| 
       147 
121 
     | 
    
         
             
                    result ||= if Scimitar.engine_configuration.token_authenticator.present?
         
     | 
| 
       148 
     | 
    
         
            -
                      authenticate_with_http_token 
     | 
| 
       149 
     | 
    
         
            -
                        instance_exec(token, options, &Scimitar.engine_configuration.token_authenticator)
         
     | 
| 
       150 
     | 
    
         
            -
                      end
         
     | 
| 
      
 122 
     | 
    
         
            +
                      authenticate_with_http_token(&Scimitar.engine_configuration.token_authenticator)
         
     | 
| 
       151 
123 
     | 
    
         
             
                    end
         
     | 
| 
       152 
124 
     | 
    
         | 
| 
       153 
125 
     | 
    
         
             
                    return result
         
     |