cozy-sharing 34.1.0 → 34.1.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 +12 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +99 -19
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +80 -28
- package/dist/components/Recipient/MemberRecipientPermissions.js +7 -5
- package/dist/components/Recipient/RecipientList.js +2 -0
- package/dist/components/ShareModal/ShareModal.js +2 -1
- package/dist/components/WhoHasAccess.js +4 -0
- package/package.json +2 -2
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +49 -3
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +36 -0
- package/src/components/Recipient/MemberRecipientPermissions.jsx +14 -5
- package/src/components/Recipient/RecipientList.jsx +2 -0
- package/src/components/ShareModal/ShareModal.jsx +7 -1
- package/src/components/WhoHasAccess.jsx +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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
|
+
## [34.1.2](https://github.com/cozy/cozy-libs/compare/cozy-sharing@34.1.1...cozy-sharing@34.1.2) (2026-06-25)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **sharing:** Call self revoke for federated recipients ([25e62c2](https://github.com/cozy/cozy-libs/commit/25e62c2416e4b91bdab1e06fbbd77b00574a0b11))
|
|
11
|
+
|
|
12
|
+
## [34.1.1](https://github.com/cozy/cozy-libs/compare/cozy-sharing@34.1.0...cozy-sharing@34.1.1) (2026-06-25)
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- **federated:** Show correct recipients for files inside shared folder ([b656e73](https://github.com/cozy/cozy-libs/commit/b656e73240a30303c8063494ee052a197736d07c))
|
|
17
|
+
|
|
6
18
|
# [34.1.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@34.0.2...cozy-sharing@34.1.0) (2026-06-25)
|
|
7
19
|
|
|
8
20
|
### Features
|
|
@@ -15,6 +15,7 @@ import { getOrCreateFromArray } from '../../helpers/contacts';
|
|
|
15
15
|
import withLocales from '../../hoc/withLocales';
|
|
16
16
|
import { usePendingRecipients } from '../../hooks/usePendingRecipients';
|
|
17
17
|
import { useSharingContext } from '../../hooks/useSharingContext';
|
|
18
|
+
import { getRecipientsFromSharing } from '../../state';
|
|
18
19
|
var styles = {
|
|
19
20
|
"share-modal-content": "share__share-modal-content___1iqEq",
|
|
20
21
|
"coz-form": "share__coz-form___1ICST",
|
|
@@ -40,9 +41,10 @@ import WhoHasAccess from '../WhoHasAccess';
|
|
|
40
41
|
var log = minilog('FederatedFolderModal');
|
|
41
42
|
|
|
42
43
|
var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
43
|
-
var _sharedDriveSharing$a;
|
|
44
|
+
var _sharedDriveSharing$a, _sharedDriveSharing$a2;
|
|
44
45
|
|
|
45
46
|
var onClose = _ref.onClose,
|
|
47
|
+
onRevokeSuccess = _ref.onRevokeSuccess,
|
|
46
48
|
existingDocument = _ref.document,
|
|
47
49
|
autoOpenShareRestriction = _ref.autoOpenShareRestriction,
|
|
48
50
|
showGenerateLinkButton = _ref.showGenerateLinkButton;
|
|
@@ -59,9 +61,12 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
59
61
|
getDocumentPermissions = _useSharingContext.getDocumentPermissions,
|
|
60
62
|
fetchSharedDriveSharingLinks = _useSharingContext.fetchSharedDriveSharingLinks,
|
|
61
63
|
getRecipients = _useSharingContext.getRecipients,
|
|
64
|
+
getSharedParentPath = _useSharingContext.getSharedParentPath,
|
|
62
65
|
hasSharedChild = _useSharingContext.hasSharedChild,
|
|
63
66
|
hasSharedParent = _useSharingContext.hasSharedParent,
|
|
64
|
-
|
|
67
|
+
isOwner = _useSharingContext.isOwner,
|
|
68
|
+
revoke = _useSharingContext.revoke,
|
|
69
|
+
revokeSelf = _useSharingContext.revokeSelf;
|
|
65
70
|
|
|
66
71
|
var _useAlert = useAlert(),
|
|
67
72
|
showAlert = _useAlert.showAlert;
|
|
@@ -220,10 +225,83 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
220
225
|
};
|
|
221
226
|
}();
|
|
222
227
|
|
|
223
|
-
var documentId = (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id) || (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.id);
|
|
224
|
-
|
|
228
|
+
var documentId = (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id) || (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.id); // Owner case: when document is inside a shared folder (via path) but has no driveId,
|
|
229
|
+
// find the parent shared folder to use its _id for recipient/permission lookups.
|
|
230
|
+
|
|
231
|
+
var sharedParentPath = !sharedDriveSharing && hasSharedParentByPath && documentPath ? getSharedParentPath(documentPath) : null;
|
|
232
|
+
|
|
233
|
+
var _useState11 = useState(null),
|
|
234
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
235
|
+
sharedParentFolder = _useState12[0],
|
|
236
|
+
setSharedParentFolder = _useState12[1];
|
|
237
|
+
|
|
238
|
+
useEffect(function () {
|
|
239
|
+
if (!sharedParentPath) return;
|
|
240
|
+
|
|
241
|
+
var fetchParentFolder = /*#__PURE__*/function () {
|
|
242
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
243
|
+
var res;
|
|
244
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
245
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
246
|
+
case 0:
|
|
247
|
+
_context2.prev = 0;
|
|
248
|
+
_context2.next = 3;
|
|
249
|
+
return client.collection('io.cozy.files').statByPath(sharedParentPath);
|
|
250
|
+
|
|
251
|
+
case 3:
|
|
252
|
+
res = _context2.sent;
|
|
253
|
+
if (res.data) setSharedParentFolder(res.data);
|
|
254
|
+
_context2.next = 10;
|
|
255
|
+
break;
|
|
256
|
+
|
|
257
|
+
case 7:
|
|
258
|
+
_context2.prev = 7;
|
|
259
|
+
_context2.t0 = _context2["catch"](0);
|
|
260
|
+
log.error('Failed to fetch shared parent folder', _context2.t0);
|
|
261
|
+
|
|
262
|
+
case 10:
|
|
263
|
+
case "end":
|
|
264
|
+
return _context2.stop();
|
|
265
|
+
}
|
|
266
|
+
}, _callee2, null, [[0, 7]]);
|
|
267
|
+
}));
|
|
268
|
+
|
|
269
|
+
return function fetchParentFolder() {
|
|
270
|
+
return _ref3.apply(this, arguments);
|
|
271
|
+
};
|
|
272
|
+
}();
|
|
273
|
+
|
|
274
|
+
fetchParentFolder();
|
|
275
|
+
}, [sharedParentPath, client]);
|
|
276
|
+
var sharingReferenceId = !sharedDriveSharing && sharedParentFolder !== null && sharedParentFolder !== void 0 && sharedParentFolder._id ? sharedParentFolder._id : documentId;
|
|
277
|
+
var existingRecipients = sharedDriveSharing !== null && sharedDriveSharing !== void 0 && (_sharedDriveSharing$a2 = sharedDriveSharing.attributes) !== null && _sharedDriveSharing$a2 !== void 0 && _sharedDriveSharing$a2.members && documentId ? getRecipientsFromSharing(sharedDriveSharing, documentId) : sharingReferenceId ? getRecipients(sharingReferenceId) : [];
|
|
225
278
|
var documentPermissions = documentId ? getDocumentPermissions(documentId) : [];
|
|
226
279
|
var displayedLink = existingDocument !== null && existingDocument !== void 0 && existingDocument.driveId ? getFederatedShareLink(existingDocument) : getSharingLink(existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id);
|
|
280
|
+
var isCurrentUserOwner = documentId ? isOwner(documentId) : false;
|
|
281
|
+
|
|
282
|
+
var handleRevokeSelf = /*#__PURE__*/function () {
|
|
283
|
+
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(document) {
|
|
284
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
285
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
286
|
+
case 0:
|
|
287
|
+
_context3.next = 2;
|
|
288
|
+
return revokeSelf(document);
|
|
289
|
+
|
|
290
|
+
case 2:
|
|
291
|
+
onRevokeSuccess === null || onRevokeSuccess === void 0 || onRevokeSuccess(document);
|
|
292
|
+
|
|
293
|
+
case 3:
|
|
294
|
+
case "end":
|
|
295
|
+
return _context3.stop();
|
|
296
|
+
}
|
|
297
|
+
}, _callee3);
|
|
298
|
+
}));
|
|
299
|
+
|
|
300
|
+
return function handleRevokeSelf(_x) {
|
|
301
|
+
return _ref4.apply(this, arguments);
|
|
302
|
+
};
|
|
303
|
+
}();
|
|
304
|
+
|
|
227
305
|
useEffect(function () {
|
|
228
306
|
if (!(existingDocument !== null && existingDocument !== void 0 && existingDocument.driveId)) return;
|
|
229
307
|
if (!documentId) return;
|
|
@@ -233,39 +311,39 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
233
311
|
if (fetchedSharingLinksDocumentId === documentId) return;
|
|
234
312
|
|
|
235
313
|
var fetchSharingLinks = /*#__PURE__*/function () {
|
|
236
|
-
var
|
|
237
|
-
return _regeneratorRuntime.wrap(function
|
|
238
|
-
while (1) switch (
|
|
314
|
+
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
|
|
315
|
+
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
316
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
239
317
|
case 0:
|
|
240
318
|
setIsFetchingSharingLinks(true);
|
|
241
|
-
|
|
242
|
-
|
|
319
|
+
_context4.prev = 1;
|
|
320
|
+
_context4.next = 4;
|
|
243
321
|
return fetchSharedDriveSharingLinks(existingDocument);
|
|
244
322
|
|
|
245
323
|
case 4:
|
|
246
|
-
|
|
324
|
+
_context4.next = 9;
|
|
247
325
|
break;
|
|
248
326
|
|
|
249
327
|
case 6:
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
log.error('Failed to fetch shared drive sharing links',
|
|
328
|
+
_context4.prev = 6;
|
|
329
|
+
_context4.t0 = _context4["catch"](1);
|
|
330
|
+
log.error('Failed to fetch shared drive sharing links', _context4.t0);
|
|
253
331
|
|
|
254
332
|
case 9:
|
|
255
|
-
|
|
333
|
+
_context4.prev = 9;
|
|
256
334
|
setFetchedSharingLinksDocumentId(documentId);
|
|
257
335
|
setIsFetchingSharingLinks(false);
|
|
258
|
-
return
|
|
336
|
+
return _context4.finish(9);
|
|
259
337
|
|
|
260
338
|
case 13:
|
|
261
339
|
case "end":
|
|
262
|
-
return
|
|
340
|
+
return _context4.stop();
|
|
263
341
|
}
|
|
264
|
-
},
|
|
342
|
+
}, _callee4, null, [[1, 6, 9, 13]]);
|
|
265
343
|
}));
|
|
266
344
|
|
|
267
345
|
return function fetchSharingLinks() {
|
|
268
|
-
return
|
|
346
|
+
return _ref5.apply(this, arguments);
|
|
269
347
|
};
|
|
270
348
|
}();
|
|
271
349
|
|
|
@@ -310,13 +388,14 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
310
388
|
onSelectedOptionChange: setSelectedOption,
|
|
311
389
|
enableCreateContact: true
|
|
312
390
|
}))), /*#__PURE__*/React.createElement(WhoHasAccess, {
|
|
313
|
-
isOwner:
|
|
391
|
+
isOwner: isCurrentUserOwner,
|
|
314
392
|
isSharedDrive: true,
|
|
315
393
|
recipients: isSending ? frozenRecipients : existingRecipients,
|
|
316
394
|
document: isSending ? frozenDoc : existingDocument,
|
|
317
395
|
documentType: "Files",
|
|
318
396
|
className: styles['share-dialog-members'],
|
|
319
397
|
onRevoke: revoke,
|
|
398
|
+
onRevokeSelf: handleRevokeSelf,
|
|
320
399
|
link: displayedLink
|
|
321
400
|
})),
|
|
322
401
|
actions: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ShareByLink, {
|
|
@@ -339,6 +418,7 @@ export var FederatedFolderModal = withLocales(function (props) {
|
|
|
339
418
|
});
|
|
340
419
|
FederatedFolderModal.propTypes = {
|
|
341
420
|
onClose: PropTypes.func.isRequired,
|
|
421
|
+
onRevokeSuccess: PropTypes.func,
|
|
342
422
|
document: PropTypes.object.isRequired,
|
|
343
423
|
autoOpenShareRestriction: PropTypes.bool,
|
|
344
424
|
showGenerateLinkButton: PropTypes.bool
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
2
|
import _extends from "@babel/runtime/helpers/extends";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
4
5
|
|
|
5
6
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
6
7
|
|
|
7
8
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
8
9
|
|
|
9
|
-
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
10
10
|
import { act, fireEvent, render, waitFor } from '@testing-library/react';
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import { createMockClient } from 'cozy-client';
|
|
@@ -17,6 +17,8 @@ import AppLike from '../SharingBanner/test/AppLike';
|
|
|
17
17
|
var mockShare = jest.fn();
|
|
18
18
|
var mockShareByLink = jest.fn();
|
|
19
19
|
var mockRevoke = jest.fn();
|
|
20
|
+
var mockRevokeSelf = jest.fn();
|
|
21
|
+
var mockIsOwner = jest.fn();
|
|
20
22
|
var mockGetSharingLink = jest.fn();
|
|
21
23
|
var mockGetFederatedShareLink = jest.fn();
|
|
22
24
|
var mockGetRecipients = jest.fn().mockReturnValue([]);
|
|
@@ -34,12 +36,15 @@ jest.mock('../../hooks/useSharingContext', function () {
|
|
|
34
36
|
share: mockShare,
|
|
35
37
|
shareByLink: mockShareByLink,
|
|
36
38
|
revoke: mockRevoke,
|
|
39
|
+
revokeSelf: mockRevokeSelf,
|
|
40
|
+
isOwner: mockIsOwner,
|
|
37
41
|
getSharingLink: mockGetSharingLink,
|
|
38
42
|
getFederatedShareLink: mockGetFederatedShareLink,
|
|
39
43
|
getDocumentPermissions: mockGetDocumentPermissions,
|
|
40
44
|
fetchSharedDriveSharingLinks: mockFetchSharedDriveSharingLinks,
|
|
41
45
|
getOwner: jest.fn(),
|
|
42
46
|
getRecipients: mockGetRecipients,
|
|
47
|
+
getSharedParentPath: jest.fn().mockReturnValue(null),
|
|
43
48
|
getSharingById: mockGetSharingById,
|
|
44
49
|
hasSharedChild: mockHasSharedChild,
|
|
45
50
|
hasSharedParent: mockHasSharedParent
|
|
@@ -122,6 +127,9 @@ describe('FederatedFolderModal', function () {
|
|
|
122
127
|
var sharingContextValue;
|
|
123
128
|
beforeEach(function () {
|
|
124
129
|
jest.clearAllMocks();
|
|
130
|
+
mockRevoke.mockResolvedValue();
|
|
131
|
+
mockRevokeSelf.mockResolvedValue();
|
|
132
|
+
mockIsOwner.mockReturnValue(false);
|
|
125
133
|
mockGetDocumentPermissions.mockReturnValue([]);
|
|
126
134
|
mockFetchSharedDriveSharingLinks.mockResolvedValue([]);
|
|
127
135
|
mockGetSharingLink.mockReturnValue('https://example.com/share/abc123');
|
|
@@ -146,6 +154,9 @@ describe('FederatedFolderModal', function () {
|
|
|
146
154
|
}
|
|
147
155
|
});
|
|
148
156
|
client = createTestClient();
|
|
157
|
+
client.options = _objectSpread(_objectSpread({}, client.options), {}, {
|
|
158
|
+
uri: 'https://me.mycozy.cloud'
|
|
159
|
+
});
|
|
149
160
|
sharingContextValue = createSharingContextValue();
|
|
150
161
|
usePendingRecipients.mockReturnValue({
|
|
151
162
|
pendingRecipients: [],
|
|
@@ -672,35 +683,76 @@ describe('FederatedFolderModal', function () {
|
|
|
672
683
|
}, _callee18);
|
|
673
684
|
})));
|
|
674
685
|
});
|
|
675
|
-
describe('
|
|
676
|
-
|
|
677
|
-
|
|
686
|
+
describe('onRevoke callback', function () {
|
|
687
|
+
var currentUserRecipient = {
|
|
688
|
+
instance: 'https://me.mycozy.cloud',
|
|
689
|
+
memberIndex: 1,
|
|
690
|
+
sharingId: 'sharing-id',
|
|
691
|
+
type: 'two-way'
|
|
692
|
+
};
|
|
693
|
+
it('should call onRevokeSelf and onRevokeSuccess when the current user is revoked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee19() {
|
|
694
|
+
var onRevokeSuccess, _setup16, findByLabelText;
|
|
678
695
|
|
|
679
696
|
return _regeneratorRuntime.wrap(function _callee19$(_context19) {
|
|
680
697
|
while (1) switch (_context19.prev = _context19.next) {
|
|
681
698
|
case 0:
|
|
682
|
-
|
|
683
|
-
|
|
699
|
+
onRevokeSuccess = jest.fn();
|
|
700
|
+
mockGetRecipients.mockReturnValue([currentUserRecipient]);
|
|
701
|
+
_setup16 = setup({
|
|
702
|
+
onRevokeSuccess: onRevokeSuccess
|
|
703
|
+
}), findByLabelText = _setup16.findByLabelText;
|
|
704
|
+
_context19.t0 = fireEvent;
|
|
705
|
+
_context19.next = 6;
|
|
706
|
+
return findByLabelText('Remove from sharing');
|
|
707
|
+
|
|
708
|
+
case 6:
|
|
709
|
+
_context19.t1 = _context19.sent;
|
|
710
|
+
|
|
711
|
+
_context19.t0.click.call(_context19.t0, _context19.t1);
|
|
712
|
+
|
|
713
|
+
_context19.next = 10;
|
|
714
|
+
return waitFor(function () {
|
|
715
|
+
expect(mockRevokeSelf).toHaveBeenCalledWith(mockDocument);
|
|
716
|
+
expect(mockRevoke).not.toHaveBeenCalled();
|
|
717
|
+
expect(onRevokeSuccess).toHaveBeenCalledWith(mockDocument);
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
case 10:
|
|
721
|
+
case "end":
|
|
722
|
+
return _context19.stop();
|
|
723
|
+
}
|
|
724
|
+
}, _callee19);
|
|
725
|
+
})));
|
|
726
|
+
});
|
|
727
|
+
describe('onClose callback', function () {
|
|
728
|
+
it('should call onClose when close button is clicked', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee20() {
|
|
729
|
+
var _setup17, findByRole, closeButton;
|
|
730
|
+
|
|
731
|
+
return _regeneratorRuntime.wrap(function _callee20$(_context20) {
|
|
732
|
+
while (1) switch (_context20.prev = _context20.next) {
|
|
733
|
+
case 0:
|
|
734
|
+
_setup17 = setup(), findByRole = _setup17.findByRole;
|
|
735
|
+
_context20.next = 3;
|
|
684
736
|
return findByRole('button', {
|
|
685
737
|
name: /close/i
|
|
686
738
|
});
|
|
687
739
|
|
|
688
740
|
case 3:
|
|
689
|
-
closeButton =
|
|
741
|
+
closeButton = _context20.sent;
|
|
690
742
|
fireEvent.click(closeButton);
|
|
691
743
|
expect(mockOnClose).toHaveBeenCalled();
|
|
692
744
|
|
|
693
745
|
case 6:
|
|
694
746
|
case "end":
|
|
695
|
-
return
|
|
747
|
+
return _context20.stop();
|
|
696
748
|
}
|
|
697
|
-
},
|
|
749
|
+
}, _callee20);
|
|
698
750
|
})));
|
|
699
|
-
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
700
|
-
var
|
|
751
|
+
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
|
|
752
|
+
var _setup18, getByRole, findByRole, getByText, closeButton;
|
|
701
753
|
|
|
702
|
-
return _regeneratorRuntime.wrap(function
|
|
703
|
-
while (1) switch (
|
|
754
|
+
return _regeneratorRuntime.wrap(function _callee21$(_context21) {
|
|
755
|
+
while (1) switch (_context21.prev = _context21.next) {
|
|
704
756
|
case 0:
|
|
705
757
|
usePendingRecipients.mockReturnValue({
|
|
706
758
|
pendingRecipients: [{
|
|
@@ -711,14 +763,14 @@ describe('FederatedFolderModal', function () {
|
|
|
711
763
|
selectedOption: 'readWrite',
|
|
712
764
|
setSelectedOption: jest.fn()
|
|
713
765
|
});
|
|
714
|
-
|
|
715
|
-
|
|
766
|
+
_setup18 = setup(), getByRole = _setup18.getByRole, findByRole = _setup18.findByRole, getByText = _setup18.getByText;
|
|
767
|
+
_context21.next = 4;
|
|
716
768
|
return findByRole('button', {
|
|
717
769
|
name: /close/i
|
|
718
770
|
});
|
|
719
771
|
|
|
720
772
|
case 4:
|
|
721
|
-
closeButton =
|
|
773
|
+
closeButton = _context21.sent;
|
|
722
774
|
fireEvent.click(closeButton);
|
|
723
775
|
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
724
776
|
expect(mockOnClose).not.toHaveBeenCalled();
|
|
@@ -729,15 +781,15 @@ describe('FederatedFolderModal', function () {
|
|
|
729
781
|
|
|
730
782
|
case 10:
|
|
731
783
|
case "end":
|
|
732
|
-
return
|
|
784
|
+
return _context21.stop();
|
|
733
785
|
}
|
|
734
|
-
},
|
|
786
|
+
}, _callee21);
|
|
735
787
|
})));
|
|
736
|
-
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
737
|
-
var
|
|
788
|
+
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee22() {
|
|
789
|
+
var _setup19, getByRole, findByRole, getByText, closeButton;
|
|
738
790
|
|
|
739
|
-
return _regeneratorRuntime.wrap(function
|
|
740
|
-
while (1) switch (
|
|
791
|
+
return _regeneratorRuntime.wrap(function _callee22$(_context22) {
|
|
792
|
+
while (1) switch (_context22.prev = _context22.next) {
|
|
741
793
|
case 0:
|
|
742
794
|
usePendingRecipients.mockReturnValue({
|
|
743
795
|
pendingRecipients: [{
|
|
@@ -748,14 +800,14 @@ describe('FederatedFolderModal', function () {
|
|
|
748
800
|
selectedOption: 'readWrite',
|
|
749
801
|
setSelectedOption: jest.fn()
|
|
750
802
|
});
|
|
751
|
-
|
|
752
|
-
|
|
803
|
+
_setup19 = setup(), getByRole = _setup19.getByRole, findByRole = _setup19.findByRole, getByText = _setup19.getByText;
|
|
804
|
+
_context22.next = 4;
|
|
753
805
|
return findByRole('button', {
|
|
754
806
|
name: /close/i
|
|
755
807
|
});
|
|
756
808
|
|
|
757
809
|
case 4:
|
|
758
|
-
closeButton =
|
|
810
|
+
closeButton = _context22.sent;
|
|
759
811
|
fireEvent.click(closeButton);
|
|
760
812
|
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
761
813
|
fireEvent.click(getByRole('button', {
|
|
@@ -765,9 +817,9 @@ describe('FederatedFolderModal', function () {
|
|
|
765
817
|
|
|
766
818
|
case 9:
|
|
767
819
|
case "end":
|
|
768
|
-
return
|
|
820
|
+
return _context22.stop();
|
|
769
821
|
}
|
|
770
|
-
},
|
|
822
|
+
}, _callee22);
|
|
771
823
|
})));
|
|
772
824
|
});
|
|
773
825
|
});
|
|
@@ -20,6 +20,8 @@ var log = minilog('MemberRecipientPermissions');
|
|
|
20
20
|
|
|
21
21
|
var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
22
22
|
var isOwner = _ref.isOwner,
|
|
23
|
+
_ref$canManageSharing = _ref.canManageSharing,
|
|
24
|
+
canManageSharing = _ref$canManageSharing === void 0 ? isOwner : _ref$canManageSharing,
|
|
23
25
|
isReadOnly = _ref.isReadOnly,
|
|
24
26
|
status = _ref.status,
|
|
25
27
|
instance = _ref.instance,
|
|
@@ -54,7 +56,7 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
|
54
56
|
|
|
55
57
|
var instanceMatchesClient = instance !== undefined && instance === client.options.uri;
|
|
56
58
|
var contactIsOwner = status === 'owner';
|
|
57
|
-
var shouldShowMenu = !isReadOnly && !revoking && !contactIsOwner && (instanceMatchesClient && !isOwner ||
|
|
59
|
+
var shouldShowMenu = !isReadOnly && !revoking && !contactIsOwner && (instanceMatchesClient && !isOwner || canManageSharing);
|
|
58
60
|
var toggleMenu = useCallback(function () {
|
|
59
61
|
setMenuDisplayed(function (displayed) {
|
|
60
62
|
return !displayed;
|
|
@@ -70,13 +72,13 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
|
70
72
|
setRevoking(true);
|
|
71
73
|
_context.prev = 1;
|
|
72
74
|
|
|
73
|
-
if (!isOwner) {
|
|
75
|
+
if (!(instanceMatchesClient && !isOwner)) {
|
|
74
76
|
_context.next = 7;
|
|
75
77
|
break;
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
_context.next = 5;
|
|
79
|
-
return
|
|
81
|
+
return onRevokeSelf(document);
|
|
80
82
|
|
|
81
83
|
case 5:
|
|
82
84
|
_context.next = 9;
|
|
@@ -84,7 +86,7 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
|
84
86
|
|
|
85
87
|
case 7:
|
|
86
88
|
_context.next = 9;
|
|
87
|
-
return
|
|
89
|
+
return onRevoke(document, sharingId, memberIndex);
|
|
88
90
|
|
|
89
91
|
case 9:
|
|
90
92
|
_context.prev = 9;
|
|
@@ -96,7 +98,7 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
|
96
98
|
return _context.stop();
|
|
97
99
|
}
|
|
98
100
|
}, _callee, null, [[1,, 9, 12]]);
|
|
99
|
-
})), [isOwner, onRevoke, onRevokeSelf,
|
|
101
|
+
})), [document, instanceMatchesClient, isOwner, memberIndex, onRevoke, onRevokeSelf, sharingId]);
|
|
100
102
|
var setType = useCallback( /*#__PURE__*/function () {
|
|
101
103
|
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(newType) {
|
|
102
104
|
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
@@ -9,6 +9,7 @@ var RecipientList = function RecipientList(_ref) {
|
|
|
9
9
|
var recipients = _ref.recipients,
|
|
10
10
|
recipientsToBeConfirmed = _ref.recipientsToBeConfirmed,
|
|
11
11
|
isOwner = _ref.isOwner,
|
|
12
|
+
canManageSharing = _ref.canManageSharing,
|
|
12
13
|
isSharedDrive = _ref.isSharedDrive,
|
|
13
14
|
isReadOnly = _ref.isReadOnly,
|
|
14
15
|
document = _ref.document,
|
|
@@ -40,6 +41,7 @@ var RecipientList = function RecipientList(_ref) {
|
|
|
40
41
|
return /*#__PURE__*/React.createElement(MemberRecipient, _extends({}, recipient, {
|
|
41
42
|
key: recipient.index,
|
|
42
43
|
isOwner: isOwner,
|
|
44
|
+
canManageSharing: canManageSharing,
|
|
43
45
|
isSharedDrive: isSharedDrive,
|
|
44
46
|
isReadOnly: isReadOnly,
|
|
45
47
|
document: document,
|
|
@@ -63,7 +63,8 @@ export var ShareModal = withLocales(function (props) {
|
|
|
63
63
|
|
|
64
64
|
if (isFederatedMode && allLoaded) {
|
|
65
65
|
return /*#__PURE__*/React.createElement(FederatedFolderModal, _extends({
|
|
66
|
-
document: document
|
|
66
|
+
document: document,
|
|
67
|
+
onRevokeSuccess: onRevokeSuccess
|
|
67
68
|
}, rest));
|
|
68
69
|
}
|
|
69
70
|
|
|
@@ -30,6 +30,8 @@ var RecipientWaitingForConfirmationAlert = function RecipientWaitingForConfirmat
|
|
|
30
30
|
var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
31
31
|
var _ref2$isOwner = _ref2.isOwner,
|
|
32
32
|
isOwner = _ref2$isOwner === void 0 ? false : _ref2$isOwner,
|
|
33
|
+
_ref2$canManageSharin = _ref2.canManageSharing,
|
|
34
|
+
canManageSharing = _ref2$canManageSharin === void 0 ? isOwner : _ref2$canManageSharin,
|
|
33
35
|
_ref2$isSharedDrive = _ref2.isSharedDrive,
|
|
34
36
|
isSharedDrive = _ref2$isSharedDrive === void 0 ? false : _ref2$isSharedDrive,
|
|
35
37
|
_ref2$isReadOnly = _ref2.isReadOnly,
|
|
@@ -68,6 +70,7 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
68
70
|
recipients: recipients,
|
|
69
71
|
recipientsToBeConfirmed: recipientsToBeConfirmed,
|
|
70
72
|
isOwner: isOwner,
|
|
73
|
+
canManageSharing: canManageSharing,
|
|
71
74
|
isSharedDrive: isSharedDrive,
|
|
72
75
|
isReadOnly: isReadOnly,
|
|
73
76
|
document: document,
|
|
@@ -81,6 +84,7 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
81
84
|
|
|
82
85
|
WhoHasAccess.propTypes = {
|
|
83
86
|
isOwner: PropTypes.bool,
|
|
87
|
+
canManageSharing: PropTypes.bool,
|
|
84
88
|
showOwner: PropTypes.bool,
|
|
85
89
|
recipients: PropTypes.array.isRequired,
|
|
86
90
|
recipientsToBeConfirmed: PropTypes.arrayOf(PropTypes.shape({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "34.1.
|
|
3
|
+
"version": "34.1.2",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"sideEffects": [
|
|
86
86
|
"*.css"
|
|
87
87
|
],
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "3f975f8efa4061617d6fa5df190f1cbb83170f09"
|
|
89
89
|
}
|
|
@@ -16,6 +16,7 @@ import { getOrCreateFromArray } from '../../helpers/contacts'
|
|
|
16
16
|
import withLocales from '../../hoc/withLocales'
|
|
17
17
|
import { usePendingRecipients } from '../../hooks/usePendingRecipients'
|
|
18
18
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
19
|
+
import { getRecipientsFromSharing } from '../../state'
|
|
19
20
|
import styles from '../../styles/share.styl'
|
|
20
21
|
import AntivirusAlert from '../AntivirusAlert'
|
|
21
22
|
import { default as DumbShareByEmail } from '../ShareByEmail'
|
|
@@ -26,6 +27,7 @@ const log = minilog('FederatedFolderModal')
|
|
|
26
27
|
|
|
27
28
|
const FederatedFolderModalContent = ({
|
|
28
29
|
onClose,
|
|
30
|
+
onRevokeSuccess,
|
|
29
31
|
document: existingDocument,
|
|
30
32
|
autoOpenShareRestriction,
|
|
31
33
|
showGenerateLinkButton
|
|
@@ -40,9 +42,12 @@ const FederatedFolderModalContent = ({
|
|
|
40
42
|
getDocumentPermissions,
|
|
41
43
|
fetchSharedDriveSharingLinks,
|
|
42
44
|
getRecipients,
|
|
45
|
+
getSharedParentPath,
|
|
43
46
|
hasSharedChild,
|
|
44
47
|
hasSharedParent,
|
|
45
|
-
|
|
48
|
+
isOwner,
|
|
49
|
+
revoke,
|
|
50
|
+
revokeSelf
|
|
46
51
|
} = useSharingContext()
|
|
47
52
|
const { showAlert } = useAlert()
|
|
48
53
|
const { showConfirmDialog, closeConfirmDialog } = useConfirmDialog()
|
|
@@ -178,13 +183,52 @@ const FederatedFolderModalContent = ({
|
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
const documentId = existingDocument?._id || existingDocument?.id
|
|
181
|
-
|
|
186
|
+
// Owner case: when document is inside a shared folder (via path) but has no driveId,
|
|
187
|
+
// find the parent shared folder to use its _id for recipient/permission lookups.
|
|
188
|
+
const sharedParentPath =
|
|
189
|
+
!sharedDriveSharing && hasSharedParentByPath && documentPath
|
|
190
|
+
? getSharedParentPath(documentPath)
|
|
191
|
+
: null
|
|
192
|
+
const [sharedParentFolder, setSharedParentFolder] = useState(null)
|
|
193
|
+
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
if (!sharedParentPath) return
|
|
196
|
+
const fetchParentFolder = async () => {
|
|
197
|
+
try {
|
|
198
|
+
const res = await client
|
|
199
|
+
.collection('io.cozy.files')
|
|
200
|
+
.statByPath(sharedParentPath)
|
|
201
|
+
if (res.data) setSharedParentFolder(res.data)
|
|
202
|
+
} catch (err) {
|
|
203
|
+
log.error('Failed to fetch shared parent folder', err)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
fetchParentFolder()
|
|
207
|
+
}, [sharedParentPath, client])
|
|
208
|
+
|
|
209
|
+
const sharingReferenceId =
|
|
210
|
+
!sharedDriveSharing && sharedParentFolder?._id
|
|
211
|
+
? sharedParentFolder._id
|
|
212
|
+
: documentId
|
|
213
|
+
|
|
214
|
+
const existingRecipients =
|
|
215
|
+
sharedDriveSharing?.attributes?.members && documentId
|
|
216
|
+
? getRecipientsFromSharing(sharedDriveSharing, documentId)
|
|
217
|
+
: sharingReferenceId
|
|
218
|
+
? getRecipients(sharingReferenceId)
|
|
219
|
+
: []
|
|
182
220
|
const documentPermissions = documentId
|
|
183
221
|
? getDocumentPermissions(documentId)
|
|
184
222
|
: []
|
|
185
223
|
const displayedLink = existingDocument?.driveId
|
|
186
224
|
? getFederatedShareLink(existingDocument)
|
|
187
225
|
: getSharingLink(existingDocument?._id)
|
|
226
|
+
const isCurrentUserOwner = documentId ? isOwner(documentId) : false
|
|
227
|
+
|
|
228
|
+
const handleRevokeSelf = async document => {
|
|
229
|
+
await revokeSelf(document)
|
|
230
|
+
onRevokeSuccess?.(document)
|
|
231
|
+
}
|
|
188
232
|
|
|
189
233
|
useEffect(() => {
|
|
190
234
|
if (!existingDocument?.driveId) return
|
|
@@ -278,13 +322,14 @@ const FederatedFolderModalContent = ({
|
|
|
278
322
|
)}
|
|
279
323
|
</div>
|
|
280
324
|
<WhoHasAccess
|
|
281
|
-
isOwner
|
|
325
|
+
isOwner={isCurrentUserOwner}
|
|
282
326
|
isSharedDrive
|
|
283
327
|
recipients={isSending ? frozenRecipients : existingRecipients}
|
|
284
328
|
document={isSending ? frozenDoc : existingDocument}
|
|
285
329
|
documentType="Files"
|
|
286
330
|
className={styles['share-dialog-members']}
|
|
287
331
|
onRevoke={revoke}
|
|
332
|
+
onRevokeSelf={handleRevokeSelf}
|
|
288
333
|
link={displayedLink}
|
|
289
334
|
/>
|
|
290
335
|
</div>
|
|
@@ -320,6 +365,7 @@ export const FederatedFolderModal = withLocales(props => (
|
|
|
320
365
|
|
|
321
366
|
FederatedFolderModal.propTypes = {
|
|
322
367
|
onClose: PropTypes.func.isRequired,
|
|
368
|
+
onRevokeSuccess: PropTypes.func,
|
|
323
369
|
document: PropTypes.object.isRequired,
|
|
324
370
|
autoOpenShareRestriction: PropTypes.bool,
|
|
325
371
|
showGenerateLinkButton: PropTypes.bool
|
|
@@ -11,6 +11,8 @@ import AppLike from '../SharingBanner/test/AppLike'
|
|
|
11
11
|
const mockShare = jest.fn()
|
|
12
12
|
const mockShareByLink = jest.fn()
|
|
13
13
|
const mockRevoke = jest.fn()
|
|
14
|
+
const mockRevokeSelf = jest.fn()
|
|
15
|
+
const mockIsOwner = jest.fn()
|
|
14
16
|
const mockGetSharingLink = jest.fn()
|
|
15
17
|
const mockGetFederatedShareLink = jest.fn()
|
|
16
18
|
const mockGetRecipients = jest.fn().mockReturnValue([])
|
|
@@ -27,12 +29,15 @@ jest.mock('../../hooks/useSharingContext', () => ({
|
|
|
27
29
|
share: mockShare,
|
|
28
30
|
shareByLink: mockShareByLink,
|
|
29
31
|
revoke: mockRevoke,
|
|
32
|
+
revokeSelf: mockRevokeSelf,
|
|
33
|
+
isOwner: mockIsOwner,
|
|
30
34
|
getSharingLink: mockGetSharingLink,
|
|
31
35
|
getFederatedShareLink: mockGetFederatedShareLink,
|
|
32
36
|
getDocumentPermissions: mockGetDocumentPermissions,
|
|
33
37
|
fetchSharedDriveSharingLinks: mockFetchSharedDriveSharingLinks,
|
|
34
38
|
getOwner: jest.fn(),
|
|
35
39
|
getRecipients: mockGetRecipients,
|
|
40
|
+
getSharedParentPath: jest.fn().mockReturnValue(null),
|
|
36
41
|
getSharingById: mockGetSharingById,
|
|
37
42
|
hasSharedChild: mockHasSharedChild,
|
|
38
43
|
hasSharedParent: mockHasSharedParent
|
|
@@ -100,6 +105,9 @@ describe('FederatedFolderModal', () => {
|
|
|
100
105
|
|
|
101
106
|
beforeEach(() => {
|
|
102
107
|
jest.clearAllMocks()
|
|
108
|
+
mockRevoke.mockResolvedValue()
|
|
109
|
+
mockRevokeSelf.mockResolvedValue()
|
|
110
|
+
mockIsOwner.mockReturnValue(false)
|
|
103
111
|
mockGetDocumentPermissions.mockReturnValue([])
|
|
104
112
|
mockFetchSharedDriveSharingLinks.mockResolvedValue([])
|
|
105
113
|
mockGetSharingLink.mockReturnValue('https://example.com/share/abc123')
|
|
@@ -124,6 +132,10 @@ describe('FederatedFolderModal', () => {
|
|
|
124
132
|
}
|
|
125
133
|
})
|
|
126
134
|
client = createTestClient()
|
|
135
|
+
client.options = {
|
|
136
|
+
...client.options,
|
|
137
|
+
uri: 'https://me.mycozy.cloud'
|
|
138
|
+
}
|
|
127
139
|
sharingContextValue = createSharingContextValue()
|
|
128
140
|
usePendingRecipients.mockReturnValue({
|
|
129
141
|
pendingRecipients: [],
|
|
@@ -437,6 +449,30 @@ describe('FederatedFolderModal', () => {
|
|
|
437
449
|
})
|
|
438
450
|
})
|
|
439
451
|
|
|
452
|
+
describe('onRevoke callback', () => {
|
|
453
|
+
const currentUserRecipient = {
|
|
454
|
+
instance: 'https://me.mycozy.cloud',
|
|
455
|
+
memberIndex: 1,
|
|
456
|
+
sharingId: 'sharing-id',
|
|
457
|
+
type: 'two-way'
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
it('should call onRevokeSelf and onRevokeSuccess when the current user is revoked', async () => {
|
|
461
|
+
const onRevokeSuccess = jest.fn()
|
|
462
|
+
mockGetRecipients.mockReturnValue([currentUserRecipient])
|
|
463
|
+
|
|
464
|
+
const { findByLabelText } = setup({ onRevokeSuccess })
|
|
465
|
+
|
|
466
|
+
fireEvent.click(await findByLabelText('Remove from sharing'))
|
|
467
|
+
|
|
468
|
+
await waitFor(() => {
|
|
469
|
+
expect(mockRevokeSelf).toHaveBeenCalledWith(mockDocument)
|
|
470
|
+
expect(mockRevoke).not.toHaveBeenCalled()
|
|
471
|
+
expect(onRevokeSuccess).toHaveBeenCalledWith(mockDocument)
|
|
472
|
+
})
|
|
473
|
+
})
|
|
474
|
+
})
|
|
475
|
+
|
|
440
476
|
describe('onClose callback', () => {
|
|
441
477
|
it('should call onClose when close button is clicked', async () => {
|
|
442
478
|
const { findByRole } = setup()
|
|
@@ -20,6 +20,7 @@ const log = minilog('MemberRecipientPermissions')
|
|
|
20
20
|
|
|
21
21
|
const MemberRecipientPermissions = ({
|
|
22
22
|
isOwner,
|
|
23
|
+
canManageSharing = isOwner,
|
|
23
24
|
isReadOnly,
|
|
24
25
|
status,
|
|
25
26
|
instance,
|
|
@@ -46,7 +47,7 @@ const MemberRecipientPermissions = ({
|
|
|
46
47
|
!isReadOnly &&
|
|
47
48
|
!revoking &&
|
|
48
49
|
!contactIsOwner &&
|
|
49
|
-
((instanceMatchesClient && !isOwner) ||
|
|
50
|
+
((instanceMatchesClient && !isOwner) || canManageSharing)
|
|
50
51
|
|
|
51
52
|
const toggleMenu = useCallback(() => {
|
|
52
53
|
setMenuDisplayed(displayed => !displayed)
|
|
@@ -58,15 +59,23 @@ const MemberRecipientPermissions = ({
|
|
|
58
59
|
const handleRevocation = useCallback(async () => {
|
|
59
60
|
setRevoking(true)
|
|
60
61
|
try {
|
|
61
|
-
if (isOwner) {
|
|
62
|
-
await onRevoke(document, sharingId, memberIndex)
|
|
63
|
-
} else {
|
|
62
|
+
if (instanceMatchesClient && !isOwner) {
|
|
64
63
|
await onRevokeSelf(document)
|
|
64
|
+
} else {
|
|
65
|
+
await onRevoke(document, sharingId, memberIndex)
|
|
65
66
|
}
|
|
66
67
|
} finally {
|
|
67
68
|
setRevoking(false)
|
|
68
69
|
}
|
|
69
|
-
}, [
|
|
70
|
+
}, [
|
|
71
|
+
document,
|
|
72
|
+
instanceMatchesClient,
|
|
73
|
+
isOwner,
|
|
74
|
+
memberIndex,
|
|
75
|
+
onRevoke,
|
|
76
|
+
onRevokeSelf,
|
|
77
|
+
sharingId
|
|
78
|
+
])
|
|
70
79
|
|
|
71
80
|
const setType = useCallback(
|
|
72
81
|
async newType => {
|
|
@@ -9,6 +9,7 @@ const RecipientList = ({
|
|
|
9
9
|
recipients,
|
|
10
10
|
recipientsToBeConfirmed,
|
|
11
11
|
isOwner,
|
|
12
|
+
canManageSharing,
|
|
12
13
|
isSharedDrive,
|
|
13
14
|
isReadOnly,
|
|
14
15
|
document,
|
|
@@ -50,6 +51,7 @@ const RecipientList = ({
|
|
|
50
51
|
{...recipient}
|
|
51
52
|
key={recipient.index}
|
|
52
53
|
isOwner={isOwner}
|
|
54
|
+
canManageSharing={canManageSharing}
|
|
53
55
|
isSharedDrive={isSharedDrive}
|
|
54
56
|
isReadOnly={isReadOnly}
|
|
55
57
|
document={document}
|
|
@@ -38,7 +38,13 @@ export const ShareModal = withLocales(props => {
|
|
|
38
38
|
if (isEditable) {
|
|
39
39
|
const isFederatedMode = flag('drive.federated-shared-folder.enabled')
|
|
40
40
|
if (isFederatedMode && allLoaded) {
|
|
41
|
-
return
|
|
41
|
+
return (
|
|
42
|
+
<FederatedFolderModal
|
|
43
|
+
document={document}
|
|
44
|
+
onRevokeSuccess={onRevokeSuccess}
|
|
45
|
+
{...rest}
|
|
46
|
+
/>
|
|
47
|
+
)
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
return <EditableSharingModal document={document} {...rest} />
|
|
@@ -28,6 +28,7 @@ const RecipientWaitingForConfirmationAlert = ({ recipientsToBeConfirmed }) => {
|
|
|
28
28
|
|
|
29
29
|
const WhoHasAccess = ({
|
|
30
30
|
isOwner = false,
|
|
31
|
+
canManageSharing = isOwner,
|
|
31
32
|
isSharedDrive = false,
|
|
32
33
|
isReadOnly = false,
|
|
33
34
|
showOwner = true,
|
|
@@ -70,6 +71,7 @@ const WhoHasAccess = ({
|
|
|
70
71
|
recipients={recipients}
|
|
71
72
|
recipientsToBeConfirmed={recipientsToBeConfirmed}
|
|
72
73
|
isOwner={isOwner}
|
|
74
|
+
canManageSharing={canManageSharing}
|
|
73
75
|
isSharedDrive={isSharedDrive}
|
|
74
76
|
isReadOnly={isReadOnly}
|
|
75
77
|
document={document}
|
|
@@ -86,6 +88,7 @@ const WhoHasAccess = ({
|
|
|
86
88
|
|
|
87
89
|
WhoHasAccess.propTypes = {
|
|
88
90
|
isOwner: PropTypes.bool,
|
|
91
|
+
canManageSharing: PropTypes.bool,
|
|
89
92
|
showOwner: PropTypes.bool,
|
|
90
93
|
recipients: PropTypes.array.isRequired,
|
|
91
94
|
recipientsToBeConfirmed: PropTypes.arrayOf(
|