scimitar 2.1.0 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d10a10d763c621e797fbe343a113a8610f9317a06455f177c60c42062663b4da
4
- data.tar.gz: 251c1b73b7dd51ded63d85f7b0816163a9bd567099db9ce5f57e4929301d7a49
3
+ metadata.gz: 68d1c5d2f9f2b72a4582a04d6430b6fd7fd62ffc3fcdfe39422f2159acdcd3e1
4
+ data.tar.gz: 23a4d69326377dc1e68d3e1ff09d17a3adbc0e922bee7be6289acec2c4d790e4
5
5
  SHA512:
6
- metadata.gz: 77accce401fb9f6fbb91a0ebf53294754286867cc2becce4f8acccbbd35f90c9062174d1da0e0ad4c80a92acc053c4a0b30898260fe95dc580bf3df33453f975
7
- data.tar.gz: 9e64bad4582b54c988f612f9a0920b291431a79f62f9656bcad2658c5a0ded291e9cf96f47cac5f2b130c47a30edbf3b68b6f8abe96ca9cb8a7bb8dcaea83bd2
6
+ metadata.gz: 98e7ececc69633a18c3e4f1b946f586959177223317a050edf8e1e8a916727f18f01e6cfb1103ff31a65c890708e6c85c41d42478636c9a4924efa99817b4a98
7
+ data.tar.gz: 9674932b834c16f8176340bfa826ebac4d06e6aade8c561c484f1031877f6803ef732210b43ed0613972fe44aeb98707a429a1f5a87388909c1a0694cdfe9f98
@@ -37,6 +37,7 @@ module Scimitar
37
37
  pagination_info = scim_pagination_info(query.count())
38
38
 
39
39
  page_of_results = query
40
+ .order(id: :asc)
40
41
  .offset(pagination_info.offset)
41
42
  .limit(pagination_info.limit)
42
43
  .to_a()
@@ -25,8 +25,8 @@ module Scimitar
25
25
  #
26
26
  # ...to "globally" invoke this handler if you wish.
27
27
  #
28
- # +_exception+:: Exception instance, used for a configured error reporter
29
- # via #handle_scim_error (if present).
28
+ # +exception+:: Exception instance, used for a configured error reporter
29
+ # via #handle_scim_error (if present).
30
30
  #
31
31
  def handle_resource_not_found(exception)
32
32
  handle_scim_error(NotFoundError.new(params[:id]), exception)
@@ -17,7 +17,7 @@ module Scimitar
17
17
  data
18
18
  end
19
19
 
20
- # From v1, Scimitar used attribute "detail" for the exception text; it was
20
+ # Originally Scimitar used attribute "detail" for exception text; it was
21
21
  # only for JSON responses at the time, but in hindsight was a bad choice.
22
22
  # It should have been "message" given inheritance from StandardError, which
23
23
  # then works properly with e.g. error reporting services.
@@ -78,7 +78,7 @@ module Scimitar
78
78
  # method's return value here.
79
79
  #
80
80
  def initialize(attribute_map)
81
- @attribute_map = attribute_map
81
+ @attribute_map = attribute_map.with_indifferent_case_insensitive_access()
82
82
  end
83
83
 
84
84
  # Parse SCIM filter query into RPN stack
@@ -605,6 +605,16 @@ module Scimitar
605
605
 
606
606
  raise Scimitar::FilterError unless all_supported
607
607
 
608
+ unless case_sensitive
609
+ lc_scim_attribute = scim_attribute.downcase()
610
+
611
+ case_sensitive = (
612
+ lc_scim_attribute == 'id' ||
613
+ lc_scim_attribute == 'externalid' ||
614
+ lc_scim_attribute.start_with?('meta.')
615
+ )
616
+ end
617
+
608
618
  column_names.each.with_index do | column_name, index |
609
619
  arel_column = arel_table[column_name]
610
620
  arel_operation = case scim_operator
@@ -902,7 +902,11 @@ module Scimitar
902
902
  altering_hash[path_component] = value
903
903
  end
904
904
  when 'replace'
905
- altering_hash[path_component] = value
905
+ if path_component == 'root'
906
+ altering_hash[path_component].merge!(value)
907
+ else
908
+ altering_hash[path_component] = value
909
+ end
906
910
  when 'remove'
