scimitar 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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')
@@ -523,14 +525,14 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
523
525
  context '#replace' do
524
526
  shared_examples 'a replacer' do | force_upper_case: |
525
527
  it 'which replaces all attributes in an instance' do
526
- attributes = { userName: '4' } # Minimum required by schema
528
+ attributes = { userName: '4' } # Minimum required by schema
527
529
  attributes = spec_helper_hupcase(attributes) if force_upper_case
528
530
 
529
531
  # Prove that certain known pathways are called; can then unit test
530
532
  # those if need be and be sure that this covers #replace actions.
531
533
  #
532
534
  expect_any_instance_of(MockUsersController).to receive(:replace).once.and_call_original
533
- 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
534
536
  expect {
535
537
  put "/Users/#{@u2.primary_key}", params: attributes.merge(format: :scim)
536
538
  }.to_not change { MockUser.count }
@@ -543,12 +545,44 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
543
545
  expect(result['id']).to eql(@u2.primary_key.to_s)
544
546
  expect(result['meta']['resourceType']).to eql('User')
545
547
 
548
+ expect(result).to have_key('name')
549
+ expect(result).to_not have_key('password')
550
+
546
551
  @u2.reload
547
552
 
548
553
  expect(@u2.username).to eql('4')
549
554
  expect(@u2.first_name).to be_nil
550
555
  expect(@u2.last_name).to be_nil
551
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
563
+
564
+ expect {
565
+ put "/Users/#{@u2.primary_key}", params: attributes.merge(format: :scim)
566
+ }.to_not change { MockUser.count }
567
+
568
+ expect(response.status ).to eql(200)
569
+ expect(response.headers['Content-Type']).to eql('application/scim+json; charset=utf-8')
570
+
571
+ result = JSON.parse(response.body)
572
+
573
+ expect(result['id']).to eql(@u2.primary_key.to_s)
574
+ expect(result['meta']['resourceType']).to eql('User')
575
+
576
+ expect(result).to have_key('name')
577
+ expect(result).to_not have_key('password')
578
+
579
+ @u2.reload
580
+
581
+ expect(@u2.username).to eql('4')
582
+ expect(@u2.first_name).to be_nil
583
+ expect(@u2.last_name).to be_nil
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: 2.7.1
4
+ version: 2.7.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