scimaenaga 0.4.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +314 -0
- data/Rakefile +34 -0
- data/app/controllers/concerns/scim_rails/exception_handler.rb +119 -0
- data/app/controllers/concerns/scim_rails/response.rb +94 -0
- data/app/controllers/scim_rails/application_controller.rb +72 -0
- data/app/controllers/scim_rails/scim_groups_controller.rb +96 -0
- data/app/controllers/scim_rails/scim_users_controller.rb +124 -0
- data/app/helpers/scim_rails/application_helper.rb +4 -0
- data/app/models/scim_rails/application_record.rb +5 -0
- data/app/models/scim_rails/authorize_api_request.rb +40 -0
- data/app/models/scim_rails/scim_count.rb +38 -0
- data/app/models/scim_rails/scim_query_parser.rb +47 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/routes.rb +12 -0
- data/lib/generators/scim_rails/USAGE +8 -0
- data/lib/generators/scim_rails/scim_rails_generator.rb +7 -0
- data/lib/generators/scim_rails/templates/initializer.rb +166 -0
- data/lib/scim_rails/config.rb +85 -0
- data/lib/scim_rails/encoder.rb +25 -0
- data/lib/scim_rails/engine.rb +12 -0
- data/lib/scim_rails/version.rb +5 -0
- data/lib/scim_rails.rb +6 -0
- data/lib/tasks/scim_rails_tasks.rake +4 -0
- data/spec/controllers/scim_rails/scim_groups_controller_spec.rb +494 -0
- data/spec/controllers/scim_rails/scim_groups_request_spec.rb +68 -0
- data/spec/controllers/scim_rails/scim_users_controller_spec.rb +681 -0
- data/spec/controllers/scim_rails/scim_users_request_spec.rb +77 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +5 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/cable.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/jobs/application_job.rb +2 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/models/company.rb +4 -0
- data/spec/dummy/app/models/group.rb +15 -0
- data/spec/dummy/app/models/group_user.rb +6 -0
- data/spec/dummy/app/models/user.rb +39 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +34 -0
- data/spec/dummy/bin/update +29 -0
- data/spec/dummy/config/application.rb +15 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/cable.yml +9 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +54 -0
- data/spec/dummy/config/environments/production.rb +86 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/new_framework_defaults.rb +24 -0
- data/spec/dummy/config/initializers/scim_rails_config.rb +85 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/puma.rb +47 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/db/migrate/20181206184304_create_users.rb +15 -0
- data/spec/dummy/db/migrate/20181206184313_create_companies.rb +11 -0
- data/spec/dummy/db/migrate/20210423075859_create_groups.rb +10 -0
- data/spec/dummy/db/migrate/20210423075950_create_group_users.rb +10 -0
- data/spec/dummy/db/schema.rb +53 -0
- data/spec/dummy/db/seeds.rb +14 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/company.rb +10 -0
- data/spec/factories/group.rb +11 -0
- data/spec/factories/user.rb +9 -0
- data/spec/lib/scim_rails/encoder_spec.rb +62 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/auth_helper.rb +7 -0
- data/spec/support/factory_bot.rb +3 -0
- data/spec/support/scim_rails_config.rb +59 -0
- metadata +339 -0
data/lib/scim_rails.rb
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.describe ScimRails::ScimGroupsController, type: :controller do
|
|
6
|
+
include AuthHelper
|
|
7
|
+
|
|
8
|
+
routes { ScimRails::Engine.routes }
|
|
9
|
+
|
|
10
|
+
describe "index" do
|
|
11
|
+
let(:company) { create(:company) }
|
|
12
|
+
|
|
13
|
+
context "when unauthorized" do
|
|
14
|
+
it "returns scim+json content type" do
|
|
15
|
+
get :index, as: :json
|
|
16
|
+
|
|
17
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "fails with no credentials" do
|
|
21
|
+
get :index, as: :json
|
|
22
|
+
|
|
23
|
+
expect(response.status).to eq 401
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "fails with invalid credentials" do
|
|
27
|
+
request.env["HTTP_AUTHORIZATION"] =
|
|
28
|
+
ActionController::HttpAuthentication::Basic
|
|
29
|
+
.encode_credentials("unauthorized", "123456")
|
|
30
|
+
|
|
31
|
+
get :index, as: :json
|
|
32
|
+
|
|
33
|
+
expect(response.status).to eq 401
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "when authorized" do
|
|
38
|
+
before :each do
|
|
39
|
+
http_login(company)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "returns scim+json content type" do
|
|
43
|
+
get :index, as: :json
|
|
44
|
+
|
|
45
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "is successful with valid credentials" do
|
|
49
|
+
get :index, as: :json
|
|
50
|
+
|
|
51
|
+
expect(response.status).to eq 200
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "returns all results" do
|
|
55
|
+
create_list(:group, 5, company: company)
|
|
56
|
+
|
|
57
|
+
get :index, as: :json
|
|
58
|
+
response_body = JSON.parse(response.body)
|
|
59
|
+
expect(response_body.dig("schemas", 0)).to(
|
|
60
|
+
eq "urn:ietf:params:scim:api:messages:2.0:ListResponse"
|
|
61
|
+
)
|
|
62
|
+
expect(response_body["totalResults"]).to eq 5
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "defaults to 100 results" do
|
|
66
|
+
create_list(:group, 300, company: company)
|
|
67
|
+
|
|
68
|
+
get :index, as: :json
|
|
69
|
+
response_body = JSON.parse(response.body)
|
|
70
|
+
expect(response_body["totalResults"]).to eq 300
|
|
71
|
+
expect(response_body["Resources"].count).to eq 100
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "paginates results" do
|
|
75
|
+
create_list(:group, 400, company: company)
|
|
76
|
+
expect(company.groups.first.id).to eq 1
|
|
77
|
+
|
|
78
|
+
get :index, params: {
|
|
79
|
+
startIndex: 101,
|
|
80
|
+
count: 200
|
|
81
|
+
}, as: :json
|
|
82
|
+
response_body = JSON.parse(response.body)
|
|
83
|
+
expect(response_body["totalResults"]).to eq 400
|
|
84
|
+
expect(response_body["Resources"].count).to eq 200
|
|
85
|
+
expect(response_body.dig("Resources", 0, "id")).to eq 101
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "paginates results by configurable scim_groups_list_order" do
|
|
89
|
+
allow(ScimRails.config).to(
|
|
90
|
+
receive(:scim_groups_list_order).and_return(created_at: :desc)
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
create_list(:group, 400, company: company)
|
|
94
|
+
expect(company.groups.first.id).to eq 1
|
|
95
|
+
|
|
96
|
+
get :index, params: {
|
|
97
|
+
startIndex: 1,
|
|
98
|
+
count: 10
|
|
99
|
+
}, as: :json
|
|
100
|
+
response_body = JSON.parse(response.body)
|
|
101
|
+
expect(response_body["totalResults"]).to eq 400
|
|
102
|
+
expect(response_body["Resources"].count).to eq 10
|
|
103
|
+
expect(response_body.dig("Resources", 0, "id")).to eq 400
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "filters results by provided displayName filter" do
|
|
107
|
+
create(:group, name: "Foo", company: company)
|
|
108
|
+
create(:group, name: "Bar", company: company)
|
|
109
|
+
|
|
110
|
+
get :index, params: {
|
|
111
|
+
filter: "displayName eq Bar"
|
|
112
|
+
}, as: :json
|
|
113
|
+
response_body = JSON.parse(response.body)
|
|
114
|
+
expect(response_body["totalResults"]).to eq 1
|
|
115
|
+
expect(response_body["Resources"].count).to eq 1
|
|
116
|
+
expect(response_body.dig("Resources", 0, "displayName")).to eq "Bar"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "returns no results for unfound filter parameters" do
|
|
120
|
+
get :index, params: {
|
|
121
|
+
filter: "displayName eq fake_not_there"
|
|
122
|
+
}, as: :json
|
|
123
|
+
response_body = JSON.parse(response.body)
|
|
124
|
+
expect(response_body["totalResults"]).to eq 0
|
|
125
|
+
expect(response_body["Resources"].count).to eq 0
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "returns no results for undefined filter queries" do
|
|
129
|
+
get :index, params: {
|
|
130
|
+
filter: "address eq 101 Nowhere USA"
|
|
131
|
+
}, as: :json
|
|
132
|
+
expect(response.status).to eq 400
|
|
133
|
+
response_body = JSON.parse(response.body)
|
|
134
|
+
expect(response_body.dig("schemas", 0)).to(
|
|
135
|
+
eq "urn:ietf:params:scim:api:messages:2.0:Error"
|
|
136
|
+
)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe "show" do
|
|
142
|
+
let(:company) { create(:company) }
|
|
143
|
+
|
|
144
|
+
context "when unauthorized" do
|
|
145
|
+
it "returns scim+json content type" do
|
|
146
|
+
get :show, params: { id: 1 }, as: :json
|
|
147
|
+
|
|
148
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "fails with no credentials" do
|
|
152
|
+
get :show, params: { id: 1 }, as: :json
|
|
153
|
+
|
|
154
|
+
expect(response.status).to eq 401
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "fails with invalid credentials" do
|
|
158
|
+
request.env["HTTP_AUTHORIZATION"] =
|
|
159
|
+
ActionController::HttpAuthentication::Basic
|
|
160
|
+
.encode_credentials("unauthorized", "123456")
|
|
161
|
+
|
|
162
|
+
get :show, params: { id: 1 }, as: :json
|
|
163
|
+
|
|
164
|
+
expect(response.status).to eq 401
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
context "when authorized" do
|
|
169
|
+
before :each do
|
|
170
|
+
http_login(company)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "returns scim+json content type" do
|
|
174
|
+
get :show, params: { id: 1 }, as: :json
|
|
175
|
+
|
|
176
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "is successful with valid credentials" do
|
|
180
|
+
create(:group, id: 1, company: company)
|
|
181
|
+
get :show, params: { id: 1 }, as: :json
|
|
182
|
+
|
|
183
|
+
expect(response.status).to eq 200
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "returns :not_found for id that cannot be found" do
|
|
187
|
+
get :show, params: { id: "fake_id" }, as: :json
|
|
188
|
+
|
|
189
|
+
expect(response.status).to eq 404
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "returns :not_found for a correct id but unauthorized company" do
|
|
193
|
+
new_company = create(:company)
|
|
194
|
+
create(:group, company: new_company, id: 1)
|
|
195
|
+
|
|
196
|
+
get :show, params: { id: 1 }, as: :json
|
|
197
|
+
|
|
198
|
+
expect(response.status).to eq 404
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
describe "create" do
|
|
204
|
+
let(:company) { create(:company) }
|
|
205
|
+
|
|
206
|
+
context "when unauthorized" do
|
|
207
|
+
it "returns scim+json content type" do
|
|
208
|
+
post :create, as: :json
|
|
209
|
+
|
|
210
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "fails with no credentials" do
|
|
214
|
+
post :create, as: :json
|
|
215
|
+
|
|
216
|
+
expect(response.status).to eq 401
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "fails with invalid credentials" do
|
|
220
|
+
request.env["HTTP_AUTHORIZATION"] =
|
|
221
|
+
ActionController::HttpAuthentication::Basic
|
|
222
|
+
.encode_credentials("unauthorized", "123456")
|
|
223
|
+
|
|
224
|
+
post :create, as: :json
|
|
225
|
+
|
|
226
|
+
expect(response.status).to eq 401
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context "when authorized" do
|
|
231
|
+
before :each do
|
|
232
|
+
http_login(company)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "returns scim+json content type" do
|
|
236
|
+
post :create, params: {
|
|
237
|
+
displayName: "Test Group",
|
|
238
|
+
members: []
|
|
239
|
+
}, as: :json
|
|
240
|
+
|
|
241
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "is successful with valid credentials" do
|
|
245
|
+
expect(company.groups.count).to eq 0
|
|
246
|
+
|
|
247
|
+
post :create, params: {
|
|
248
|
+
displayName: "Test Group",
|
|
249
|
+
members: []
|
|
250
|
+
}, as: :json
|
|
251
|
+
|
|
252
|
+
expect(response.status).to eq 201
|
|
253
|
+
expect(company.groups.count).to eq 1
|
|
254
|
+
group = company.groups.first
|
|
255
|
+
expect(group.persisted?).to eq true
|
|
256
|
+
expect(group.name).to eq "Test Group"
|
|
257
|
+
expect(group.users).to eq []
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it "ignores unconfigured params" do
|
|
261
|
+
post :create, params: {
|
|
262
|
+
displayName: "Test Group",
|
|
263
|
+
department: "Best Department",
|
|
264
|
+
members: []
|
|
265
|
+
}, as: :json
|
|
266
|
+
|
|
267
|
+
expect(response.status).to eq 201
|
|
268
|
+
expect(company.groups.count).to eq 1
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "returns 422 if required params are missing" do
|
|
272
|
+
post :create, params: {
|
|
273
|
+
members: []
|
|
274
|
+
}, as: :json
|
|
275
|
+
|
|
276
|
+
expect(response.status).to eq 422
|
|
277
|
+
expect(company.users.count).to eq 0
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it "returns 409 if group already exists" do
|
|
281
|
+
create(:group, name: "Test Group", company: company)
|
|
282
|
+
|
|
283
|
+
post :create, params: {
|
|
284
|
+
displayName: "Test Group",
|
|
285
|
+
members: []
|
|
286
|
+
}, as: :json
|
|
287
|
+
|
|
288
|
+
expect(response.status).to eq 409
|
|
289
|
+
expect(company.groups.count).to eq 1
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it "creates group" do
|
|
293
|
+
users = create_list(:user, 3, company: company)
|
|
294
|
+
|
|
295
|
+
post :create, params: {
|
|
296
|
+
displayName: "Test Group",
|
|
297
|
+
members: users.map do |user|
|
|
298
|
+
{ value: user.id.to_s, display: user.email }
|
|
299
|
+
end
|
|
300
|
+
}, as: :json
|
|
301
|
+
|
|
302
|
+
expect(response.status).to eq 201
|
|
303
|
+
expect(company.groups.count).to eq 1
|
|
304
|
+
group = company.groups.first
|
|
305
|
+
expect(group.name).to eq "Test Group"
|
|
306
|
+
expect(group.users.count).to eq 3
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
describe "put update" do
|
|
312
|
+
let(:company) { create(:company) }
|
|
313
|
+
|
|
314
|
+
context "when unauthorized" do
|
|
315
|
+
it "returns scim+json content type" do
|
|
316
|
+
put :put_update, params: { id: 1 }, as: :json
|
|
317
|
+
|
|
318
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "fails with no credentials" do
|
|
322
|
+
put :put_update, params: { id: 1 }, as: :json
|
|
323
|
+
|
|
324
|
+
expect(response.status).to eq 401
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it "fails with invalid credentials" do
|
|
328
|
+
request.env["HTTP_AUTHORIZATION"] =
|
|
329
|
+
ActionController::HttpAuthentication::Basic
|
|
330
|
+
.encode_credentials("unauthorized", "123456")
|
|
331
|
+
|
|
332
|
+
put :put_update, params: { id: 1 }, as: :json
|
|
333
|
+
|
|
334
|
+
expect(response.status).to eq 401
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
context "when authorized" do
|
|
339
|
+
let!(:group) { create(:group, id: 1, company: company) }
|
|
340
|
+
|
|
341
|
+
before :each do
|
|
342
|
+
http_login(company)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "returns scim+json content type" do
|
|
346
|
+
put :put_update, params: put_params, as: :json
|
|
347
|
+
|
|
348
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it "is successful with with valid credentials" do
|
|
352
|
+
put :put_update, params: put_params, as: :json
|
|
353
|
+
|
|
354
|
+
expect(response.status).to eq 200
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
it "can add and delete Users from a Group at once" do
|
|
358
|
+
user1 = create(:user, company: company, groups: [group])
|
|
359
|
+
user2 = create(:user, company: company)
|
|
360
|
+
|
|
361
|
+
expect do
|
|
362
|
+
put :put_update, params: put_params(users: [user2]), as: :json
|
|
363
|
+
end.to change { group.reload.users }.from([user1]).to([user2])
|
|
364
|
+
|
|
365
|
+
expect(response.status).to eq 200
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it "returns :not_found for id that cannot be found" do
|
|
369
|
+
put :put_update, params: { id: "fake_id" }, as: :json
|
|
370
|
+
|
|
371
|
+
expect(response.status).to eq 404
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
it "returns :not_found for a correct id but unauthorized company" do
|
|
375
|
+
new_company = create(:company)
|
|
376
|
+
create(:group, company: new_company, id: 1000)
|
|
377
|
+
|
|
378
|
+
put :put_update, params: { id: 1000 }, as: :json
|
|
379
|
+
|
|
380
|
+
expect(response.status).to eq 404
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it "returns 422 with incomplete request" do
|
|
384
|
+
put :put_update, params: {
|
|
385
|
+
id: 1,
|
|
386
|
+
members: []
|
|
387
|
+
}, as: :json
|
|
388
|
+
|
|
389
|
+
expect(response.status).to eq 422
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
describe "destroy" do
|
|
395
|
+
let(:company) { create(:company) }
|
|
396
|
+
|
|
397
|
+
context "when unauthorized" do
|
|
398
|
+
it "returns scim+json content type" do
|
|
399
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
400
|
+
|
|
401
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
it "fails with no credentials" do
|
|
405
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
406
|
+
|
|
407
|
+
expect(response.status).to eq 401
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
it "fails with invalid credentials" do
|
|
411
|
+
request.env["HTTP_AUTHORIZATION"] =
|
|
412
|
+
ActionController::HttpAuthentication::Basic
|
|
413
|
+
.encode_credentials("unauthorized", "123456")
|
|
414
|
+
|
|
415
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
416
|
+
|
|
417
|
+
expect(response.status).to eq 401
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
context "when authorized" do
|
|
422
|
+
let!(:group) { create(:group, id: 1, company: company) }
|
|
423
|
+
|
|
424
|
+
before :each do
|
|
425
|
+
http_login(company)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
context "when Group destroy method is configured" do
|
|
429
|
+
before do
|
|
430
|
+
allow(ScimRails.config).to(
|
|
431
|
+
receive(:group_destroy_method).and_return(:destroy!)
|
|
432
|
+
)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
it "returns empty response" do
|
|
436
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
437
|
+
|
|
438
|
+
expect(response.body).to be_empty
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "is successful with valid credentials" do
|
|
442
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
443
|
+
|
|
444
|
+
expect(response.status).to eq 204
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it "returns :not_found for id that cannot be found" do
|
|
448
|
+
delete :destroy, params: { id: "fake_id" }, as: :json
|
|
449
|
+
|
|
450
|
+
expect(response.status).to eq 404
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
it "returns :not_found for a correct id but unauthorized company" do
|
|
454
|
+
new_company = create(:company)
|
|
455
|
+
create(:group, company: new_company, id: 1000)
|
|
456
|
+
|
|
457
|
+
delete :destroy, params: { id: 1000 }, as: :json
|
|
458
|
+
|
|
459
|
+
expect(response.status).to eq 404
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
it "successfully deletes Group" do
|
|
463
|
+
expect do
|
|
464
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
465
|
+
end.to change { company.groups.reload.count }.from(1).to(0)
|
|
466
|
+
|
|
467
|
+
expect(response.status).to eq 204
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
context "when Group destroy method is not configured" do
|
|
472
|
+
it "does not delete Group" do
|
|
473
|
+
allow(ScimRails.config).to(
|
|
474
|
+
receive(:group_destroy_method).and_return(nil)
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
expect do
|
|
478
|
+
delete :destroy, params: { id: 1 }, as: :json
|
|
479
|
+
end.not_to change { company.groups.reload.count }.from(1)
|
|
480
|
+
|
|
481
|
+
expect(response.status).to eq 501
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def put_params(name: "Test Group", users: [])
|
|
488
|
+
{
|
|
489
|
+
id: 1,
|
|
490
|
+
displayName: name,
|
|
491
|
+
members: users.map { |user| { value: user.id.to_s, display: user.email } }
|
|
492
|
+
}
|
|
493
|
+
end
|
|
494
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.describe ScimRails::ScimGroupsController, 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 post_request(content_type = "application/scim+json")
|
|
13
|
+
post "/scim/v2/Groups",
|
|
14
|
+
params: {
|
|
15
|
+
displayName: "Dummy Group",
|
|
16
|
+
members: []
|
|
17
|
+
}.to_json,
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: authorization,
|
|
20
|
+
'Content-Type': content_type
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "Content-Type" do
|
|
25
|
+
it "accepts scim+json" do
|
|
26
|
+
expect(company.groups.count).to eq 0
|
|
27
|
+
|
|
28
|
+
post_request("application/scim+json")
|
|
29
|
+
|
|
30
|
+
expect(request.params).to include :displayName
|
|
31
|
+
expect(response.status).to eq 201
|
|
32
|
+
expect(response.media_type).to eq "application/scim+json"
|
|
33
|
+
expect(company.groups.count).to eq 1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "can not parse unfamiliar content types" do
|
|
37
|
+
expect(company.groups.count).to eq 0
|
|
38
|
+
|
|
39
|
+
post_request("text/csv")
|
|
40
|
+
|
|
41
|
+
expect(request.params).not_to include :displayName
|
|
42
|
+
expect(response.status).to eq 422
|
|
43
|
+
expect(company.groups.count).to eq 0
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "OAuth Bearer Authorization" do
|
|
48
|
+
context "with valid token" do
|
|
49
|
+
let(:authorization) { "Bearer #{company.api_token}" }
|
|
50
|
+
|
|
51
|
+
it "supports OAuth bearer authorization and succeeds" do
|
|
52
|
+
expect { post_request }.to change(company.groups, :count).from(0).to(1)
|
|
53
|
+
|
|
54
|
+
expect(response.status).to eq 201
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "with invalid token" do
|
|
59
|
+
let(:authorization) { "Bearer #{SecureRandom.hex}" }
|
|
60
|
+
|
|
61
|
+
it "The request fails" do
|
|
62
|
+
expect { post_request }.not_to change(company.groups, :count)
|
|
63
|
+
|
|
64
|
+
expect(response.status).to eq 401
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|