scimitar 2.1.1 → 2.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2418199bee8396f36fd0588b82f111b019d28b095d8830c82c808cc67323f220
4
- data.tar.gz: 0b3fcf08adbbc8d9385e245f4e55b3ca2e30c7a8ce254d9417e4a4ab3a662dcf
3
+ metadata.gz: 68d1c5d2f9f2b72a4582a04d6430b6fd7fd62ffc3fcdfe39422f2159acdcd3e1
4
+ data.tar.gz: 23a4d69326377dc1e68d3e1ff09d17a3adbc0e922bee7be6289acec2c4d790e4
5
5
  SHA512:
6
- metadata.gz: 3c52d9e9d70525d25e5c3cc9ee627a41e2de7946b53829525506716cb502076aa42fa2c6fa253edbee990799fe8bf6b1ae089325f6aeb8015f3a3f5b14eff5eb
7
- data.tar.gz: 41cfeb646bd77b2f0a53ccac2c5f94cbc1ca02261adc169ad21b3a96a7edc2cdcdcd75f4f0ef1e0e5ae387f8f4c3bd7c67382258515bd4612911bb5c15f85260
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()
@@ -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
@@ -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.1'
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-11-04'
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
@@ -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
@@ -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.1
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-11-04 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
@@ -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