scimitar 1.8.1 → 1.8.2

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.
@@ -14,7 +14,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
14
14
  ids = 3.times.map { SecureRandom.uuid }.sort()
15
15
 
16
16
  @u1 = MockUser.create!(primary_key: ids.shift(), username: '1', first_name: 'Foo', last_name: 'Ark', home_email_address: 'home_1@test.com', scim_uid: '001', created_at: lmt, updated_at: lmt + 1)
17
- @u2 = MockUser.create!(primary_key: ids.shift(), username: '2', first_name: 'Foo', last_name: 'Bar', home_email_address: 'home_2@test.com', scim_uid: '002', created_at: lmt, updated_at: lmt + 2)
17
+ @u2 = MockUser.create!(primary_key: ids.shift(), username: '2', first_name: 'Foo', last_name: 'Bar', home_email_address: 'home_2@test.com', scim_uid: '002', created_at: lmt, updated_at: lmt + 2, password: 'oldpassword')
18
18
  @u3 = MockUser.create!(primary_key: ids.shift(), username: '3', first_name: 'Foo', home_email_address: 'home_3@test.com', scim_uid: '003', created_at: lmt, updated_at: lmt + 3)
19
19
 
20
20
  @g1 = MockGroup.create!(display_name: 'Group 1')
@@ -345,6 +345,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
345
345
 