907
911
  altering_hash.delete(path_component)
908
912
  end
@@ -3,11 +3,11 @@ module Scimitar
3
3
  # Gem version. If this changes, be sure to re-run "bundle install" or
4
4
  # "bundle update".
5
5
  #
6
- VERSION = '2.1.0'
6
+ VERSION = '2.1.3'
7
7
 
8
8
  # Date for VERSION. If this changes, be sure to re-run "bundle install"
9
9
  # or "bundle update".
10
10
  #
11
- DATE = '2022-07-14'
11
+ DATE = '2023-01-09'
12
12
 
13
13
  end
@@ -92,11 +92,14 @@ class MockUser < ActiveRecord::Base
92
92
 
93
93
  def self.scim_queryable_attributes
94
94
  return {
95
- 'name.givenName' => { column: :first_name },
96
- 'name.familyName' => { column: :last_name },
97
- 'emails' => { columns: [ :work_email_address, :home_email_address ] },
98
- 'emails.value' => { columns: [ :work_email_address, :home_email_address ] },
99
- 'emails.type' => { ignore: true } # We can't filter on that; it'll just search all e-mails
95
+ 'id' => { column: :id },
96
+ 'externalId' => { column: :scim_uid },
97
+ 'meta.lastModified' => { column: :updated_at },
98
+ 'name.givenName' => { column: :first_name },
99
+ 'name.familyName' => { column: :last_name },
100
+ 'emails' => { columns: [ :work_email_address, :home_email_address ] },
101
+ 'emails.value' => { columns: [ :work_email_address, :home_email_address ] },
102
+ 'emails.type' => { ignore: true } # We can't filter on that; it'll just search all e-mails
100
103
  }
101
104
  end
102
105
 
@@ -0,0 +1,5 @@
1
+ class AddTimestampsToMockUser < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_timestamps :mock_users
4
+ end
5
+ end
@@ -10,8 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2021_03_08_044214) do
14
-
13
+ ActiveRecord::Schema[7.0].define(version: 2023_01_09_012729) do
15
14
  # These are extensions that must be enabled in order to support this database
16
15
  enable_extension "plpgsql"
17
16
 
@@ -37,6 +36,8 @@ ActiveRecord::Schema.define(version: 2021_03_08_044214) do
37
36
  t.text "work_email_address"
38
37
  t.text "home_email_address"
39
38
  t.text "work_phone_number"
39
+ t.datetime "created_at", null: false
40
+ t.datetime "updated_at", null: false
40
41
  end
41
42
 
42
43
  end
@@ -208,7 +208,11 @@ RSpec.describe Scimitar::ApplicationController do
208
208
  context 'and bad JSON' do
209
209
  controller do
210
210
  def index
211
- raise ActionDispatch::Http::Parameters::ParseError.new("Hello")
211
+ begin
212
+ raise 'Hello'
213
+ rescue
214
+ raise ActionDispatch::Http::Parameters::ParseError
215
+ end
212
216
  end
213
217
  end
214
218
 
@@ -590,7 +590,7 @@ RSpec.describe Scimitar::Lists::QueryParser do
590
590
  end
591
591
 
592
592
  it 'complains if there is no column mapping available' do
593
- expect { @instance.send(:activerecord_columns, 'externalId') }.to raise_error(Scimitar::FilterError)
593
+ expect { @instance.send(:activerecord_columns, 'userName') }.to raise_error(Scimitar::FilterError)
594
594
  end
595
595
 
596
596
  it 'complains about malformed declarations' do
@@ -1747,6 +1747,24 @@ RSpec.describe Scimitar::Resources::Mixin do
1747
1747
  expect(scim_hash['emails'][0]['type' ]).to eql('work')
1748
1748
  expect(scim_hash['emails'][0]['value']).to eql('work@test.com')
1749
1749
  end
