scimitar 1.8.1 → 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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scimitar/active_record_backed_resources_controller.rb +20 -94
  3. data/app/controllers/scimitar/application_controller.rb +13 -41
  4. data/app/controllers/scimitar/schemas_controller.rb +0 -5
  5. data/app/models/scimitar/complex_types/address.rb +6 -0
  6. data/app/models/scimitar/engine_configuration.rb +5 -13
  7. data/app/models/scimitar/error_response.rb +0 -12
  8. data/app/models/scimitar/lists/query_parser.rb +10 -25
  9. data/app/models/scimitar/resource_invalid_error.rb +1 -1
  10. data/app/models/scimitar/resources/base.rb +4 -14
  11. data/app/models/scimitar/resources/mixin.rb +13 -140
  12. data/app/models/scimitar/schema/address.rb +0 -1
  13. data/app/models/scimitar/schema/attribute.rb +5 -14
  14. data/app/models/scimitar/schema/base.rb +1 -1
  15. data/app/models/scimitar/schema/vdtp.rb +1 -1
  16. data/app/models/scimitar/service_provider_configuration.rb +3 -14
  17. data/config/initializers/scimitar.rb +3 -28
  18. data/lib/scimitar/version.rb +2 -2
  19. data/lib/scimitar.rb +2 -7
  20. data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
  21. data/spec/apps/dummy/app/models/mock_group.rb +1 -1
  22. data/spec/apps/dummy/app/models/mock_user.rb +8 -36
  23. data/spec/apps/dummy/config/application.rb +1 -0
  24. data/spec/apps/dummy/config/environments/test.rb +28 -5
  25. data/spec/apps/dummy/config/initializers/scimitar.rb +10 -61
  26. data/spec/apps/dummy/config/routes.rb +7 -28
  27. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -10
  28. data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
  29. data/spec/apps/dummy/db/schema.rb +4 -11
  30. data/spec/controllers/scimitar/application_controller_spec.rb +3 -126
  31. data/spec/controllers/scimitar/resource_types_controller_spec.rb +2 -2
  32. data/spec/controllers/scimitar/schemas_controller_spec.rb +2 -10
  33. data/spec/models/scimitar/complex_types/address_spec.rb +4 -3
  34. data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
  35. data/spec/models/scimitar/lists/query_parser_spec.rb +9 -76
  36. data/spec/models/scimitar/resources/base_spec.rb +70 -208
  37. data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
  38. data/spec/models/scimitar/resources/mixin_spec.rb +43 -790
  39. data/spec/models/scimitar/schema/attribute_spec.rb +3 -22
  40. data/spec/models/scimitar/schema/base_spec.rb +1 -1
  41. data/spec/models/scimitar/schema/user_spec.rb +0 -10
  42. data/spec/requests/active_record_backed_resources_controller_spec.rb +66 -709
  43. data/spec/requests/application_controller_spec.rb +3 -16
  44. data/spec/spec_helper.rb +0 -8
  45. metadata +14 -25
  46. data/LICENSE.txt +0 -21
  47. data/README.md +0 -710
  48. data/lib/scimitar/support/utilities.rb +0 -51
  49. data/spec/apps/dummy/app/controllers/custom_create_mock_users_controller.rb +0 -25
  50. data/spec/apps/dummy/app/controllers/custom_replace_mock_users_controller.rb +0 -25
  51. data/spec/apps/dummy/app/controllers/custom_save_mock_users_controller.rb +0 -24
  52. data/spec/apps/dummy/app/controllers/custom_update_mock_users_controller.rb +0 -25
@@ -14,10 +14,7 @@ RSpec.describe Scimitar::Resources::Base do
14
14
  ),
15
15
  Scimitar::Schema::Attribute.new(
16
16
  name: 'names', multiValued: true, complexType: Scimitar::ComplexTypes::Name, required: false
17
- ),
18
- Scimitar::Schema::Attribute.new(
19
- name: 'privateName', complexType: Scimitar::ComplexTypes::Name, required: false, returned: false
20
- ),
17
+ )
21
18
  ]
22
19
  end
23
20
  end
@@ -33,10 +30,6 @@ RSpec.describe Scimitar::Resources::Base do
33
30
  name: {
34
31
  givenName: 'John',
35
32
  familyName: 'Smith'
36
- },
37
- privateName: {
38
- givenName: 'Alt John',
39
- familyName: 'Alt Smith'
40
33
  }
41
34
  }
42
35
 
@@ -46,9 +39,6 @@ RSpec.describe Scimitar::Resources::Base do
46
39
  expect(resource.name.is_a?(Scimitar::ComplexTypes::Name)).to be(true)
47
40
  expect(resource.name.givenName).to eql('John')
48
41
  expect(resource.name.familyName).to eql('Smith')
49
- expect(resource.privateName.is_a?(Scimitar::ComplexTypes::Name)).to be(true)
50
- expect(resource.privateName.givenName).to eql('Alt John')
51
- expect(resource.privateName.familyName).to eql('Alt Smith')
52
42
  end
53
43
 
54
44
  it 'which builds an array of nested resources' do
@@ -111,38 +101,14 @@ RSpec.describe Scimitar::Resources::Base do
111
101
  context '#as_json' do
112
102
  it 'renders the json with the resourceType' do
113
103
  resource = CustomResourse.new(name: {
114
- givenName: 'John',
104
+ givenName: 'John',
115
105
  familyName: 'Smith'
116
106
  })
117
107
 
118
108
  result = resource.as_json
119
-
120
- expect(result['schemas'] ).to eql(['custom-id'])
109
+ expect(result['schemas']).to eql(['custom-id'])
121
110
  expect(result['meta']['resourceType']).to eql('CustomResourse')
122
- expect(result['errors'] ).to be_nil
123
- end
124
-
125
- it 'excludes attributes that are flagged as do-not-return' do
126
- resource = CustomResourse.new(
127
- name: {
128
- givenName: 'John',
129
- familyName: 'Smith'
130
- },
131
- privateName: {
132
- givenName: 'Alt John',
133
- familyName: 'Alt Smith'
134
- }
135
- )
136
-
137
- result = resource.as_json
138
-
139
- expect(result['schemas'] ).to eql(['custom-id'])
140
- expect(result['meta']['resourceType']).to eql('CustomResourse')
141
- expect(result['errors'] ).to be_nil
142
- expect(result['name'] ).to be_present
143
- expect(result['name']['givenName'] ).to eql('John')
144
- expect(result['name']['familyName'] ).to eql('Smith')
145
- expect(result['privateName'] ).to be_present
111
+ expect(result['errors']).to be_nil
146
112
  end
147
113
  end # "context '#as_json' do"
148
114
 
@@ -284,194 +250,90 @@ RSpec.describe Scimitar::Resources::Base do
284
250
  end # "context 'dynamic setters based on schema' do"
285
251
 
286
252
  context 'schema extension' do
287
- context 'of custom schema' do
288
- ThirdCustomSchema = Class.new(Scimitar::Schema::Base) do
289
- def self.id
290
- 'custom-id'
291
- end
292
-
293
- def self.scim_attributes
294
- [ Scimitar::Schema::Attribute.new(name: 'name', type: 'string') ]
295
- end
253
+ ThirdCustomSchema = Class.new(Scimitar::Schema::Base) do
254
+ def self.id
255
+ 'custom-id'
296
256
  end
297
257
 
298
- ExtensionSchema = Class.new(Scimitar::Schema::Base) do
299
- def self.id
300
- 'extension-id'
301
- end
302
-
303
- def self.scim_attributes
304
- [
305
- Scimitar::Schema::Attribute.new(name: 'relationship', type: 'string', required: true),
306
- Scimitar::Schema::Attribute.new(name: "userGroups", multiValued: true, complexType: Scimitar::ComplexTypes::ReferenceGroup, mutability: "writeOnly")
307
- ]
308
- end
258
+ def self.scim_attributes
259
+ [ Scimitar::Schema::Attribute.new(name: 'name', type: 'string') ]
309
260
  end
