scimitar 2.7.3 → 2.9.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/README.md +27 -18
- data/app/controllers/scimitar/active_record_backed_resources_controller.rb +5 -4
- data/app/controllers/scimitar/resource_types_controller.rb +0 -2
- data/app/controllers/scimitar/resources_controller.rb +0 -2
- data/app/controllers/scimitar/schemas_controller.rb +361 -3
- data/app/controllers/scimitar/service_provider_configurations_controller.rb +0 -1
- data/app/models/scimitar/engine_configuration.rb +3 -1
- data/app/models/scimitar/lists/query_parser.rb +88 -3
- data/app/models/scimitar/resources/base.rb +36 -5
- data/app/models/scimitar/resources/mixin.rb +87 -20
- data/app/models/scimitar/schema/name.rb +2 -2
- data/app/models/scimitar/schema/user.rb +10 -10
- data/config/initializers/scimitar.rb +41 -0
- data/lib/scimitar/engine.rb +57 -12
- data/lib/scimitar/support/utilities.rb +8 -3
- data/lib/scimitar/version.rb +2 -2
- data/spec/apps/dummy/app/models/mock_user.rb +18 -3
- data/spec/apps/dummy/config/initializers/scimitar.rb +31 -2
- data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -0
- data/spec/apps/dummy/db/schema.rb +1 -0
- data/spec/controllers/scimitar/schemas_controller_spec.rb +342 -54
- data/spec/models/scimitar/lists/query_parser_spec.rb +70 -0
- data/spec/models/scimitar/resources/base_spec.rb +11 -11
- data/spec/models/scimitar/resources/base_validation_spec.rb +16 -3
- data/spec/models/scimitar/resources/mixin_spec.rb +71 -10
- data/spec/models/scimitar/schema/user_spec.rb +2 -2
- data/spec/requests/active_record_backed_resources_controller_spec.rb +132 -1
- data/spec/requests/engine_spec.rb +75 -0
- data/spec/spec_helper.rb +1 -1
- metadata +20 -20
@@ -4,7 +4,7 @@ RSpec.describe Scimitar::Resources::Base do
|
|
4
4
|
context 'basic operation' do
|
5
5
|
FirstCustomSchema = Class.new(Scimitar::Schema::Base) do
|
6
6
|
def self.id
|
7
|
-
'custom-id'
|
7
|
+
'urn:ietf:params:scim:schemas:custom-id'
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.scim_attributes
|
@@ -125,7 +125,7 @@ RSpec.describe Scimitar::Resources::Base do
|
|
125
125
|
|
126
126
|
result = resource.as_json
|
127
127
|
|
128
|
-
expect(result['schemas'] ).to eql(['custom-id'])
|
128
|
+
expect(result['schemas'] ).to eql(['urn:ietf:params:scim:schemas:custom-id'])
|
129
129
|
expect(result['meta']['resourceType']).to eql('CustomResourse')
|
130
130
|
expect(result['errors'] ).to be_nil
|
131
131
|
end
|
@@ -144,7 +144,7 @@ RSpec.describe Scimitar::Resources::Base do
|
|
144
144
|
|
145
145
|
result = resource.as_json
|
146
146
|
|
147
|
-
expect(result['schemas'] ).to eql(['custom-id'])
|
147
|
+
expect(result['schemas'] ).to eql(['urn:ietf:params:scim:schemas:custom-id'])
|
148
148
|
expect(result['meta']['resourceType']).to eql('CustomResourse')
|
149
149
|
expect(result['errors'] ).to be_nil
|
150
150
|
expect(result['name'] ).to be_present
|
@@ -295,7 +295,7 @@ RSpec.describe Scimitar::Resources::Base do
|
|
295
295
|
context 'of custom schema' do
|
296
296
|
ThirdCustomSchema = Class.new(Scimitar::Schema::Base) do
|
297
297
|
def self.id
|
298
|
-
'custom-id'
|
298
|
+
'urn:ietf:params:scim:schemas:custom-id'
|
299
299
|
end
|
300
300
|
|
301
301
|
def self.scim_attributes
|
@@ -305,7 +305,7 @@ RSpec.describe Scimitar::Resources::Base do
|
|
305
305
|
|
306
306
|
ExtensionSchema = Class.new(Scimitar::Schema::Base) do
|
307
307
|
def self.id
|
308
|
-
'extension
|
308
|
+
'urn:ietf:params:scim:schemas:extension'
|
309
309
|
end
|
310
310
|
|
311
311
|
def self.scim_attributes
|
@@ -333,13 +333,13 @@ RSpec.describe Scimitar::Resources::Base do
|
|
333
333
|
|
334
334
|
context '#initialize' do
|
335
335
|
it 'allows setting extension attributes' do
|
336
|
-
resource = resource_class.new('extension
|
336
|
+
resource = resource_class.new('urn:ietf:params:scim:schemas:extension' => {relationship: 'GAGA'})
|
337
337
|
expect(resource.relationship).to eql('GAGA')
|
338
338
|
end
|
339
339
|
|
340
340
|
it 'allows setting complex extension attributes' do
|
341
341
|
user_groups = [{ value: '123' }, { value: '456'}]
|
342
|
-
resource = resource_class.new('extension
|
342
|
+
resource = resource_class.new('urn:ietf:params:scim:schemas:extension' => {userGroups: user_groups})
|
343
343
|
expect(resource.userGroups.map(&:value)).to eql(['123', '456'])
|
344
344
|
end
|
345
345
|
end # "context '#initialize' do"
|
@@ -348,8 +348,8 @@ RSpec.describe Scimitar::Resources::Base do
|
|
348
348
|
it 'namespaces the extension attributes' do
|
349
349
|
resource = resource_class.new(relationship: 'GAGA')
|
350
350
|
hash = resource.as_json
|
351
|
-
expect(hash["schemas"]).to eql(['custom-id', 'extension
|
352
|
-
expect(hash["extension
|
351
|
+
expect(hash["schemas"]).to eql(['urn:ietf:params:scim:schemas:custom-id', 'urn:ietf:params:scim:schemas:extension'])
|
352
|
+
expect(hash["urn:ietf:params:scim:schemas:extension"]).to eql("relationship" => 'GAGA')
|
353
353
|
end
|
354
354
|
end # "context '#as_json' do"
|
355
355
|
|
@@ -362,10 +362,10 @@ RSpec.describe Scimitar::Resources::Base do
|
|
362
362
|
|
363
363
|
context 'validation' do
|
364
364
|
it 'validates into custom schema' do
|
365
|
-
resource = resource_class.new('extension
|
365
|
+
resource = resource_class.new('urn:ietf:params:scim:schemas:extension' => {})
|
366
366
|
expect(resource.valid?).to eql(false)
|
367
367
|
|
368
|
-
resource = resource_class.new('extension
|
368
|
+
resource = resource_class.new('urn:ietf:params:scim:schemas:extension' => {relationship: 'GAGA'})
|
369
369
|
expect(resource.relationship).to eql('GAGA')
|
370
370
|
expect(resource.valid?).to eql(true)
|
371
371
|
end
|
@@ -4,7 +4,20 @@ RSpec.describe Scimitar::Resources::Base do
|
|
4
4
|
context '#valid?' do
|
5
5
|
MyCustomSchema = Class.new(Scimitar::Schema::Base) do
|
6
6
|
def self.id
|
7
|
-
'custom-id'
|
7
|
+
'urn:ietf:params:scim:schemas:custom-id'
|
8
|
+
end
|
9
|
+
|
10
|
+
class NameWithRequirementsSchema < Scimitar::Schema::Base
|
11
|
+
def self.scim_attributes
|
12
|
+
@scim_attributes ||= [
|
13
|
+
Scimitar::Schema::Attribute.new(name: 'familyName', type: 'string', required: true),
|
14
|
+
Scimitar::Schema::Attribute.new(name: 'givenName', type: 'string', required: true),
|
15
|
+
]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class NameWithRequirementsComplexType < Scimitar::ComplexTypes::Base
|
20
|
+
set_schema NameWithRequirementsSchema
|
8
21
|
end
|
9
22
|
|
10
23
|
def self.scim_attributes
|
@@ -16,10 +29,10 @@ RSpec.describe Scimitar::Resources::Base do
|
|
16
29
|
name: 'enforce', type: 'boolean', required: true
|
17
30
|
),
|
18
31
|
Scimitar::Schema::Attribute.new(
|
19
|
-
name: 'complexName', complexType:
|
32
|
+
name: 'complexName', complexType: NameWithRequirementsComplexType, required: false
|
20
33
|
),
|
21
34
|
Scimitar::Schema::Attribute.new(
|
22
|
-
name: 'complexNames', complexType: Scimitar::ComplexTypes::Name, multiValued:true, required: false
|
35
|
+
name: 'complexNames', complexType: Scimitar::ComplexTypes::Name, multiValued: true, required: false
|
23
36
|
),
|
24
37
|
Scimitar::Schema::Attribute.new(
|
25
38
|
name: 'vdtpTestByEmail', complexType: Scimitar::ComplexTypes::Email, required: false
|
@@ -255,6 +255,52 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
255
255
|
# =========================================================================
|
256
256
|
|
257
257
|
context '#to_scim' do
|
258
|
+
context 'with list of requested attributes' do
|
259
|
+
it 'compiles instance attribute values into a SCIM representation, including only the requested attributes' do
|
260
|
+
uuid = SecureRandom.uuid
|
261
|
+
|
262
|
+
instance = MockUser.new
|
263
|
+
instance.primary_key = uuid
|
264
|
+
instance.scim_uid = 'AA02984'
|
265
|
+
instance.username = 'foo'
|
266
|
+
instance.password = 'correcthorsebatterystaple'
|
267
|
+
instance.first_name = 'Foo'
|
268
|
+
instance.last_name = 'Bar'
|
269
|
+
instance.work_email_address = 'foo.bar@test.com'
|
270
|
+
instance.home_email_address = nil
|
271
|
+
instance.work_phone_number = '+642201234567'
|
272
|
+
instance.organization = 'SOMEORG'
|
273
|
+
|
274
|
+
g1 = MockGroup.create!(display_name: 'Group 1')
|
275
|
+
g2 = MockGroup.create!(display_name: 'Group 2')
|
276
|
+
g3 = MockGroup.create!(display_name: 'Group 3')
|
277
|
+
|
278
|
+
g1.mock_users << instance
|
279
|
+
g3.mock_users << instance
|
280
|
+
|
281
|
+
scim = instance.to_scim(location: "https://test.com/mock_users/#{uuid}", include_attributes: %w[id userName name groups.display groups.value organization])
|
282
|
+
json = scim.to_json()
|
283
|
+
hash = JSON.parse(json)
|
284
|
+
|
285
|
+
expect(hash).to eql({
|
286
|
+
'id' => uuid,
|
287
|
+
'userName' => 'foo',
|
288
|
+
'name' => {'givenName'=>'Foo', 'familyName'=>'Bar'},
|
289
|
+
'groups' => [{'display'=>g1.display_name, 'value'=>g1.id.to_s}, {'display'=>g3.display_name, 'value'=>g3.id.to_s}],
|
290
|
+
'meta' => {'location'=>"https://test.com/mock_users/#{uuid}", 'resourceType'=>'User'},
|
291
|
+
'schemas' => [
|
292
|
+
'urn:ietf:params:scim:schemas:core:2.0:User',
|
293
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',
|
294
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User',
|
295
|
+
],
|
296
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {
|
297
|
+
'organization' => 'SOMEORG',
|
298
|
+
},
|
299
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User' => {},
|
300
|
+
})
|
301
|
+
end
|
302
|
+
end # "context 'with list of requested attributes' do"
|
303
|
+
|
258
304
|
context 'with a UUID, renamed primary key column' do
|
259
305
|
it 'compiles instance attribute values into a SCIM representation, but omits do-not-return fields' do
|
260
306
|
uuid = SecureRandom.uuid
|
@@ -292,12 +338,19 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
292
338
|
'externalId' => 'AA02984',
|
293
339
|
'groups' => [{'display'=>g1.display_name, 'value'=>g1.id.to_s}, {'display'=>g3.display_name, 'value'=>g3.id.to_s}],
|
294
340
|
'meta' => {'location'=>"https://test.com/mock_users/#{uuid}", 'resourceType'=>'User'},
|
295
|
-
'schemas' => [
|
296
|
-
|
341
|
+
'schemas' => [
|
342
|
+
'urn:ietf:params:scim:schemas:core:2.0:User',
|
343
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',
|
344
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User',
|
345
|
+
],
|
297
346
|
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {
|
298
347
|
'organization' => 'SOMEORG',
|
299
|
-
'department' => nil
|
300
|
-
|
348
|
+
'department' => nil,
|
349
|
+
'primaryEmail' => instance.work_email_address,
|
350
|
+
},
|
351
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User' => {
|
352
|
+
'manager' => nil
|
353
|
+
},
|
301
354
|
})
|
302
355
|
end
|
303
356
|
end # "context 'with a UUID, renamed primary key column' do"
|
@@ -421,9 +474,13 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
421
474
|
],
|
422
475
|
|
423
476
|
'meta' => {'location'=>'https://test.com/static_map_test', 'resourceType'=>'User'},
|
424
|
-
'schemas' => [
|
425
|
-
|
426
|
-
|
477
|
+
'schemas' => [
|
478
|
+
'urn:ietf:params:scim:schemas:core:2.0:User',
|
479
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',
|
480
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User',
|
481
|
+
],
|
482
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {},
|
483
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User' => {},
|
427
484
|
})
|
428
485
|
end
|
429
486
|
end # "context 'using static mappings' do"
|
@@ -450,9 +507,13 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
450
507
|
],
|
451
508
|
|
452
509
|
'meta' => {'location'=>'https://test.com/dynamic_map_test', 'resourceType'=>'User'},
|
453
|
-
'schemas' => [
|
454
|
-
|
455
|
-
|
510
|
+
'schemas' => [
|
511
|
+
'urn:ietf:params:scim:schemas:core:2.0:User',
|
512
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',
|
513
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User',
|
514
|
+
],
|
515
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {},
|
516
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User' => {},
|
456
517
|
})
|
457
518
|
end
|
458
519
|
end # "context 'using dynamic lists' do"
|
@@ -27,7 +27,7 @@ RSpec.describe Scimitar::Schema::User do
|
|
27
27
|
"subAttributes": [
|
28
28
|
{
|
29
29
|
"multiValued": false,
|
30
|
-
"required":
|
30
|
+
"required": false,
|
31
31
|
"caseExact": false,
|
32
32
|
"mutability": "readWrite",
|
33
33
|
"uniqueness": "none",
|
@@ -37,7 +37,7 @@ RSpec.describe Scimitar::Schema::User do
|
|
37
37
|
},
|
38
38
|
{
|
39
39
|
"multiValued": false,
|
40
|
-
"required":
|
40
|
+
"required": false,
|
41
41
|
"caseExact": false,
|
42
42
|
"mutability": "readWrite",
|
43
43
|
"uniqueness": "none",
|
@@ -107,6 +107,37 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
107
107
|
expect(usernames).to match_array(['2'])
|
108
108
|
end
|
109
109
|
|
110
|
+
it 'returns only the requested attributes' do
|
111
|
+
get '/Users', params: {
|
112
|
+
format: :scim,
|
113
|
+
attributes: "id,name"
|
114
|
+
}
|
115
|
+
|
116
|
+
expect(response.status ).to eql(200)
|
117
|
+
expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
|
118
|
+
|
119
|
+
result = JSON.parse(response.body)
|
120
|
+
|
121
|
+
expect(result['totalResults']).to eql(3)
|
122
|
+
expect(result['Resources'].size).to eql(3)
|
123
|
+
|
124
|
+
keys = result['Resources'].map { |resource| resource.keys }.flatten.uniq
|
125
|
+
|
126
|
+
expect(keys).to match_array(%w[
|
127
|
+
id
|
128
|
+
meta
|
129
|
+
name
|
130
|
+
schemas
|
131
|
+
urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
|
132
|
+
urn:ietf:params:scim:schemas:extension:manager:1.0:User
|
133
|
+
])
|
134
|
+
expect(result.dig('Resources', 0, 'id')).to eql @u1.primary_key.to_s
|
135
|
+
expect(result.dig('Resources', 0, 'name', 'givenName')).to eql 'Foo'
|
136
|
+
expect(result.dig('Resources', 0, 'name', 'familyName')).to eql 'Ark'
|
137
|
+
end
|
138
|
+
|
139
|
+
# https://github.com/RIPAGlobal/scimitar/issues/37
|
140
|
+
#
|
110
141
|
it 'applies a filter, with case-insensitive attribute matching (GitHub issue #37)' do
|
111
142
|
get '/Users', params: {
|
112
143
|
format: :scim,
|
@@ -128,6 +159,30 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
128
159
|
expect(usernames).to match_array(['2'])
|
129
160
|
end
|
130
161
|
|
162
|
+
# https://github.com/RIPAGlobal/scimitar/issues/115
|
163
|
+
#
|
164
|
+
it 'handles broken Microsoft filters (GitHub issue #115)' do
|
165
|
+
get '/Users', params: {
|
166
|
+
format: :scim,
|
167
|
+
filter: 'name[givenName eq "FOO"].familyName pr and emails ne "home_1@test.com"'
|
168
|
+
}
|
169
|
+
|
170
|
+
expect(response.status ).to eql(200)
|
171
|
+
expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
|
172
|
+
|
173
|
+
result = JSON.parse(response.body)
|
174
|
+
|
175
|
+
expect(result['totalResults']).to eql(1)
|
176
|
+
expect(result['Resources'].size).to eql(1)
|
177
|
+
|
178
|
+
ids = result['Resources'].map { |resource| resource['id'] }
|
179
|
+
expect(ids).to match_array([@u2.primary_key.to_s])
|
180
|
+
|
181
|
+
usernames = result['Resources'].map { |resource| resource['userName'] }
|
182
|
+
expect(usernames).to match_array(['2'])
|
183
|
+
end
|
184
|
+
|
185
|
+
|
131
186
|
# Strange attribute capitalisation in tests here builds on test coverage
|
132
187
|
# for now-fixed GitHub issue #37.
|
133
188
|
#
|
@@ -386,6 +441,76 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
386
441
|
expect(new_mock.home_email_address).to eql('home_4@test.com')
|
387
442
|
expect(new_mock.work_email_address).to eql('work_4@test.com')
|
388
443
|
end
|
444
|
+
|
445
|
+
it 'with schema ID value keys without inline attributes' do
|
446
|
+
mock_before = MockUser.all.to_a
|
447
|
+
|
448
|
+
attributes = {
|
449
|
+
userName: '4',
|
450
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User': {
|
451
|
+
organization: 'Foo Bar!',
|
452
|
+
department: 'Bar Foo!'
|
453
|
+
},
|
454
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User': {
|
455
|
+
manager: 'Foo Baz!'
|
456
|
+
}
|
457
|
+
}
|
458
|
+
|
459
|
+
attributes = spec_helper_hupcase(attributes) if force_upper_case
|
460
|
+
|
461
|
+
expect {
|
462
|
+
post "/Users", params: attributes.merge(format: :scim)
|
463
|
+
}.to change { MockUser.count }.by(1)
|
464
|
+
|
465
|
+
mock_after = MockUser.all.to_a
|
466
|
+
new_mock = (mock_after - mock_before).first
|
467
|
+
|
468
|
+
expect(response.status ).to eql(201)
|
469
|
+
expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
|
470
|
+
|
471
|
+
result = JSON.parse(response.body)
|
472
|
+
|
473
|
+
expect(new_mock.organization).to eql('Foo Bar!')
|
474
|
+
expect(new_mock.department ).to eql('Bar Foo!')
|
475
|
+
expect(new_mock.manager ).to eql('Foo Baz!')
|
476
|
+
|
477
|
+
expect(result['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']['organization']).to eql(new_mock.organization)
|
478
|
+
expect(result['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']['department' ]).to eql(new_mock.department )
|
479
|
+
expect(result['urn:ietf:params:scim:schemas:extension:manager:1.0:User' ]['manager' ]).to eql(new_mock.manager )
|
480
|
+
end
|
481
|
+
|
482
|
+
it 'with schema ID value keys that have inline attributes' do
|
483
|
+
mock_before = MockUser.all.to_a
|
484
|
+
|
485
|
+
attributes = {
|
486
|
+
userName: '4',
|
487
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization': 'Foo Bar!',
|
488
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department': 'Bar Foo!',
|
489
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User:manager': 'Foo Baz!'
|
490
|
+
}
|
491
|
+
|
492
|
+
attributes = spec_helper_hupcase(attributes) if force_upper_case
|
493
|
+
|
494
|
+
expect {
|
495
|
+
post "/Users", params: attributes.merge(format: :scim)
|
496
|
+
}.to change { MockUser.count }.by(1)
|
497
|
+
|
498
|
+
mock_after = MockUser.all.to_a
|
499
|
+
new_mock = (mock_after - mock_before).first
|
500
|
+
|
501
|
+
expect(response.status ).to eql(201)
|
502
|
+
expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
|
503
|
+
|
504
|
+
result = JSON.parse(response.body)
|
505
|
+
|
506
|
+
expect(new_mock.organization).to eql('Foo Bar!')
|
507
|
+
expect(new_mock.department ).to eql('Bar Foo!')
|
508
|
+
expect(new_mock.manager ).to eql('Foo Baz!')
|
509
|
+
|
510
|
+
expect(result['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']['organization']).to eql(new_mock.organization)
|
511
|
+
expect(result['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']['department' ]).to eql(new_mock.department )
|
512
|
+
expect(result['urn:ietf:params:scim:schemas:extension:manager:1.0:User' ]['manager' ]).to eql(new_mock.manager )
|
513
|
+
end
|
389
514
|
end # "shared_examples 'a creator' do | force_upper_case: |"
|
390
515
|
|
391
516
|
context 'using schema-matched case' do
|
@@ -808,6 +933,9 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
808
933
|
'organization' => 'Foo Bar!',
|
809
934
|
'department' => 'Bar Foo!'
|
810
935
|
},
|
936
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User': {
|
937
|
+
'manager' => 'Foo Baz!'
|
938
|
+
}
|
811
939
|
},
|
812
940
|
},
|
813
941
|
]
|
@@ -825,6 +953,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
825
953
|
|
826
954
|
expect(@u2.organization).to eql('Foo Bar!')
|
827
955
|
expect(@u2.department ).to eql('Bar Foo!')
|
956
|
+
expect(@u2.manager ).to eql('Foo Baz!')
|
828
957
|
end
|
829
958
|
end
|
830
959
|
|
@@ -839,7 +968,8 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
839
968
|
op: 'add',
|
840
969
|
value: {
|
841
970
|
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization' => 'Foo Bar!',
|
842
|
-
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department' => 'Bar Foo!'
|
971
|
+
'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department' => 'Bar Foo!',
|
972
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User:manager' => 'Foo Baz!'
|
843
973
|
},
|
844
974
|
},
|
845
975
|
]
|
@@ -857,6 +987,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
|
|
857
987
|
|
858
988
|
expect(@u2.organization).to eql('Foo Bar!')
|
859
989
|
expect(@u2.department ).to eql('Bar Foo!')
|
990
|
+
expect(@u2.manager ).to eql('Foo Baz!')
|
860
991
|
end
|
861
992
|
end
|
862
993
|
|
@@ -42,4 +42,79 @@ RSpec.describe Scimitar::Engine do
|
|
42
42
|
expect(JSON.parse(response.body)['name']['familyName']).to eql('baz')
|
43
43
|
end
|
44
44
|
end # "context 'parameter parser' do"
|
45
|
+
|
46
|
+
# These are unit tests rather than request tests; seems like a reasonable
|
47
|
+
# place to put them in the absence of a standardised RSpec "engine" location.
|
48
|
+
#
|
49
|
+
context 'engine unit tests' do
|
50
|
+
around :each do | example |
|
51
|
+
license_schema = Class.new(Scimitar::Schema::Base) do
|
52
|
+
def initialize(options = {})
|
53
|
+
super(name: 'License', id: self.class.id(), description: 'Represents a License')
|
54
|
+
end
|
55
|
+
def self.id; 'urn:ietf:params:scim:schemas:license'; end
|
56
|
+
def self.scim_attributes; []; end
|
57
|
+
end
|
58
|
+
|
59
|
+
@license_resource = Class.new(Scimitar::Resources::Base) do
|
60
|
+
self.set_schema(license_schema)
|
61
|
+
def self.endpoint; '/License'; end
|
62
|
+
end
|
63
|
+
|
64
|
+
example.run()
|
65
|
+
ensure
|
66
|
+
Scimitar::Engine.reset_default_resources()
|
67
|
+
Scimitar::Engine.reset_custom_resources()
|
68
|
+
end
|
69
|
+
|
70
|
+
context '::resources, :add_custom_resource, ::set_default_resources' do
|
71
|
+
it 'returns default resources' do
|
72
|
+
expect(Scimitar::Engine.resources()).to match_array([Scimitar::Resources::User, Scimitar::Resources::Group])
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'includes custom resources' do
|
76
|
+
Scimitar::Engine.add_custom_resource(@license_resource)
|
77
|
+
expect(Scimitar::Engine.resources()).to match_array([Scimitar::Resources::User, Scimitar::Resources::Group, @license_resource])
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'notes changes to defaults' do
|
81
|
+
Scimitar::Engine::set_default_resources([Scimitar::Resources::User])
|
82
|
+
expect(Scimitar::Engine.resources()).to match_array([Scimitar::Resources::User])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'notes changes to defaults with custom resources added' do
|
86
|
+
Scimitar::Engine::set_default_resources([Scimitar::Resources::User])
|
87
|
+
Scimitar::Engine.add_custom_resource(@license_resource)
|
88
|
+
expect(Scimitar::Engine.resources()).to match_array([Scimitar::Resources::User, @license_resource])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'rejects bad defaults' do
|
92
|
+
expect {
|
93
|
+
Scimitar::Engine::set_default_resources([@license_resource])
|
94
|
+
}.to raise_error('Scimitar::Engine::set_default_resources: Only Scimitar::Resources::User, Scimitar::Resources::Group are supported')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'rejects empty defaults' do
|
98
|
+
expect {
|
99
|
+
Scimitar::Engine::set_default_resources([])
|
100
|
+
}.to raise_error('Scimitar::Engine::set_default_resources: At least one resource must be given')
|
101
|
+
end
|
102
|
+
end # "context '::resources, :add_custom_resource, ::set_default_resources' do"
|
103
|
+
|
104
|
+
context '#schemas' do
|
105
|
+
it 'returns schema instances from ::resources' do
|
106
|
+
expect(Scimitar::Engine).to receive(:resources).and_return([Scimitar::Resources::User, @license_resource])
|
107
|
+
|
108
|
+
schema_instances = Scimitar::Engine.schemas()
|
109
|
+
schema_classes = schema_instances.map(&:class)
|
110
|
+
|
111
|
+
expect(schema_classes).to match_array([
|
112
|
+
Scimitar::Schema::User,
|
113
|
+
ScimSchemaExtensions::User::Enterprise,
|
114
|
+
ScimSchemaExtensions::User::Manager,
|
115
|
+
@license_resource.schemas.first
|
116
|
+
])
|
117
|
+
end
|
118
|
+
end # "context '#schemas' do"
|
119
|
+
end # "context 'engine unit tests' do"
|
45
120
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -19,7 +19,7 @@ require File.expand_path('../apps/dummy/config/environment', __FILE__)
|
|
19
19
|
abort("The Rails environment is running in production mode!") if Rails.env.production?
|
20
20
|
|
21
21
|
require 'rspec/rails'
|
22
|
-
require '
|
22
|
+
require 'debug'
|
23
23
|
require 'scimitar'
|
24
24
|
|
25
25
|
# ============================================================================
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scimitar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RIPA Global
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-06-
|
12
|
+
date: 2024-06-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -26,89 +26,89 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '7.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: debug
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '1.9'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '1.9'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: rake
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '13.2'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '13.2'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
57
|
+
name: pg
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '1.5'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '1.5'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
71
|
+
name: simplecov-rcov
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '0.3'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
83
|
+
version: '0.3'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
85
|
+
name: rdoc
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
88
|
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: '6.
|
90
|
+
version: '6.7'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: '6.
|
97
|
+
version: '6.7'
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
|
-
name:
|
99
|
+
name: rspec-rails
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
102
|
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: '
|
104
|
+
version: '6.1'
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
109
|
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: '
|
111
|
+
version: '6.1'
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: doggo
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|