cozy-sharing 39.0.2 → 39.0.3

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 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
+ ## [39.0.3](https://github.com/cozy/cozy-libs/compare/cozy-sharing@39.0.2...cozy-sharing@39.0.3) (2026-10-08)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **cozy-sharing:** Keep drive members after a recipient changes a role ([13e609c](https://github.com/cozy/cozy-libs/commit/13e609c5edf6b051321d53956b3b5e0b390ce207))
11
+ - **cozy-sharing:** Refetch the displayed document after a role change ([5cfb13d](https://github.com/cozy/cozy-libs/commit/5cfb13dd6acf0a2c03a6d9acd2539bb06d5c04a6))
12
+
6
13
  ## [39.0.2](https://github.com/cozy/cozy-libs/compare/cozy-sharing@39.0.1...cozy-sharing@39.0.2) (2026-10-06)
7
14
 
8
15
  ### Bug Fixes
package/README.md CHANGED
@@ -198,7 +198,7 @@ Link and email sharing can coexist on the same resource. The recipient's permiss
198
198
  |-----------|------|--------|
199
199
  | Editable modal | `isEditable = !byDocId[doc] \|\| isOwner(doc) \|\| canReshare(doc)` | `ShareModal.jsx:35-36` |
200
200
  | Non-editable view | `SharingDetailsModal` — read-only members (no cross/perm menu), with link management (gear + copy link) for shared drives | `ShareModal.jsx:53-62` |
201
- | Updating member type | `updateSharingMemberType` calls `setReadOnly` / `setReadWrite` on the stack | `SharingProvider.jsx:361-420` |
201
+ | Updating member type | `updateSharingMemberType` calls `setReadOnly` / `setReadWrite` on the stack, then refetches the effective recipients of the given document (through its `driveId` on the recipient side) | `SharingProvider.jsx:361-420` |
202
202
  | Revoke self | Available to all recipients | `SharingProvider.jsx:349-353` |
203
203
  | Revoke group | Available to owner/editor; removes all group members at once | `SharingProvider.jsx:336-347` |
204
204
 
@@ -489,10 +489,11 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
489
489
  * @param {string} sharingId - The ID of the sharing
490
490
  * @param {number} memberIndex - The index of the member in the sharing members array
491
491
  * @param {string} newType - 'one-way' for read-only, 'two-way' for read-write
492
+ * @param {object} [document] - Document whose effective recipients are refetched once updated
492
493
  */
493
494
  _defineProperty(_this2, "updateSharingMemberType", /*#__PURE__*/function () {
494
- var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10(sharingId, memberIndex, newType) {
495
- var sharing, member, makeReadOnly, optimisticSharing, currentSharing, rollbackSharing, docId, driveId;
495
+ var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10(sharingId, memberIndex, newType, document) {
496
+ var sharing, member, makeReadOnly, optimisticSharing, currentSharing, rollbackSharing;
496
497
  return _regeneratorRuntime.wrap(function _callee10$(_context10) {
497
498
  while (1) switch (_context10.prev = _context10.next) {
498
499
  case 0:
@@ -584,29 +585,22 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
584
585
  throw _context10.t0;
585
586
 
586
587
  case 30:
587
- docId = Object.keys(_this2.state.byDocId).find(function (id) {
588
- var _this2$state$byDocId$;
589
-
590
- return (_this2$state$byDocId$ = _this2.state.byDocId[id].sharings) === null || _this2$state$byDocId$ === void 0 ? void 0 : _this2$state$byDocId$.includes(sharingId);
591
- });
592
-
593
- if (!docId) {
594
- _context10.next = 35;
588
+ if (!document) {
589
+ _context10.next = 33;
595
590
  break;
596
591
  }
597
592
 
598
- driveId = _this2.state.byDocId[docId].driveId;
599
- _context10.next = 35;
600
- return _this2.fetchEffectiveRecipients(docId, driveId);
593
+ _context10.next = 33;
594
+ return _this2.fetchEffectiveRecipients(getDocumentId(document), document.driveId);
601
595
 
602
- case 35:
596
+ case 33:
603
597
  case "end":
604
598
  return _context10.stop();
605
599
  }
606
600
  }, _callee10, null, [[12, 22]]);
607
601
  }));
608
602
 
609
- return function (_x16, _x17, _x18) {
603
+ return function (_x16, _x17, _x18, _x19) {
610
604
  return _ref12.apply(this, arguments);
611
605
  };
612
606
  }());
@@ -652,7 +646,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
652
646
  }, _callee11, null, [[0, 7]]);
653
647
  }));
654
648
 
655
- return function (_x19, _x20) {
649
+ return function (_x20, _x21) {
656
650
  return _ref13.apply(this, arguments);
657
651
  };
658
652
  }());
@@ -730,7 +724,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
730
724
  }, _callee12, null, [[0, 15]]);