261
+ end
310
262
 
311
- let(:resource_class) {
312
- Class.new(Scimitar::Resources::Base) do
313
- set_schema ThirdCustomSchema
314
- extend_schema ExtensionSchema
315
-
316
- def self.endpoint
317
- '/gaga'
318
- end
319
-
320
- def self.resource_type_id
321
- 'CustomResource'
322
- end
323
- end
324
- }
325
-
326
- context '#initialize' do
327
- it 'allows setting extension attributes' do
328
- resource = resource_class.new('extension-id' => {relationship: 'GAGA'})
329
- expect(resource.relationship).to eql('GAGA')
330
- end
331
-
332
- it 'allows setting complex extension attributes' do
333
- user_groups = [{ value: '123' }, { value: '456'}]
334
- resource = resource_class.new('extension-id' => {userGroups: user_groups})
335
- expect(resource.userGroups.map(&:value)).to eql(['123', '456'])
336
- end
337
- end # "context '#initialize' do"
338
-
339
- context '#as_json' do
340
- it 'namespaces the extension attributes' do
341
- resource = resource_class.new(relationship: 'GAGA')
342
- hash = resource.as_json
343
- expect(hash["schemas"]).to eql(['custom-id', 'extension-id'])
344
- expect(hash["extension-id"]).to eql("relationship" => 'GAGA')
345
- end
346
- end # "context '#as_json' do"
347
-
348
- context '.resource_type' do
349
- it 'appends the extension schemas' do
350
- resource_type = resource_class.resource_type('http://gaga')
351
- expect(resource_type.meta.location).to eql('http://gaga')
352
- expect(resource_type.schemaExtensions.count).to eql(1)
353
- end
354
-
355
- context 'validation' do
356
- it 'validates into custom schema' do
357
- resource = resource_class.new('extension-id' => {})
358
- expect(resource.valid?).to eql(false)
359
-
360
- resource = resource_class.new('extension-id' => {relationship: 'GAGA'})
361
- expect(resource.relationship).to eql('GAGA')
362
- expect(resource.valid?).to eql(true)
363
- end
364
- end # context 'validation'
365
- end # "context '.resource_type' do"
263
+ ExtensionSchema = Class.new(Scimitar::Schema::Base) do
264
+ def self.id
265
+ 'extension-id'
266
+ end
366
267
 
367
- context '.find_attribute' do
368
- it 'finds in first schema' do
369
- found = resource_class().find_attribute('name') # Defined in ThirdCustomSchema
370
- expect(found).to be_present
371
- expect(found.name).to eql('name')
372
- expect(found.type).to eql('string')
373
- end
268
+ def self.scim_attributes
269
+ [ Scimitar::Schema::Attribute.new(name: 'relationship', type: 'string', required: true) ]
270
+ end
271
+ end
374
272
 
375
- it 'finds across schemas' do
376
- found = resource_class().find_attribute('relationship') # Defined in ExtensionSchema
377
- expect(found).to be_present
378
- expect(found.name).to eql('relationship')
379
- expect(found.type).to eql('string')
380
- end
381
- end # "context '.find_attribute' do"
382
- end # "context 'of custom schema' do"
273
+ let(:resource_class) {
274
+ Class.new(Scimitar::Resources::Base) do
275
+ set_schema ThirdCustomSchema
276
+ extend_schema ExtensionSchema
383
277
 
384
- context 'of core schema' do
385
- EnterpriseExtensionSchema = Class.new(Scimitar::Schema::Base) do
386
- def self.id
387
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'
278
+ def self.endpoint
279
+ '/gaga'
388
280
  end
389
281
 
390
- def self.scim_attributes
391
- [
392
- Scimitar::Schema::Attribute.new(name: 'organization', type: 'string'),
393
- Scimitar::Schema::Attribute.new(name: 'department', type: 'string')
394
- ]
282
+ def self.resource_type_id
283
+ 'CustomResource'
395
284
  end
396
285
  end
286
+ }
397
287
 
