cozy-sharing 38.1.5 → 38.1.6
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.
- package/CHANGELOG.md +6 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +3 -2
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +175 -147
- package/package.json +3 -3
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +4 -1
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +21 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [38.1.6](https://github.com/cozy/cozy-libs/compare/cozy-sharing@38.1.5...cozy-sharing@38.1.6) (2026-10-01)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **cozy-sharing:** Keep an unshared folder shareable by its owner ([d0bdac7](https://github.com/cozy/cozy-libs/commit/d0bdac725d3b854be789def6c67ae31ca8db59bd)), closes [linagora/twake-drive#4264](https://github.com/linagora/twake-drive/issues/4264)
|
|
11
|
+
|
|
6
12
|
## [38.1.5](https://github.com/cozy/cozy-libs/compare/cozy-sharing@38.1.4...cozy-sharing@38.1.5) (2026-09-30)
|
|
7
13
|
|
|
8
14
|
**Note:** Version bump only for package cozy-sharing
|
|
@@ -123,8 +123,9 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
123
123
|
var displayedLink = existingDocument !== null && existingDocument !== void 0 && existingDocument.driveId ? getFederatedShareLink(existingDocument) : getSharingLink(existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id);
|
|
124
124
|
var isSharedDriveRoot = Boolean((existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.driveId) && sharedDriveRootIds.some(function (id) {
|
|
125
125
|
return id === (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id) || id === (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.id);
|
|
126
|
-
}));
|
|
127
|
-
|
|
126
|
+
})); // Ignore a stale driveId left after an owner revokes the last recipient, so their own folder isn't wrongly restricted to link-only (linagora/twake-drive#4264).
|
|
127
|
+
|
|
128
|
+
var isInsideSharedDrive = Boolean((existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.driveId) && !isSharedDriveRoot && (sharedDriveSharing || !isOwner(documentId)));
|
|
128
129
|
var isCurrentUserOwner = existingDocument !== null && existingDocument !== void 0 && existingDocument.driveId ? Boolean(sharedDriveSharing === null || sharedDriveSharing === void 0 || (_sharedDriveSharing$a2 = sharedDriveSharing.attributes) === null || _sharedDriveSharing$a2 === void 0 ? void 0 : _sharedDriveSharing$a2.owner) : documentId ? isOwner(documentId) : false;
|
|
129
130
|
var isMemberReadOnly = isInsideSharedDrive && !isCurrentUserOwner && !hasWriteAccess(documentId, existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.driveId);
|
|
130
131
|
var canManageSharing = isCurrentUserOwner || (documentId ? canReshare(documentId) : false);
|
|
@@ -385,11 +385,39 @@ describe('FederatedFolderModal', function () {
|
|
|
385
385
|
}
|
|
386
386
|
}, _callee8);
|
|
387
387
|
})));
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
388
|
+
it('should allow share by email when the owner revoked the sharing of a folder that still carries a stale driveId', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
|
|
389
|
+
var _setup9, findByText, queryByText;
|
|
390
|
+
|
|
391
391
|
return _regeneratorRuntime.wrap(function _callee9$(_context9) {
|
|
392
392
|
while (1) switch (_context9.prev = _context9.next) {
|
|
393
|
+
case 0:
|
|
394
|
+
// Owner revoked the last recipient: stale driveId, sharing gone, but still owner → stays shareable (linagora/twake-drive#4264).
|
|
395
|
+
mockGetSharingById.mockReturnValue(null);
|
|
396
|
+
mockIsOwner.mockReturnValue(true);
|
|
397
|
+
_setup9 = setup({
|
|
398
|
+
document: _objectSpread(_objectSpread({}, mockDocument), {}, {
|
|
399
|
+
driveId: 'federated-folder-id',
|
|
400
|
+
type: 'directory'
|
|
401
|
+
})
|
|
402
|
+
}), findByText = _setup9.findByText, queryByText = _setup9.queryByText;
|
|
403
|
+
_context9.next = 5;
|
|
404
|
+
return findByText('Add users');
|
|
405
|
+
|
|
406
|
+
case 5:
|
|
407
|
+
expect(queryByText('This folder can only be shared by link, because')).toBe(null);
|
|
408
|
+
expect(queryByText('it has a shared parent')).toBe(null);
|
|
409
|
+
|
|
410
|
+
case 7:
|
|
411
|
+
case "end":
|
|
412
|
+
return _context9.stop();
|
|
413
|
+
}
|
|
414
|
+
}, _callee9);
|
|
415
|
+
})));
|
|
416
|
+
});
|
|
417
|
+
describe('shared drive link fetch on mount', function () {
|
|
418
|
+
it('should fetch shared drive sharing links when document has a driveId and no permissions yet', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
|
|
419
|
+
return _regeneratorRuntime.wrap(function _callee10$(_context10) {
|
|
420
|
+
while (1) switch (_context10.prev = _context10.next) {
|
|
393
421
|
case 0:
|
|
394
422
|
mockGetDocumentPermissions.mockReturnValue([]);
|
|
395
423
|
setup({
|
|
@@ -397,7 +425,7 @@ describe('FederatedFolderModal', function () {
|
|
|
397
425
|
driveId: 'federated-folder-id'
|
|
398
426
|
})
|
|
399
427
|
});
|
|
400
|
-
|
|
428
|
+
_context10.next = 4;
|
|
401
429
|
return waitFor(function () {
|
|
402
430
|
expect(mockFetchSharedDriveSharingLinks).toHaveBeenCalledTimes(1);
|
|
403
431
|
});
|
|
@@ -410,14 +438,14 @@ describe('FederatedFolderModal', function () {
|
|
|
410
438
|
|
|
411
439
|
case 5:
|
|
412
440
|
case "end":
|
|
413
|
-
return
|
|
441
|
+
return _context10.stop();
|
|
414
442
|
}
|
|
415
|
-
},
|
|
443
|
+
}, _callee10);
|
|
416
444
|
})));
|
|
417
|
-
it('should use document.id when _id is missing', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
445
|
+
it('should use document.id when _id is missing', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
|
|
418
446
|
var document;
|
|
419
|
-
return _regeneratorRuntime.wrap(function
|
|
420
|
-
while (1) switch (
|
|
447
|
+
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
|
|
448
|
+
while (1) switch (_context11.prev = _context11.next) {
|
|
421
449
|
case 0:
|
|
422
450
|
document = {
|
|
423
451
|
id: 'folder-id-only',
|
|
@@ -428,7 +456,7 @@ describe('FederatedFolderModal', function () {
|
|
|
428
456
|
setup({
|
|
429
457
|
document: document
|
|
430
458
|
});
|
|
431
|
-
|
|
459
|
+
_context11.next = 4;
|
|
432
460
|
return waitFor(function () {
|
|
433
461
|
expect(mockFetchSharedDriveSharingLinks).toHaveBeenCalledWith(document);
|
|
434
462
|
});
|
|
@@ -438,20 +466,20 @@ describe('FederatedFolderModal', function () {
|
|
|
438
466
|
|
|
439
467
|
case 5:
|
|
440
468
|
case "end":
|
|
441
|
-
return
|
|
469
|
+
return _context11.stop();
|
|
442
470
|
}
|
|
443
|
-
},
|
|
471
|
+
}, _callee11);
|
|
444
472
|
})));
|
|
445
|
-
it('should not fetch shared drive sharing links when document has no driveId', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
446
|
-
var
|
|
473
|
+
it('should not fetch shared drive sharing links when document has no driveId', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12() {
|
|
474
|
+
var _setup10, findByText;
|
|
447
475
|
|
|
448
|
-
return _regeneratorRuntime.wrap(function
|
|
449
|
-
while (1) switch (
|
|
476
|
+
return _regeneratorRuntime.wrap(function _callee12$(_context12) {
|
|
477
|
+
while (1) switch (_context12.prev = _context12.next) {
|
|
450
478
|
case 0:
|
|
451
|
-
|
|
479
|
+
_setup10 = setup({
|
|
452
480
|
document: mockDocument
|
|
453
|
-
}), findByText =
|
|
454
|
-
|
|
481
|
+
}), findByText = _setup10.findByText;
|
|
482
|
+
_context12.next = 3;
|
|
455
483
|
return findByText('Copy link');
|
|
456
484
|
|
|
457
485
|
case 3:
|
|
@@ -459,23 +487,23 @@ describe('FederatedFolderModal', function () {
|
|
|
459
487
|
|
|
460
488
|
case 4:
|
|
461
489
|
case "end":
|
|
462
|
-
return
|
|
490
|
+
return _context12.stop();
|
|
463
491
|
}
|
|
464
|
-
},
|
|
492
|
+
}, _callee12);
|
|
465
493
|
})));
|
|
466
|
-
it('should not refetch after one attempt when permissions stay empty', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
467
|
-
var document,
|
|
494
|
+
it('should not refetch after one attempt when permissions stay empty', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee13() {
|
|
495
|
+
var document, _setup11, rerender;
|
|
468
496
|
|
|
469
|
-
return _regeneratorRuntime.wrap(function
|
|
470
|
-
while (1) switch (
|
|
497
|
+
return _regeneratorRuntime.wrap(function _callee13$(_context13) {
|
|
498
|
+
while (1) switch (_context13.prev = _context13.next) {
|
|
471
499
|
case 0:
|
|
472
500
|
document = _objectSpread(_objectSpread({}, mockDocument), {}, {
|
|
473
501
|
driveId: 'federated-folder-id'
|
|
474
502
|
});
|
|
475
|
-
|
|
503
|
+
_setup11 = setup({
|
|
476
504
|
document: document
|
|
477
|
-
}), rerender =
|
|
478
|
-
|
|
505
|
+
}), rerender = _setup11.rerender;
|
|
506
|
+
_context13.next = 4;
|
|
479
507
|
return waitFor(function () {
|
|
480
508
|
expect(mockFetchSharedDriveSharingLinks).toHaveBeenCalledTimes(1);
|
|
481
509
|
});
|
|
@@ -492,15 +520,15 @@ describe('FederatedFolderModal', function () {
|
|
|
492
520
|
|
|
493
521
|
case 6:
|
|
494
522
|
case "end":
|
|
495
|
-
return
|
|
523
|
+
return _context13.stop();
|
|
496
524
|
}
|
|
497
|
-
},
|
|
525
|
+
}, _callee13);
|
|
498
526
|
})));
|
|
499
|
-
it('should not fetch shared drive sharing links when permissions are already loaded', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
500
|
-
var
|
|
527
|
+
it('should not fetch shared drive sharing links when permissions are already loaded', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
|
|
528
|
+
var _setup12, findByText;
|
|
501
529
|
|
|
502
|
-
return _regeneratorRuntime.wrap(function
|
|
503
|
-
while (1) switch (
|
|
530
|
+
return _regeneratorRuntime.wrap(function _callee14$(_context14) {
|
|
531
|
+
while (1) switch (_context14.prev = _context14.next) {
|
|
504
532
|
case 0:
|
|
505
533
|
mockGetDocumentPermissions.mockReturnValue([{
|
|
506
534
|
id: 'perm-1',
|
|
@@ -511,12 +539,12 @@ describe('FederatedFolderModal', function () {
|
|
|
511
539
|
}
|
|
512
540
|
}
|
|
513
541
|
}]);
|
|
514
|
-
|
|
542
|
+
_setup12 = setup({
|
|
515
543
|
document: _objectSpread(_objectSpread({}, mockDocument), {}, {
|
|
516
544
|
driveId: 'federated-folder-id'
|
|
517
545
|
})
|
|
518
|
-
}), findByText =
|
|
519
|
-
|
|
546
|
+
}), findByText = _setup12.findByText;
|
|
547
|
+
_context14.next = 4;
|
|
520
548
|
return findByText('Copy link');
|
|
521
549
|
|
|
522
550
|
case 4:
|
|
@@ -524,9 +552,9 @@ describe('FederatedFolderModal', function () {
|
|
|
524
552
|
|
|
525
553
|
case 5:
|
|
526
554
|
case "end":
|
|
527
|
-
return
|
|
555
|
+
return _context14.stop();
|
|
528
556
|
}
|
|
529
|
-
},
|
|
557
|
+
}, _callee14);
|
|
530
558
|
})));
|
|
531
559
|
});
|
|
532
560
|
describe('onSend callback', function () {
|
|
@@ -534,21 +562,21 @@ describe('FederatedFolderModal', function () {
|
|
|
534
562
|
name: 'Alice',
|
|
535
563
|
email: 'alice@example.com'
|
|
536
564
|
};
|
|
537
|
-
it('should call onClose and skip share when there are no pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
538
|
-
var
|
|
565
|
+
it('should call onClose and skip share when there are no pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee15() {
|
|
566
|
+
var _setup13, findByText, sendButton;
|
|
539
567
|
|
|
540
|
-
return _regeneratorRuntime.wrap(function
|
|
541
|
-
while (1) switch (
|
|
568
|
+
return _regeneratorRuntime.wrap(function _callee15$(_context15) {
|
|
569
|
+
while (1) switch (_context15.prev = _context15.next) {
|
|
542
570
|
case 0:
|
|
543
571
|
// pendingRecipients defaults to [] via beforeEach
|
|
544
|
-
|
|
545
|
-
|
|
572
|
+
_setup13 = setup(), findByText = _setup13.findByText;
|
|
573
|
+
_context15.next = 3;
|
|
546
574
|
return findByText('Done');
|
|
547
575
|
|
|
548
576
|
case 3:
|
|
549
|
-
sendButton =
|
|
577
|
+
sendButton = _context15.sent;
|
|
550
578
|
fireEvent.click(sendButton);
|
|
551
|
-
|
|
579
|
+
_context15.next = 7;
|
|
552
580
|
return waitFor(function () {
|
|
553
581
|
expect(mockOnClose).toHaveBeenCalled();
|
|
554
582
|
expect(mockShare).not.toHaveBeenCalled();
|
|
@@ -556,15 +584,15 @@ describe('FederatedFolderModal', function () {
|
|
|
556
584
|
|
|
557
585
|
case 7:
|
|
558
586
|
case "end":
|
|
559
|
-
return
|
|
587
|
+
return _context15.stop();
|
|
560
588
|
}
|
|
561
|
-
},
|
|
589
|
+
}, _callee15);
|
|
562
590
|
})));
|
|
563
|
-
it('should call share with correct parameters', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
564
|
-
var
|
|
591
|
+
it('should call share with correct parameters', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee16() {
|
|
592
|
+
var _setup14, findByText, sendButton;
|
|
565
593
|
|
|
566
|
-
return _regeneratorRuntime.wrap(function
|
|
567
|
-
while (1) switch (
|
|
594
|
+
return _regeneratorRuntime.wrap(function _callee16$(_context16) {
|
|
595
|
+
while (1) switch (_context16.prev = _context16.next) {
|
|
568
596
|
case 0:
|
|
569
597
|
usePendingRecipients.mockReturnValue({
|
|
570
598
|
pendingRecipients: [pendingRecipient],
|
|
@@ -574,14 +602,14 @@ describe('FederatedFolderModal', function () {
|
|
|
574
602
|
});
|
|
575
603
|
getOrCreateFromArray.mockResolvedValue([pendingRecipient]);
|
|
576
604
|
mockShare.mockResolvedValueOnce({});
|
|
577
|
-
|
|
578
|
-
|
|
605
|
+
_setup14 = setup(), findByText = _setup14.findByText;
|
|
606
|
+
_context16.next = 6;
|
|
579
607
|
return findByText('Done');
|
|
580
608
|
|
|
581
609
|
case 6:
|
|
582
|
-
sendButton =
|
|
610
|
+
sendButton = _context16.sent;
|
|
583
611
|
fireEvent.click(sendButton);
|
|
584
|
-
|
|
612
|
+
_context16.next = 10;
|
|
585
613
|
return waitFor(function () {
|
|
586
614
|
expect(mockShare).toHaveBeenCalledWith({
|
|
587
615
|
description: 'My Test Folder',
|
|
@@ -595,15 +623,15 @@ describe('FederatedFolderModal', function () {
|
|
|
595
623
|
|
|
596
624
|
case 10:
|
|
597
625
|
case "end":
|
|
598
|
-
return
|
|
626
|
+
return _context16.stop();
|
|
599
627
|
}
|
|
600
|
-
},
|
|
628
|
+
}, _callee16);
|
|
601
629
|
})));
|
|
602
|
-
it('should show success alert and close modal on successful share', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
603
|
-
var
|
|
630
|
+
it('should show success alert and close modal on successful share', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee17() {
|
|
631
|
+
var _setup15, findByText, sendButton;
|
|
604
632
|
|
|
605
|
-
return _regeneratorRuntime.wrap(function
|
|
606
|
-
while (1) switch (
|
|
633
|
+
return _regeneratorRuntime.wrap(function _callee17$(_context17) {
|
|
634
|
+
while (1) switch (_context17.prev = _context17.next) {
|
|
607
635
|
case 0:
|
|
608
636
|
usePendingRecipients.mockReturnValue({
|
|
609
637
|
pendingRecipients: [pendingRecipient],
|
|
@@ -613,14 +641,14 @@ describe('FederatedFolderModal', function () {
|
|
|
613
641
|
});
|
|
614
642
|
getOrCreateFromArray.mockResolvedValue([pendingRecipient]);
|
|
615
643
|
mockShare.mockResolvedValueOnce({});
|
|
616
|
-
|
|
617
|
-
|
|
644
|
+
_setup15 = setup(), findByText = _setup15.findByText;
|
|
645
|
+
_context17.next = 6;
|
|
618
646
|
return findByText('Done');
|
|
619
647
|
|
|
620
648
|
case 6:
|
|
621
|
-
sendButton =
|
|
649
|
+
sendButton = _context17.sent;
|
|
622
650
|
fireEvent.click(sendButton);
|
|
623
|
-
|
|
651
|
+
_context17.next = 10;
|
|
624
652
|
return waitFor(function () {
|
|
625
653
|
expect(mockShowAlert).toHaveBeenCalledWith({
|
|
626
654
|
message: 'Folder has been shared',
|
|
@@ -632,15 +660,15 @@ describe('FederatedFolderModal', function () {
|
|
|
632
660
|
|
|
633
661
|
case 10:
|
|
634
662
|
case "end":
|
|
635
|
-
return
|
|
663
|
+
return _context17.stop();
|
|
636
664
|
}
|
|
637
|
-
},
|
|
665
|
+
}, _callee17);
|
|
638
666
|
})));
|
|
639
|
-
it('should show error alert when share fails', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
640
|
-
var
|
|
667
|
+
it('should show error alert when share fails', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee18() {
|
|
668
|
+
var _setup16, findByText, sendButton;
|
|
641
669
|
|
|
642
|
-
return _regeneratorRuntime.wrap(function
|
|
643
|
-
while (1) switch (
|
|
670
|
+
return _regeneratorRuntime.wrap(function _callee18$(_context18) {
|
|
671
|
+
while (1) switch (_context18.prev = _context18.next) {
|
|
644
672
|
case 0:
|
|
645
673
|
usePendingRecipients.mockReturnValue({
|
|
646
674
|
pendingRecipients: [pendingRecipient],
|
|
@@ -650,14 +678,14 @@ describe('FederatedFolderModal', function () {
|
|
|
650
678
|
});
|
|
651
679
|
getOrCreateFromArray.mockResolvedValue([pendingRecipient]);
|
|
652
680
|
mockShare.mockRejectedValueOnce(new Error('Share failed'));
|
|
653
|
-
|
|
654
|
-
|
|
681
|
+
_setup16 = setup(), findByText = _setup16.findByText;
|
|
682
|
+
_context18.next = 6;
|
|
655
683
|
return findByText('Done');
|
|
656
684
|
|
|
657
685
|
case 6:
|
|
658
|
-
sendButton =
|
|
686
|
+
sendButton = _context18.sent;
|
|
659
687
|
fireEvent.click(sendButton);
|
|
660
|
-
|
|
688
|
+
_context18.next = 10;
|
|
661
689
|
return waitFor(function () {
|
|
662
690
|
expect(mockShowAlert).toHaveBeenCalledWith({
|
|
663
691
|
message: 'Error while sharing folder',
|
|
@@ -669,15 +697,15 @@ describe('FederatedFolderModal', function () {
|
|
|
669
697
|
|
|
670
698
|
case 10:
|
|
671
699
|
case "end":
|
|
672
|
-
return
|
|
700
|
+
return _context18.stop();
|
|
673
701
|
}
|
|
674
|
-
},
|
|
702
|
+
}, _callee18);
|
|
675
703
|
})));
|
|
676
|
-
it('should show progress icon on Done button while share is in progress', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
677
|
-
var resolveShare,
|
|
704
|
+
it('should show progress icon on Done button while share is in progress', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee20() {
|
|
705
|
+
var resolveShare, _setup17, findByText, getByRole, queryByRole, sendButton;
|
|
678
706
|
|
|
679
|
-
return _regeneratorRuntime.wrap(function
|
|
680
|
-
while (1) switch (
|
|
707
|
+
return _regeneratorRuntime.wrap(function _callee20$(_context20) {
|
|
708
|
+
while (1) switch (_context20.prev = _context20.next) {
|
|
681
709
|
case 0:
|
|
682
710
|
usePendingRecipients.mockReturnValue({
|
|
683
711
|
pendingRecipients: [pendingRecipient],
|
|
@@ -689,14 +717,14 @@ describe('FederatedFolderModal', function () {
|
|
|
689
717
|
mockShare.mockReturnValueOnce(new Promise(function (resolve) {
|
|
690
718
|
resolveShare = resolve;
|
|
691
719
|
}));
|
|
692
|
-
|
|
693
|
-
|
|
720
|
+
_setup17 = setup(), findByText = _setup17.findByText, getByRole = _setup17.getByRole, queryByRole = _setup17.queryByRole;
|
|
721
|
+
_context20.next = 6;
|
|
694
722
|
return findByText('Done');
|
|
695
723
|
|
|
696
724
|
case 6:
|
|
697
|
-
sendButton =
|
|
725
|
+
sendButton = _context20.sent;
|
|
698
726
|
fireEvent.click(sendButton);
|
|
699
|
-
|
|
727
|
+
_context20.next = 10;
|
|
700
728
|
return waitFor(function () {
|
|
701
729
|
expect(getByRole('button', {
|
|
702
730
|
name: 'Done'
|
|
@@ -705,25 +733,25 @@ describe('FederatedFolderModal', function () {
|
|
|
705
733
|
});
|
|
706
734
|
|
|
707
735
|
case 10:
|
|
708
|
-
|
|
709
|
-
return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
710
|
-
return _regeneratorRuntime.wrap(function
|
|
711
|
-
while (1) switch (
|
|
736
|
+
_context20.next = 12;
|
|
737
|
+
return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee19() {
|
|
738
|
+
return _regeneratorRuntime.wrap(function _callee19$(_context19) {
|
|
739
|
+
while (1) switch (_context19.prev = _context19.next) {
|
|
712
740
|
case 0:
|
|
713
741
|
resolveShare({});
|
|
714
742
|
|
|
715
743
|
case 1:
|
|
716
744
|
case "end":
|
|
717
|
-
return
|
|
745
|
+
return _context19.stop();
|
|
718
746
|
}
|
|
719
|
-
},
|
|
747
|
+
}, _callee19);
|
|
720
748
|
})));
|
|
721
749
|
|
|
722
750
|
case 12:
|
|
723
751
|
case "end":
|
|
724
|
-
return
|
|
752
|
+
return _context20.stop();
|
|
725
753
|
}
|
|
726
|
-
},
|
|
754
|
+
}, _callee20);
|
|
727
755
|
})));
|
|
728
756
|
});
|
|
729
757
|
describe('onRevoke callback', function () {
|
|
@@ -736,27 +764,27 @@ describe('FederatedFolderModal', function () {
|
|
|
736
764
|
name: 'Me',
|
|
737
765
|
email: 'me@test.com'
|
|
738
766
|
};
|
|
739
|
-
it('should call onRevokeSelf and onRevokeSuccess when the current user is revoked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
740
|
-
var onRevokeSuccess,
|
|
767
|
+
it('should call onRevokeSelf and onRevokeSuccess when the current user is revoked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
|
|
768
|
+
var onRevokeSuccess, _setup18, findByLabelText;
|
|
741
769
|
|
|
742
|
-
return _regeneratorRuntime.wrap(function
|
|
743
|
-
while (1) switch (
|
|
770
|
+
return _regeneratorRuntime.wrap(function _callee21$(_context21) {
|
|
771
|
+
while (1) switch (_context21.prev = _context21.next) {
|
|
744
772
|
case 0:
|
|
745
773
|
onRevokeSuccess = jest.fn();
|
|
746
774
|
mockGetEffectiveRecipients.mockReturnValue([currentUserRecipient]);
|
|
747
|
-
|
|
775
|
+
_setup18 = setup({
|
|
748
776
|
onRevokeSuccess: onRevokeSuccess
|
|
749
|
-
}), findByLabelText =
|
|
750
|
-
|
|
751
|
-
|
|
777
|
+
}), findByLabelText = _setup18.findByLabelText;
|
|
778
|
+
_context21.t0 = fireEvent;
|
|
779
|
+
_context21.next = 6;
|
|
752
780
|
return findByLabelText('Remove from sharing');
|
|
753
781
|
|
|
754
782
|
case 6:
|
|
755
|
-
|
|
783
|
+
_context21.t1 = _context21.sent;
|
|
756
784
|
|
|
757
|
-
|
|
785
|
+
_context21.t0.click.call(_context21.t0, _context21.t1);
|
|
758
786
|
|
|
759
|
-
|
|
787
|
+
_context21.next = 10;
|
|
760
788
|
return waitFor(function () {
|
|
761
789
|
expect(mockRevokeSelf).toHaveBeenCalledWith(mockDocument);
|
|
762
790
|
expect(mockRevoke).not.toHaveBeenCalled();
|
|
@@ -765,15 +793,15 @@ describe('FederatedFolderModal', function () {
|
|
|
765
793
|
|
|
766
794
|
case 10:
|
|
767
795
|
case "end":
|
|
768
|
-
return
|
|
796
|
+
return _context21.stop();
|
|
769
797
|
}
|
|
770
|
-
},
|
|
798
|
+
}, _callee21);
|
|
771
799
|
})));
|
|
772
|
-
it('should allow a write recipient to revoke another recipient', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
773
|
-
var otherRecipient,
|
|
800
|
+
it('should allow a write recipient to revoke another recipient', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee22() {
|
|
801
|
+
var otherRecipient, _setup19, findByLabelText;
|
|
774
802
|
|
|
775
|
-
return _regeneratorRuntime.wrap(function
|
|
776
|
-
while (1) switch (
|
|
803
|
+
return _regeneratorRuntime.wrap(function _callee22$(_context22) {
|
|
804
|
+
while (1) switch (_context22.prev = _context22.next) {
|
|
777
805
|
case 0:
|
|
778
806
|
otherRecipient = {
|
|
779
807
|
instance: 'https://other.mycozy.cloud',
|
|
@@ -786,17 +814,17 @@ describe('FederatedFolderModal', function () {
|
|
|
786
814
|
};
|
|
787
815
|
mockCanReshare.mockReturnValue(true);
|
|
788
816
|
mockGetEffectiveRecipients.mockReturnValue([otherRecipient]);
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
817
|
+
_setup19 = setup(), findByLabelText = _setup19.findByLabelText;
|
|
818
|
+
_context22.t0 = fireEvent;
|
|
819
|
+
_context22.next = 7;
|
|
792
820
|
return findByLabelText('Remove from sharing');
|
|
793
821
|
|
|
794
822
|
case 7:
|
|
795
|
-
|
|
823
|
+
_context22.t1 = _context22.sent;
|
|
796
824
|
|
|
797
|
-
|
|
825
|
+
_context22.t0.click.call(_context22.t0, _context22.t1);
|
|
798
826
|
|
|
799
|
-
|
|
827
|
+
_context22.next = 11;
|
|
800
828
|
return waitFor(function () {
|
|
801
829
|
expect(mockCanReshare).toHaveBeenCalledWith(mockDocument._id);
|
|
802
830
|
expect(mockRevoke).toHaveBeenCalledWith(mockDocument, otherRecipient.sharingId, otherRecipient.memberIndex);
|
|
@@ -805,40 +833,40 @@ describe('FederatedFolderModal', function () {
|
|
|
805
833
|
|
|
806
834
|
case 11:
|
|
807
835
|
case "end":
|
|
808
|
-
return
|
|
836
|
+
return _context22.stop();
|
|
809
837
|
}
|
|
810
|
-
},
|
|
838
|
+
}, _callee22);
|
|
811
839
|
})));
|
|
812
840
|
});
|
|
813
841
|
describe('onClose callback', function () {
|
|
814
|
-
it('should call onClose when close button is clicked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
815
|
-
var
|
|
842
|
+
it('should call onClose when close button is clicked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee23() {
|
|
843
|
+
var _setup20, findByRole, closeButton;
|
|
816
844
|
|
|
817
|
-
return _regeneratorRuntime.wrap(function
|
|
818
|
-
while (1) switch (
|
|
845
|
+
return _regeneratorRuntime.wrap(function _callee23$(_context23) {
|
|
846
|
+
while (1) switch (_context23.prev = _context23.next) {
|
|
819
847
|
case 0:
|
|
820
|
-
|
|
821
|
-
|
|
848
|
+
_setup20 = setup(), findByRole = _setup20.findByRole;
|
|
849
|
+
_context23.next = 3;
|
|
822
850
|
return findByRole('button', {
|
|
823
851
|
name: /close/i
|
|
824
852
|
});
|
|
825
853
|
|
|
826
854
|
case 3:
|
|
827
|
-
closeButton =
|
|
855
|
+
closeButton = _context23.sent;
|
|
828
856
|
fireEvent.click(closeButton);
|
|
829
857
|
expect(mockOnClose).toHaveBeenCalled();
|
|
830
858
|
|
|
831
859
|
case 6:
|
|
832
860
|
case "end":
|
|
833
|
-
return
|
|
861
|
+
return _context23.stop();
|
|
834
862
|
}
|
|
835
|
-
},
|
|
863
|
+
}, _callee23);
|
|
836
864
|
})));
|
|
837
|
-
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
838
|
-
var
|
|
865
|
+
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee24() {
|
|
866
|
+
var _setup21, getByRole, findByRole, getByText, closeButton;
|
|
839
867
|
|
|
840
|
-
return _regeneratorRuntime.wrap(function
|
|
841
|
-
while (1) switch (
|
|
868
|
+
return _regeneratorRuntime.wrap(function _callee24$(_context24) {
|
|
869
|
+
while (1) switch (_context24.prev = _context24.next) {
|
|
842
870
|
case 0:
|
|
843
871
|
usePendingRecipients.mockReturnValue({
|
|
844
872
|
pendingRecipients: [{
|
|
@@ -849,14 +877,14 @@ describe('FederatedFolderModal', function () {
|
|
|
849
877
|
selectedOption: 'readWrite',
|
|
850
878
|
setSelectedOption: jest.fn()
|
|
851
879
|
});
|
|
852
|
-
|
|
853
|
-
|
|
880
|
+
_setup21 = setup(), getByRole = _setup21.getByRole, findByRole = _setup21.findByRole, getByText = _setup21.getByText;
|
|
881
|
+
_context24.next = 4;
|
|
854
882
|
return findByRole('button', {
|
|
855
883
|
name: /close/i
|
|
856
884
|
});
|
|
857
885
|
|
|
858
886
|
case 4:
|
|
859
|
-
closeButton =
|
|
887
|
+
closeButton = _context24.sent;
|
|
860
888
|
fireEvent.click(closeButton);
|
|
861
889
|
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
862
890
|
expect(mockOnClose).not.toHaveBeenCalled();
|
|
@@ -867,15 +895,15 @@ describe('FederatedFolderModal', function () {
|
|
|
867
895
|
|
|
868
896
|
case 10:
|
|
869
897
|
case "end":
|
|
870
|
-
return
|
|
898
|
+
return _context24.stop();
|
|
871
899
|
}
|
|
872
|
-
},
|
|
900
|
+
}, _callee24);
|
|
873
901
|
})));
|
|
874
|
-
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
875
|
-
var
|
|
902
|
+
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee25() {
|
|
903
|
+
var _setup22, getByRole, findByRole, getByText, closeButton;
|
|
876
904
|
|
|
877
|
-
return _regeneratorRuntime.wrap(function
|
|
878
|
-
while (1) switch (
|
|
905
|
+
return _regeneratorRuntime.wrap(function _callee25$(_context25) {
|
|
906
|
+
while (1) switch (_context25.prev = _context25.next) {
|
|
879
907
|
case 0:
|
|
880
908
|
usePendingRecipients.mockReturnValue({
|
|
881
909
|
pendingRecipients: [{
|
|
@@ -886,14 +914,14 @@ describe('FederatedFolderModal', function () {
|
|
|
886
914
|
selectedOption: 'readWrite',
|
|
887
915
|
setSelectedOption: jest.fn()
|
|
888
916
|
});
|
|
889
|
-
|
|
890
|
-
|
|
917
|
+
_setup22 = setup(), getByRole = _setup22.getByRole, findByRole = _setup22.findByRole, getByText = _setup22.getByText;
|
|
918
|
+
_context25.next = 4;
|
|
891
919
|
return findByRole('button', {
|
|
892
920
|
name: /close/i
|
|
893
921
|
});
|
|
894
922
|
|
|
895
923
|
case 4:
|
|
896
|
-
closeButton =
|
|
924
|
+
closeButton = _context25.sent;
|
|
897
925
|
fireEvent.click(closeButton);
|
|
898
926
|
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
899
927
|
fireEvent.click(getByRole('button', {
|
|
@@ -903,9 +931,9 @@ describe('FederatedFolderModal', function () {
|
|
|
903
931
|
|
|
904
932
|
case 9:
|
|
905
933
|
case "end":
|
|
906
|
-
return
|
|
934
|
+
return _context25.stop();
|
|
907
935
|
}
|
|
908
|
-
},
|
|
936
|
+
}, _callee25);
|
|
909
937
|
})));
|
|
910
938
|
});
|
|
911
939
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "38.1.
|
|
3
|
+
"version": "38.1.6",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"cozy-intent": "^2.31.1",
|
|
59
59
|
"cozy-minilog": "^3.10.1",
|
|
60
60
|
"cozy-ui": "^140.5.0",
|
|
61
|
-
"cozy-ui-plus": "^13.0.
|
|
61
|
+
"cozy-ui-plus": "^13.0.10",
|
|
62
62
|
"jest": "30.3.0",
|
|
63
63
|
"jest-environment-jsdom": "30.3.0",
|
|
64
64
|
"react": "16.12.0",
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"sideEffects": [
|
|
85
85
|
"*.css"
|
|
86
86
|
],
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "59aff51cc02c4315da7889122d476df36d4c90e2"
|
|
88
88
|
}
|
|
@@ -92,8 +92,11 @@ const FederatedFolderModalContent = ({
|
|
|
92
92
|
id => id === existingDocument?._id || id === existingDocument?.id
|
|
93
93
|
)
|
|
94
94
|
)
|
|
95
|
+
// Ignore a stale driveId left after an owner revokes the last recipient, so their own folder isn't wrongly restricted to link-only (linagora/twake-drive#4264).
|
|
95
96
|
const isInsideSharedDrive = Boolean(
|
|
96
|
-
existingDocument?.driveId &&
|
|
97
|
+
existingDocument?.driveId &&
|
|
98
|
+
!isSharedDriveRoot &&
|
|
99
|
+
(sharedDriveSharing || !isOwner(documentId))
|
|
97
100
|
)
|
|
98
101
|
const isCurrentUserOwner = existingDocument?.driveId
|
|
99
102
|
? Boolean(sharedDriveSharing?.attributes?.owner)
|
|
@@ -271,6 +271,27 @@ describe('FederatedFolderModal', () => {
|
|
|
271
271
|
).toBe(null)
|
|
272
272
|
expect(queryByText('it has a shared parent')).toBe(null)
|
|
273
273
|
})
|
|
274
|
+
|
|
275
|
+
it('should allow share by email when the owner revoked the sharing of a folder that still carries a stale driveId', async () => {
|
|
276
|
+
// Owner revoked the last recipient: stale driveId, sharing gone, but still owner → stays shareable (linagora/twake-drive#4264).
|
|
277
|
+
mockGetSharingById.mockReturnValue(null)
|
|
278
|
+
mockIsOwner.mockReturnValue(true)
|
|
279
|
+
|
|
280
|
+
const { findByText, queryByText } = setup({
|
|
281
|
+
document: {
|
|
282
|
+
...mockDocument,
|
|
283
|
+
driveId: 'federated-folder-id',
|
|
284
|
+
type: 'directory'
|
|
285
|
+
}
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
await findByText('Add users')
|
|
289
|
+
|
|
290
|
+
expect(
|
|
291
|
+
queryByText('This folder can only be shared by link, because')
|
|
292
|
+
).toBe(null)
|
|
293
|
+
expect(queryByText('it has a shared parent')).toBe(null)
|
|
294
|
+
})
|
|
274
295
|
})
|
|
275
296
|
|
|
276
297
|
describe('shared drive link fetch on mount', () => {
|