731
725
  }));
732
726
 
733
- return function (_x21, _x22) {
727
+ return function (_x22, _x23) {
734
728
  return _ref14.apply(this, arguments);
735
729
  };
736
730
  }());
@@ -805,7 +799,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
805
799
  }, _callee13);
806
800
  }));
807
801
 
808
- return function (_x23) {
802
+ return function (_x24) {
809
803
  return _ref15.apply(this, arguments);
810
804
  };
811
805
  }());
@@ -913,7 +907,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
913
907
  }, _callee14);
914
908
  }));
915
909
 
916
- return function (_x24, _x25) {
910
+ return function (_x25, _x26) {
917
911
  return _ref16.apply(this, arguments);
918
912
  };
919
913
  }());
@@ -966,7 +960,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
966
960
  }, _callee15);
967
961
  }));
968
962
 
969
- return function (_x26, _x27) {
963
+ return function (_x27, _x28) {
970
964
  return _ref17.apply(this, arguments);
971
965
  };
972
966
  }());
@@ -998,7 +992,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
998
992
  }, _callee16);
999
993
  }));
1000
994
 
1001
- return function (_x28) {
995
+ return function (_x29) {
1002
996
  return _ref18.apply(this, arguments);
1003
997
  };
1004
998
  }());
@@ -1034,7 +1028,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
1034
1028
  }, _callee17);
1035
1029
  }));
1036
1030
 
1037
- return function (_x29, _x30, _x31, _x32) {
1031
+ return function (_x30, _x31, _x32, _x33) {
1038
1032
  return _ref19.apply(this, arguments);
1039
1033
  };
1040
1034
  }());
@@ -1132,7 +1126,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
1132
1126
  }, _callee18);
1133
1127
  }));
1134
1128
 
1135
- return function (_x35) {
1129
+ return function (_x36) {
1136
1130
  return _ref21.apply(this, arguments);
1137
1131
  };
1138
1132
  }()));
@@ -1148,7 +1142,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
1148
1142
  }, _callee19);
1149
1143
  }));
1150
1144
 
1151
- return function (_x33, _x34) {
1145
+ return function (_x34, _x35) {
1152
1146
  return _ref20.apply(this, arguments);
1153
1147
  };
1154
1148
  }());
@@ -1175,7 +1169,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
1175
1169
  }, _callee20);
1176
1170
  }));
1177
1171
 
1178
- return function (_x36, _x37) {
1172
+ return function (_x37, _x38) {
1179
1173
  return _ref24.apply(this, arguments);
1180
1174
  };
1181
1175
  }());
@@ -1218,7 +1212,7 @@ export var SharingProvider = /*#__PURE__*/function (_Component) {
1218
1212
  }, _callee21);
1219
1213
  }));
1220
1214
 
1221
- return function (_x38) {
1215
+ return function (_x39) {
1222
1216
  return _ref25.apply(this, arguments);
1223
1217
  };
1224
1218
  }());
@@ -1715,6 +1715,71 @@ describe('updateSharingMemberType', function () {
1715
1715
  }
1716
1716
  }, _callee39);
1717
1717
  })));
1718
+ it('should refetch effective recipients of the given document through its drive', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee40() {
1719
+ return _regeneratorRuntime.wrap(function _callee40$(_context40) {
1720
+ while (1) switch (_context40.prev = _context40.next) {
1721
+ case 0:
1722
+ _context40.next = 2;
1723
+ return instance.updateSharingMemberType('sharing-123', 1, 'one-way', {
1724
+ _id: 'nested-folder',
1725
+ driveId: 'drive-sharing'
1726
+ });
1727
+
1728
+ case 2:
1729
+ expect(instance.sharingCol.fetchEffectiveRecipients).toHaveBeenCalledWith('nested-folder', {
1730
+ driveId: 'drive-sharing'
1731
+ });
1732
+
1733
+ case 3:
1734
+ case "end":
1735
+ return _context40.stop();
1736
+ }
1737
+ }, _callee40);
1738
+ })));
1739
+ it('should refetch effective recipients of an owned document locally', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee41() {
1740
+ return _regeneratorRuntime.wrap(function _callee41$(_context41) {
1741
+ while (1) switch (_context41.prev = _context41.next) {
1742
+ case 0:
1743
+ _context41.next = 2;
1744
+ return instance.updateSharingMemberType('sharing-123', 1, 'one-way', {
1745
+ _id: 'owned-folder'
1746
+ });
1747
+
1748
+ case 2:
1749
+ expect(instance.sharingCol.fetchEffectiveRecipients).toHaveBeenCalledWith('owned-folder', {
1750
+ driveId: undefined
1751
+ });
1752
+
1753
+ case 3:
1754
+ case "end":
1755
+ return _context41.stop();
1756
+ }
1757
+ }, _callee41);
1758
+ })));
1759
+ it('should not refetch effective recipients without a document', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee42() {
1760
+ return _regeneratorRuntime.wrap(function _callee42$(_context42) {
1761
+ while (1) switch (_context42.prev = _context42.next) {
1762
+ case 0:
1763
+ instance.state = _objectSpread(_objectSpread({}, instance.state), {}, {
1764
+ byDocId: {
1765
+ 'drive-root': {
1766
+ sharings: ['sharing-123'],
1767
+ permissions: []
1768
+ }
1769
+ }
1770
+ });
1771
+ _context42.next = 3;
1772
+ return instance.updateSharingMemberType('sharing-123', 1, 'one-way');
1773
+
1774
+ case 3:
1775
+ expect(instance.sharingCol.fetchEffectiveRecipients).not.toHaveBeenCalled();
1776
+
1777
+ case 4:
1778
+ case "end":
1779
+ return _context42.stop();
1780
+ }
1781
+ }, _callee42);
1782
+ })));
1718
1783
  });