398
- let(:resource_class) {
399
- Class.new(Scimitar::Resources::Base) do
400
- set_schema Scimitar::Schema::User
401
- extend_schema EnterpriseExtensionSchema
402
-
403
- def self.endpoint
404
- '/Users'
405
- end
406
-
407
- def self.resource_type_id
408
- 'User'
409
- end
410
- end
411
- }
412
-
413
- context '#initialize' do
414
- it 'allows setting extension attributes' do
415
- resource = resource_class.new('urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {organization: 'SOMEORG', department: 'SOMEDPT'})
288
+ context '#initialize' do
289
+ it 'allows setting extension attributes' do
290
+ resource = resource_class.new('extension-id' => {relationship: 'GAGA'})
291
+ expect(resource.relationship).to eql('GAGA')
292
+ end
293
+ end # "context '#initialize' do"
416
294
 
417
- expect(resource.organization).to eql('SOMEORG')
418
- expect(resource.department ).to eql('SOMEDPT')
419
- end
420
- end # "context '#initialize' do"
295
+ context '#as_json' do
296
+ it 'namespaces the extension attributes' do
297
+ resource = resource_class.new(relationship: 'GAGA')
298
+ hash = resource.as_json
299
+ expect(hash["schemas"]).to eql(['custom-id', 'extension-id'])
300
+ expect(hash["extension-id"]).to eql("relationship" => 'GAGA')
301
+ end
302
+ end # "context '#as_json' do"
421
303
 
422
- context '#as_json' do
423
- it 'namespaces the extension attributes' do
424
- resource = resource_class.new(organization: 'SOMEORG', department: 'SOMEDPT')
425
- hash = resource.as_json
304
+ context '.resource_type' do
305
+ it 'appends the extension schemas' do
306
+ resource_type = resource_class.resource_type('http://gaga')
307
+ expect(resource_type.meta.location).to eql('http://gaga')
308
+ expect(resource_type.schemaExtensions.count).to eql(1)
309
+ end
426
310
 
427
- expect(hash['schemas']).to eql(['urn:ietf:params:scim:schemas:core:2.0:User', 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'])
428
- expect(hash['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User']).to eql('organization' => 'SOMEORG', 'department' => 'SOMEDPT')
429
- end
430
- end # "context '#as_json' do"
311
+ context 'validation' do
312
+ it 'validates into custom schema' do
313
+ resource = resource_class.new('extension-id' => {})
314
+ expect(resource.valid?).to eql(false)
431
315
 
432
- context '.resource_type' do
433
- it 'appends the extension schemas' do
434
- resource_type = resource_class.resource_type('http://example.com')
435
- expect(resource_type.meta.location).to eql('http://example.com')
436
- expect(resource_type.schemaExtensions.count).to eql(1)
316
+ resource = resource_class.new('extension-id' => {relationship: 'GAGA'})
317
+ expect(resource.relationship).to eql('GAGA')
318
+ expect(resource.valid?).to eql(true)
437
319
  end
320
+ end # context 'validation'
321
+ end # "context '.resource_type' do"
438
322
 
439
- context 'validation' do
440
- it 'validates into custom schema' do
441
- resource = resource_class.new('urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {})
442
- expect(resource.valid?).to eql(false)
443
-
444
- resource = resource_class.new(
445
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => {
446
- userName: 'SOMEUSR',
447
- organization: 'SOMEORG',
448
- department: 'SOMEDPT'
449
- }
450
- )
451
-
452
- expect(resource.organization).to eql('SOMEORG')
453
- expect(resource.department ).to eql('SOMEDPT')
454
- expect(resource.valid? ).to eql(true)
455
- end
456
- end # context 'validation'
457
- end # "context '.resource_type' do"
458
-
459
- context '.find_attribute' do
460
- it 'finds in first schema' do
461
- found = resource_class().find_attribute('userName') # Defined in Scimitar::Schema::User
462
-
463
- expect(found).to be_present
464
- expect(found.name).to eql('userName')
465
- expect(found.type).to eql('string')
466
- end
323
+ context '.find_attribute' do
324
+ it 'finds in first schema' do
325
+ found = resource_class().find_attribute('name') # Defined in ThirdCustomSchema
326
+ expect(found).to be_present
327
+ expect(found.name).to eql('name')
328
+ expect(found.type).to eql('string')
329
+ end
467
330
 
468
- it 'finds across schemas' do
469
- found = resource_class().find_attribute('organization') # Defined in EnterpriseExtensionSchema
470
- expect(found).to be_present
471
- expect(found.name).to eql('organization')
472
- expect(found.type).to eql('string')
473
- end
474
- end # "context '.find_attribute' do"
475
- end # "context 'of core schema' do"
331
+ it 'finds across schemas' do
332
+ found = resource_class().find_attribute('relationship') # Defined in ExtensionSchema
333
+ expect(found).to be_present
334
+ expect(found.name).to eql('relationship')
335
+ expect(found.type).to eql('string')
336
+ end
337
+ end # "context '.find_attribute' do"
476
338
  end # "context 'schema extension' do"
477
339
  end
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Scimitar::Resources::Base do
4
+
4
5
  context '#valid?' do
5
6
  MyCustomSchema = Class.new(Scimitar::Schema::Base) do
6
7
  def self.id
@@ -20,9 +21,6 @@ RSpec.describe Scimitar::Resources::Base do
20
21
  ),
21
22
  Scimitar::Schema::Attribute.new(
22
23
  name: 'complexNames', complexType: Scimitar::ComplexTypes::Name, multiValued:true, required: false
23
- ),
24
- Scimitar::Schema::Attribute.new(
25
- name: 'vdtpTestByEmail', complexType: Scimitar::ComplexTypes::Email, required: false
26
24
  )
27
25
  ]
28
26
  end
@@ -59,28 +57,5 @@ RSpec.describe Scimitar::Resources::Base do
59
57
  expect(resource.valid?).to be(false)
60
58
  expect(resource.errors.full_messages).to match_array(["Complexnames has to follow the complexType format.", "Complexnames familyname has the wrong type. It has to be a(n) string."])
61
59
  end
62
-
63
- context 'configuration of required values in VDTP schema' do
64
- around :each do | example |
65
- original_configuration = Scimitar.engine_configuration.optional_value_fields_required
66
- Scimitar::Schema::Email.instance_variable_set('@scim_attributes', nil)
67
- example.run()
68
- ensure
69
- Scimitar.engine_configuration.optional_value_fields_required = original_configuration
70
- Scimitar::Schema::Email.instance_variable_set('@scim_attributes', nil)
71
- end
72
-
73
- it 'requires a value by default' do
74
- resource = MyCustomResource.new(vdtpTestByEmail: { value: nil }, enforce: false)
75
- expect(resource.valid?).to be(false)
76
- expect(resource.errors.full_messages).to match_array(['Vdtptestbyemail value is required'])
77
- end
78
-
79
- it 'can be configured for optional values' do
80
- Scimitar.engine_configuration.optional_value_fields_required = false
81
- resource = MyCustomResource.new(vdtpTestByEmail: { value: nil }, enforce: false)
82
- expect(resource.valid?).to be(true)
83
- end
84
- end # "context 'configuration of required values in VDTP schema' do"
85
- end # "context '#valid?' do"
60
+ end
86
61
  end