1750
+
1751
+ context 'when prior value already exists, and no path' do
1752
+ it 'simple value: overwrites' do
1753
+ path = [ 'root' ]
1754
+ scim_hash = { 'root' => { 'userName' => 'bar', 'active' => true } }.with_indifferent_case_insensitive_access()
1755
+
1756
+ @instance.send(
1757
+ :from_patch_backend!,
1758
+ nature: 'replace',
1759
+ path: path,
1760
+ value: { 'active' => false }.with_indifferent_case_insensitive_access(),
1761
+ altering_hash: scim_hash
1762
+ )
1763
+
1764
+ expect(scim_hash['root']['userName']).to eql('bar')
1765
+ expect(scim_hash['root']['active']).to eql(false)
1766
+ end
1767
+ end
1750
1768
  end # context 'when value is not present' do
1751
1769
  end # "context 'replace' do"
1752
1770
 
@@ -21,10 +21,8 @@ RSpec.describe Scimitar::Schema::Attribute do
21
21
  expect(name.type).to eql('complex')
22
22
  expect(name.subAttributes).to eql(Scimitar::Schema::Name.scim_attributes)
23
23
  end
24
-
25
24
  end
26
25
 
27
-
28
26
  context '#valid?' do
29
27
  it 'is invalid if attribute is required but value is blank' do
30
28
  attribute = described_class.new(name: 'userName', type: 'string', required: true)
@@ -76,5 +74,4 @@ RSpec.describe Scimitar::Schema::Attribute do
76
74
  expect(described_class.new(name: 'startDate', type: 'dateTime').valid?('gaga')).to be(false)
77
75
  end
78
76
  end
79
-
80
77
  end
@@ -1,12 +1,15 @@
1
1
  require 'spec_helper'
2
+ require 'time'
2
3
 
3
4
  RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
4
5
  before :each do
5
6
  allow_any_instance_of(Scimitar::ApplicationController).to receive(:authenticated?).and_return(true)
6
7
 
7
- @u1 = MockUser.create(username: '1', first_name: 'Foo', last_name: 'Ark', home_email_address: 'home_1@test.com')
8
- @u2 = MockUser.create(username: '2', first_name: 'Foo', last_name: 'Bar', home_email_address: 'home_2@test.com')
9
- @u3 = MockUser.create(username: '3', first_name: 'Foo', home_email_address: 'home_3@test.com')
8
+ lmt = Time.parse("2023-01-09 14:25:00 +1300")
9
+
10
+ @u1 = MockUser.create(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)
11
+ @u2 = MockUser.create(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)
12
+ @u3 = MockUser.create(username: '3', first_name: 'Foo', home_email_address: 'home_3@test.com', scim_uid: '003', created_at: lmt, updated_at: lmt + 3)
10
13
  end
11
14
 
12
15
  # ===========================================================================
@@ -48,7 +51,7 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
48
51
  it 'applies a filter, with case-insensitive value comparison' do
49
52
  get '/Users', params: {
50
53
  format: :scim,
51
- filter: 'name.givenName eq "Foo" and name.familyName pr and emails ne "home_1@TEST.COM"'
54
+ filter: 'name.givenName eq "FOO" and name.familyName pr and emails ne "home_1@test.com"'
52
55
  }
53
56
 
54
57
  expect(response.status).to eql(200)
@@ -64,6 +67,87 @@ RSpec.describe Scimitar::ActiveRecordBackedResourcesController do
64
67
  expect(usernames).to match_array(['2'])
65
68
  end
66
69
 
