scimaenaga 0.7.0 → 0.9.1
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 +4 -4
- data/README.md +22 -7
- data/Rakefile +6 -8
- data/app/controllers/concerns/{scim_rails → scimaenaga}/exception_handler.rb +47 -37
- data/app/controllers/concerns/scimaenaga/response.rb +94 -0
- data/app/controllers/scimaenaga/application_controller.rb +72 -0
- data/app/controllers/{scim_rails → scimaenaga}/scim_groups_controller.rb +26 -26
- data/app/controllers/scimaenaga/scim_schemas_controller.rb +42 -0
- data/app/controllers/scimaenaga/scim_users_controller.rb +104 -0
- data/app/helpers/{scim_rails → scimaenaga}/application_helper.rb +1 -1
- data/app/libraries/scim_patch.rb +16 -9
- data/app/libraries/scim_patch_operation.rb +51 -141
- data/app/libraries/scim_patch_operation_converter.rb +90 -0
- data/app/libraries/scim_patch_operation_group.rb +100 -0
- data/app/libraries/scim_patch_operation_user.rb +53 -0
- data/app/models/{scim_rails → scimaenaga}/application_record.rb +1 -1
- data/app/models/scimaenaga/authorize_api_request.rb +39 -0
- data/app/models/{scim_rails → scimaenaga}/scim_count.rb +8 -4
- data/app/models/scimaenaga/scim_query_parser.rb +49 -0
- data/config/routes.rb +15 -13
- data/lib/generators/scimaenaga/USAGE +8 -0
- data/lib/generators/scimaenaga/scimaenaga_generator.rb +7 -0
- data/lib/generators/{scim_rails → scimaenaga}/templates/initializer.rb +128 -22
- data/lib/{scim_rails → scimaenaga}/config.rb +9 -7
- data/lib/scimaenaga/encoder.rb +27 -0
- data/lib/scimaenaga/engine.rb +12 -0
- data/lib/scimaenaga/version.rb +5 -0
- data/lib/scimaenaga.rb +6 -0
- data/lib/tasks/{scim_rails_tasks.rake → scimaenaga_tasks.rake} +1 -1
- data/spec/controllers/{scim_rails → scimaenaga}/scim_groups_controller_spec.rb +8 -8
- data/spec/controllers/{scim_rails → scimaenaga}/scim_groups_request_spec.rb +18 -18
- data/spec/controllers/scimaenaga/scim_schemas_controller_spec.rb +238 -0
- data/spec/controllers/scimaenaga/scim_schemas_request_spec.rb +39 -0
- data/spec/controllers/{scim_rails → scimaenaga}/scim_users_controller_spec.rb +14 -15
- data/spec/controllers/{scim_rails → scimaenaga}/scim_users_request_spec.rb +20 -20
- data/spec/dummy/app/assets/config/manifest.js +1 -1
- data/spec/dummy/config/application.rb +1 -2
- data/spec/dummy/config/initializers/{scim_rails_config.rb → scimaenaga_config.rb} +25 -25
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/factories/company.rb +3 -3
- data/spec/lib/scimaenaga/encoder_spec.rb +64 -0
- data/spec/libraries/scim_patch_operation_group_spec.rb +165 -0
- data/spec/libraries/scim_patch_operation_user_spec.rb +101 -0
- data/spec/libraries/scim_patch_spec.rb +129 -45
- data/spec/models/scim_query_parser_spec.rb +5 -6
- metadata +107 -108
- data/app/controllers/concerns/scim_rails/response.rb +0 -94
- data/app/controllers/scim_rails/application_controller.rb +0 -72
- data/app/controllers/scim_rails/scim_users_controller.rb +0 -107
- data/app/models/scim_rails/authorize_api_request.rb +0 -40
- data/app/models/scim_rails/scim_query_parser.rb +0 -49
- data/lib/generators/scim_rails/USAGE +0 -8
- data/lib/generators/scim_rails/scim_rails_generator.rb +0 -7
- data/lib/scim_rails/encoder.rb +0 -25
- data/lib/scim_rails/engine.rb +0 -12
- data/lib/scim_rails/version.rb +0 -5
- data/lib/scim_rails.rb +0 -6
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +0 -0
- data/spec/dummy/log/test.log +0 -5770
- data/spec/dummy/put_group.http +0 -5
- data/spec/dummy/tmp/restart.txt +0 -0
- data/spec/lib/scim_rails/encoder_spec.rb +0 -62
- data/spec/libraries/scim_patch_operation_spec.rb +0 -116
@@ -0,0 +1,238 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Scimaenaga::ScimSchemasController, type: :controller do
|
6
|
+
include AuthHelper
|
7
|
+
|
8
|
+
routes { Scimaenaga::Engine.routes }
|
9
|
+
|
10
|
+
let(:schemas) do
|
11
|
+
[
|
12
|
+
{
|
13
|
+
schemas: ['urn:ietf:params:scim:schemas:core:2.0:Schema'],
|
14
|
+
id: 'urn:ietf:params:scim:schemas:core:2.0:User',
|
15
|
+
name: 'User',
|
16
|
+
description: 'User Account',
|
17
|
+
attributes: [
|
18
|
+
{
|
19
|
+
name: 'userName',
|
20
|
+
type: 'string',
|
21
|
+
multiValued: false,
|
22
|
+
description: 'Unique identifier for the User. REQUIRED.',
|
23
|
+
required: true,
|
24
|
+
caseExact: false,
|
25
|
+
mutability: 'readWrite',
|
26
|
+
returned: 'default',
|
27
|
+
uniqueness: 'server',
|
28
|
+
}
|
29
|
+
],
|
30
|
+
meta: {
|
31
|
+
resourceType: 'Schema',
|
32
|
+
location:
|
33
|
+
'/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:User',
|
34
|
+
},
|
35
|
+
},
|
36
|
+
{
|
37
|
+
schemas: ['urn:ietf:params:scim:schemas:core:2.0:Schema'],
|
38
|
+
id: 'urn:ietf:params:scim:schemas:core:2.0:Group',
|
39
|
+
name: 'Group',
|
40
|
+
description: 'Group',
|
41
|
+
attributes: [
|
42
|
+
{
|
43
|
+
name: 'displayName',
|
44
|
+
type: 'string',
|
45
|
+
multiValued: false,
|
46
|
+
description: 'A human-readable name for the Group. REQUIRED.',
|
47
|
+
required: false,
|
48
|
+
caseExact: false,
|
49
|
+
mutability: 'readWrite',
|
50
|
+
returned: 'default',
|
51
|
+
uniqueness: 'none',
|
52
|
+
}
|
53
|
+
],
|
54
|
+
meta: {
|
55
|
+
resourceType: 'Schema',
|
56
|
+
location: '/v2/Schemas/urn:ietf:params:scim:schemas:core:2.0:Group',
|
57
|
+
},
|
58
|
+
}
|
59
|
+
]
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:schemas_110) do
|
63
|
+
[
|
64
|
+
{ id: 'dummy1' }, { id: 'dummy2' }, { id: 'dummy3' },
|
65
|
+
{ id: 'dummy4' }, { id: 'dummy5' }, { id: 'dummy6' },
|
66
|
+
{ id: 'dummy7' }, { id: 'dummy8' }, { id: 'dummy9' },
|
67
|
+
{ id: 'dummy10' }, { id: 'dummy11' }, { id: 'dummy12' },
|
68
|
+
{ id: 'dummy13' }, { id: 'dummy14' }, { id: 'dummy15' },
|
69
|
+
{ id: 'dummy16' }, { id: 'dummy17' }, { id: 'dummy18' },
|
70
|
+
{ id: 'dummy19' }, { id: 'dummy20' }, { id: 'dummy21' },
|
71
|
+
{ id: 'dummy22' }, { id: 'dummy23' }, { id: 'dummy24' },
|
72
|
+
{ id: 'dummy25' }, { id: 'dummy26' }, { id: 'dummy27' },
|
73
|
+
{ id: 'dummy28' }, { id: 'dummy29' }, { id: 'dummy30' },
|
74
|
+
{ id: 'dummy31' }, { id: 'dummy32' }, { id: 'dummy33' },
|
75
|
+
{ id: 'dummy34' }, { id: 'dummy35' }, { id: 'dummy36' },
|
76
|
+
{ id: 'dummy37' }, { id: 'dummy38' }, { id: 'dummy39' },
|
77
|
+
{ id: 'dummy40' }, { id: 'dummy41' }, { id: 'dummy42' },
|
78
|
+
{ id: 'dummy43' }, { id: 'dummy44' }, { id: 'dummy45' },
|
79
|
+
{ id: 'dummy46' }, { id: 'dummy47' }, { id: 'dummy48' },
|
80
|
+
{ id: 'dummy49' }, { id: 'dummy50' }, { id: 'dummy51' },
|
81
|
+
{ id: 'dummy52' }, { id: 'dummy53' }, { id: 'dummy54' },
|
82
|
+
{ id: 'dummy55' }, { id: 'dummy56' }, { id: 'dummy57' },
|
83
|
+
{ id: 'dummy58' }, { id: 'dummy59' }, { id: 'dummy60' },
|
84
|
+
{ id: 'dummy61' }, { id: 'dummy62' }, { id: 'dummy63' },
|
85
|
+
{ id: 'dummy64' }, { id: 'dummy65' }, { id: 'dummy66' },
|
86
|
+
{ id: 'dummy67' }, { id: 'dummy68' }, { id: 'dummy69' },
|
87
|
+
{ id: 'dummy70' }, { id: 'dummy71' }, { id: 'dummy72' },
|
88
|
+
{ id: 'dummy73' }, { id: 'dummy74' }, { id: 'dummy75' },
|
89
|
+
{ id: 'dummy76' }, { id: 'dummy77' }, { id: 'dummy78' },
|
90
|
+
{ id: 'dummy79' }, { id: 'dummy80' }, { id: 'dummy81' },
|
91
|
+
{ id: 'dummy82' }, { id: 'dummy83' }, { id: 'dummy84' },
|
92
|
+
{ id: 'dummy85' }, { id: 'dummy86' }, { id: 'dummy87' },
|
93
|
+
{ id: 'dummy88' }, { id: 'dummy89' }, { id: 'dummy90' },
|
94
|
+
{ id: 'dummy91' }, { id: 'dummy92' }, { id: 'dummy93' },
|
95
|
+
{ id: 'dummy94' }, { id: 'dummy95' }, { id: 'dummy96' },
|
96
|
+
{ id: 'dummy97' }, { id: 'dummy98' }, { id: 'dummy99' },
|
97
|
+
{ id: 'dummy100' }, { id: 'dummy101' }, { id: 'dummy102' },
|
98
|
+
{ id: 'dummy103' }, { id: 'dummy104' }, { id: 'dummy105' },
|
99
|
+
{ id: 'dummy106' }, { id: 'dummy107' }, { id: 'dummy108' },
|
100
|
+
{ id: 'dummy109' }, { id: 'dummy110' }
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'index' do
|
105
|
+
let(:company) { create(:company) }
|
106
|
+
|
107
|
+
context 'when unauthorized' do
|
108
|
+
it 'returns scim+json content type' do
|
109
|
+
get :index, as: :json
|
110
|
+
|
111
|
+
expect(response.media_type).to eq 'application/scim+json'
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'fails with no credentials' do
|
115
|
+
get :index, as: :json
|
116
|
+
|
117
|
+
expect(response.status).to eq 401
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'fails with invalid credentials' do
|
121
|
+
request.env['HTTP_AUTHORIZATION'] =
|
122
|
+
ActionController::HttpAuthentication::Basic
|
123
|
+
.encode_credentials('unauthorized', '123456')
|
124
|
+
|
125
|
+
get :index, as: :json
|
126
|
+
|
127
|
+
expect(response.status).to eq 401
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'when authorized' do
|
132
|
+
before :each do
|
133
|
+
http_login(company)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'returns scim+json content type' do
|
137
|
+
get :index, as: :json
|
138
|
+
|
139
|
+
expect(response.media_type).to eq 'application/scim+json'
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'is successful with valid credentials' do
|
143
|
+
get :index, as: :json
|
144
|
+
|
145
|
+
expect(response.status).to eq 200
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns all results' do
|
149
|
+
allow(Scimaenaga.config).to(receive(:schemas).and_return(schemas))
|
150
|
+
get :index, as: :json
|
151
|
+
response_body = JSON.parse(response.body)
|
152
|
+
expect(response_body.dig('schemas', 0)).to(
|
153
|
+
eq 'urn:ietf:params:scim:api:messages:2.0:ListResponse'
|
154
|
+
)
|
155
|
+
expect(response_body['totalResults']).to eq 2
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'defaults to 100 results' do
|
159
|
+
allow(Scimaenaga.config).to(receive(:schemas).and_return(schemas_110))
|
160
|
+
|
161
|
+
get :index, as: :json
|
162
|
+
response_body = JSON.parse(response.body)
|
163
|
+
expect(response_body['totalResults']).to eq 110
|
164
|
+
expect(response_body['startIndex']).to eq 1
|
165
|
+
expect(response_body['Resources'].count).to eq 100
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'paginates results' do
|
169
|
+
allow(Scimaenaga.config).to(receive(:schemas).and_return(schemas_110))
|
170
|
+
get :index, params: {
|
171
|
+
startIndex: 101,
|
172
|
+
count: 5,
|
173
|
+
}, as: :json
|
174
|
+
response_body = JSON.parse(response.body)
|
175
|
+
expect(response_body['totalResults']).to eq 110
|
176
|
+
expect(response_body['startIndex']).to eq 101
|
177
|
+
expect(response_body['Resources'].count).to eq 5
|
178
|
+
expect(response_body.dig('Resources', 0, 'id')).to eq 'dummy101'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe 'show' do
|
184
|
+
let(:company) { create(:company) }
|
185
|
+
|
186
|
+
context 'when unauthorized' do
|
187
|
+
it 'returns scim+json content type' do
|
188
|
+
get :show, params: { id: 1 }, as: :json
|
189
|
+
|
190
|
+
expect(response.media_type).to eq 'application/scim+json'
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'fails with no credentials' do
|
194
|
+
get :show, params: { id: 1 }, as: :json
|
195
|
+
|
196
|
+
expect(response.status).to eq 401
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'fails with invalid credentials' do
|
200
|
+
request.env['HTTP_AUTHORIZATION'] =
|
201
|
+
ActionController::HttpAuthentication::Basic
|
202
|
+
.encode_credentials('unauthorized', '123456')
|
203
|
+
|
204
|
+
get :show, params: { id: 1 }, as: :json
|
205
|
+
|
206
|
+
expect(response.status).to eq 401
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when authorized' do
|
211
|
+
before :each do
|
212
|
+
http_login(company)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'returns scim+json content type' do
|
216
|
+
allow(Scimaenaga.config).to(receive(:schemas).and_return(schemas))
|
217
|
+
get :show, params: { id: 'urn:ietf:params:scim:schemas:core:2.0:User' }, as: :json
|
218
|
+
|
219
|
+
expect(response.media_type).to eq 'application/scim+json'
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'is successful with valid credentials' do
|
223
|
+
allow(Scimaenaga.config).to(receive(:schemas).and_return(schemas))
|
224
|
+
get :show, params: { id: 'urn:ietf:params:scim:schemas:core:2.0:User' }, as: :json
|
225
|
+
|
226
|
+
response_body = JSON.parse(response.body)
|
227
|
+
expect(response.status).to eq 200
|
228
|
+
expect(response_body['name']).to eq 'User'
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'returns :not_found for id that cannot be found' do
|
232
|
+
get :show, params: { id: 'fake_id' }, as: :json
|
233
|
+
|
234
|
+
expect(response.status).to eq 404
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Scimaenaga::ScimSchemasController, type: :request do
|
6
|
+
let(:company) { create(:company) }
|
7
|
+
let(:credentials) do
|
8
|
+
Base64.encode64("#{company.subdomain}:#{company.api_token}")
|
9
|
+
end
|
10
|
+
let(:authorization) { "Basic #{credentials}" }
|
11
|
+
|
12
|
+
def get_request(content_type = 'application/scim+json')
|
13
|
+
get '/scim/v2/Schemas',
|
14
|
+
headers: {
|
15
|
+
Authorization: authorization,
|
16
|
+
'Content-Type': content_type,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'OAuth Bearer Authorization' do
|
21
|
+
context 'with valid token' do
|
22
|
+
let(:authorization) { "Bearer #{company.api_token}" }
|
23
|
+
|
24
|
+
it 'supports OAuth bearer authorization and succeeds' do
|
25
|
+
get_request
|
26
|
+
expect(response.status).to eq 200
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with invalid token' do
|
31
|
+
let(:authorization) { "Bearer #{SecureRandom.hex}" }
|
32
|
+
|
33
|
+
it 'The request fails' do
|
34
|
+
get_request
|
35
|
+
expect(response.status).to eq 401
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
RSpec.describe
|
5
|
+
RSpec.describe Scimaenaga::ScimUsersController, type: :controller do
|
6
6
|
include AuthHelper
|
7
7
|
|
8
|
-
routes {
|
8
|
+
routes { Scimaenaga::Engine.routes }
|
9
9
|
|
10
10
|
describe 'index' do
|
11
11
|
let(:company) { create(:company) }
|
@@ -85,7 +85,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'paginates results by configurable scim_users_list_order' do
|
88
|
-
allow(
|
88
|
+
allow(Scimaenaga.config).to receive(:scim_users_list_order).and_return({ created_at: :desc })
|
89
89
|
|
90
90
|
create_list(:user, 400, company: company)
|
91
91
|
expect(company.users.first.id).to eq 1
|
@@ -334,7 +334,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
334
334
|
end
|
335
335
|
|
336
336
|
it 'returns 409 if user already exists and config.scim_user_prevent_update_on_create is set to true' do
|
337
|
-
allow(
|
337
|
+
allow(Scimaenaga.config).to receive(:scim_user_prevent_update_on_create).and_return(true)
|
338
338
|
create(:user, email: 'new@example.com', company: company)
|
339
339
|
|
340
340
|
post :create, params: {
|
@@ -755,23 +755,23 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
755
755
|
describe 'destroy' do
|
756
756
|
let(:company) { create(:company) }
|
757
757
|
|
758
|
-
context
|
759
|
-
it
|
758
|
+
context 'when unauthorized' do
|
759
|
+
it 'returns scim+json content type' do
|
760
760
|
delete :destroy, params: { id: 1 }, as: :json
|
761
761
|
|
762
|
-
expect(response.media_type).to eq
|
762
|
+
expect(response.media_type).to eq 'application/scim+json'
|
763
763
|
end
|
764
764
|
|
765
|
-
it
|
765
|
+
it 'fails with no credentials' do
|
766
766
|
delete :destroy, params: { id: 1 }, as: :json
|
767
767
|
|
768
768
|
expect(response.status).to eq 401
|
769
769
|
end
|
770
770
|
|
771
|
-
it
|
772
|
-
request.env[
|
771
|
+
it 'fails with invalid credentials' do
|
772
|
+
request.env['HTTP_AUTHORIZATION'] =
|
773
773
|
ActionController::HttpAuthentication::Basic
|
774
|
-
.encode_credentials(
|
774
|
+
.encode_credentials('unauthorized', '123456')
|
775
775
|
|
776
776
|
delete :destroy, params: { id: 1 }, as: :json
|
777
777
|
|
@@ -787,7 +787,6 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
787
787
|
end
|
788
788
|
|
789
789
|
context 'when User destroy method is configured' do
|
790
|
-
|
791
790
|
it 'is sucessful with valid credentials' do
|
792
791
|
delete :destroy, params: { id: 1 }, as: :json
|
793
792
|
|
@@ -811,7 +810,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
811
810
|
|
812
811
|
context 'when User destroy method is not configured' do
|
813
812
|
it 'does not delete User' do
|
814
|
-
allow(
|
813
|
+
allow(Scimaenaga.config).to(
|
815
814
|
receive(:user_destroy_method).and_return(nil)
|
816
815
|
)
|
817
816
|
|
@@ -825,7 +824,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
825
824
|
|
826
825
|
context 'when User destroy method is invalid' do
|
827
826
|
it 'does not delete User' do
|
828
|
-
allow(
|
827
|
+
allow(Scimaenaga.config).to(
|
829
828
|
receive(:user_destroy_method).and_return('destory!')
|
830
829
|
)
|
831
830
|
|
@@ -840,7 +839,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
840
839
|
context 'when target User is not found' do
|
841
840
|
it 'return 404 not found' do
|
842
841
|
expect do
|
843
|
-
delete :destroy, params: { id:
|
842
|
+
delete :destroy, params: { id: 999_999 }, as: :json
|
844
843
|
end.not_to change { company.users.reload.count }.from(1)
|
845
844
|
|
846
845
|
expect(response.status).to eq 404
|
@@ -1,51 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'spec_helper'
|
4
4
|
|
5
|
-
RSpec.describe
|
5
|
+
RSpec.describe Scimaenaga::ScimUsersController, type: :request do
|
6
6
|
let(:company) { create(:company) }
|
7
7
|
let(:credentials) do
|
8
8
|
Base64.encode64("#{company.subdomain}:#{company.api_token}")
|
9
9
|
end
|
10
10
|
let(:authorization) { "Basic #{credentials}" }
|
11
11
|
|
12
|
-
def post_request(content_type =
|
12
|
+
def post_request(content_type = 'application/scim+json')
|
13
13
|
# params need to be transformed into a string to test if they are being parsed by Rack
|
14
14
|
|
15
|
-
post
|
15
|
+
post '/scim/v2/Users',
|
16
16
|
params: {
|
17
17
|
name: {
|
18
|
-
givenName:
|
19
|
-
familyName:
|
18
|
+
givenName: 'New',
|
19
|
+
familyName: 'User',
|
20
20
|
},
|
21
21
|
emails: [
|
22
22
|
{
|
23
|
-
value:
|
23
|
+
value: 'new@example.com',
|
24
24
|
}
|
25
|
-
]
|
25
|
+
],
|
26
26
|
}.to_json,
|
27
27
|
headers: {
|
28
28
|
Authorization: authorization,
|
29
|
-
'Content-Type': content_type
|
29
|
+
'Content-Type': content_type,
|
30
30
|
}
|
31
31
|
end
|
32
32
|
|
33
|
-
describe
|
34
|
-
it
|
33
|
+
describe 'Content-Type' do
|
34
|
+
it 'accepts scim+json' do
|
35
35
|
expect(company.users.count).to eq 0
|
36
36
|
|
37
|
-
post_request(
|
37
|
+
post_request('application/scim+json')
|
38
38
|
|
39
39
|
expect(request.params).to include :name
|
40
40
|
expect(response.status).to eq 201
|
41
|
-
expect(response.media_type).to eq
|
41
|
+
expect(response.media_type).to eq 'application/scim+json'
|
42
42
|
expect(company.users.count).to eq 1
|
43
43
|
end
|
44
44
|
|
45
|
-
it
|
45
|
+
it 'can not parse unfamiliar content types' do
|
46
46
|
expect(company.users.count).to eq 0
|
47
47
|
|
48
|
-
post_request(
|
48
|
+
post_request('text/csv')
|
49
49
|
|
50
50
|
expect(request.params).not_to include :name
|
51
51
|
expect(response.status).to eq 422
|
@@ -53,21 +53,21 @@ RSpec.describe ScimRails::ScimUsersController, type: :request do
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
context
|
57
|
-
context
|
56
|
+
context 'OAuth Bearer Authorization' do
|
57
|
+
context 'with valid token' do
|
58
58
|
let(:authorization) { "Bearer #{company.api_token}" }
|
59
59
|
|
60
|
-
it
|
60
|
+
it 'supports OAuth bearer authorization and succeeds' do
|
61
61
|
expect { post_request }.to change(company.users, :count).from(0).to(1)
|
62
62
|
|
63
63
|
expect(response.status).to eq 201
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
context
|
67
|
+
context 'with invalid token' do
|
68
68
|
let(:authorization) { "Bearer #{SecureRandom.hex}" }
|
69
69
|
|
70
|
-
it
|
70
|
+
it 'The request fails' do
|
71
71
|
expect { post_request }.not_to change(company.users, :count)
|
72
72
|
|
73
73
|
expect(response.status).to eq 401
|
@@ -3,7 +3,7 @@ require_relative 'boot'
|
|
3
3
|
require 'rails/all'
|
4
4
|
|
5
5
|
Bundler.require(*Rails.groups)
|
6
|
-
require
|
6
|
+
require 'scimaenaga'
|
7
7
|
|
8
8
|
module Dummy
|
9
9
|
class Application < Rails::Application
|
@@ -12,4 +12,3 @@ module Dummy
|
|
12
12
|
# -- all .rb files in that directory are automatically loaded.
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
config.basic_auth_model =
|
3
|
-
config.scim_users_model =
|
4
|
-
config.scim_groups_model =
|
1
|
+
Scimaenaga.configure do |config|
|
2
|
+
config.basic_auth_model = 'Company'
|
3
|
+
config.scim_users_model = 'User'
|
4
|
+
config.scim_groups_model = 'Group'
|
5
5
|
|
6
6
|
config.basic_auth_model_searchable_attribute = :subdomain
|
7
7
|
config.basic_auth_model_authenticatable_attribute = :api_token
|
@@ -9,57 +9,57 @@ ScimRails.configure do |config|
|
|
9
9
|
config.scim_users_list_order = :id
|
10
10
|
config.scim_groups_scope = :groups
|
11
11
|
|
12
|
-
config.signing_algorithm =
|
13
|
-
config.signing_secret =
|
12
|
+
config.signing_algorithm = 'HS256'
|
13
|
+
config.signing_secret = '2d6806dd11c2fece2e81b8ca76dcb0062f5b08e28e3264e8ba1c44bbd3578b70'
|
14
14
|
|
15
15
|
config.user_destroy_method = :destroy!
|
16
16
|
config.group_destroy_method = :destroy!
|
17
17
|
|
18
|
-
config.mutable_user_attributes = [
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
config.mutable_user_attributes = %i[
|
19
|
+
first_name
|
20
|
+
last_name
|
21
|
+
email
|
22
|
+
active
|
23
23
|
]
|
24
24
|
|
25
25
|
config.queryable_user_attributes = {
|
26
26
|
userName: :email,
|
27
27
|
givenName: :first_name,
|
28
28
|
familyName: :last_name,
|
29
|
-
email: :email
|
29
|
+
email: :email,
|
30
30
|
}
|
31
31
|
|
32
32
|
config.mutable_user_attributes_schema = {
|
33
33
|
name: {
|
34
34
|
givenName: :first_name,
|
35
|
-
familyName: :last_name
|
35
|
+
familyName: :last_name,
|
36
36
|
},
|
37
37
|
emails: [
|
38
38
|
{
|
39
|
-
value: :email
|
39
|
+
value: :email,
|
40
40
|
}
|
41
41
|
],
|
42
|
-
active: :active
|
42
|
+
active: :active,
|
43
43
|
}
|
44
44
|
|
45
45
|
config.user_schema = {
|
46
|
-
schemas: [
|
46
|
+
schemas: ['urn:ietf:params:scim:schemas:core:2.0:User'],
|
47
47
|
id: :id,
|
48
48
|
userName: :email,
|
49
49
|
name: {
|
50
50
|
givenName: :first_name,
|
51
|
-
familyName: :last_name
|
51
|
+
familyName: :last_name,
|
52
52
|
},
|
53
53
|
emails: [
|
54
54
|
{
|
55
|
-
value: :email
|
56
|
-
}
|
55
|
+
value: :email,
|
56
|
+
}
|
57
57
|
],
|
58
|
-
active: :unarchived
|
58
|
+
active: :unarchived?,
|
59
59
|
}
|
60
60
|
|
61
61
|
config.queryable_group_attributes = {
|
62
|
-
displayName: :name
|
62
|
+
displayName: :name,
|
63
63
|
}
|
64
64
|
|
65
65
|
config.mutable_group_attributes = [
|
@@ -67,21 +67,21 @@ ScimRails.configure do |config|
|
|
67
67
|
]
|
68
68
|
|
69
69
|
config.mutable_group_attributes_schema = {
|
70
|
-
displayName: :name
|
70
|
+
displayName: :name,
|
71
71
|
}
|
72
72
|
|
73
73
|
config.group_member_relation_attribute = :user_ids
|
74
74
|
config.group_member_relation_schema = { value: :user_ids }
|
75
75
|
|
76
76
|
config.group_schema = {
|
77
|
-
schemas: [
|
77
|
+
schemas: ['urn:ietf:params:scim:schemas:core:2.0:Group'],
|
78
78
|
id: :id,
|
79
79
|
displayName: :name,
|
80
|
-
members: :users
|
80
|
+
members: :users,
|
81
81
|
}
|
82
82
|
|
83
83
|
config.group_abbreviated_schema = {
|
84
84
|
value: :id,
|
85
|
-
display: :name
|
85
|
+
display: :name,
|
86
86
|
}
|
87
87
|
end
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/factories/company.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
FactoryBot.define do
|
2
2
|
factory :company do
|
3
|
-
name {
|
4
|
-
subdomain {
|
3
|
+
name { 'Test Company' }
|
4
|
+
subdomain { 'test' }
|
5
5
|
|
6
6
|
after(:build) do |company|
|
7
|
-
company.api_token =
|
7
|
+
company.api_token = Scimaenaga::Encoder.encode(company)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|