1719
1784
  describe('hasWriteAccess', function () {
1720
1785
  var createClient = function createClient() {
@@ -182,7 +182,7 @@ var PermissionTypeMenuComponent = function PermissionTypeMenuComponent(_ref) {
182
182
 
183
183
  case 33:
184
184
  _context.next = 35;
185
- return updateSharingMemberType(sharingId, memberIndex, newType);
185
+ return updateSharingMemberType(sharingId, memberIndex, newType, document);
186
186
 
187
187
  case 35:
188
188
  _context.next = 41;
@@ -105,7 +105,7 @@ describe('PermissionTypeMenu component', function () {
105
105
  fireEvent.click(getByRole('menuitem', {
106
106
  name: 'Viewer'
107
107
  }));
108
- expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'one-way');
108
+ expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'one-way', undefined);
109
109
 
110
110
  case 5:
111
111
  case "end":
@@ -129,7 +129,7 @@ describe('PermissionTypeMenu component', function () {
129
129
  fireEvent.click(getByRole('menuitem', {
130
130
  name: 'Editor'
131
131
  }));
132
- expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'two-way');
132
+ expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'two-way', undefined);
133
133
 
134
134
  case 5:
135
135
  case "end":
@@ -318,7 +318,7 @@ describe('PermissionTypeMenu component', function () {
318
318
  }));
319
319
  _context6.next = 7;
320
320
  return waitFor(function () {
321
- expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'one-way');
321
+ expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'one-way', folderDocument);
322
322
  });
323
323
 
324
324
  case 7:
@@ -367,7 +367,7 @@ describe('PermissionTypeMenu component', function () {
367
367
  }));
368
368
  _context7.next = 7;
369
369
  return waitFor(function () {
370
- expect(mockUpdateSharingMemberType.mock.calls).toEqual([['sharing-parent', 2, 'one-way'], ['sharing-123', 1, 'one-way']]);
370
+ expect(mockUpdateSharingMemberType.mock.calls).toEqual([['sharing-parent', 2, 'one-way'], ['sharing-123', 1, 'one-way', folderDocument]]);
371
371
  });
372
372
 
373
373
  case 7:
@@ -414,7 +414,7 @@ describe('PermissionTypeMenu component', function () {
414
414
  fireEvent.click(getByRole('menuitem', {
415
415
  name: 'Viewer'
416
416
  }));
417
- expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'one-way');
417
+ expect(mockUpdateSharingMemberType).toHaveBeenCalledWith('sharing-123', 1, 'one-way', folderDocument);
418
418
  expect(queryByRole('button', {
419
419
  name: 'Update parent'
420
420
  })).toBe(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-sharing",
3
- "version": "39.0.2",
3
+ "version": "39.0.3",
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": "^14.0.1",
61
+ "cozy-ui-plus": "^14.0.2",
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": "a9f046c1c02c5ffc85bf5c46da1acb41407dc584"
87
+ "gitHead": "1cea8c57eb694f2b8adce458b2e692566e49f27d"
88
88
  }
@@ -387,8 +387,14 @@ export class SharingProvider extends Component {
387
387
  * @param {string} sharingId - The ID of the sharing
388
388
  * @param {number} memberIndex - The index of the member in the sharing members array
389
389
  * @param {string} newType - 'one-way' for read-only, 'two-way' for read-write
390
+ * @param {object} [document] - Document whose effective recipients are refetched once updated
390
391
  */
391
- updateSharingMemberType = async (sharingId, memberIndex, newType) => {
392
+ updateSharingMemberType = async (
393
+ sharingId,
394
+ memberIndex,
395
+ newType,
396
+ document
397
+ ) => {
392
398
  const sharing = getSharingById(this.state, sharingId)
393
399
  if (!sharing) throw new Error('Sharing not found')
394
400
 
@@ -454,12 +460,11 @@ export class SharingProvider extends Component {
454
460
  throw error
455
461
  }
456
462
 
457
- const docId = Object.keys(this.state.byDocId).find(id =>
458
- this.state.byDocId[id].sharings?.includes(sharingId)
459
- )
460
- if (docId) {
461
- const driveId = this.state.byDocId[docId].driveId
462
- await this.fetchEffectiveRecipients(docId, driveId)
463
+ if (document) {
464
+ await this.fetchEffectiveRecipients(
465
+ getDocumentId(document),
466
+ document.driveId
467
+ )
463
468
  }
464
469
  }
465
470
 
@@ -1331,6 +1331,42 @@ describe('updateSharingMemberType', () => {
1331
1331
  readOnly: false
1332
1332
  })
1333
1333
  })
1334
+
1335
+ it('should refetch effective recipients of the given document through its drive', async () => {
1336
+ await instance.updateSharingMemberType('sharing-123', 1, 'one-way', {
1337
+ _id: 'nested-folder',
1338
+ driveId: 'drive-sharing'
1339
+ })
1340
+
1341
+ expect(instance.sharingCol.fetchEffectiveRecipients).toHaveBeenCalledWith(
1342
+ 'nested-folder',
1343
+ { driveId: 'drive-sharing' }
1344
+ )
1345
+ })
1346
+
1347
+ it('should refetch effective recipients of an owned document locally', async () => {
1348
+ await instance.updateSharingMemberType('sharing-123', 1, 'one-way', {
1349
+ _id: 'owned-folder'
1350
+ })
1351
+
1352
+ expect(instance.sharingCol.fetchEffectiveRecipients).toHaveBeenCalledWith(
1353
+ 'owned-folder',
1354
+ { driveId: undefined }
1355
+ )
1356
+ })
1357
+
1358
+ it('should not refetch effective recipients without a document', async () => {
1359
+ instance.state = {
1360
+ ...instance.state,
1361
+ byDocId: {
1362
+ 'drive-root': { sharings: ['sharing-123'], permissions: [] }
1363
+ }
1364
+ }
1365
+
1366
+ await instance.updateSharingMemberType('sharing-123', 1, 'one-way')
1367
+
1368
+ expect(instance.sharingCol.fetchEffectiveRecipients).not.toHaveBeenCalled()
1369
+ })
1334
1370
  })
1335
1371
 
1336
1372
  describe('hasWriteAccess', () => {
@@ -91,7 +91,7 @@ const PermissionTypeMenuComponent = ({
91
91
  }
92
92
  }
93
93
 
94
- await updateSharingMemberType(sharingId, memberIndex, newType)
94
+ await updateSharingMemberType(sharingId, memberIndex, newType, document)
95
95
  } catch (error) {
96
96
  log.error('Failed to change member permission type', error)
97
97
  showAlert({
@@ -95,7 +95,8 @@ describe('PermissionTypeMenu component', () => {
95
95
  expect(mockUpdateSharingMemberType).toHaveBeenCalledWith(
96
96
  'sharing-123',
97
97
  1,
98
- 'one-way'
98
+ 'one-way',
99
+ undefined
99
100
  )
100
101
  })
101
102
 
@@ -110,7 +111,8 @@ describe('PermissionTypeMenu component', () => {
110
111
  expect(mockUpdateSharingMemberType).toHaveBeenCalledWith(
111
112
  'sharing-123',
112
113
  1,
113
- 'two-way'
114
+ 'two-way',
115
+ undefined
114
116
  )
115
117
  })
116
118
 
@@ -238,7 +240,8 @@ describe('PermissionTypeMenu component', () => {
238
240
  expect(mockUpdateSharingMemberType).toHaveBeenCalledWith(
239
241
  'sharing-123',
240
242
  1,
241
- 'one-way'
243
+ 'one-way',
244
+ folderDocument
242
245
  )
243
246
  })
244
247
  })
@@ -276,7 +279,7 @@ describe('PermissionTypeMenu component', () => {
276
279
  await waitFor(() => {
277
280
  expect(mockUpdateSharingMemberType.mock.calls).toEqual([
278
281
  ['sharing-parent', 2, 'one-way'],
279
- ['sharing-123', 1, 'one-way']
282
+ ['sharing-123', 1, 'one-way', folderDocument]
280
283
  ])
281
284
  })
282
285
  })
@@ -309,7 +312,8 @@ describe('PermissionTypeMenu component', () => {
309
312
  expect(mockUpdateSharingMemberType).toHaveBeenCalledWith(
310
313
  'sharing-123',
311
314
  1,
312
- 'one-way'
315
+ 'one-way',
316
+ folderDocument
313
317
  )
314
318
  expect(queryByRole('button', { name: 'Update parent' })).toBe(null)
315
319
  })