scimitar 2.8.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +23 -18
  4. data/app/controllers/scimitar/application_controller.rb +4 -5
  5. data/app/controllers/scimitar/resource_types_controller.rb +7 -1
  6. data/app/controllers/scimitar/schemas_controller.rb +361 -1
  7. data/app/models/scimitar/engine_configuration.rb +3 -1
  8. data/app/models/scimitar/lists/query_parser.rb +10 -10
  9. data/app/models/scimitar/resource_type.rb +4 -6
  10. data/app/models/scimitar/resources/base.rb +37 -6
  11. data/app/models/scimitar/resources/mixin.rb +15 -10
  12. data/app/models/scimitar/schema/base.rb +1 -1
  13. data/config/initializers/scimitar.rb +41 -0
  14. data/lib/scimitar/engine.rb +50 -12
  15. data/lib/scimitar/support/utilities.rb +8 -3
  16. data/lib/scimitar/version.rb +2 -2
  17. data/spec/apps/dummy/app/models/mock_user.rb +11 -3
  18. data/spec/apps/dummy/config/initializers/scimitar.rb +29 -1
  19. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -0
  20. data/spec/apps/dummy/db/schema.rb +1 -0
  21. data/spec/controllers/scimitar/resource_types_controller_spec.rb +8 -4
  22. data/spec/controllers/scimitar/schemas_controller_spec.rb +342 -54
  23. data/spec/models/scimitar/lists/query_parser_spec.rb +5 -0
  24. data/spec/models/scimitar/resources/base_spec.rb +11 -11
  25. data/spec/models/scimitar/resources/base_validation_spec.rb +1 -1
  26. data/spec/models/scimitar/resources/mixin_spec.rb +31 -12
  27. data/spec/requests/active_record_backed_resources_controller_spec.rb +86 -2
  28. data/spec/requests/engine_spec.rb +75 -0
  29. data/spec/spec_helper.rb +1 -1
  30. metadata +21 -21
@@ -122,7 +122,15 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
122
122
  expect(result['Resources'].size).to eql(3)
123
123
 
124
124
  keys = result['Resources'].map { |resource| resource.keys }.flatten.uniq
125
- expect(keys).to match_array(%w[id meta name schemas urn:ietf:params:scim:schemas:extension:enterprise:2.0:User])
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
+ ])
126
134
  expect(result.dig('Resources', 0, 'id')).to eql @u1.primary_key.to_s
127
135
  expect(result.dig('Resources', 0, 'name', 'givenName')).to eql 'Foo'
128
136
  expect(result.dig('Resources', 0, 'name', 'familyName')).to eql 'Ark'
@@ -433,6 +441,76 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
433
441
  expect(new_mock.home_email_address).to eql('home_4@test.com')
434
442
  expect(new_mock.work_email_address).to eql('work_4@test.com')
435
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
436
514
  end # "shared_examples 'a creator' do | force_upper_case: |"
437
515
 
438
516
  context 'using schema-matched case' do
@@ -855,6 +933,9 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
855
933
  'organization' => 'Foo Bar!',
856
934
  'department' => 'Bar Foo!'
857
935
  },
936
+ 'urn:ietf:params:scim:schemas:extension:manager:1.0:User': {
937
+ 'manager' => 'Foo Baz!'
938
+ }
858
939
  },
859
940
  },
860
941
  ]
@@ -872,6 +953,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
872
953
 
873
954
  expect(@u2.organization).to eql('Foo Bar!')
874
955
  expect(@u2.department ).to eql('Bar Foo!')
956
+ expect(@u2.manager ).to eql('Foo Baz!')
875
957
  end
876
958
  end
877
959
 
@@ -886,7 +968,8 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
886
968
  op: 'add',
887
969
  value: {
888
970
  'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization' => 'Foo Bar!',
889
- '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!'
890
973
  },
891
974
  },
892
975
  ]
@@ -904,6 +987,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
904
987
 
905
988
  expect(@u2.organization).to eql('Foo Bar!')
906
989
  expect(@u2.department ).to eql('Bar Foo!')
990
+ expect(@u2.manager ).to eql('Foo Baz!')
907
991
  end
908
992
  end
909
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.8.0
4
+ version: 2.10.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-13 00:00:00.000000000 Z
12
+ date: 2024-10-22 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: '7.0'
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: '7.0'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: doggo
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -267,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
267
267
  - !ruby/object:Gem::Version
268
268
  version: '0'
269
269
  requirements: []
270
- rubygems_version: 3.5.4
270
+ rubygems_version: 3.5.16
271
271
  signing_key:
272
272
  specification_version: 4
273
273
  summary: SCIM v2 for Rails