346
346
  attributes = {
347
347
  userName: '4',
348
+ password: 'correcthorsebatterystaple',
348
349
  name: {
349
350
  givenName: 'Given',
350
351
  familyName: 'Family'
@@ -379,6 +380,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
379
380
  expect(result['id']).to eql(new_mock.id.to_s)
380
381
  expect(result['meta']['resourceType']).to eql('User')
381
382
  expect(new_mock.username).to eql('4')
383
+ expect(new_mock.password).to eql('correcthorsebatterystaple')
382
384
  expect(new_mock.first_name).to eql('Given')
383
385
  expect(new_mock.last_name).to eql('Family')
384
386
  expect(new_mock.home_email_address).to eql('home_4@test.com')
@@ -511,6 +513,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
511
513
  expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
512
514
 
513
515
  result = JSON.parse(response.body)
516
+
514
517
  expect(result['scimType']).to eql('invalidValue')
515
518
  expect(result['detail']).to include('is reserved')
516
519
  end
@@ -522,14 +525,41 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
522
525
  context '#replace' do
523
526
  shared_examples 'a replacer' do | force_upper_case: |
524
527
  it 'which replaces all attributes in an instance' do
525
- attributes = { userName: '4' } # Minimum required by schema
528
+ attributes = { userName: '4' } # Minimum required by schema
526
529
  attributes = spec_helper_hupcase(attributes) if force_upper_case
527
530
 
528
531
  # Prove that certain known pathways are called; can then unit test
529
532
  # those if need be and be sure that this covers #replace actions.
530
533
  #
531
534
  expect_any_instance_of(MockUsersController).to receive(:replace).once.and_call_original
532
- expect_any_instance_of(MockUsersController).to receive(:save! ).once.and_call_original
535
+ expect_any_instance_of(MockUsersController).to receive(:save! ).once.and_call_original
536
+ expect {
537
+ put "/Users/#{@u2.primary_key}", params: attributes.merge(format: :scim)
538
+ }.to_not change { MockUser.count }
539
+
540
+ expect(response.status ).to eql(200)
541
+ expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
542
+
543
+ result = JSON.parse(response.body)
544
+
545
+ expect(result['id']).to eql(@u2.primary_key.to_s)
546
+ expect(result['meta']['resourceType']).to eql('User')
547
+
548
+ expect(result).to have_key('name')
549
+ expect(result).to_not have_key('password')
550
+
551
+ @u2.reload
552
+
553
+ expect(@u2.username).to eql('4')
554
+ expect(@u2.first_name).to be_nil
555
+ expect(@u2.last_name).to be_nil
556
+ expect(@u2.home_email_address).to be_nil
557
+ expect(@u2.password).to be_nil
558
+ end
559
+
560
+ it 'can replace passwords' do
561
+ attributes = { userName: '4', password: 'correcthorsebatterystaple' }
562
+ attributes = spec_helper_hupcase(attributes) if force_upper_case
533
563
 
534
564
  expect {
535
565
  put "/Users/#{@u2.primary_key}", params: attributes.merge(format: :scim)
@@ -543,12 +573,16 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
543
573
  expect(result['id']).to eql(@u2.primary_key.to_s)
544
574
  expect(result['meta']['resourceType']).to eql('User')
545
575
 
576
+ expect(result).to have_key('name')
577
+ expect(result).to_not have_key('password')
578
+
546
579
  @u2.reload
547
580
 
548
581
  expect(@u2.username).to eql('4')
549
582
  expect(@u2.first_name).to be_nil
550
583
  expect(@u2.last_name).to be_nil
551
584
  expect(@u2.home_email_address).to be_nil
585
+ expect(@u2.password).to eql('correcthorsebatterystaple')
552
586
  end
553
587
  end # "shared_examples 'a replacer' do | force_upper_case: |"
554
588
 
@@ -626,7 +660,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
626
660
 
627
661
  context 'with a block' do
628
662
  it 'invokes the block' do
629
- attributes = { userName: '4' } # Minimum required by schema
663
+ attributes = { userName: '4' } # Minimum required by schema
630
664
 
631
665
  expect_any_instance_of(CustomReplaceMockUsersController).to receive(:replace).once.and_call_original
632
666
  expect {
@@ -681,7 +715,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
681
715
 
682
716
  context '#update' do
683
717
  shared_examples 'an updater' do | force_upper_case: |
684
- it 'which patches specific attributes' do
718
+ it 'which patches regular attributes' do
685
719
  payload = {
686
720
  Operations: [
687
721
  {
@@ -717,6 +751,9 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
717
751
  expect(result['id']).to eql(@u2.primary_key.to_s)
718
752
  expect(result['meta']['resourceType']).to eql('User')
719
753
 
754
+ expect(result).to have_key('name')
755
+ expect(result).to_not have_key('password')
756
+
720
757
  @u2.reload
721
758
 
722
759
  expect(@u2.username).to eql('4')
@@ -724,6 +761,45 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
724
761
  expect(@u2.last_name).to eql('Bar')
725
762
  expect(@u2.home_email_address).to eql('home_2@test.com')
726
763
  expect(@u2.work_email_address).to eql('work_4@test.com')
764
+ expect(@u2.password).to eql('oldpassword')
765
+ end
766
+
767
+ it 'which patches "returned: \'never\'" fields' do
768
+ payload = {
769
+ Operations: [
770
+ {
771
+ op: 'replace',
772
+ path: 'password',
773
+ value: 'correcthorsebatterystaple'
774
+ }
775
+ ]
776
+ }
777
+
778
+ payload = spec_helper_hupcase(payload) if force_upper_case
779
+
780
+ expect {
781
+ patch "/Users/#{@u2.primary_key}", params: payload.merge(format: :scim)
782
+ }.to_not change { MockUser.count }
783
+
784
+ expect(response.status ).to eql(200)
785
+ expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
786
+
787
+ result = JSON.parse(response.body)
788
+
789
+ expect(result['id']).to eql(@u2.primary_key.to_s)
790
+ expect(result['meta']['resourceType']).to eql('User')
791
+
792
+ expect(result).to have_key('name')
793
+ expect(result).to_not have_key('password')
794
+
795
+ @u2.reload
796
+
797
+ expect(@u2.username).to eql('2')
798
+ expect(@u2.first_name).to eql('Foo')
799
+ expect(@u2.last_name).to eql('Bar')
800
+ expect(@u2.home_email_address).to eql('home_2@test.com')
801
+ expect(@u2.work_email_address).to be_nil
802
+ expect(@u2.password).to eql('correcthorsebatterystaple')
727
803
  end
728
804
 
729
805
  context 'which clears attributes' do
@@ -37,6 +37,114 @@ RSpec.describe Scimitar::Support::HashWithIndifferentCaseInsensitiveAccess do
37
37
  expect(subject()).to_not have_key('bar')
38
38
  end
39
39
  end # "context 'where keys set as symbols' do"
40
+
41
+ context 'access and merging' do
42
+ before :each do
43
+ @original_subject = subject().to_h().dup()
44
+ end
45
+
46
+ it 'returns keys as Strings' do
47
+ subject()[:foo] = 1
48
+ subject()[:BAR] = 2
49
+
50
+ expect(subject().keys).to match_array(@original_subject.keys + ['foo', 'BAR'])
51
+ end
52
+
53
+ it 'retains original case of keys' do
54
+ subject()[:foo ] = 1
55
+ subject()['FoO'] = 40 # (first-time-set case preservation test in passing)
56
+ subject()[:BAR ] = 2
57
+ subject()['Baz'] = 3
58
+
59
+ expectation = @original_subject.merge({
60
+ 'foo' => 40,
61
+ 'BAR' => 2,
62
+ 'Baz' => 3
63
+ })
64
+
65
+ expect(subject()).to eql(expectation)
66
+ end
67
+
68
+ it '#merge does not mutate the receiver and retains case of first-set keys' do
69
+ subject()[:foo] = 1
70
+ subject()[:BAR] = 2
71
+
72
+ pre_merge_subject = subject().dup()
73
+
74
+ result = subject().merge({:FOO => { 'onE' => 40 }, :Baz => 3})
75
+ expectation = @original_subject.merge({
76
+ 'foo' => { 'onE' => 40 },
77
+ 'BAR' => 2,
78
+ 'Baz' => 3
79
+ })
80
+
81
+ expect(subject()).to eql(pre_merge_subject)
82
+ expect(result).to eql(expectation)
83
+ end
84
+
85
+ it '#merge! mutates the receiver retains case of first-set keys' do
86
+ subject()[:foo] = 1
87
+ subject()[:BAR] = 2
88
+
89
+ subject().merge!({:FOO => { 'onE' => 40 }, :Baz => 3})
90
+
91
+ expectation = @original_subject.merge({
92
+ 'foo' => { 'onE' => 40 },
93
+ 'BAR' => 2,
94
+ 'Baz' => 3
95
+ })
96
+
97
+ expect(subject()).to eql(expectation)
98
+ end
99
+
100
+ it '#deep_merge does not mutate the receiver and retains nested key cases' do
101
+ subject()[:foo] = { :one => 10 }
102
+ subject()[:BAR] = 2
103
+
104
+ pre_merge_subject = subject().dup()
105
+
106
+ result = subject().deep_merge({:FOO => { 'ONE' => 40, :TWO => 20 }, :Baz => 3})
107
+ expectation = @original_subject.merge({
108
+ 'foo' => { 'one' => 40, 'TWO' => 20 },
109
+ 'BAR' => 2,
110
+ 'Baz' => 3
111
+ })
112
+
113
+ expect(subject()).to eql(pre_merge_subject)
114
+ expect(result).to eql(expectation)
115
+ end
116
+
117
+ it '#deep_merge! mutates the receiver and retains nested key cases' do
118
+ subject()[:foo] = { :one => 10 }
119
+ subject()[:BAR] = 2
120
+
121
+ subject().deep_merge!({:FOO => { 'ONE' => 40, :TWO => 20 }, :Baz => 3})
122
+
123
+ expectation = @original_subject.merge({
124
+ 'foo' => { 'one' => 40, 'TWO' => 20 },
125
+ 'BAR' => 2,
126
+ 'Baz' => 3
127
+ })
128
+
129
+ expect(subject()).to eql(expectation)
130
+ end
131
+
132
+ it 'retains indifferent behaviour after duplication' do
133
+ subject()[:foo] = { 'onE' => 40 }
134
+ subject()[:BAR] = 2
135
+
136
+ duplicate = subject().dup()
137
+ duplicate.merge!({ 'FOO' => true, 'baz' => 3 })
138
+
139
+ expectation = @original_subject.merge({
140
+ 'foo' => true,
141
+ 'BAR' => 2,
142
+ 'baz' => 3
143
+ })
144
+
145
+ expect(duplicate.to_h).to eql(expectation.to_h)
146
+ end
147
+ end # "context 'access and merging' do"
40
148
  end # "shared_examples 'an indifferent access, case insensitive Hash' do"
41
149
 
42
150
  context 'when created directly' do
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: 1.8.1
4
+ version: 1.8.2
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-01-16 00:00:00.000000000 Z
12
+ date: 2024-03-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails