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.
- checksums.yaml +4 -4
 - data/app/controllers/scimitar/active_record_backed_resources_controller.rb +6 -27
 - data/app/controllers/scimitar/application_controller.rb +9 -29
 - data/app/models/scimitar/engine_configuration.rb +3 -7
 - data/app/models/scimitar/error_response.rb +0 -12
 - data/app/models/scimitar/errors.rb +1 -1
 - data/app/models/scimitar/lists/query_parser.rb +4 -14
 - data/app/models/scimitar/resources/base.rb +1 -1
 - data/app/models/scimitar/resources/mixin.rb +4 -113
 - data/app/models/scimitar/schema/address.rb +0 -1
 - data/app/models/scimitar/schema/attribute.rb +1 -1
 - data/app/models/scimitar/schema/base.rb +3 -1
 - data/app/models/scimitar/schema/vdtp.rb +1 -1
 - data/config/initializers/scimitar.rb +70 -86
 - data/lib/scimitar/version.rb +2 -2
 - 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 +8 -19
 - 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 +9 -44
 - data/spec/apps/dummy/config/routes.rb +0 -4
 - data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -9
 - 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 -10
 - data/spec/controllers/scimitar/application_controller_spec.rb +1 -70
 - data/spec/controllers/scimitar/schemas_controller_spec.rb +2 -2
 - data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
 - data/spec/models/scimitar/lists/query_parser_spec.rb +9 -9
 - data/spec/models/scimitar/resources/base_spec.rb +66 -161
 - data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
 - data/spec/models/scimitar/resources/mixin_spec.rb +43 -757
 - data/spec/models/scimitar/resources/user_spec.rb +4 -4
 - data/spec/models/scimitar/schema/attribute_spec.rb +3 -0
 - data/spec/models/scimitar/schema/base_spec.rb +1 -1
 - data/spec/models/scimitar/schema/user_spec.rb +0 -10
 - data/spec/requests/active_record_backed_resources_controller_spec.rb +40 -309
 - data/spec/requests/application_controller_spec.rb +3 -17
 - metadata +7 -7
 
    
        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
         
     | 
| 
         @@ -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 
     | 
    
         
            -
                     
     | 
| 
      
 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 
     | 
    
         
            -
                     
     | 
| 
      
 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 
     | 
    
         
            -
                       
     | 
| 
      
 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 
     | 
    
         
            -
                       
     | 
| 
      
 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 
     | 
    
         
            -
                       
     | 
| 
      
 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(). 
     | 
| 
       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 
     | 
    
         
            -
                   
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       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 
     | 
    
         
            -
                   
     | 
| 
       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}") 
     | 
| 
      
 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) 
     | 
| 
      
 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 
     | 
    
         
            -
                     
     | 
| 
       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'] =  
     | 
| 
      
 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 #{ 
     | 
| 
      
 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 
     | 
    
         
            -
                  #  
     | 
| 
      
 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
         
     | 
| 
         @@ -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 
     | 
| 
      
 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 
     | 
| 
      
 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 
     | 
| 
      
 659 
     | 
    
         
            +
                      raise Scimitar::FilterError if scim_attribute.blank?
         
     | 
| 
       670 
660 
     | 
    
         | 
| 
       671 
661 
     | 
    
         
             
                      mapped_attribute = self.attribute_map()[scim_attribute]
         
     | 
| 
       672 
     | 
    
         
            -
                      raise Scimitar::FilterError 
     | 
| 
      
 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 
     | 
| 
      
 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:           
     | 
| 
      
 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 
     | 
    
         
            -
                               
     | 
| 
       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 
     | 
    
         
            -
                               
     | 
| 
       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 
     | 
    
         
            -
                               
     | 
| 
       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'),
         
     | 
| 
         @@ -26,7 +26,9 @@ module Scimitar 
     | 
|
| 
       26 
26 
     | 
    
         
             
                  #
         
     | 
| 
       27 
27 
     | 
    
         
             
                  def self.valid?(resource)
         
     | 
| 
       28 
28 
     | 
    
         
             
                    cloned_scim_attributes.each do |scim_attribute|
         
     | 
| 
       29 
     | 
    
         
            -
                       
     | 
| 
      
 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:  
     | 
| 
      
 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 
     | 
    
         
            -
              #  
     | 
| 
      
 7 
     | 
    
         
            +
              # ===========================================================================
         
     | 
| 
      
 8 
     | 
    
         
            +
              # SERVICE PROVIDER CONFIGURATION
         
     | 
| 
      
 9 
     | 
    
         
            +
              # ===========================================================================
         
     | 
| 
       18 
10 
     | 
    
         
             
              #
         
     | 
| 
       19 
     | 
    
         
            -
              #  
     | 
| 
       20 
     | 
    
         
            -
              #  
     | 
| 
       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 
     | 
    
         
            -
              # 
     | 
| 
      
 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 
     | 
    
         
            -
              #  
     | 
| 
       38 
     | 
    
         
            -
              #  
     | 
| 
       39 
     | 
    
         
            -
              #  
     | 
| 
       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 
     | 
    
         
            -
              # 
     | 
| 
       48 
     | 
    
         
            -
              # 
     | 
| 
       49 
     | 
    
         
            -
              # 
     | 
| 
      
 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 
     | 
    
         
            -
               
     | 
| 
       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 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       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 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            -
               
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       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
         
     |