scimitar 2.7.3 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +27 -18
  3. data/app/controllers/scimitar/active_record_backed_resources_controller.rb +5 -4
  4. data/app/controllers/scimitar/resource_types_controller.rb +0 -2
  5. data/app/controllers/scimitar/resources_controller.rb +0 -2
  6. data/app/controllers/scimitar/schemas_controller.rb +361 -3
  7. data/app/controllers/scimitar/service_provider_configurations_controller.rb +0 -1
  8. data/app/models/scimitar/engine_configuration.rb +3 -1
  9. data/app/models/scimitar/lists/query_parser.rb +88 -3
  10. data/app/models/scimitar/resources/base.rb +36 -5
  11. data/app/models/scimitar/resources/mixin.rb +87 -20
  12. data/app/models/scimitar/schema/name.rb +2 -2
  13. data/app/models/scimitar/schema/user.rb +10 -10
  14. data/config/initializers/scimitar.rb +41 -0
  15. data/lib/scimitar/engine.rb +57 -12
  16. data/lib/scimitar/support/utilities.rb +8 -3
  17. data/lib/scimitar/version.rb +2 -2
  18. data/spec/apps/dummy/app/models/mock_user.rb +18 -3
  19. data/spec/apps/dummy/config/initializers/scimitar.rb +31 -2
  20. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -0
  21. data/spec/apps/dummy/db/schema.rb +1 -0
  22. data/spec/controllers/scimitar/schemas_controller_spec.rb +342 -54
  23. data/spec/models/scimitar/lists/query_parser_spec.rb +70 -0
  24. data/spec/models/scimitar/resources/base_spec.rb +11 -11
  25. data/spec/models/scimitar/resources/base_validation_spec.rb +16 -3
  26. data/spec/models/scimitar/resources/mixin_spec.rb +71 -10
  27. data/spec/models/scimitar/schema/user_spec.rb +2 -2
  28. data/spec/requests/active_record_backed_resources_controller_spec.rb +132 -1
  29. data/spec/requests/engine_spec.rb +75 -0
  30. data/spec/spec_helper.rb +1 -1
  31. 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-id'
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-id' => {relationship: 'GAGA'})
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-id' => {userGroups: user_groups})
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-id'])
352
- expect(hash["extension-id"]).to eql("relationship" => 'GAGA')
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-id' => {})
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-id' => {relationship: 'GAGA'})
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: Scimitar::ComplexTypes::Name, required: false
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' => ['urn:ietf:params:scim:schemas:core:2.0:User', 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'],
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' => ['urn:ietf:params:scim:schemas:core:2.0:User', 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'],
425
-
426
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {}
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' => ['urn:ietf:params:scim:schemas:core:2.0:User', 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'],
454
-
455
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {}
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": true,
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": true,
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 'byebug'
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.7.3
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-11 00:00:00.000000000 Z
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: rake
29
+ name: debug
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '13.1'
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: '13.1'
41
+ version: '1.9'
42
42
  - !ruby/object:Gem::Dependency
43
- name: pg
43
+ name: rake
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '1.5'
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: '1.5'
55
+ version: '13.2'
56
56
  - !ruby/object:Gem::Dependency
57
- name: simplecov-rcov
57
+ name: pg
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '0.3'
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: '0.3'
69
+ version: '1.5'
70
70
  - !ruby/object:Gem::Dependency
71
- name: rdoc
71
+ name: simplecov-rcov
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '6.6'
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: '6.6'
83
+ version: '0.3'
84
84
  - !ruby/object:Gem::Dependency
85
- name: rspec-rails
85
+ name: rdoc
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: '6.1'
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.1'
97
+ version: '6.7'
98
98
  - !ruby/object:Gem::Dependency
99
- name: byebug
99
+ name: rspec-rails
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: '11.1'
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: '11.1'
111
+ version: '6.1'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: doggo
114
114
  requirement: !ruby/object:Gem::Requirement