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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scimitar/active_record_backed_resources_controller.rb +6 -27
  3. data/app/controllers/scimitar/application_controller.rb +9 -29
  4. data/app/models/scimitar/engine_configuration.rb +3 -7
  5. data/app/models/scimitar/error_response.rb +0 -12
  6. data/app/models/scimitar/errors.rb +1 -1
  7. data/app/models/scimitar/lists/query_parser.rb +4 -14
  8. data/app/models/scimitar/resources/base.rb +1 -1
  9. data/app/models/scimitar/resources/mixin.rb +2 -78
  10. data/app/models/scimitar/schema/address.rb +0 -1
  11. data/app/models/scimitar/schema/attribute.rb +1 -1
  12. data/app/models/scimitar/schema/base.rb +3 -1
  13. data/app/models/scimitar/schema/vdtp.rb +1 -1
  14. data/config/initializers/scimitar.rb +70 -86
  15. data/lib/scimitar/version.rb +2 -2
  16. data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
  17. data/spec/apps/dummy/app/models/mock_group.rb +1 -1
  18. data/spec/apps/dummy/app/models/mock_user.rb +7 -10
  19. data/spec/apps/dummy/config/application.rb +1 -0
  20. data/spec/apps/dummy/config/environments/test.rb +28 -5
  21. data/spec/apps/dummy/config/initializers/scimitar.rb +10 -8
  22. data/spec/apps/dummy/config/routes.rb +0 -4
  23. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +2 -2
  24. data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
  25. data/spec/apps/dummy/db/schema.rb +4 -8
  26. data/spec/controllers/scimitar/application_controller_spec.rb +1 -70
  27. data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
  28. data/spec/models/scimitar/lists/query_parser_spec.rb +9 -9
  29. data/spec/models/scimitar/resources/base_validation_spec.rb +2 -27
  30. data/spec/models/scimitar/resources/mixin_spec.rb +40 -675
  31. data/spec/models/scimitar/resources/user_spec.rb +4 -4
  32. data/spec/models/scimitar/schema/attribute_spec.rb +3 -0
  33. data/spec/models/scimitar/schema/base_spec.rb +1 -1
  34. data/spec/models/scimitar/schema/user_spec.rb +0 -10
  35. data/spec/requests/active_record_backed_resources_controller_spec.rb +40 -309
  36. data/spec/requests/application_controller_spec.rb +3 -7
  37. metadata +7 -7
@@ -159,67 +159,41 @@ RSpec.describe Scimitar::Resources::Mixin do
159
159
  # =========================================================================
160
160
 
161
161
  context '#to_scim' do
162
- context 'with a UUID, renamed primary key column' do
163
- it 'compiles instance attribute values into a SCIM representation' do
164
- uuid = SecureRandom.uuid
165
-
166
- instance = MockUser.new
167
- instance.primary_key = uuid
168
- instance.scim_uid = 'AA02984'
169
- instance.username = 'foo'
170
- instance.first_name = 'Foo'
171
- instance.last_name = 'Bar'
172
- instance.work_email_address = 'foo.bar@test.com'
173
- instance.home_email_address = nil
174
- instance.work_phone_number = '+642201234567'
175
-
176
- g1 = MockGroup.create!(display_name: 'Group 1')
177
- g2 = MockGroup.create!(display_name: 'Group 2')
178
- g3 = MockGroup.create!(display_name: 'Group 3')
179
-
180
- g1.mock_users << instance
181
- g3.mock_users << instance
182
-
183
- scim = instance.to_scim(location: "https://test.com/mock_users/#{uuid}")
184
- json = scim.to_json()
185
- hash = JSON.parse(json)
186
-
187
- expect(hash).to eql({
188
- 'userName' => 'foo',
189
- 'name' => {'givenName'=>'Foo', 'familyName'=>'Bar'},
190
- 'active' => true,
191
- 'emails' => [{'type'=>'work', 'primary'=>true, 'value'=>'foo.bar@test.com'}, {"primary"=>false, "type"=>"home", "value"=>nil}],
192
- 'phoneNumbers'=> [{'type'=>'work', 'primary'=>false, 'value'=>'+642201234567'}],
193
- 'id' => uuid,
194
- 'externalId' => 'AA02984',
195
- 'groups' => [{'display'=>g1.display_name, 'value'=>g1.id.to_s}, {'display'=>g3.display_name, 'value'=>g3.id.to_s}],
196
- 'meta' => {'location'=>"https://test.com/mock_users/#{uuid}", 'resourceType'=>'User'},
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.primary_key.to_s},
435
- {'type' => 'User', 'value' => u3.primary_key.to_s}
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.primary_key = uuid
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.primary_key ).to eql(uuid)
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: nil,
1911
+ value: [{ 'deeper' => 'addition' }],
2547
1912
  altering_hash: scim_hash
2548
1913
  )
2549
1914