scimitar 2.13.0 → 2.14.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5f63ca5b1572be0cb53a95a47280099713fd32be8f5650396a0db6a0c92550e
|
|
4
|
+
data.tar.gz: 2f1f2a7ec7a6877607875f6b86e7b9859ae9124f71d295541847940dd31c8b1f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08626642f4b3e9dd29a6141c72bea784ab094ec197d9f3b9278957a59bfe230f4ef7ec84d52b1584127af647809351607bc01ef408d7269cc39dcf1f17180d49'
|
|
7
|
+
data.tar.gz: 53845ba684f54f8e2e90e696b769aadfe803809fa3004fa35f779794d6e04bfa034ee231847382591cdc5600cc7544bbad4c959e2031c0271e67e5632d431f6c
|
data/README.md
CHANGED
|
@@ -64,7 +64,7 @@ Some aspects of configuration are handled via a `config/initializers/scimitar.rb
|
|
|
64
64
|
Rails.application.config.to_prepare do
|
|
65
65
|
Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
|
|
66
66
|
# ...see subsections below for configuration options...
|
|
67
|
-
|
|
67
|
+
})
|
|
68
68
|
end
|
|
69
69
|
```
|
|
70
70
|
|
|
@@ -184,7 +184,36 @@ Note that Okta has some [curious documentation on its use of `POST` vs `PATCH` f
|
|
|
184
184
|
|
|
185
185
|
### Google Workspace note
|
|
186
186
|
|
|
187
|
-
Using SCIM with Google Workspace might only work for a subset of applications. Since web UIs for major service providers change very often, it doesn't make sense to provide extensive documentation here as it would get out of date quickly; you may have to figure out the setup as best you can using whatever current Google documentation exists for their system. There are [some notes which were relevant around mid-2025](https://github.com/pond/scimitar/issues/142#issuecomment-2699050541) (from when a
|
|
187
|
+
Using SCIM with Google Workspace might only work for a subset of applications. Since web UIs for major service providers change very often, it doesn't make sense to provide extensive documentation here as it would get out of date quickly; you may have to figure out the setup as best you can using whatever current Google documentation exists for their system. There are [some notes which were relevant around mid-2025](https://github.com/pond/scimitar/issues/142#issuecomment-2699050541) (from when a workaround/fix was incorporated into Scimitar to allow it to work with Google Workspace) which may help you get started.
|
|
188
|
+
|
|
189
|
+
### Request content type handling
|
|
190
|
+
|
|
191
|
+
The correct content type for SCIM is `application/scim+json`. Scimitar tolerates some variants of this, rewriting things internally so that the request continues to be processed by the rest of the gem (including ending up in subclass code you write) under this media type, with a Rails request format of `:scim`. Sometimes, callers into SCIM endpoints might use a content type that Scimitar rejects. If so, you can configure a custom request sanitizer Proc (with a "z", in keeping with Rails spelling of "sanitize"):
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
Rails.application.config.to_prepare do
|
|
195
|
+
Scimitar.engine_configuration = Scimitar::EngineConfiguration.new({
|
|
196
|
+
|
|
197
|
+
custom_request_sanitizer: Proc.new do | request |
|
|
198
|
+
#
|
|
199
|
+
# Examine e.g. 'request.media_type' and evaluate to a Symbol:
|
|
200
|
+
#
|
|
201
|
+
# :success - set the standard content type and ensure the Rails request
|
|
202
|
+
# format is :scim; continue processing normally
|
|
203
|
+
#
|
|
204
|
+
# :preserve - retain the existing content type and Rails request format;
|
|
205
|
+
# continue processing normally
|
|
206
|
+
#
|
|
207
|
+
# :fail - the request format appears to be invalid; generate a 406
|
|
208
|
+
# ("Not Acceptable") response
|
|
209
|
+
#
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
})
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The Proc is passed the [`ActionDispatch::Request`](https://api.rubyonrails.org/classes/ActionDispatch/Request.html) instance for the current request. It **must** evaluable to a Symbol as shown above. Typically, `:preserve` is only for very special use cases where you understand that the request headers and/or format might not match what other parts of Scimitar expect, but have written appropriate custom code elsewhere to deal with that.
|
|
188
217
|
|
|
189
218
|
### Data models
|
|
190
219
|
|
|
@@ -93,19 +93,37 @@ module Scimitar
|
|
|
93
93
|
#
|
|
94
94
|
def require_scim
|
|
95
95
|
scim_mime_type = Mime::Type.lookup_by_extension(:scim).to_s
|
|
96
|
+
failure_detail = "Only #{scim_mime_type} type is accepted."
|
|
97
|
+
|
|
98
|
+
if Scimitar.engine_configuration.custom_request_sanitizer.is_a?(Proc)
|
|
99
|
+
|
|
100
|
+
result = Scimitar.engine_configuration.custom_request_sanitizer.call(request)
|
|
101
|
+
case result
|
|
102
|
+
when :fail
|
|
103
|
+
handle_scim_error(ErrorResponse.new(status: 406, detail: failure_detail))
|
|
104
|
+
when :preserve
|
|
105
|
+
# Do nothing
|
|
106
|
+
else
|
|
107
|
+
request.format = :scim
|
|
108
|
+
request.headers['CONTENT_TYPE'] = scim_mime_type
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
else # "if Scimitar.engine_configuration.custom_request_sanitizer.present?"
|
|
112
|
+
|
|
113
|
+
if request.media_type.nil? || request.media_type.empty?
|
|
114
|
+
request.format = :scim
|
|
115
|
+
request.headers['CONTENT_TYPE'] = scim_mime_type
|
|
116
|
+
elsif request.media_type.downcase == scim_mime_type
|
|
117
|
+
request.format = :scim
|
|
118
|
+
elsif request.format == :scim
|
|
119
|
+
request.headers['CONTENT_TYPE'] = scim_mime_type
|
|
120
|
+
elsif request.media_type.downcase == 'application/json' && request.user_agent&.start_with?('Google') # https://github.com/pond/scimitar/issues/142
|
|
121
|
+
request.format = :scim
|
|
122
|
+
request.headers["CONTENT_TYPE"] = scim_mime_type
|
|
123
|
+
else
|
|
124
|
+
handle_scim_error(ErrorResponse.new(status: 406, detail: failure_detail))
|
|
125
|
+
end
|
|
96
126
|
|
|
97
|
-
if request.media_type.nil? || request.media_type.empty?
|
|
98
|
-
request.format = :scim
|
|
99
|
-
request.headers['CONTENT_TYPE'] = scim_mime_type
|
|
100
|
-
elsif request.media_type.downcase == scim_mime_type
|
|
101
|
-
request.format = :scim
|
|
102
|
-
elsif request.format == :scim
|
|
103
|
-
request.headers['CONTENT_TYPE'] = scim_mime_type
|
|
104
|
-
elsif request.media_type.downcase == 'application/json' && request.user_agent.start_with?('Google') # https://github.com/pond/scimitar/issues/142
|
|
105
|
-
request.format = :scim
|
|
106
|
-
request.headers["CONTENT_TYPE"] = scim_mime_type
|
|
107
|
-
else
|
|
108
|
-
handle_scim_error(ErrorResponse.new(status: 406, detail: "Only #{scim_mime_type} type is accepted."))
|
|
109
127
|
end
|
|
110
128
|
end
|
|
111
129
|
|
data/lib/scimitar/version.rb
CHANGED
|
@@ -3,11 +3,11 @@ module Scimitar
|
|
|
3
3
|
# Gem version. If this changes, be sure to re-run "bundle install" or
|
|
4
4
|
# "bundle update".
|
|
5
5
|
#
|
|
6
|
-
VERSION = '2.
|
|
6
|
+
VERSION = '2.14.0'
|
|
7
7
|
|
|
8
8
|
# Date for VERSION. If this changes, be sure to re-run "bundle install"
|
|
9
9
|
# or "bundle update".
|
|
10
10
|
#
|
|
11
|
-
DATE = '2025-
|
|
11
|
+
DATE = '2025-11-14'
|
|
12
12
|
|
|
13
13
|
end
|
|
@@ -435,6 +435,61 @@ RSpec.describe Scimitar::ApplicationController do
|
|
|
435
435
|
expect(@exception.message).to eql('Only application/scim+json type is accepted.')
|
|
436
436
|
end
|
|
437
437
|
end # "context 'and with Google SCIM calls' do"
|
|
438
|
+
|
|
439
|
+
context 'and with a custom request sanitizer' do
|
|
440
|
+
around :each do | example |
|
|
441
|
+
original_configuration = Scimitar.engine_configuration.custom_request_sanitizer
|
|
442
|
+
Scimitar.engine_configuration.custom_request_sanitizer = Proc.new do | request |
|
|
443
|
+
case request.media_type
|
|
444
|
+
when 'application/json+success'
|
|
445
|
+
:success
|
|
446
|
+
when 'application/json+preserve'
|
|
447
|
+
:preserve
|
|
448
|
+
else
|
|
449
|
+
:fail
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
example.run()
|
|
453
|
+
ensure
|
|
454
|
+
Scimitar.engine_configuration.custom_request_sanitizer = original_configuration
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
context 'returning "success"' do
|
|
458
|
+
it 'reaches the controller action with cleaned up request data' do
|
|
459
|
+
request.headers['Content-Type'] = 'application/json+success'
|
|
460
|
+
get :index
|
|
461
|
+
|
|
462
|
+
expect(@exception).to be_a(RuntimeError)
|
|
463
|
+
expect(@exception.message).to eql('Bang')
|
|
464
|
+
|
|
465
|
+
expect(request.format == :scim).to eql(true)
|
|
466
|
+
expect(request.headers['CONTENT_TYPE']).to eql('application/scim+json')
|
|
467
|
+
end
|
|
468
|
+
end # "context 'returning "success"' do"
|
|
469
|
+
|
|
470
|
+
context 'returning "preserve"' do
|
|
471
|
+
it 'reaches the controller action with unmodified request data' do
|
|
472
|
+
request.headers['Content-Type'] = 'application/json+preserve'
|
|
473
|
+
get :index
|
|
474
|
+
|
|
475
|
+
expect(@exception).to be_a(RuntimeError)
|
|
476
|
+
expect(@exception.message).to eql('Bang')
|
|
477
|
+
|
|
478
|
+
expect(request.format == :html).to eql(true)
|
|
479
|
+
expect(request.headers['CONTENT_TYPE']).to eql('application/json+preserve')
|
|
480
|
+
end
|
|
481
|
+
end # "context 'returning "keep"' do"
|
|
482
|
+
|
|
483
|
+
context 'returning "fail"' do
|
|
484
|
+
it 'is invoked' do
|
|
485
|
+
request.headers['Content-Type'] = 'application/json+fail'
|
|
486
|
+
get :index
|
|
487
|
+
|
|
488
|
+
expect(@exception).to be_a(Scimitar::ErrorResponse)
|
|
489
|
+
expect(@exception.message).to eql('Only application/scim+json type is accepted.')
|
|
490
|
+
end
|
|
491
|
+
end # "context 'returning "fail"' do"
|
|
492
|
+
end # "context 'and with a custom request sanitizer' do"
|
|
438
493
|
end # "context 'exception reporter' do"
|
|
439
494
|
end # "context 'error handling' do"
|
|
440
495
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: scimitar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- RIPA Global
|
|
8
8
|
- Andrew David Hodgkinson
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '13.
|
|
47
|
+
version: '13.3'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '13.
|
|
54
|
+
version: '13.3'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: pg
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '6.
|
|
89
|
+
version: '6.15'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '6.
|
|
96
|
+
version: '6.15'
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: warden
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|