scimitar 1.5.0 → 2.0.0
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/app/controllers/scimitar/active_record_backed_resources_controller.rb +6 -27
- data/app/controllers/scimitar/application_controller.rb +9 -29
- data/app/models/scimitar/engine_configuration.rb +3 -7
- data/app/models/scimitar/error_response.rb +0 -12
- data/app/models/scimitar/errors.rb +1 -1
- data/app/models/scimitar/lists/query_parser.rb +4 -14
- data/app/models/scimitar/resources/base.rb +1 -1
- data/app/models/scimitar/resources/mixin.rb +2 -78
- data/app/models/scimitar/schema/address.rb +0 -1
- data/app/models/scimitar/schema/attribute.rb +1 -1
- data/app/models/scimitar/schema/base.rb +3 -1
- data/app/models/scimitar/schema/vdtp.rb +1 -1
- data/config/initializers/scimitar.rb +70 -86
- data/lib/scimitar/version.rb +2 -2
- data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
- data/spec/apps/dummy/app/models/mock_group.rb +1 -1
- data/spec/apps/dummy/app/models/mock_user.rb +7 -10
- data/spec/apps/dummy/config/application.rb +1 -0
- data/spec/apps/dummy/config/environments/test.rb +28 -5
- data/spec/apps/dummy/config/initializers/scimitar.rb +10 -8
- data/spec/apps/dummy/config/routes.rb +0 -4
- data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +2 -2
- data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
- data/spec/apps/dummy/db/schema.rb +4 -8
- data/spec/controllers/scimitar/application_controller_spec.rb +1 -70
- data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
- data/spec/models/scimitar/lists/query_parser_spec.rb +9 -9
- data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
- data/spec/models/scimitar/resources/mixin_spec.rb +40 -675
- data/spec/models/scimitar/resources/user_spec.rb +4 -4
- data/spec/models/scimitar/schema/attribute_spec.rb +3 -0
- data/spec/models/scimitar/schema/base_spec.rb +1 -1
- data/spec/models/scimitar/schema/user_spec.rb +0 -10
- data/spec/requests/active_record_backed_resources_controller_spec.rb +40 -309
- data/spec/requests/application_controller_spec.rb +3 -7
- metadata +7 -7
@@ -159,67 +159,41 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
159
159
|
# =========================================================================
|
160
160
|
|
161
161
|
context '#to_scim' do
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
'schemas' => ['urn:ietf:params:scim:schemas:core:2.0:User']
|
198
|
-
})
|
199
|
-
end
|
200
|
-
end # "context 'with a UUID, renamed primary key column' do"
|
201
|
-
|
202
|
-
context 'with an integer, conventionally named primary key column' do
|
203
|
-
it 'compiles instance attribute values into a SCIM representation' do
|
204
|
-
instance = MockGroup.new
|
205
|
-
instance.id = 42
|
206
|
-
instance.scim_uid = 'GG02984'
|
207
|
-
instance.display_name = 'Some group'
|
208
|
-
|
209
|
-
scim = instance.to_scim(location: 'https://test.com/mock_groups/42')
|
210
|
-
json = scim.to_json()
|
211
|
-
hash = JSON.parse(json)
|
212
|
-
|
213
|
-
expect(hash).to eql({
|
214
|
-
'displayName' => 'Some group',
|
215
|
-
'id' => '42', # Note, String
|
216
|
-
'externalId' => 'GG02984',
|
217
|
-
'members' => [],
|
218
|
-
'meta' => {'location'=>'https://test.com/mock_groups/42', 'resourceType'=>'Group'},
|
219
|
-
'schemas' => ['urn:ietf:params:scim:schemas:core:2.0:Group']
|
220
|
-
})
|
221
|
-
end
|
222
|
-
end # "context 'with an integer, conventionally named primary key column' do"
|
162
|
+
it 'compiles instance attribute values into a SCIM representation' do
|
163
|
+
instance = MockUser.new
|
164
|
+
instance.id = 42
|
165
|
+
instance.scim_uid = 'AA02984'
|
166
|
+
instance.username = 'foo'
|
167
|
+
instance.first_name = 'Foo'
|
168
|
+
instance.last_name = 'Bar'
|
169
|
+
instance.work_email_address = 'foo.bar@test.com'
|
170
|
+
instance.home_email_address = nil
|
171
|
+
instance.work_phone_number = '+642201234567'
|
172
|
+
|
173
|
+
g1 = MockGroup.create!(display_name: 'Group 1')
|
174
|
+
g2 = MockGroup.create!(display_name: 'Group 2')
|
175
|
+
g3 = MockGroup.create!(display_name: 'Group 3')
|
176
|
+
|
177
|
+
g1.mock_users << instance
|
178
|
+
g3.mock_users << instance
|
179
|
+
|
180
|
+
scim = instance.to_scim(location: 'https://test.com/mock_users/42')
|
181
|
+
json = scim.to_json()
|
182
|
+
hash = JSON.parse(json)
|
183
|
+
|
184
|
+
expect(hash).to eql({
|
185
|
+
'userName' => 'foo',
|
186
|
+
'name' => {'givenName'=>'Foo', 'familyName'=>'Bar'},
|
187
|
+
'active' => true,
|
188
|
+
'emails' => [{'type'=>'work', 'primary'=>true, 'value'=>'foo.bar@test.com'}, {"primary"=>false, "type"=>"home", "value"=>nil}],
|
189
|
+
'phoneNumbers'=> [{'type'=>'work', 'primary'=>false, 'value'=>'+642201234567'}],
|
190
|
+
'id' => '42', # Note, String
|
191
|
+
'externalId' => 'AA02984',
|
192
|
+
'groups' => [{'display'=>g1.display_name, 'value'=>g1.id.to_s}, {'display'=>g3.display_name, 'value'=>g3.id.to_s}],
|
193
|
+
'meta' => {'location'=>'https://test.com/mock_users/42', 'resourceType'=>'User'},
|
194
|
+
'schemas' => ['urn:ietf:params:scim:schemas:core:2.0:User']
|
195
|
+
})
|
196
|
+
end
|
223
197
|
|
224
198
|
context 'with optional timestamps' do
|
225
199
|
context 'creation only' do
|
@@ -431,8 +405,8 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
431
405
|
'displayName' => 'Foo Group',
|
432
406
|
'members' => [
|
433
407
|
{'type' => 'Group', 'value' => g1.id.to_s},
|
434
|
-
{'type' => 'User', 'value' => u1.
|
435
|
-
{'type' => 'User', 'value' => u3.
|
408
|
+
{'type' => 'User', 'value' => u1.id.to_s},
|
409
|
+
{'type' => 'User', 'value' => u3.id.to_s}
|
436
410
|
],
|
437
411
|
'externalId' => 'GG01536',
|
438
412
|
'meta' => {'location'=>'https://test.com/mock_groups/1', 'resourceType'=>'Group'},
|
@@ -479,10 +453,8 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
479
453
|
end # "context 'using upper case' do"
|
480
454
|
|
481
455
|
it 'clears things not present in input' do
|
482
|
-
uuid = SecureRandom.uuid
|
483
|
-
|
484
456
|
instance = MockUser.new
|
485
|
-
instance.
|
457
|
+
instance.id = 42
|
486
458
|
instance.scim_uid = 'AA02984'
|
487
459
|
instance.username = 'foo'
|
488
460
|
instance.first_name = 'Foo'
|
@@ -493,7 +465,7 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
493
465
|
|
494
466
|
instance.from_scim!(scim_hash: {})
|
495
467
|
|
496
|
-
expect(instance.
|
468
|
+
expect(instance.id ).to eql(42)
|
497
469
|
expect(instance.scim_uid ).to be_nil
|
498
470
|
expect(instance.username ).to be_nil
|
499
471
|
expect(instance.first_name ).to be_nil
|
@@ -1230,595 +1202,6 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
1230
1202
|
|
1231
1203
|
expect(scim_hash).to_not have_key('emails')
|
1232
1204
|
end
|
1233
|
-
|
1234
|
-
# What we expect:
|
1235
|
-
#
|
1236
|
-
# https://www.rfc-editor.org/rfc/rfc7644#section-3.5.2.2
|
1237
|
-
# https://docs.snowflake.com/en/user-guide/scim-intro.html#patch-scim-v2-groups-id
|
1238
|
-
#
|
1239
|
-
# ...vs accounting for the unusual payloads we sometimes get,
|
1240
|
-
# tested here.
|
1241
|
-
#
|
1242
|
-
context 'special cases' do
|
1243
|
-
|
1244
|
-
# https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#update-group-remove-members
|
1245
|
-
#
|
1246
|
-
context 'Microsoft-style payload' do
|
1247
|
-
context 'removing a user from a group' do
|
1248
|
-
it 'removes identified user' do
|
1249
|
-
path = [ 'members' ]
|
1250
|
-
value = [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c' } ]
|
1251
|
-
scim_hash = {
|
1252
|
-
'displayname' => 'Mock group',
|
1253
|
-
'members' => [
|
1254
|
-
{
|
1255
|
-
'value' => '50ca93d04ab0c2de4772',
|
1256
|
-
'display' => 'Ingrid Smith',
|
1257
|
-
'type' => 'User'
|
1258
|
-
},
|
1259
|
-
{
|
1260
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1261
|
-
'display' => 'Fred Smith',
|
1262
|
-
'type' => 'User'
|
1263
|
-
},
|
1264
|
-
{
|
1265
|
-
'value' => 'a774d480e8112101375b',
|
1266
|
-
'display' => 'Taylor Smith',
|
1267
|
-
'type' => 'User'
|
1268
|
-
}
|
1269
|
-
]
|
1270
|
-
}.with_indifferent_case_insensitive_access()
|
1271
|
-
|
1272
|
-
@instance.send(
|
1273
|
-
:from_patch_backend!,
|
1274
|
-
nature: 'remove',
|
1275
|
-
path: path,
|
1276
|
-
value: value,
|
1277
|
-
altering_hash: scim_hash
|
1278
|
-
)
|
1279
|
-
|
1280
|
-
expect(scim_hash).to eql({
|
1281
|
-
'displayname' => 'Mock group',
|
1282
|
-
'members' => [
|
1283
|
-
{
|
1284
|
-
'value' => '50ca93d04ab0c2de4772',
|
1285
|
-
'display' => 'Ingrid Smith',
|
1286
|
-
'type' => 'User'
|
1287
|
-
},
|
1288
|
-
{
|
1289
|
-
'value' => 'a774d480e8112101375b',
|
1290
|
-
'display' => 'Taylor Smith',
|
1291
|
-
'type' => 'User'
|
1292
|
-
}
|
1293
|
-
]
|
1294
|
-
})
|
1295
|
-
end
|
1296
|
-
|
1297
|
-
it 'removes multiple identified users' do
|
1298
|
-
path = [ 'members' ]
|
1299
|
-
value = [
|
1300
|
-
{ '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c' },
|
1301
|
-
{ '$ref' => nil, 'value' => '50ca93d04ab0c2de4772' }
|
1302
|
-
]
|
1303
|
-
scim_hash = {
|
1304
|
-
'displayname' => 'Mock group',
|
1305
|
-
'members' => [
|
1306
|
-
{
|
1307
|
-
'value' => '50ca93d04ab0c2de4772',
|
1308
|
-
'display' => 'Ingrid Smith',
|
1309
|
-
'type' => 'User'
|
1310
|
-
},
|
1311
|
-
{
|
1312
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1313
|
-
'display' => 'Fred Smith',
|
1314
|
-
'type' => 'User'
|
1315
|
-
},
|
1316
|
-
{
|
1317
|
-
'value' => 'a774d480e8112101375b',
|
1318
|
-
'display' => 'Taylor Smith',
|
1319
|
-
'type' => 'User'
|
1320
|
-
}
|
1321
|
-
]
|
1322
|
-
}.with_indifferent_case_insensitive_access()
|
1323
|
-
|
1324
|
-
@instance.send(
|
1325
|
-
:from_patch_backend!,
|
1326
|
-
nature: 'remove',
|
1327
|
-
path: path,
|
1328
|
-
value: value,
|
1329
|
-
altering_hash: scim_hash
|
1330
|
-
)
|
1331
|
-
|
1332
|
-
expect(scim_hash).to eql({
|
1333
|
-
'displayname' => 'Mock group',
|
1334
|
-
'members' => [
|
1335
|
-
{
|
1336
|
-
'value' => 'a774d480e8112101375b',
|
1337
|
-
'display' => 'Taylor Smith',
|
1338
|
-
'type' => 'User'
|
1339
|
-
}
|
1340
|
-
]
|
1341
|
-
})
|
1342
|
-
end
|
1343
|
-
|
1344
|
-
it 'removes all users individually without error' do
|
1345
|
-
path = [ 'members' ]
|
1346
|
-
value = [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c' } ]
|
1347
|
-
scim_hash = {
|
1348
|
-
'displayname' => 'Mock group',
|
1349
|
-
'members' => [
|
1350
|
-
{
|
1351
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1352
|
-
'display' => 'Fred Smith',
|
1353
|
-
'type' => 'User'
|
1354
|
-
}
|
1355
|
-
]
|
1356
|
-
}.with_indifferent_case_insensitive_access()
|
1357
|
-
|
1358
|
-
@instance.send(
|
1359
|
-
:from_patch_backend!,
|
1360
|
-
nature: 'remove',
|
1361
|
-
path: path,
|
1362
|
-
value: value,
|
1363
|
-
altering_hash: scim_hash
|
1364
|
-
)
|
1365
|
-
|
1366
|
-
expect(scim_hash).to eql({
|
1367
|
-
'displayname' => 'Mock group',
|
1368
|
-
'members' => []
|
1369
|
-
})
|
1370
|
-
end
|
1371
|
-
|
1372
|
-
it 'can match on multiple attributes' do
|
1373
|
-
path = [ 'members' ]
|
1374
|
-
value = [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c', 'type' => 'User' } ]
|
1375
|
-
scim_hash = {
|
1376
|
-
'displayname' => 'Mock group',
|
1377
|
-
'members' => [
|
1378
|
-
{
|
1379
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1380
|
-
'display' => 'Fred Smith',
|
1381
|
-
'type' => 'User'
|
1382
|
-
}
|
1383
|
-
]
|
1384
|
-
}.with_indifferent_case_insensitive_access()
|
1385
|
-
|
1386
|
-
@instance.send(
|
1387
|
-
:from_patch_backend!,
|
1388
|
-
nature: 'remove',
|
1389
|
-
path: path,
|
1390
|
-
value: value,
|
1391
|
-
altering_hash: scim_hash
|
1392
|
-
)
|
1393
|
-
|
1394
|
-
expect(scim_hash).to eql({
|
1395
|
-
'displayname' => 'Mock group',
|
1396
|
-
'members' => []
|
1397
|
-
})
|
1398
|
-
end
|
1399
|
-
|
1400
|
-
it 'ignores unrecognised users' do
|
1401
|
-
path = [ 'members' ]
|
1402
|
-
value = [ { '$ref' => nil, 'value' => '11b054a9c85216ed9356' } ]
|
1403
|
-
scim_hash = {
|
1404
|
-
'displayname' => 'Mock group',
|
1405
|
-
'members' => [
|
1406
|
-
{
|
1407
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1408
|
-
'display' => 'Fred Smith',
|
1409
|
-
'type' => 'User'
|
1410
|
-
}
|
1411
|
-
]
|
1412
|
-
}.with_indifferent_case_insensitive_access()
|
1413
|
-
|
1414
|
-
@instance.send(
|
1415
|
-
:from_patch_backend!,
|
1416
|
-
nature: 'remove',
|
1417
|
-
path: path,
|
1418
|
-
value: value,
|
1419
|
-
altering_hash: scim_hash
|
1420
|
-
)
|
1421
|
-
|
1422
|
-
# The 'value' mismatched, so the user was not removed.
|
1423
|
-
#
|
1424
|
-
expect(scim_hash).to eql({
|
1425
|
-
'displayname' => 'Mock group',
|
1426
|
-
'members' => [
|
1427
|
-
{
|
1428
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1429
|
-
'display' => 'Fred Smith',
|
1430
|
-
'type' => 'User'
|
1431
|
-
}
|
1432
|
-
]
|
1433
|
-
})
|
1434
|
-
end
|
1435
|
-
|
1436
|
-
it 'ignores a mismatch on (for example) "type"' do
|
1437
|
-
path = [ 'members' ]
|
1438
|
-
value = [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c', 'type' => 'Group' } ]
|
1439
|
-
scim_hash = {
|
1440
|
-
'displayname' => 'Mock group',
|
1441
|
-
'members' => [
|
1442
|
-
{
|
1443
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1444
|
-
'display' => 'Fred Smith',
|
1445
|
-
'type' => 'User'
|
1446
|
-
}
|
1447
|
-
]
|
1448
|
-
}.with_indifferent_case_insensitive_access()
|
1449
|
-
|
1450
|
-
@instance.send(
|
1451
|
-
:from_patch_backend!,
|
1452
|
-
nature: 'remove',
|
1453
|
-
path: path,
|
1454
|
-
value: value,
|
1455
|
-
altering_hash: scim_hash
|
1456
|
-
)
|
1457
|
-
|
1458
|
-
# Type 'Group' mismatches 'User', so the user was not
|
1459
|
-
# removed.
|
1460
|
-
#
|
1461
|
-
expect(scim_hash).to eql({
|
1462
|
-
'displayname' => 'Mock group',
|
1463
|
-
'members' => [
|
1464
|
-
{
|
1465
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1466
|
-
'display' => 'Fred Smith',
|
1467
|
-
'type' => 'User'
|
1468
|
-
}
|
1469
|
-
]
|
1470
|
-
})
|
1471
|
-
end
|
1472
|
-
|
1473
|
-
it 'matches keys case-insensitive' do
|
1474
|
-
path = [ 'members' ]
|
1475
|
-
value = [ { '$ref' => nil, 'VALUe' => 'f648f8d5ea4e4cd38e9c' } ]
|
1476
|
-
scim_hash = {
|
1477
|
-
'displayname' => 'Mock group',
|
1478
|
-
'memBERS' => [
|
1479
|
-
{
|
1480
|
-
'vaLUe' => 'f648f8d5ea4e4cd38e9c',
|
1481
|
-
'display' => 'Fred Smith',
|
1482
|
-
'type' => 'User'
|
1483
|
-
}
|
1484
|
-
]
|
1485
|
-
}.with_indifferent_case_insensitive_access()
|
1486
|
-
|
1487
|
-
@instance.send(
|
1488
|
-
:from_patch_backend!,
|
1489
|
-
nature: 'remove',
|
1490
|
-
path: path,
|
1491
|
-
value: value,
|
1492
|
-
altering_hash: scim_hash
|
1493
|
-
)
|
1494
|
-
|
1495
|
-
expect(scim_hash).to eql({
|
1496
|
-
'displayname' => 'Mock group',
|
1497
|
-
'members' => []
|
1498
|
-
})
|
1499
|
-
end
|
1500
|
-
|
1501
|
-
it 'matches values case-sensitive' do
|
1502
|
-
path = [ 'members' ]
|
1503
|
-
value = [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c', 'type' => 'USER' } ]
|
1504
|
-
scim_hash = {
|
1505
|
-
'displayname' => 'Mock group',
|
1506
|
-
'members' => [
|
1507
|
-
{
|
1508
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1509
|
-
'display' => 'Fred Smith',
|
1510
|
-
'type' => 'User'
|
1511
|
-
}
|
1512
|
-
]
|
1513
|
-
}.with_indifferent_case_insensitive_access()
|
1514
|
-
|
1515
|
-
@instance.send(
|
1516
|
-
:from_patch_backend!,
|
1517
|
-
nature: 'remove',
|
1518
|
-
path: path,
|
1519
|
-
value: value,
|
1520
|
-
altering_hash: scim_hash
|
1521
|
-
)
|
1522
|
-
|
1523
|
-
# USER mismatchs User, so the user was not removed.
|
1524
|
-
#
|
1525
|
-
expect(scim_hash).to eql({
|
1526
|
-
'displayname' => 'Mock group',
|
1527
|
-
'members' => [
|
1528
|
-
{
|
1529
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1530
|
-
'display' => 'Fred Smith',
|
1531
|
-
'type' => 'User'
|
1532
|
-
}
|
1533
|
-
]
|
1534
|
-
})
|
1535
|
-
end
|
1536
|
-
end # "context 'removing a user from a group' do"
|
1537
|
-
|
1538
|
-
context 'generic use' do
|
1539
|
-
it 'removes matched items' do
|
1540
|
-
path = [ 'emails' ]
|
1541
|
-
value = [ { 'type' => 'work' } ]
|
1542
|
-
scim_hash = {
|
1543
|
-
'emails' => [
|
1544
|
-
{
|
1545
|
-
'type' => 'home',
|
1546
|
-
'value' => 'home@test.com'
|
1547
|
-
},
|
1548
|
-
{
|
1549
|
-
'type' => 'work',
|
1550
|
-
'value' => 'work@test.com'
|
1551
|
-
}
|
1552
|
-
]
|
1553
|
-
}.with_indifferent_case_insensitive_access()
|
1554
|
-
|
1555
|
-
@instance.send(
|
1556
|
-
:from_patch_backend!,
|
1557
|
-
nature: 'remove',
|
1558
|
-
path: path,
|
1559
|
-
value: value,
|
1560
|
-
altering_hash: scim_hash
|
1561
|
-
)
|
1562
|
-
|
1563
|
-
expect(scim_hash).to eql({
|
1564
|
-
'emails' => [
|
1565
|
-
{
|
1566
|
-
'type' => 'home',
|
1567
|
-
'value' => 'home@test.com'
|
1568
|
-
}
|
1569
|
-
]
|
1570
|
-
})
|
1571
|
-
end
|
1572
|
-
|
1573
|
-
it 'ignores unmatched items' do
|
1574
|
-
path = [ 'emails' ]
|
1575
|
-
value = [ { 'type' => 'missing' } ]
|
1576
|
-
scim_hash = {
|
1577
|
-
'emails' => [
|
1578
|
-
{
|
1579
|
-
'type' => 'home',
|
1580
|
-
'value' => 'home@test.com'
|
1581
|
-
},
|
1582
|
-
{
|
1583
|
-
'type' => 'work',
|
1584
|
-
'value' => 'work@test.com'
|
1585
|
-
}
|
1586
|
-
]
|
1587
|
-
}.with_indifferent_case_insensitive_access()
|
1588
|
-
|
1589
|
-
@instance.send(
|
1590
|
-
:from_patch_backend!,
|
1591
|
-
nature: 'remove',
|
1592
|
-
path: path,
|
1593
|
-
value: value,
|
1594
|
-
altering_hash: scim_hash
|
1595
|
-
)
|
1596
|
-
|
1597
|
-
expect(scim_hash).to eql({
|
1598
|
-
'emails' => [
|
1599
|
-
{
|
1600
|
-
'type' => 'home',
|
1601
|
-
'value' => 'home@test.com'
|
1602
|
-
},
|
1603
|
-
{
|
1604
|
-
'type' => 'work',
|
1605
|
-
'value' => 'work@test.com'
|
1606
|
-
}
|
1607
|
-
]
|
1608
|
-
})
|
1609
|
-
end
|
1610
|
-
|
1611
|
-
it 'compares string forms' do
|
1612
|
-
path = [ 'test' ]
|
1613
|
-
value = [
|
1614
|
-
{ 'active' => true, 'value' => '12' },
|
1615
|
-
{ 'active' => 'false', 'value' => 42 }
|
1616
|
-
]
|
1617
|
-
scim_hash = {
|
1618
|
-
'test' => [
|
1619
|
-
{
|
1620
|
-
'active' => 'true',
|
1621
|
-
'value' => 12
|
1622
|
-
},
|
1623
|
-
{
|
1624
|
-
'active' => false,
|
1625
|
-
'value' => '42'
|
1626
|
-
}
|
1627
|
-
]
|
1628
|
-
}.with_indifferent_case_insensitive_access()
|
1629
|
-
|
1630
|
-
@instance.send(
|
1631
|
-
:from_patch_backend!,
|
1632
|
-
nature: 'remove',
|
1633
|
-
path: path,
|
1634
|
-
value: value,
|
1635
|
-
altering_hash: scim_hash
|
1636
|
-
)
|
1637
|
-
|
1638
|
-
expect(scim_hash).to eql({'test' => []})
|
1639
|
-
end
|
1640
|
-
|
1641
|
-
it 'handles a singular to-remove value rather than an array' do
|
1642
|
-
path = [ 'emails' ]
|
1643
|
-
value = { 'type' => 'work' }
|
1644
|
-
scim_hash = {
|
1645
|
-
'emails' => [
|
1646
|
-
{
|
1647
|
-
'type' => 'home',
|
1648
|
-
'value' => 'home@test.com'
|
1649
|
-
},
|
1650
|
-
{
|
1651
|
-
'type' => 'work',
|
1652
|
-
'value' => 'work@test.com'
|
1653
|
-
}
|
1654
|
-
]
|
1655
|
-
}.with_indifferent_case_insensitive_access()
|
1656
|
-
|
1657
|
-
@instance.send(
|
1658
|
-
:from_patch_backend!,
|
1659
|
-
nature: 'remove',
|
1660
|
-
path: path,
|
1661
|
-
value: value,
|
1662
|
-
altering_hash: scim_hash
|
1663
|
-
)
|
1664
|
-
|
1665
|
-
expect(scim_hash).to eql({
|
1666
|
-
'emails' => [
|
1667
|
-
{
|
1668
|
-
'type' => 'home',
|
1669
|
-
'value' => 'home@test.com'
|
1670
|
-
}
|
1671
|
-
]
|
1672
|
-
})
|
1673
|
-
end
|
1674
|
-
|
1675
|
-
it 'handles simple values rather than object (Hash) values' do
|
1676
|
-
path = [ 'test' ]
|
1677
|
-
value = 42
|
1678
|
-
scim_hash = {
|
1679
|
-
'test' => [
|
1680
|
-
'21',
|
1681
|
-
'42',
|
1682
|
-
'15'
|
1683
|
-
]
|
1684
|
-
}.with_indifferent_case_insensitive_access()
|
1685
|
-
|
1686
|
-
@instance.send(
|
1687
|
-
:from_patch_backend!,
|
1688
|
-
nature: 'remove',
|
1689
|
-
path: path,
|
1690
|
-
value: value,
|
1691
|
-
altering_hash: scim_hash
|
1692
|
-
)
|
1693
|
-
|
1694
|
-
expect(scim_hash).to eql({
|
1695
|
-
'test' => [
|
1696
|
-
'21',
|
1697
|
-
'15'
|
1698
|
-
]
|
1699
|
-
})
|
1700
|
-
end
|
1701
|
-
end
|
1702
|
-
end # "context 'Microsoft-style payload' do"
|
1703
|
-
|
1704
|
-
# https://help.salesforce.com/s/articleView?id=sf.identity_scim_manage_groups.htm&type=5
|
1705
|
-
#
|
1706
|
-
context 'Salesforce-style payload' do
|
1707
|
-
it 'removes identified user' do
|
1708
|
-
path = [ 'members' ]
|
1709
|
-
value = { 'members' => [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c' } ] }
|
1710
|
-
scim_hash = {
|
1711
|
-
'displayname' => 'Mock group',
|
1712
|
-
'members' => [
|
1713
|
-
{
|
1714
|
-
'value' => '50ca93d04ab0c2de4772',
|
1715
|
-
'display' => 'Ingrid Smith',
|
1716
|
-
'type' => 'User'
|
1717
|
-
},
|
1718
|
-
{
|
1719
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1720
|
-
'display' => 'Fred Smith',
|
1721
|
-
'type' => 'User'
|
1722
|
-
}
|
1723
|
-
]
|
1724
|
-
}.with_indifferent_case_insensitive_access()
|
1725
|
-
|
1726
|
-
@instance.send(
|
1727
|
-
:from_patch_backend!,
|
1728
|
-
nature: 'remove',
|
1729
|
-
path: path,
|
1730
|
-
value: value,
|
1731
|
-
altering_hash: scim_hash
|
1732
|
-
)
|
1733
|
-
|
1734
|
-
expect(scim_hash).to eql({
|
1735
|
-
'displayname' => 'Mock group',
|
1736
|
-
'members' => [
|
1737
|
-
{
|
1738
|
-
'value' => '50ca93d04ab0c2de4772',
|
1739
|
-
'display' => 'Ingrid Smith',
|
1740
|
-
'type' => 'User'
|
1741
|
-
}
|
1742
|
-
]
|
1743
|
-
})
|
1744
|
-
end
|
1745
|
-
|
1746
|
-
it 'matches the "members" key case-insensitive' do
|
1747
|
-
path = [ 'members' ]
|
1748
|
-
value = { 'MEMBERS' => [ { '$ref' => nil, 'value' => 'f648f8d5ea4e4cd38e9c' } ] }
|
1749
|
-
scim_hash = {
|
1750
|
-
'displayname' => 'Mock group',
|
1751
|
-
'members' => [
|
1752
|
-
{
|
1753
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1754
|
-
'display' => 'Fred Smith',
|
1755
|
-
'type' => 'User'
|
1756
|
-
},
|
1757
|
-
{
|
1758
|
-
'value' => 'a774d480e8112101375b',
|
1759
|
-
'display' => 'Taylor Smith',
|
1760
|
-
'type' => 'User'
|
1761
|
-
}
|
1762
|
-
]
|
1763
|
-
}.with_indifferent_case_insensitive_access()
|
1764
|
-
|
1765
|
-
@instance.send(
|
1766
|
-
:from_patch_backend!,
|
1767
|
-
nature: 'remove',
|
1768
|
-
path: path,
|
1769
|
-
value: value,
|
1770
|
-
altering_hash: scim_hash
|
1771
|
-
)
|
1772
|
-
|
1773
|
-
expect(scim_hash).to eql({
|
1774
|
-
'displayname' => 'Mock group',
|
1775
|
-
'members' => [
|
1776
|
-
{
|
1777
|
-
'value' => 'a774d480e8112101375b',
|
1778
|
-
'display' => 'Taylor Smith',
|
1779
|
-
'type' => 'User'
|
1780
|
-
}
|
1781
|
-
]
|
1782
|
-
})
|
1783
|
-
end
|
1784
|
-
|
1785
|
-
it 'ignores unrecognised users' do
|
1786
|
-
path = [ 'members' ]
|
1787
|
-
value = { 'members' => [ { '$ref' => nil, 'value' => '11b054a9c85216ed9356' } ] }
|
1788
|
-
scim_hash = {
|
1789
|
-
'displayname' => 'Mock group',
|
1790
|
-
'members' => [
|
1791
|
-
{
|
1792
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1793
|
-
'display' => 'Fred Smith',
|
1794
|
-
'type' => 'User'
|
1795
|
-
}
|
1796
|
-
]
|
1797
|
-
}.with_indifferent_case_insensitive_access()
|
1798
|
-
|
1799
|
-
@instance.send(
|
1800
|
-
:from_patch_backend!,
|
1801
|
-
nature: 'remove',
|
1802
|
-
path: path,
|
1803
|
-
value: value,
|
1804
|
-
altering_hash: scim_hash
|
1805
|
-
)
|
1806
|
-
|
1807
|
-
# The 'value' mismatched, so the user was not removed.
|
1808
|
-
#
|
1809
|
-
expect(scim_hash).to eql({
|
1810
|
-
'displayname' => 'Mock group',
|
1811
|
-
'members' => [
|
1812
|
-
{
|
1813
|
-
'value' => 'f648f8d5ea4e4cd38e9c',
|
1814
|
-
'display' => 'Fred Smith',
|
1815
|
-
'type' => 'User'
|
1816
|
-
}
|
1817
|
-
]
|
1818
|
-
})
|
1819
|
-
end
|
1820
|
-
end # "context 'Salesforce-style payload' do"
|
1821
|
-
end # "context 'special cases' do"
|
1822
1205
|
end # context 'when prior value already exists' do
|
1823
1206
|
|
1824
1207
|
context 'when value is not present' do
|
@@ -2364,24 +1747,6 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
2364
1747
|
expect(scim_hash['emails'][0]['type' ]).to eql('work')
|
2365
1748
|
expect(scim_hash['emails'][0]['value']).to eql('work@test.com')
|
2366
1749
|
end
|
2367
|
-
|
2368
|
-
context 'when prior value already exists, and no path' do
|
2369
|
-
it 'simple value: overwrites' do
|
2370
|
-
path = [ 'root' ]
|
2371
|
-
scim_hash = { 'root' => { 'userName' => 'bar', 'active' => true } }.with_indifferent_case_insensitive_access()
|
2372
|
-
|
2373
|
-
@instance.send(
|
2374
|
-
:from_patch_backend!,
|
2375
|
-
nature: 'replace',
|
2376
|
-
path: path,
|
2377
|
-
value: { 'active' => false }.with_indifferent_case_insensitive_access(),
|
2378
|
-
altering_hash: scim_hash
|
2379
|
-
)
|
2380
|
-
|
2381
|
-
expect(scim_hash['root']['userName']).to eql('bar')
|
2382
|
-
expect(scim_hash['root']['active']).to eql(false)
|
2383
|
-
end
|
2384
|
-
end
|
2385
1750
|
end # context 'when value is not present' do
|
2386
1751
|
end # "context 'replace' do"
|
2387
1752
|
|
@@ -2543,7 +1908,7 @@ RSpec.describe Scimitar::Resources::Mixin do
|
|
2543
1908
|
:from_patch_backend!,
|
2544
1909
|
nature: 'remove',
|
2545
1910
|
path: ['complex[type eq "type1"]', 'data', 'nested[nature eq "nature2"]', 'info'],
|
2546
|
-
value:
|
1911
|
+
value: [{ 'deeper' => 'addition' }],
|
2547
1912
|
altering_hash: scim_hash
|
2548
1913
|
)
|
2549
1914
|
|