scimitar 1.4.0 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -693,6 +693,142 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
693
693
  result = JSON.parse(response.body)
694
694
  expect(result['status']).to eql('404')
695
695
  end
696
+
697
+ context 'when removing users from groups' do
698
+ before :each do
699
+ @g1.mock_users << @u1
700
+ @g1.mock_users << @u2
701
+ @g1.mock_users << @u3
702
+
703
+ # (Self-check) Verify group representation
704
+ #
705
+ get "/Groups/#{@g1.id}", params: { format: :scim }
706
+
707
+ expect(response.status).to eql(200)
708
+ result = JSON.parse(response.body)
709
+
710
+ expect(result['members'].map { |m| m['value'] }.sort()).to eql(MockUser.pluck(:primary_key).sort())
711
+ end
712
+
713
+ it 'can remove all users' do
714
+ expect {
715
+ expect {
716
+ patch "/Groups/#{@g1.id}", params: {
717
+ format: :scim,
718
+ Operations: [
719
+ {
720
+ op: 'remove',
721
+ path: 'members'
722
+ }
723
+ ]
724
+ }
725
+ }.to_not change { MockUser.count }
726
+ }.to_not change { MockGroup.count }
727
+
728
+ get "/Groups/#{@g1.id}", params: { format: :scim }
729
+
730
+ expect(response.status).to eql(200)
731
+ result = JSON.parse(response.body)
732
+
733
+ expect(result['members']).to be_empty
734
+ expect(@g1.reload().mock_users).to be_empty
735
+ end
736
+
737
+ # Define via 'let':
738
+ #
739
+ # * Hash 'payload', to send via 'patch'
740
+ # * MockUser 'removed_user', which is the user that should be removed
741
+ #
742
+ shared_examples 'a user remover' do
743
+ it 'which removes the identified user' do
744
+ expect {
745
+ expect {
746
+ patch "/Groups/#{@g1.id}", params: payload()
747
+ }.to_not change { MockUser.count }
748
+ }.to_not change { MockGroup.count }
749
+
750
+ expected_remaining_user_ids = MockUser
751
+ .where.not(primary_key: removed_user().id)
752
+ .pluck(:primary_key)
753
+ .sort()
754
+
755
+ get "/Groups/#{@g1.id}", params: { format: :scim }
756
+
757
+ expect(response.status).to eql(200)
758
+ result = JSON.parse(response.body)
759
+
760
+ expect(result['members'].map { |m| m['value'] }.sort()).to eql(expected_remaining_user_ids)
761
+ expect(@g1.reload().mock_users.map(&:primary_key).sort()).to eql(expected_remaining_user_ids)
762
+ end
763
+ end
764
+
765
+ # https://tools.ietf.org/html/rfc7644#section-3.5.2.2
766
+ #
767
+ context 'and using an RFC-compliant payload' do
768
+ let(:removed_user) { @u2 }
769
+ let(:payload) do
770
+ {
771
+ format: :scim,
772
+ Operations: [
773
+ {
774
+ op: 'remove',
775
+ path: "members[value eq \"#{removed_user().primary_key}\"]",
776
+ }
777
+ ]
778
+ }
779
+ end
780
+
781
+ it_behaves_like 'a user remover'
782
+ end # context 'and using an RFC-compliant payload' do
783
+
784
+ # https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#update-group-remove-members
785
+ #
786
+ context 'and using a Microsoft variant payload' do
787
+ let(:removed_user) { @u2 }
788
+ let(:payload) do
789
+ {
790
+ format: :scim,
791
+ Operations: [
792
+ {
793
+ op: 'remove',
794
+ path: 'members',
795
+ value: [{
796
+ '$ref' => nil,
797
+ 'value' => removed_user().primary_key
798
+ }]
799
+ }
800
+ ]
801
+ }
802
+ end
803
+
804
+ it_behaves_like 'a user remover'
805
+ end # context 'and using a Microsoft variant payload' do
806
+
807
+ # https://help.salesforce.com/s/articleView?id=sf.identity_scim_manage_groups.htm&type=5
808
+ #
809
+ context 'and using a Salesforce variant payload' do
810
+ let(:removed_user) { @u2 }
811
+ let(:payload) do
812
+ {
813
+ format: :scim,
814
+ Operations: [
815
+ {
816
+ op: 'remove',
817
+ path: 'members',
818
+ value: {
819
+ 'members' => [{
820
+ '$ref' => nil,
821
+ 'value' => removed_user().primary_key
822
+ }]
823
+ }
824
+ }
825
+ ]
826
+ }
827
+ end
828
+
829
+ it_behaves_like 'a user remover'
830
+ end # context 'and using a Salesforce variant payload' do
831
+ end # "context 'when removing users from groups' do"
696
832
  end # "context '#update' do"
697
833
 
698
834
  # ===========================================================================
@@ -39,6 +39,16 @@ RSpec.describe Scimitar::ApplicationController do
39
39
  expect(parsed_body['request']['content_type']).to eql('application/scim+json')
40
40
  end
41
41
 
42
+ it 'translates Content-Type with charset to Rails request format' do
43
+ get '/CustomRequestVerifiers', headers: { 'CONTENT_TYPE' => 'application/scim+json; charset=utf-8' }
44
+
45
+ expect(response).to have_http_status(:ok)
46
+ parsed_body = JSON.parse(response.body)
47
+ expect(parsed_body['request']['is_scim' ]).to eql(true)
48
+ expect(parsed_body['request']['format' ]).to eql('application/scim+json')
49
+ expect(parsed_body['request']['content_type']).to eql('application/scim+json; charset=utf-8')
50
+ end
51
+
42
52
  it 'translates Rails request format to header' do
43
53
  get '/CustomRequestVerifiers', params: { format: :scim }
44
54
 
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.4.0
4
+ version: 1.5.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: 2023-01-26 00:00:00.000000000 Z
12
+ date: 2023-03-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails