cozy-sharing 33.2.1 → 33.2.2
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 +7 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +13 -1
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +120 -84
- package/package.json +2 -2
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +21 -2
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +29 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
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
|
+
## [33.2.2](https://github.com/cozy/cozy-libs/compare/cozy-sharing@33.2.1...cozy-sharing@33.2.2) (2026-06-10)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **cozy-sharing:** Allow sharing shared drive folder root by email ([5110b4f](https://github.com/cozy/cozy-libs/commit/5110b4fb306bb664f2c6b62f209ef4af1e25c293))
|
|
11
|
+
- **cozy-sharing:** Fix lint issue in master ([5acd30a](https://github.com/cozy/cozy-libs/commit/5acd30a31412552be6b6223e43df2b320ea07098))
|
|
12
|
+
|
|
6
13
|
## [33.2.1](https://github.com/cozy/cozy-libs/compare/cozy-sharing@33.2.0...cozy-sharing@33.2.1) (2026-06-09)
|
|
7
14
|
|
|
8
15
|
### Bug Fixes
|
|
@@ -38,6 +38,8 @@ import ShareByLink from '../ShareByLink';
|
|
|
38
38
|
import WhoHasAccess from '../WhoHasAccess';
|
|
39
39
|
|
|
40
40
|
var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
41
|
+
var _sharedDriveSharing$a;
|
|
42
|
+
|
|
41
43
|
var onClose = _ref.onClose,
|
|
42
44
|
existingDocument = _ref.document,
|
|
43
45
|
autoOpenShareRestriction = _ref.autoOpenShareRestriction,
|
|
@@ -49,6 +51,7 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
49
51
|
|
|
50
52
|
var _useSharingContext = useSharingContext(),
|
|
51
53
|
share = _useSharingContext.share,
|
|
54
|
+
getSharingById = _useSharingContext.getSharingById,
|
|
52
55
|
getSharingLink = _useSharingContext.getSharingLink,
|
|
53
56
|
getFederatedShareLink = _useSharingContext.getFederatedShareLink,
|
|
54
57
|
getRecipients = _useSharingContext.getRecipients,
|
|
@@ -116,7 +119,16 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
116
119
|
}, [closeConfirmDialog, onClose, pendingRecipients.length, showConfirmDialog, t]);
|
|
117
120
|
var folderName = (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.name) || '';
|
|
118
121
|
var documentPath = existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.path;
|
|
119
|
-
var
|
|
122
|
+
var sharedDriveSharing = existingDocument !== null && existingDocument !== void 0 && existingDocument.driveId ? getSharingById(existingDocument.driveId) : null;
|
|
123
|
+
var sharedDriveRootIds = (sharedDriveSharing === null || sharedDriveSharing === void 0 || (_sharedDriveSharing$a = sharedDriveSharing.attributes) === null || _sharedDriveSharing$a === void 0 || (_sharedDriveSharing$a = _sharedDriveSharing$a.rules) === null || _sharedDriveSharing$a === void 0 ? void 0 : _sharedDriveSharing$a.reduce(function (ids, rule) {
|
|
124
|
+
return ids.concat(rule.values || []);
|
|
125
|
+
}, [])) || [];
|
|
126
|
+
var isSharedDriveRoot = Boolean((existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.driveId) && sharedDriveRootIds.some(function (id) {
|
|
127
|
+
return id === (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id) || id === (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.id);
|
|
128
|
+
}));
|
|
129
|
+
var isInsideSharedDrive = Boolean((existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.driveId) && !isSharedDriveRoot);
|
|
130
|
+
var hasSharedParentByPath = Boolean(documentPath && hasSharedParent(documentPath));
|
|
131
|
+
var hasParentRestriction = isInsideSharedDrive || hasSharedParentByPath;
|
|
120
132
|
var hasChildRestriction = Boolean(documentPath && hasSharedChild(documentPath));
|
|
121
133
|
var canShareByEmail = !hasParentRestriction && !hasChildRestriction;
|
|
122
134
|
|
|
@@ -20,6 +20,7 @@ var mockRevoke = jest.fn();
|
|
|
20
20
|
var mockGetSharingLink = jest.fn();
|
|
21
21
|
var mockGetFederatedShareLink = jest.fn();
|
|
22
22
|
var mockGetRecipients = jest.fn().mockReturnValue([]);
|
|
23
|
+
var mockGetSharingById = jest.fn();
|
|
23
24
|
var mockHasSharedChild = jest.fn();
|
|
24
25
|
var mockHasSharedParent = jest.fn();
|
|
25
26
|
var mockShowAlert = jest.fn();
|
|
@@ -35,8 +36,8 @@ jest.mock('../../hooks/useSharingContext', function () {
|
|
|
35
36
|
getFederatedShareLink: mockGetFederatedShareLink,
|
|
36
37
|
getDocumentPermissions: jest.fn().mockReturnValue([]),
|
|
37
38
|
getOwner: jest.fn(),
|
|
38
|
-
getSharingById: jest.fn(),
|
|
39
39
|
getRecipients: mockGetRecipients,
|
|
40
|
+
getSharingById: mockGetSharingById,
|
|
40
41
|
hasSharedChild: mockHasSharedChild,
|
|
41
42
|
hasSharedParent: mockHasSharedParent
|
|
42
43
|
};
|
|
@@ -120,6 +121,7 @@ describe('FederatedFolderModal', function () {
|
|
|
120
121
|
mockGetSharingLink.mockReturnValue('https://example.com/share/abc123');
|
|
121
122
|
mockGetFederatedShareLink.mockReturnValue('https://example.com/share/federated-abc123');
|
|
122
123
|
mockGetRecipients.mockReturnValue([]);
|
|
124
|
+
mockGetSharingById.mockReturnValue(null);
|
|
123
125
|
mockHasSharedChild.mockReturnValue(false);
|
|
124
126
|
mockHasSharedParent.mockReturnValue(false);
|
|
125
127
|
mockShareByLink.mockResolvedValue({
|
|
@@ -289,27 +291,61 @@ describe('FederatedFolderModal', function () {
|
|
|
289
291
|
}
|
|
290
292
|
}, _callee6);
|
|
291
293
|
})));
|
|
294
|
+
it('should allow share by email when document is the federated shared folder root', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
|
|
295
|
+
var _setup7, findByText, queryByText;
|
|
296
|
+
|
|
297
|
+
return _regeneratorRuntime.wrap(function _callee7$(_context7) {
|
|
298
|
+
while (1) switch (_context7.prev = _context7.next) {
|
|
299
|
+
case 0:
|
|
300
|
+
mockGetSharingById.mockReturnValue({
|
|
301
|
+
attributes: {
|
|
302
|
+
rules: [{
|
|
303
|
+
values: ['another-folder-id']
|
|
304
|
+
}, {
|
|
305
|
+
values: ['yet-another-folder-id', mockDocument._id]
|
|
306
|
+
}]
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
_setup7 = setup({
|
|
310
|
+
document: _objectSpread(_objectSpread({}, mockDocument), {}, {
|
|
311
|
+
driveId: 'federated-folder-id',
|
|
312
|
+
type: 'directory'
|
|
313
|
+
})
|
|
314
|
+
}), findByText = _setup7.findByText, queryByText = _setup7.queryByText;
|
|
315
|
+
_context7.next = 4;
|
|
316
|
+
return findByText('Add users');
|
|
317
|
+
|
|
318
|
+
case 4:
|
|
319
|
+
expect(queryByText('This folder can only be shared by link, because')).toBe(null);
|
|
320
|
+
expect(queryByText('it has a shared parent')).toBe(null);
|
|
321
|
+
|
|
322
|
+
case 6:
|
|
323
|
+
case "end":
|
|
324
|
+
return _context7.stop();
|
|
325
|
+
}
|
|
326
|
+
}, _callee7);
|
|
327
|
+
})));
|
|
292
328
|
});
|
|
293
329
|
describe('onSend callback', function () {
|
|
294
330
|
var pendingRecipient = {
|
|
295
331
|
name: 'Alice',
|
|
296
332
|
email: 'alice@example.com'
|
|
297
333
|
};
|
|
298
|
-
it('should call onClose and skip share when there are no pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
299
|
-
var
|
|
334
|
+
it('should call onClose and skip share when there are no pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
|
|
335
|
+
var _setup8, findByText, sendButton;
|
|
300
336
|
|
|
301
|
-
return _regeneratorRuntime.wrap(function
|
|
302
|
-
while (1) switch (
|
|
337
|
+
return _regeneratorRuntime.wrap(function _callee8$(_context8) {
|
|
338
|
+
while (1) switch (_context8.prev = _context8.next) {
|
|
303
339
|
case 0:
|
|
304
340
|
// pendingRecipients defaults to [] via beforeEach
|
|
305
|
-
|
|
306
|
-
|
|
341
|
+
_setup8 = setup(), findByText = _setup8.findByText;
|
|
342
|
+
_context8.next = 3;
|
|
307
343
|
return findByText('Done');
|
|
308
344
|
|
|
309
345
|
case 3:
|
|
310
|
-
sendButton =
|
|
346
|
+
sendButton = _context8.sent;
|
|
311
347
|
fireEvent.click(sendButton);
|
|
312
|
-
|
|
348
|
+
_context8.next = 7;
|
|
313
349
|
return waitFor(function () {
|
|
314
350
|
expect(mockOnClose).toHaveBeenCalled();
|
|
315
351
|
expect(mockShare).not.toHaveBeenCalled();
|
|
@@ -317,15 +353,15 @@ describe('FederatedFolderModal', function () {
|
|
|
317
353
|
|
|
318
354
|
case 7:
|
|
319
355
|
case "end":
|
|
320
|
-
return
|
|
356
|
+
return _context8.stop();
|
|
321
357
|
}
|
|
322
|
-
},
|
|
358
|
+
}, _callee8);
|
|
323
359
|
})));
|
|
324
|
-
it('should call share with correct parameters', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
325
|
-
var
|
|
360
|
+
it('should call share with correct parameters', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
|
|
361
|
+
var _setup9, findByText, sendButton;
|
|
326
362
|
|
|
327
|
-
return _regeneratorRuntime.wrap(function
|
|
328
|
-
while (1) switch (
|
|
363
|
+
return _regeneratorRuntime.wrap(function _callee9$(_context9) {
|
|
364
|
+
while (1) switch (_context9.prev = _context9.next) {
|
|
329
365
|
case 0:
|
|
330
366
|
usePendingRecipients.mockReturnValue({
|
|
331
367
|
pendingRecipients: [pendingRecipient],
|
|
@@ -335,14 +371,14 @@ describe('FederatedFolderModal', function () {
|
|
|
335
371
|
});
|
|
336
372
|
getOrCreateFromArray.mockResolvedValue([pendingRecipient]);
|
|
337
373
|
mockShare.mockResolvedValueOnce({});
|
|
338
|
-
|
|
339
|
-
|
|
374
|
+
_setup9 = setup(), findByText = _setup9.findByText;
|
|
375
|
+
_context9.next = 6;
|
|
340
376
|
return findByText('Done');
|
|
341
377
|
|
|
342
378
|
case 6:
|
|
343
|
-
sendButton =
|
|
379
|
+
sendButton = _context9.sent;
|
|
344
380
|
fireEvent.click(sendButton);
|
|
345
|
-
|
|
381
|
+
_context9.next = 10;
|
|
346
382
|
return waitFor(function () {
|
|
347
383
|
expect(mockShare).toHaveBeenCalledWith({
|
|
348
384
|
description: 'My Test Folder',
|
|
@@ -356,15 +392,15 @@ describe('FederatedFolderModal', function () {
|
|
|
356
392
|
|
|
357
393
|
case 10:
|
|
358
394
|
case "end":
|
|
359
|
-
return
|
|
395
|
+
return _context9.stop();
|
|
360
396
|
}
|
|
361
|
-
},
|
|
397
|
+
}, _callee9);
|
|
362
398
|
})));
|
|
363
|
-
it('should show success alert and close modal on successful share', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
364
|
-
var
|
|
399
|
+
it('should show success alert and close modal on successful share', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
|
|
400
|
+
var _setup10, findByText, sendButton;
|
|
365
401
|
|
|
366
|
-
return _regeneratorRuntime.wrap(function
|
|
367
|
-
while (1) switch (
|
|
402
|
+
return _regeneratorRuntime.wrap(function _callee10$(_context10) {
|
|
403
|
+
while (1) switch (_context10.prev = _context10.next) {
|
|
368
404
|
case 0:
|
|
369
405
|
usePendingRecipients.mockReturnValue({
|
|
370
406
|
pendingRecipients: [pendingRecipient],
|
|
@@ -374,14 +410,14 @@ describe('FederatedFolderModal', function () {
|
|
|
374
410
|
});
|
|
375
411
|
getOrCreateFromArray.mockResolvedValue([pendingRecipient]);
|
|
376
412
|
mockShare.mockResolvedValueOnce({});
|
|
377
|
-
|
|
378
|
-
|
|
413
|
+
_setup10 = setup(), findByText = _setup10.findByText;
|
|
414
|
+
_context10.next = 6;
|
|
379
415
|
return findByText('Done');
|
|
380
416
|
|
|
381
417
|
case 6:
|
|
382
|
-
sendButton =
|
|
418
|
+
sendButton = _context10.sent;
|
|
383
419
|
fireEvent.click(sendButton);
|
|
384
|
-
|
|
420
|
+
_context10.next = 10;
|
|
385
421
|
return waitFor(function () {
|
|
386
422
|
expect(mockShowAlert).toHaveBeenCalledWith({
|
|
387
423
|
message: 'Folder has been shared',
|
|
@@ -393,15 +429,15 @@ describe('FederatedFolderModal', function () {
|
|
|
393
429
|
|
|
394
430
|
case 10:
|
|
395
431
|
case "end":
|
|
396
|
-
return
|
|
432
|
+
return _context10.stop();
|
|
397
433
|
}
|
|
398
|
-
},
|
|
434
|
+
}, _callee10);
|
|
399
435
|
})));
|
|
400
|
-
it('should show error alert when share fails', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
401
|
-
var
|
|
436
|
+
it('should show error alert when share fails', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
|
|
437
|
+
var _setup11, findByText, sendButton;
|
|
402
438
|
|
|
403
|
-
return _regeneratorRuntime.wrap(function
|
|
404
|
-
while (1) switch (
|
|
439
|
+
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
|
|
440
|
+
while (1) switch (_context11.prev = _context11.next) {
|
|
405
441
|
case 0:
|
|
406
442
|
usePendingRecipients.mockReturnValue({
|
|
407
443
|
pendingRecipients: [pendingRecipient],
|
|
@@ -411,14 +447,14 @@ describe('FederatedFolderModal', function () {
|
|
|
411
447
|
});
|
|
412
448
|
getOrCreateFromArray.mockResolvedValue([pendingRecipient]);
|
|
413
449
|
mockShare.mockRejectedValueOnce(new Error('Share failed'));
|
|
414
|
-
|
|
415
|
-
|
|
450
|
+
_setup11 = setup(), findByText = _setup11.findByText;
|
|
451
|
+
_context11.next = 6;
|
|
416
452
|
return findByText('Done');
|
|
417
453
|
|
|
418
454
|
case 6:
|
|
419
|
-
sendButton =
|
|
455
|
+
sendButton = _context11.sent;
|
|
420
456
|
fireEvent.click(sendButton);
|
|
421
|
-
|
|
457
|
+
_context11.next = 10;
|
|
422
458
|
return waitFor(function () {
|
|
423
459
|
expect(mockShowAlert).toHaveBeenCalledWith({
|
|
424
460
|
message: 'Error while sharing folder',
|
|
@@ -430,15 +466,15 @@ describe('FederatedFolderModal', function () {
|
|
|
430
466
|
|
|
431
467
|
case 10:
|
|
432
468
|
case "end":
|
|
433
|
-
return
|
|
469
|
+
return _context11.stop();
|
|
434
470
|
}
|
|
435
|
-
},
|
|
471
|
+
}, _callee11);
|
|
436
472
|
})));
|
|
437
|
-
it('should show progress icon on Done button while share is in progress', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
438
|
-
var resolveShare,
|
|
473
|
+
it('should show progress icon on Done button while share is in progress', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee13() {
|
|
474
|
+
var resolveShare, _setup12, findByText, getByRole, queryByRole, sendButton;
|
|
439
475
|
|
|
440
|
-
return _regeneratorRuntime.wrap(function
|
|
441
|
-
while (1) switch (
|
|
476
|
+
return _regeneratorRuntime.wrap(function _callee13$(_context13) {
|
|
477
|
+
while (1) switch (_context13.prev = _context13.next) {
|
|
442
478
|
case 0:
|
|
443
479
|
usePendingRecipients.mockReturnValue({
|
|
444
480
|
pendingRecipients: [pendingRecipient],
|
|
@@ -450,14 +486,14 @@ describe('FederatedFolderModal', function () {
|
|
|
450
486
|
mockShare.mockReturnValueOnce(new Promise(function (resolve) {
|
|
451
487
|
resolveShare = resolve;
|
|
452
488
|
}));
|
|
453
|
-
|
|
454
|
-
|
|
489
|
+
_setup12 = setup(), findByText = _setup12.findByText, getByRole = _setup12.getByRole, queryByRole = _setup12.queryByRole;
|
|
490
|
+
_context13.next = 6;
|
|
455
491
|
return findByText('Done');
|
|
456
492
|
|
|
457
493
|
case 6:
|
|
458
|
-
sendButton =
|
|
494
|
+
sendButton = _context13.sent;
|
|
459
495
|
fireEvent.click(sendButton);
|
|
460
|
-
|
|
496
|
+
_context13.next = 10;
|
|
461
497
|
return waitFor(function () {
|
|
462
498
|
expect(getByRole('button', {
|
|
463
499
|
name: 'Done'
|
|
@@ -466,56 +502,56 @@ describe('FederatedFolderModal', function () {
|
|
|
466
502
|
});
|
|
467
503
|
|
|
468
504
|
case 10:
|
|
469
|
-
|
|
470
|
-
return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
471
|
-
return _regeneratorRuntime.wrap(function
|
|
472
|
-
while (1) switch (
|
|
505
|
+
_context13.next = 12;
|
|
506
|
+
return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12() {
|
|
507
|
+
return _regeneratorRuntime.wrap(function _callee12$(_context12) {
|
|
508
|
+
while (1) switch (_context12.prev = _context12.next) {
|
|
473
509
|
case 0:
|
|
474
510
|
resolveShare({});
|
|
475
511
|
|
|
476
512
|
case 1:
|
|
477
513
|
case "end":
|
|
478
|
-
return
|
|
514
|
+
return _context12.stop();
|
|
479
515
|
}
|
|
480
|
-
},
|
|
516
|
+
}, _callee12);
|
|
481
517
|
})));
|
|
482
518
|
|
|
483
519
|
case 12:
|
|
484
520
|
case "end":
|
|
485
|
-
return
|
|
521
|
+
return _context13.stop();
|
|
486
522
|
}
|
|
487
|
-
},
|
|
523
|
+
}, _callee13);
|
|
488
524
|
})));
|
|
489
525
|
});
|
|
490
526
|
describe('onClose callback', function () {
|
|
491
|
-
it('should call onClose when close button is clicked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
492
|
-
var
|
|
527
|
+
it('should call onClose when close button is clicked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
|
|
528
|
+
var _setup13, findByRole, closeButton;
|
|
493
529
|
|
|
494
|
-
return _regeneratorRuntime.wrap(function
|
|
495
|
-
while (1) switch (
|
|
530
|
+
return _regeneratorRuntime.wrap(function _callee14$(_context14) {
|
|
531
|
+
while (1) switch (_context14.prev = _context14.next) {
|
|
496
532
|
case 0:
|
|
497
|
-
|
|
498
|
-
|
|
533
|
+
_setup13 = setup(), findByRole = _setup13.findByRole;
|
|
534
|
+
_context14.next = 3;
|
|
499
535
|
return findByRole('button', {
|
|
500
536
|
name: /close/i
|
|
501
537
|
});
|
|
502
538
|
|
|
503
539
|
case 3:
|
|
504
|
-
closeButton =
|
|
540
|
+
closeButton = _context14.sent;
|
|
505
541
|
fireEvent.click(closeButton);
|
|
506
542
|
expect(mockOnClose).toHaveBeenCalled();
|
|
507
543
|
|
|
508
544
|
case 6:
|
|
509
545
|
case "end":
|
|
510
|
-
return
|
|
546
|
+
return _context14.stop();
|
|
511
547
|
}
|
|
512
|
-
},
|
|
548
|
+
}, _callee14);
|
|
513
549
|
})));
|
|
514
|
-
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
515
|
-
var
|
|
550
|
+
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee15() {
|
|
551
|
+
var _setup14, getByRole, findByRole, getByText, closeButton;
|
|
516
552
|
|
|
517
|
-
return _regeneratorRuntime.wrap(function
|
|
518
|
-
while (1) switch (
|
|
553
|
+
return _regeneratorRuntime.wrap(function _callee15$(_context15) {
|
|
554
|
+
while (1) switch (_context15.prev = _context15.next) {
|
|
519
555
|
case 0:
|
|
520
556
|
usePendingRecipients.mockReturnValue({
|
|
521
557
|
pendingRecipients: [{
|
|
@@ -526,14 +562,14 @@ describe('FederatedFolderModal', function () {
|
|
|
526
562
|
selectedOption: 'readWrite',
|
|
527
563
|
setSelectedOption: jest.fn()
|
|
528
564
|
});
|
|
529
|
-
|
|
530
|
-
|
|
565
|
+
_setup14 = setup(), getByRole = _setup14.getByRole, findByRole = _setup14.findByRole, getByText = _setup14.getByText;
|
|
566
|
+
_context15.next = 4;
|
|
531
567
|
return findByRole('button', {
|
|
532
568
|
name: /close/i
|
|
533
569
|
});
|
|
534
570
|
|
|
535
571
|
case 4:
|
|
536
|
-
closeButton =
|
|
572
|
+
closeButton = _context15.sent;
|
|
537
573
|
fireEvent.click(closeButton);
|
|
538
574
|
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
539
575
|
expect(mockOnClose).not.toHaveBeenCalled();
|
|
@@ -544,15 +580,15 @@ describe('FederatedFolderModal', function () {
|
|
|
544
580
|
|
|
545
581
|
case 10:
|
|
546
582
|
case "end":
|
|
547
|
-
return
|
|
583
|
+
return _context15.stop();
|
|
548
584
|
}
|
|
549
|
-
},
|
|
585
|
+
}, _callee15);
|
|
550
586
|
})));
|
|
551
|
-
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
552
|
-
var
|
|
587
|
+
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee16() {
|
|
588
|
+
var _setup15, getByRole, findByRole, getByText, closeButton;
|
|
553
589
|
|
|
554
|
-
return _regeneratorRuntime.wrap(function
|
|
555
|
-
while (1) switch (
|
|
590
|
+
return _regeneratorRuntime.wrap(function _callee16$(_context16) {
|
|
591
|
+
while (1) switch (_context16.prev = _context16.next) {
|
|
556
592
|
case 0:
|
|
557
593
|
usePendingRecipients.mockReturnValue({
|
|
558
594
|
pendingRecipients: [{
|
|
@@ -563,14 +599,14 @@ describe('FederatedFolderModal', function () {
|
|
|
563
599
|
selectedOption: 'readWrite',
|
|
564
600
|
setSelectedOption: jest.fn()
|
|
565
601
|
});
|
|
566
|
-
|
|
567
|
-
|
|
602
|
+
_setup15 = setup(), getByRole = _setup15.getByRole, findByRole = _setup15.findByRole, getByText = _setup15.getByText;
|
|
603
|
+
_context16.next = 4;
|
|
568
604
|
return findByRole('button', {
|
|
569
605
|
name: /close/i
|
|
570
606
|
});
|
|
571
607
|
|
|
572
608
|
case 4:
|
|
573
|
-
closeButton =
|
|
609
|
+
closeButton = _context16.sent;
|
|
574
610
|
fireEvent.click(closeButton);
|
|
575
611
|
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
576
612
|
fireEvent.click(getByRole('button', {
|
|
@@ -580,9 +616,9 @@ describe('FederatedFolderModal', function () {
|
|
|
580
616
|
|
|
581
617
|
case 9:
|
|
582
618
|
case "end":
|
|
583
|
-
return
|
|
619
|
+
return _context16.stop();
|
|
584
620
|
}
|
|
585
|
-
},
|
|
621
|
+
}, _callee16);
|
|
586
622
|
})));
|
|
587
623
|
});
|
|
588
624
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "33.2.
|
|
3
|
+
"version": "33.2.2",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"sideEffects": [
|
|
84
84
|
"*.css"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "d4513639ed420da6b9edfef7cb3230d90d0cf537"
|
|
87
87
|
}
|
|
@@ -31,6 +31,7 @@ const FederatedFolderModalContent = ({
|
|
|
31
31
|
const { t } = useI18n()
|
|
32
32
|
const {
|
|
33
33
|
share,
|
|
34
|
+
getSharingById,
|
|
34
35
|
getSharingLink,
|
|
35
36
|
getFederatedShareLink,
|
|
36
37
|
getRecipients,
|
|
@@ -96,9 +97,27 @@ const FederatedFolderModalContent = ({
|
|
|
96
97
|
|
|
97
98
|
const folderName = existingDocument?.name || ''
|
|
98
99
|
const documentPath = existingDocument?.path
|
|
99
|
-
const
|
|
100
|
-
existingDocument
|
|
100
|
+
const sharedDriveSharing = existingDocument?.driveId
|
|
101
|
+
? getSharingById(existingDocument.driveId)
|
|
102
|
+
: null
|
|
103
|
+
const sharedDriveRootIds =
|
|
104
|
+
sharedDriveSharing?.attributes?.rules?.reduce(
|
|
105
|
+
(ids, rule) => ids.concat(rule.values || []),
|
|
106
|
+
[]
|
|
107
|
+
) || []
|
|
108
|
+
const isSharedDriveRoot = Boolean(
|
|
109
|
+
existingDocument?.driveId &&
|
|
110
|
+
sharedDriveRootIds.some(
|
|
111
|
+
id => id === existingDocument?._id || id === existingDocument?.id
|
|
112
|
+
)
|
|
101
113
|
)
|
|
114
|
+
const isInsideSharedDrive = Boolean(
|
|
115
|
+
existingDocument?.driveId && !isSharedDriveRoot
|
|
116
|
+
)
|
|
117
|
+
const hasSharedParentByPath = Boolean(
|
|
118
|
+
documentPath && hasSharedParent(documentPath)
|
|
119
|
+
)
|
|
120
|
+
const hasParentRestriction = isInsideSharedDrive || hasSharedParentByPath
|
|
102
121
|
const hasChildRestriction = Boolean(
|
|
103
122
|
documentPath && hasSharedChild(documentPath)
|
|
104
123
|
)
|
|
@@ -14,6 +14,7 @@ const mockRevoke = jest.fn()
|
|
|
14
14
|
const mockGetSharingLink = jest.fn()
|
|
15
15
|
const mockGetFederatedShareLink = jest.fn()
|
|
16
16
|
const mockGetRecipients = jest.fn().mockReturnValue([])
|
|
17
|
+
const mockGetSharingById = jest.fn()
|
|
17
18
|
const mockHasSharedChild = jest.fn()
|
|
18
19
|
const mockHasSharedParent = jest.fn()
|
|
19
20
|
const mockShowAlert = jest.fn()
|
|
@@ -28,8 +29,8 @@ jest.mock('../../hooks/useSharingContext', () => ({
|
|
|
28
29
|
getFederatedShareLink: mockGetFederatedShareLink,
|
|
29
30
|
getDocumentPermissions: jest.fn().mockReturnValue([]),
|
|
30
31
|
getOwner: jest.fn(),
|
|
31
|
-
getSharingById: jest.fn(),
|
|
32
32
|
getRecipients: mockGetRecipients,
|
|
33
|
+
getSharingById: mockGetSharingById,
|
|
33
34
|
hasSharedChild: mockHasSharedChild,
|
|
34
35
|
hasSharedParent: mockHasSharedParent
|
|
35
36
|
})
|
|
@@ -100,6 +101,7 @@ describe('FederatedFolderModal', () => {
|
|
|
100
101
|
'https://example.com/share/federated-abc123'
|
|
101
102
|
)
|
|
102
103
|
mockGetRecipients.mockReturnValue([])
|
|
104
|
+
mockGetSharingById.mockReturnValue(null)
|
|
103
105
|
mockHasSharedChild.mockReturnValue(false)
|
|
104
106
|
mockHasSharedParent.mockReturnValue(false)
|
|
105
107
|
mockShareByLink.mockResolvedValue({
|
|
@@ -197,6 +199,32 @@ describe('FederatedFolderModal', () => {
|
|
|
197
199
|
await findByText('This folder can only be shared by link, because')
|
|
198
200
|
await findByText('it has a shared parent')
|
|
199
201
|
})
|
|
202
|
+
|
|
203
|
+
it('should allow share by email when document is the federated shared folder root', async () => {
|
|
204
|
+
mockGetSharingById.mockReturnValue({
|
|
205
|
+
attributes: {
|
|
206
|
+
rules: [
|
|
207
|
+
{ values: ['another-folder-id'] },
|
|
208
|
+
{ values: ['yet-another-folder-id', mockDocument._id] }
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
const { findByText, queryByText } = setup({
|
|
214
|
+
document: {
|
|
215
|
+
...mockDocument,
|
|
216
|
+
driveId: 'federated-folder-id',
|
|
217
|
+
type: 'directory'
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
await findByText('Add users')
|
|
222
|
+
|
|
223
|
+
expect(
|
|
224
|
+
queryByText('This folder can only be shared by link, because')
|
|
225
|
+
).toBe(null)
|
|
226
|
+
expect(queryByText('it has a shared parent')).toBe(null)
|
|
227
|
+
})
|
|
200
228
|
})
|
|
201
229
|
|
|
202
230
|
describe('onSend callback', () => {
|