70
+ it 'applies a filter, with case-insensitive attribute matching (GitHub issue #37)' do
71
+ get '/Users', params: {
72
+ format: :scim,
73
+ filter: 'name.GIVENNAME eq "Foo" and name.Familyname pr and emails ne "home_1@test.com"'
74
+ }
75
+
76
+ expect(response.status).to eql(200)
77
+ result = JSON.parse(response.body)
78
+
79
+ expect(result['totalResults']).to eql(1)
80
+ expect(result['Resources'].size).to eql(1)
81
+
82
+ ids = result['Resources'].map { |resource| resource['id'] }
83
+ expect(ids).to match_array([@u2.id.to_s])
84
+
85
+ usernames = result['Resources'].map { |resource| resource['userName'] }
86
+ expect(usernames).to match_array(['2'])
87
+ end
88
+
89
+ # Strange attribute capitalisation in tests here builds on test coverage
90
+ # for now-fixed GitHub issue #37.
91
+ #
92
+ context '"meta" / IDs (GitHub issue #36)' do
93
+ it 'applies a filter on primary keys, using direct comparison (rather than e.g. case-insensitive operators)' do
94
+ get '/Users', params: {
95
+ format: :scim,
96
+ filter: "id eq \"#{@u3.id}\""
97
+ }
98
+
99
+ expect(response.status).to eql(200)
100
+ result = JSON.parse(response.body)
101
+
102
+ expect(result['totalResults']).to eql(1)
103
+ expect(result['Resources'].size).to eql(1)
104
+
105
+ ids = result['Resources'].map { |resource| resource['id'] }
106
+ expect(ids).to match_array([@u3.id.to_s])
107
+
108
+ usernames = result['Resources'].map { |resource| resource['userName'] }
109
+ expect(usernames).to match_array(['3'])
110
+ end
111
+
112
+ it 'applies a filter on external IDs, using direct comparison' do
113
+ get '/Users', params: {
114
+ format: :scim,
115
+ filter: "externalID eq \"#{@u2.scim_uid}\""
116
+ }
117
+
118
+ expect(response.status).to eql(200)
119
+ result = JSON.parse(response.body)
120
+
121
+ expect(result['totalResults']).to eql(1)
122
+ expect(result['Resources'].size).to eql(1)
123
+
124
+ ids = result['Resources'].map { |resource| resource['id'] }
125
+ expect(ids).to match_array([@u2.id.to_s])
126
+
127
+ usernames = result['Resources'].map { |resource| resource['userName'] }
128
+ expect(usernames).to match_array(['2'])
129
+ end
130
+
131
+ it 'applies a filter on "meta" entries, using direct comparison' do
132
+ get '/Users', params: {
133
+ format: :scim,
134
+ filter: "Meta.LastModified eq \"#{@u3.updated_at}\""
135
+ }
136
+
137
+ expect(response.status).to eql(200)
138
+ result = JSON.parse(response.body)
139
+
140
+ expect(result['totalResults']).to eql(1)
141
+ expect(result['Resources'].size).to eql(1)
142
+
143
+ ids = result['Resources'].map { |resource| resource['id'] }
144
+ expect(ids).to match_array([@u3.id.to_s])
145
+
146
+ usernames = result['Resources'].map { |resource| resource['userName'] }
147
+ expect(usernames).to match_array(['3'])
148
+ end
149
+ end # "context '"meta" / IDs (GitHub issue #36)' do"
150
+
67
151
  it 'obeys a page size' do
68
152
  get '/Users', params: {
69
153
  format: :scim,
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.1.0
4
+ version: 2.1.3
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: 2022-07-14 00:00:00.000000000 Z
12
+ date: 2023-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -211,6 +211,7 @@ files:
211
211
  - spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb
212
212
  - spec/apps/dummy/db/migrate/20210308020313_create_mock_groups.rb
213
213
  - spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb
214
+ - spec/apps/dummy/db/migrate/20230109012729_add_timestamps_to_mock_user.rb
214
215
  - spec/apps/dummy/db/schema.rb
215
216
  - spec/controllers/scimitar/application_controller_spec.rb
216
217
  - spec/controllers/scimitar/resource_types_controller_spec.rb
@@ -260,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
260
261
  - !ruby/object:Gem::Version
261
262
  version: '0'
262
263
  requirements: []
263
- rubygems_version: 3.3.7
264
+ rubygems_version: 3.3.13
264
265
  signing_key:
265
266
  specification_version: 4
266
267
  summary: SCIM v2 for Rails
@@ -282,6 +283,7 @@ test_files:
282
283
  - spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb
283
284
  - spec/apps/dummy/db/migrate/20210308020313_create_mock_groups.rb
284
285
  - spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb
286
+ - spec/apps/dummy/db/migrate/20230109012729_add_timestamps_to_mock_user.rb
285
287
  - spec/apps/dummy/db/schema.rb
286
288
  - spec/controllers/scimitar/application_controller_spec.rb
287
289
  - spec/controllers/scimitar/resource_types_controller_spec.rb