cozy-sharing 37.5.4 → 37.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +3 -2
- package/dist/SharingProvider.js +270 -196
- package/dist/SharingProvider.spec.js +34 -4
- package/dist/components/FederatedFolder/FederatedFolderModal.js +61 -82
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +19 -8
- package/dist/components/ShareDialogCozyToCozy.js +21 -108
- package/dist/components/ShareModal/EditableSharingModal.js +44 -8
- package/dist/components/ShareModal/ShareModal.js +2 -2
- package/dist/components/ShareModal.js +2 -2
- package/dist/components/SharingContent.js +92 -0
- package/dist/helpers/effectiveRecipients.js +40 -0
- package/dist/helpers/effectiveRecipients.spec.js +134 -0
- package/dist/state.js +68 -1
- package/dist/state.spec.js +2 -1
- package/package.json +3 -3
- package/src/SharingProvider.jsx +61 -1
- package/src/SharingProvider.spec.jsx +28 -2
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +50 -65
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +16 -8
- package/src/components/ShareDialogCozyToCozy.jsx +1 -87
- package/src/components/ShareModal/EditableSharingModal.jsx +61 -8
- package/src/components/ShareModal/ShareModal.jsx +2 -2
- package/src/components/ShareModal.jsx +2 -2
- package/src/components/SharingContent.jsx +94 -0
- package/src/helpers/effectiveRecipients.js +34 -0
- package/src/helpers/effectiveRecipients.spec.js +125 -0
- package/src/state.js +52 -1
- package/src/state.spec.js +2 -1
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
|
-
var _excluded = ["document"]
|
|
3
|
+
var _excluded = ["document", "recipients"],
|
|
4
|
+
_excluded2 = ["document"];
|
|
4
5
|
import PropTypes from 'prop-types';
|
|
5
|
-
import React from 'react';
|
|
6
|
+
import React, { useEffect } from 'react';
|
|
6
7
|
import { useClient } from 'cozy-client';
|
|
8
|
+
import flag from 'cozy-flags';
|
|
9
|
+
import minilog from 'cozy-minilog';
|
|
7
10
|
import { useFetchDocumentPath } from '../../hooks/useFetchDocumentPath';
|
|
8
11
|
import { useSharingContext } from '../../hooks/useSharingContext';
|
|
9
12
|
import { Contact } from '../../models';
|
|
10
13
|
import { ShareModal } from '../ShareModal';
|
|
11
14
|
export var EditableSharingModal = function EditableSharingModal(_ref) {
|
|
12
15
|
var document = _ref.document,
|
|
16
|
+
recipients = _ref.recipients,
|
|
13
17
|
rest = _objectWithoutProperties(_ref, _excluded);
|
|
14
18
|
|
|
15
19
|
var client = useClient();
|
|
20
|
+
var isFederatedMode = flag('drive.federated-shared-folder.enabled');
|
|
16
21
|
var documentPath = useFetchDocumentPath(client, document);
|
|
17
22
|
|
|
18
23
|
var _useSharingContext = useSharingContext(),
|
|
19
24
|
documentType = _useSharingContext.documentType,
|
|
20
25
|
getDocumentPermissions = _useSharingContext.getDocumentPermissions,
|
|
21
|
-
getRecipients = _useSharingContext.getRecipients,
|
|
22
26
|
getSharingForSelf = _useSharingContext.getSharingForSelf,
|
|
23
27
|
getSharingLink = _useSharingContext.getSharingLink,
|
|
24
28
|
hasSharedChild = _useSharingContext.hasSharedChild,
|
|
@@ -34,19 +38,51 @@ export var EditableSharingModal = function EditableSharingModal(_ref) {
|
|
|
34
38
|
},
|
|
35
39
|
document: document,
|
|
36
40
|
documentType: documentType,
|
|
37
|
-
hasSharedChild: documentPath && hasSharedChild(documentPath),
|
|
38
|
-
hasSharedParent: documentPath && hasSharedParent(documentPath),
|
|
41
|
+
hasSharedChild: isFederatedMode ? undefined : documentPath && hasSharedChild(documentPath),
|
|
42
|
+
hasSharedParent: isFederatedMode ? undefined : documentPath && hasSharedParent(documentPath),
|
|
39
43
|
isOwner: isOwner(document._id),
|
|
40
44
|
link: getSharingLink(document._id),
|
|
41
45
|
onRevoke: revoke,
|
|
42
46
|
onRevokeSelf: revokeSelf,
|
|
43
47
|
onShare: share,
|
|
44
48
|
permissions: getDocumentPermissions(document._id),
|
|
45
|
-
recipients:
|
|
49
|
+
recipients: recipients,
|
|
46
50
|
sharing: getSharingForSelf(document._id)
|
|
47
51
|
}, rest));
|
|
48
52
|
};
|
|
49
53
|
EditableSharingModal.propTypes = {
|
|
50
|
-
document: PropTypes.object
|
|
54
|
+
document: PropTypes.object,
|
|
55
|
+
recipients: PropTypes.array
|
|
51
56
|
};
|
|
52
|
-
export
|
|
57
|
+
export var EditableSharingModalWrapper = function EditableSharingModalWrapper(_ref2) {
|
|
58
|
+
var document = _ref2.document,
|
|
59
|
+
rest = _objectWithoutProperties(_ref2, _excluded2);
|
|
60
|
+
|
|
61
|
+
var log = minilog('EditableSharingModal');
|
|
62
|
+
var isFederatedMode = flag('drive.federated-shared-folder.enabled');
|
|
63
|
+
|
|
64
|
+
var _useSharingContext2 = useSharingContext(),
|
|
65
|
+
getRecipients = _useSharingContext2.getRecipients,
|
|
66
|
+
getEffectiveRecipients = _useSharingContext2.getEffectiveRecipients,
|
|
67
|
+
fetchEffectiveRecipients = _useSharingContext2.fetchEffectiveRecipients,
|
|
68
|
+
invalidateEffectiveRecipients = _useSharingContext2.invalidateEffectiveRecipients;
|
|
69
|
+
|
|
70
|
+
var fileId = document._id || document.id;
|
|
71
|
+
useEffect(function () {
|
|
72
|
+
if (isFederatedMode && fileId) {
|
|
73
|
+
fetchEffectiveRecipients(fileId, document.driveId).catch(log.error);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return function () {
|
|
77
|
+
if (fileId) {
|
|
78
|
+
invalidateEffectiveRecipients(fileId);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}, [fileId, document.driveId, isFederatedMode, fetchEffectiveRecipients, invalidateEffectiveRecipients]);
|
|
82
|
+
var recipients = isFederatedMode ? getEffectiveRecipients(fileId) : getRecipients(fileId);
|
|
83
|
+
return /*#__PURE__*/React.createElement(EditableSharingModal, _extends({
|
|
84
|
+
document: document,
|
|
85
|
+
recipients: recipients
|
|
86
|
+
}, rest));
|
|
87
|
+
};
|
|
88
|
+
export default EditableSharingModalWrapper;
|
|
@@ -9,10 +9,10 @@ import React from 'react';
|
|
|
9
9
|
import { useLocation } from 'react-router';
|
|
10
10
|
import flag from 'cozy-flags';
|
|
11
11
|
import EditableSharingModal from './EditableSharingModal';
|
|
12
|
-
import
|
|
12
|
+
import SharingDetailsModal from './SharingDetailsModal';
|
|
13
13
|
import withLocales from '../../hoc/withLocales';
|
|
14
14
|
import { useSharingContext } from '../../hooks/useSharingContext';
|
|
15
|
-
import
|
|
15
|
+
import FederatedFolderModal from '../FederatedFolder/FederatedFolderModal';
|
|
16
16
|
export var ShareModal = withLocales(function (props) {
|
|
17
17
|
var _location$state;
|
|
18
18
|
|
|
@@ -64,7 +64,6 @@ export var ShareModal = function ShareModal(_ref) {
|
|
|
64
64
|
twoStepsConfirmationMethods: twoStepsConfirmationMethods
|
|
65
65
|
});
|
|
66
66
|
};
|
|
67
|
-
export default ShareModal;
|
|
68
67
|
ShareModal.propTypes = {
|
|
69
68
|
autoOpenShareRestriction: PropTypes.bool,
|
|
70
69
|
createContact: PropTypes.func.isRequired,
|
|
@@ -87,4 +86,5 @@ ShareModal.propTypes = {
|
|
|
87
86
|
rejectRecipient: PropTypes.func,
|
|
88
87
|
recipientConfirmationDialogContent: PropTypes.func
|
|
89
88
|
})
|
|
90
|
-
};
|
|
89
|
+
};
|
|
90
|
+
export default ShareModal;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import cx from 'classnames';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Typography from 'cozy-ui/transpiled/react/Typography';
|
|
4
|
+
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints';
|
|
5
|
+
import { useI18n } from 'twake-i18n';
|
|
6
|
+
import AntivirusAlert from './AntivirusAlert';
|
|
7
|
+
import { default as DumbShareByEmail } from './ShareByEmail';
|
|
8
|
+
import WhoHasAccess from './WhoHasAccess';
|
|
9
|
+
var styles = {
|
|
10
|
+
"share-modal-content": "share__share-modal-content___1iqEq",
|
|
11
|
+
"coz-form": "share__coz-form___1ICST",
|
|
12
|
+
"coz-form-group": "share__coz-form-group___VsQp7",
|
|
13
|
+
"coz-form-desc": "share__coz-form-desc___2mYN4",
|
|
14
|
+
"coz-form-label": "share__coz-form-label___bogBw",
|
|
15
|
+
"coz-form-label--error": "share__coz-form-label--error___3YPkf",
|
|
16
|
+
"coz-form-errors": "share__coz-form-errors___2xYRz",
|
|
17
|
+
"coz-form-controls": "share__coz-form-controls___H8kGc",
|
|
18
|
+
"coz-form-controls--full": "share__coz-form-controls--full___1oQXF",
|
|
19
|
+
"coz-form-controls--dispatch": "share__coz-form-controls--dispatch___1zIxt",
|
|
20
|
+
"error": "share__error___pwqPO",
|
|
21
|
+
"share-dialog-scrollable-content": "share__share-dialog-scrollable-content___2Xyoq",
|
|
22
|
+
"share-dialog-scrollable-body": "share__share-dialog-scrollable-body___2O5UT",
|
|
23
|
+
"share-dialog-members": "share__share-dialog-members___CNHKJ",
|
|
24
|
+
"share-byemail-onlybylink": "share__share-byemail-onlybylink___29W-t",
|
|
25
|
+
"aligned-dropdown-button": "share__aligned-dropdown-button___3crgG"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
var SharingContent = function SharingContent(_ref) {
|
|
29
|
+
var document = _ref.document,
|
|
30
|
+
documentType = _ref.documentType,
|
|
31
|
+
hasSharedParent = _ref.hasSharedParent,
|
|
32
|
+
isOwner = _ref.isOwner,
|
|
33
|
+
onRevoke = _ref.onRevoke,
|
|
34
|
+
onRevokeSelf = _ref.onRevokeSelf,
|
|
35
|
+
recipients = _ref.recipients,
|
|
36
|
+
sharing = _ref.sharing,
|
|
37
|
+
showShareByEmail = _ref.showShareByEmail,
|
|
38
|
+
showShareOnlyByLink = _ref.showShareOnlyByLink,
|
|
39
|
+
showWhoHasAccess = _ref.showWhoHasAccess,
|
|
40
|
+
recipientsToBeConfirmed = _ref.recipientsToBeConfirmed,
|
|
41
|
+
verifyRecipient = _ref.verifyRecipient,
|
|
42
|
+
link = _ref.link,
|
|
43
|
+
permissions = _ref.permissions,
|
|
44
|
+
pendingRecipients = _ref.pendingRecipients,
|
|
45
|
+
onPendingRecipientsChange = _ref.onPendingRecipientsChange,
|
|
46
|
+
selectedOption = _ref.selectedOption,
|
|
47
|
+
onSelectedOptionChange = _ref.onSelectedOptionChange;
|
|
48
|
+
|
|
49
|
+
var _useI18n = useI18n(),
|
|
50
|
+
t = _useI18n.t;
|
|
51
|
+
|
|
52
|
+
var _useBreakpoints = useBreakpoints(),
|
|
53
|
+
isMobile = _useBreakpoints.isMobile;
|
|
54
|
+
|
|
55
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
56
|
+
className: cx(styles['share-modal-content'])
|
|
57
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
58
|
+
className: cx('u-pt-1-half', isMobile ? 'u-ph-1' : 'u-ph-2')
|
|
59
|
+
}, /*#__PURE__*/React.createElement(AntivirusAlert, {
|
|
60
|
+
document: document
|
|
61
|
+
}), showShareOnlyByLink && /*#__PURE__*/React.createElement("div", {
|
|
62
|
+
className: styles['share-byemail-onlybylink']
|
|
63
|
+
}, t("".concat(documentType, ".share.shareByEmail.onlyByLink"), {
|
|
64
|
+
type: t("".concat(documentType, ".share.shareByEmail.type.").concat(document.type === 'directory' ? 'folder' : 'file'))
|
|
65
|
+
}), ' ', /*#__PURE__*/React.createElement("strong", null, t("".concat(documentType, ".share.shareByEmail.").concat(hasSharedParent ? 'hasSharedParent' : 'hasSharedChild')))), /*#__PURE__*/React.createElement(Typography, {
|
|
66
|
+
variant: "h6",
|
|
67
|
+
className: "u-mb-half"
|
|
68
|
+
}, t('Share.contacts.addUsers')), showShareByEmail && /*#__PURE__*/React.createElement(DumbShareByEmail, {
|
|
69
|
+
currentRecipients: recipients,
|
|
70
|
+
document: document,
|
|
71
|
+
documentType: documentType,
|
|
72
|
+
sharing: sharing,
|
|
73
|
+
pendingRecipients: pendingRecipients,
|
|
74
|
+
onPendingRecipientsChange: onPendingRecipientsChange,
|
|
75
|
+
selectedOption: selectedOption,
|
|
76
|
+
onSelectedOptionChange: onSelectedOptionChange,
|
|
77
|
+
enableCreateContact: true
|
|
78
|
+
})), showWhoHasAccess && /*#__PURE__*/React.createElement(WhoHasAccess, {
|
|
79
|
+
document: document,
|
|
80
|
+
documentType: documentType,
|
|
81
|
+
isOwner: isOwner,
|
|
82
|
+
onRevoke: onRevoke,
|
|
83
|
+
onRevokeSelf: onRevokeSelf,
|
|
84
|
+
recipients: recipients,
|
|
85
|
+
recipientsToBeConfirmed: recipientsToBeConfirmed,
|
|
86
|
+
verifyRecipient: verifyRecipient,
|
|
87
|
+
link: link,
|
|
88
|
+
permissions: permissions
|
|
89
|
+
}));
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default SharingContent;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pick the most relevant source for a recipient: prefer the target's own
|
|
3
|
+
* share ("self"), fall back to the first ancestor source.
|
|
4
|
+
* Needed because revoke/RO-RW actions target a specific sharing+member index.
|
|
5
|
+
*/
|
|
6
|
+
var getBestSource = function getBestSource(effectiveRecipient) {
|
|
7
|
+
var sources = effectiveRecipient.sources || [];
|
|
8
|
+
return sources.find(function (s) {
|
|
9
|
+
return s.kind === 'self';
|
|
10
|
+
}) || sources[0];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Build a view object for MemberRecipient/MemberRecipientPermissions.
|
|
14
|
+
* Extracts sharingId/memberIndex/avatarPath/type from the source so
|
|
15
|
+
* existing components work without reading sources[] directly.
|
|
16
|
+
* Does not spread the backend data — only the fields needed for rendering.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
var mapToRecipient = function mapToRecipient(effectiveRecipient, source) {
|
|
21
|
+
return {
|
|
22
|
+
name: effectiveRecipient.name,
|
|
23
|
+
email: effectiveRecipient.email,
|
|
24
|
+
instance: effectiveRecipient.instance,
|
|
25
|
+
status: effectiveRecipient.status,
|
|
26
|
+
read_only: effectiveRecipient.read_only,
|
|
27
|
+
index: "effective-".concat(source.sharing_id, "-").concat(source.member_index),
|
|
28
|
+
sharingId: source.sharing_id,
|
|
29
|
+
memberIndex: source.member_index,
|
|
30
|
+
avatarPath: "/sharings/".concat(source.sharing_id, "/recipients/").concat(source.member_index, "/avatar"),
|
|
31
|
+
type: effectiveRecipient.read_only ? 'one-way' : 'two-way'
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export var mapEffectiveRecipients = function mapEffectiveRecipients(effectiveRecipients) {
|
|
36
|
+
return (effectiveRecipients || []).map(function (recipient) {
|
|
37
|
+
var source = getBestSource(recipient);
|
|
38
|
+
return source ? mapToRecipient(recipient, source) : recipient;
|
|
39
|
+
});
|
|
40
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
|
|
3
|
+
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; }
|
|
4
|
+
|
|
5
|
+
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; }
|
|
6
|
+
|
|
7
|
+
import { mapEffectiveRecipients } from './effectiveRecipients';
|
|
8
|
+
|
|
9
|
+
var makeAncestorSource = function makeAncestorSource() {
|
|
10
|
+
var rootName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Parent Folder';
|
|
11
|
+
return {
|
|
12
|
+
sharing_id: 'sharing-1',
|
|
13
|
+
root_id: 'root-1',
|
|
14
|
+
root_name: rootName,
|
|
15
|
+
kind: 'ancestor',
|
|
16
|
+
member_index: 1,
|
|
17
|
+
read_only: false,
|
|
18
|
+
manageable: false
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
var makeSelfSource = function makeSelfSource() {
|
|
23
|
+
var _opts$memberIndex, _opts$readOnly, _opts$manageable;
|
|
24
|
+
|
|
25
|
+
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
26
|
+
return {
|
|
27
|
+
sharing_id: opts.sharing_id || 'sharing-2',
|
|
28
|
+
root_id: 'root-2',
|
|
29
|
+
root_name: 'Child Folder',
|
|
30
|
+
kind: 'self',
|
|
31
|
+
member_index: (_opts$memberIndex = opts.memberIndex) !== null && _opts$memberIndex !== void 0 ? _opts$memberIndex : 1,
|
|
32
|
+
read_only: (_opts$readOnly = opts.readOnly) !== null && _opts$readOnly !== void 0 ? _opts$readOnly : false,
|
|
33
|
+
manageable: (_opts$manageable = opts.manageable) !== null && _opts$manageable !== void 0 ? _opts$manageable : true
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
var makeRecipient = function makeRecipient() {
|
|
38
|
+
var overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
39
|
+
return _objectSpread({
|
|
40
|
+
id: 'recip-1',
|
|
41
|
+
name: 'Alice',
|
|
42
|
+
email: 'alice@example.com',
|
|
43
|
+
instance: 'https://alice.mycozy.cloud',
|
|
44
|
+
status: 'ready',
|
|
45
|
+
read_only: false,
|
|
46
|
+
can_edit_here: false,
|
|
47
|
+
sources: overrides.sources || []
|
|
48
|
+
}, overrides);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
describe('mapEffectiveRecipients', function () {
|
|
52
|
+
it('returns empty array for empty input', function () {
|
|
53
|
+
expect(mapEffectiveRecipients([])).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
it('returns empty array for null or undefined', function () {
|
|
56
|
+
expect(mapEffectiveRecipients(null)).toEqual([]);
|
|
57
|
+
expect(mapEffectiveRecipients(undefined)).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
it('maps a recipient with a self source using the self source', function () {
|
|
60
|
+
var recipient = makeRecipient({
|
|
61
|
+
sources: [makeSelfSource()]
|
|
62
|
+
});
|
|
63
|
+
var result = mapEffectiveRecipients([recipient]);
|
|
64
|
+
expect(result).toHaveLength(1);
|
|
65
|
+
expect(result[0].sharingId).toBe('sharing-2');
|
|
66
|
+
expect(result[0].memberIndex).toBe(1);
|
|
67
|
+
expect(result[0].avatarPath).toBe('/sharings/sharing-2/recipients/1/avatar');
|
|
68
|
+
expect(result[0].type).toBe('two-way');
|
|
69
|
+
});
|
|
70
|
+
it('maps a recipient with only ancestor sources using the ancestor source', function () {
|
|
71
|
+
var recipient = makeRecipient({
|
|
72
|
+
sources: [makeAncestorSource('Shared Parent')]
|
|
73
|
+
});
|
|
74
|
+
var result = mapEffectiveRecipients([recipient]);
|
|
75
|
+
expect(result).toHaveLength(1);
|
|
76
|
+
expect(result[0].sharingId).toBe('sharing-1');
|
|
77
|
+
expect(result[0].memberIndex).toBe(1);
|
|
78
|
+
expect(result[0].name).toBe('Alice');
|
|
79
|
+
expect(result[0].email).toBe('alice@example.com');
|
|
80
|
+
});
|
|
81
|
+
it('maps an owner (self source, index 0) correctly', function () {
|
|
82
|
+
var recipient = makeRecipient({
|
|
83
|
+
status: 'owner',
|
|
84
|
+
read_only: true,
|
|
85
|
+
sources: [makeSelfSource({
|
|
86
|
+
memberIndex: 0,
|
|
87
|
+
manageable: false
|
|
88
|
+
})]
|
|
89
|
+
});
|
|
90
|
+
var result = mapEffectiveRecipients([recipient]);
|
|
91
|
+
expect(result).toHaveLength(1);
|
|
92
|
+
expect(result[0].status).toBe('owner');
|
|
93
|
+
expect(result[0].type).toBe('one-way');
|
|
94
|
+
});
|
|
95
|
+
it('maps an owner with only ancestor sources correctly', function () {
|
|
96
|
+
var recipient = makeRecipient({
|
|
97
|
+
status: 'owner',
|
|
98
|
+
sources: [makeAncestorSource('Parent Folder')]
|
|
99
|
+
});
|
|
100
|
+
var result = mapEffectiveRecipients([recipient]);
|
|
101
|
+
expect(result).toHaveLength(1);
|
|
102
|
+
expect(result[0].status).toBe('owner');
|
|
103
|
+
expect(result[0].sharingId).toBe('sharing-1');
|
|
104
|
+
expect(result[0].memberIndex).toBe(1);
|
|
105
|
+
});
|
|
106
|
+
it('sets type to one-way for read_only recipients', function () {
|
|
107
|
+
var recipient = makeRecipient({
|
|
108
|
+
read_only: true,
|
|
109
|
+
sources: [makeSelfSource({
|
|
110
|
+
readOnly: true
|
|
111
|
+
})]
|
|
112
|
+
});
|
|
113
|
+
var result = mapEffectiveRecipients([recipient]);
|
|
114
|
+
expect(result[0].type).toBe('one-way');
|
|
115
|
+
});
|
|
116
|
+
it('handles all recipients in the same array regardless of source kind', function () {
|
|
117
|
+
var selfRecipient = makeRecipient({
|
|
118
|
+
id: 'self-1',
|
|
119
|
+
name: 'Bob',
|
|
120
|
+
email: 'bob@example.com',
|
|
121
|
+
sources: [makeSelfSource()]
|
|
122
|
+
});
|
|
123
|
+
var ancestorRecipient = makeRecipient({
|
|
124
|
+
id: 'ancestor-1',
|
|
125
|
+
name: 'Carol',
|
|
126
|
+
email: 'carol@example.com',
|
|
127
|
+
sources: [makeAncestorSource('Root Folder')]
|
|
128
|
+
});
|
|
129
|
+
var result = mapEffectiveRecipients([selfRecipient, ancestorRecipient]);
|
|
130
|
+
expect(result).toHaveLength(2);
|
|
131
|
+
expect(result[0].sharingId).toBe('sharing-2');
|
|
132
|
+
expect(result[1].sharingId).toBe('sharing-1');
|
|
133
|
+
});
|
|
134
|
+
});
|
package/dist/state.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
1
2
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
3
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
4
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
@@ -23,6 +24,9 @@ var ADD_SHARING_LINK = 'ADD_SHARING_LINK';
|
|
|
23
24
|
var UPDATE_SHARING_LINK = 'UPDATE_SHARING_LINK';
|
|
24
25
|
var REVOKE_SHARING_LINK = 'REVOKE_SHARING_LINK';
|
|
25
26
|
var RECEIVE_PATHS = 'RECEIVE_PATHS';
|
|
27
|
+
var RECEIVE_EFFECTIVE_RECIPIENTS = 'RECEIVE_EFFECTIVE_RECIPIENTS';
|
|
28
|
+
var UPDATE_EFFECTIVE_RECIPIENT = 'UPDATE_EFFECTIVE_RECIPIENT';
|
|
29
|
+
var INVALIDATE_EFFECTIVE_RECIPIENTS = 'INVALIDATE_EFFECTIVE_RECIPIENTS';
|
|
26
30
|
export var SHARING_TYPE = {
|
|
27
31
|
TWO_WAY: 'two-way',
|
|
28
32
|
ONE_WAY: 'one-way'
|
|
@@ -136,6 +140,27 @@ export var receivePaths = function receivePaths(paths) {
|
|
|
136
140
|
paths: paths
|
|
137
141
|
};
|
|
138
142
|
};
|
|
143
|
+
export var receiveEffectiveRecipients = function receiveEffectiveRecipients(docId, recipients) {
|
|
144
|
+
return {
|
|
145
|
+
type: RECEIVE_EFFECTIVE_RECIPIENTS,
|
|
146
|
+
docId: docId,
|
|
147
|
+
recipients: recipients
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
export var updateEffectiveRecipient = function updateEffectiveRecipient(sharingId, memberIndex, readOnly) {
|
|
151
|
+
return {
|
|
152
|
+
type: UPDATE_EFFECTIVE_RECIPIENT,
|
|
153
|
+
sharingId: sharingId,
|
|
154
|
+
memberIndex: memberIndex,
|
|
155
|
+
readOnly: readOnly
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
export var invalidateEffectiveRecipients = function invalidateEffectiveRecipients(docId) {
|
|
159
|
+
return {
|
|
160
|
+
type: INVALIDATE_EFFECTIVE_RECIPIENTS,
|
|
161
|
+
docId: docId
|
|
162
|
+
};
|
|
163
|
+
};
|
|
139
164
|
export var matchingInstanceName = function matchingInstanceName() {
|
|
140
165
|
var instanceUri = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
141
166
|
return function (shareMember) {
|
|
@@ -373,6 +398,42 @@ var sharedPaths = function sharedPaths() {
|
|
|
373
398
|
}
|
|
374
399
|
};
|
|
375
400
|
|
|
401
|
+
var effectiveRecipients = function effectiveRecipients() {
|
|
402
|
+
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
403
|
+
var action = arguments.length > 1 ? arguments[1] : undefined;
|
|
404
|
+
|
|
405
|
+
switch (action.type) {
|
|
406
|
+
case RECEIVE_EFFECTIVE_RECIPIENTS:
|
|
407
|
+
return _objectSpread(_objectSpread({}, state), {}, _defineProperty({}, action.docId, action.recipients));
|
|
408
|
+
|
|
409
|
+
case UPDATE_EFFECTIVE_RECIPIENT:
|
|
410
|
+
return Object.fromEntries(Object.entries(state).map(function (_ref2) {
|
|
411
|
+
var _ref3 = _slicedToArray(_ref2, 2),
|
|
412
|
+
docId = _ref3[0],
|
|
413
|
+
recipients = _ref3[1];
|
|
414
|
+
|
|
415
|
+
return [docId, recipients.map(function (r) {
|
|
416
|
+
return r.sharingId === action.sharingId && r.memberIndex === action.memberIndex ? _objectSpread(_objectSpread({}, r), {}, {
|
|
417
|
+
read_only: action.readOnly,
|
|
418
|
+
type: action.readOnly ? 'one-way' : 'two-way'
|
|
419
|
+
}) : r;
|
|
420
|
+
})];
|
|
421
|
+
}));
|
|
422
|
+
|
|
423
|
+
case INVALIDATE_EFFECTIVE_RECIPIENTS:
|
|
424
|
+
{
|
|
425
|
+
var _action$docId2 = action.docId,
|
|
426
|
+
_ = state[_action$docId2],
|
|
427
|
+
rest = _objectWithoutProperties(state, [_action$docId2].map(_toPropertyKey));
|
|
428
|
+
|
|
429
|
+
return rest;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
default:
|
|
433
|
+
return state;
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
|
|
376
437
|
var reducer = function reducer() {
|
|
377
438
|
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
378
439
|
var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -380,7 +441,8 @@ var reducer = function reducer() {
|
|
|
380
441
|
byDocId: byDocId(state.byDocId, action),
|
|
381
442
|
sharings: sharings(state.sharings, action),
|
|
382
443
|
permissions: permissions(state.permissions, action),
|
|
383
|
-
sharedPaths: sharedPaths(state.sharedPaths, action)
|
|
444
|
+
sharedPaths: sharedPaths(state.sharedPaths, action),
|
|
445
|
+
effectiveRecipients: effectiveRecipients(state.effectiveRecipients, action)
|
|
384
446
|
};
|
|
385
447
|
};
|
|
386
448
|
|
|
@@ -643,6 +705,11 @@ export var getSharedParentPath = function getSharedParentPath(state, documentPat
|
|
|
643
705
|
}
|
|
644
706
|
|
|
645
707
|
return null;
|
|
708
|
+
};
|
|
709
|
+
export var getEffectiveRecipients = function getEffectiveRecipients(state, docId) {
|
|
710
|
+
var _state$effectiveRecip;
|
|
711
|
+
|
|
712
|
+
return ((_state$effectiveRecip = state.effectiveRecipients) === null || _state$effectiveRecip === void 0 ? void 0 : _state$effectiveRecip[docId]) || [];
|
|
646
713
|
}; // helpers
|
|
647
714
|
|
|
648
715
|
export var getSharedDocIds = function getSharedDocIds(doc) {
|
package/dist/state.spec.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "37.
|
|
3
|
+
"version": "37.6.0",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"cozy-intent": "^2.31.1",
|
|
60
60
|
"cozy-minilog": "^3.10.1",
|
|
61
61
|
"cozy-ui": "^140.5.0",
|
|
62
|
-
"cozy-ui-plus": "^12.3.
|
|
62
|
+
"cozy-ui-plus": "^12.3.15",
|
|
63
63
|
"jest": "30.3.0",
|
|
64
64
|
"jest-environment-jsdom": "30.3.0",
|
|
65
65
|
"react": "16.12.0",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"sideEffects": [
|
|
86
86
|
"*.css"
|
|
87
87
|
],
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "aa6c91c03a8b734177fddb3075aa26110516c218"
|
|
89
89
|
}
|
package/src/SharingProvider.jsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from './components/ShareRestrictionModal/helpers'
|
|
10
10
|
import SharingContext from './context'
|
|
11
11
|
import { fetchNextPermissions } from './fetchNextPermissions'
|
|
12
|
+
import { mapEffectiveRecipients } from './helpers/effectiveRecipients'
|
|
12
13
|
import { fetchFilesPaths } from './helpers/files'
|
|
13
14
|
import {
|
|
14
15
|
getSharingObject,
|
|
@@ -28,6 +29,10 @@ import reducer, {
|
|
|
28
29
|
revokeGroup as revokeGroupFromState,
|
|
29
30
|
revokeSelf,
|
|
30
31
|
receivePaths,
|
|
32
|
+
receiveEffectiveRecipients,
|
|
33
|
+
updateEffectiveRecipient,
|
|
34
|
+
invalidateEffectiveRecipients,
|
|
35
|
+
getEffectiveRecipients,
|
|
31
36
|
isOwner,
|
|
32
37
|
isSharedDrive,
|
|
33
38
|
isOrgSharedDrive,
|
|
@@ -109,7 +114,11 @@ export class SharingProvider extends Component {
|
|
|
109
114
|
refresh: this.fetchAllSharings,
|
|
110
115
|
hasWriteAccess: this.hasWriteAccess,
|
|
111
116
|
renameSharedDrive: this.renameSharedDrive,
|
|
112
|
-
updateSharingMemberType: this.updateSharingMemberType
|
|
117
|
+
updateSharingMemberType: this.updateSharingMemberType,
|
|
118
|
+
getEffectiveRecipients: docId =>
|
|
119
|
+
getEffectiveRecipients(this.state, docId),
|
|
120
|
+
fetchEffectiveRecipients: this.fetchEffectiveRecipients,
|
|
121
|
+
invalidateEffectiveRecipients: this.invalidateEffectiveRecipients
|
|
113
122
|
}
|
|
114
123
|
this.isPublic = props.isPublic ?? false
|
|
115
124
|
this.realtime = null
|
|
@@ -261,6 +270,11 @@ export class SharingProvider extends Component {
|
|
|
261
270
|
|
|
262
271
|
await this.state.onShared({ document, recipients, readOnlyRecipients })
|
|
263
272
|
|
|
273
|
+
await this.fetchEffectiveRecipients(
|
|
274
|
+
getDocumentId(document),
|
|
275
|
+
document.driveId
|
|
276
|
+
)
|
|
277
|
+
|
|
264
278
|
return sharingResult
|
|
265
279
|
}
|
|
266
280
|
|
|
@@ -284,6 +298,10 @@ export class SharingProvider extends Component {
|
|
|
284
298
|
)
|
|
285
299
|
|
|
286
300
|
await this.state.onShared({ document, recipients, readOnlyRecipients })
|
|
301
|
+
await this.fetchEffectiveRecipients(
|
|
302
|
+
getDocumentId(document),
|
|
303
|
+
document.driveId
|
|
304
|
+
)
|
|
287
305
|
return data
|
|
288
306
|
}
|
|
289
307
|
|
|
@@ -318,6 +336,10 @@ export class SharingProvider extends Component {
|
|
|
318
336
|
)
|
|
319
337
|
)
|
|
320
338
|
})
|
|
339
|
+
await this.fetchEffectiveRecipients(
|
|
340
|
+
getDocumentId(document),
|
|
341
|
+
document.driveId
|
|
342
|
+
)
|
|
321
343
|
}
|
|
322
344
|
|
|
323
345
|
revoke = async (document, sharingId, recipientIndex) => {
|
|
@@ -331,6 +353,10 @@ export class SharingProvider extends Component {
|
|
|
331
353
|
document.path || (await fetchFilesPaths(client, doctype, [document]))
|
|
332
354
|
)
|
|
333
355
|
)
|
|
356
|
+
await this.fetchEffectiveRecipients(
|
|
357
|
+
getDocumentId(document),
|
|
358
|
+
document.driveId
|
|
359
|
+
)
|
|
334
360
|
}
|
|
335
361
|
|
|
336
362
|
revokeGroup = async (document, sharingId, recipientIndex) => {
|
|
@@ -350,6 +376,10 @@ export class SharingProvider extends Component {
|
|
|
350
376
|
const sharing = getSharingForSelf(this.state, document.id)
|
|
351
377
|
await this.sharingCol.revokeSelf(sharing)
|
|
352
378
|
this.dispatch(revokeSelf(sharing))
|
|
379
|
+
await this.fetchEffectiveRecipients(
|
|
380
|
+
getDocumentId(document),
|
|
381
|
+
document.driveId
|
|
382
|
+
)
|
|
353
383
|
}
|
|
354
384
|
|
|
355
385
|
/**
|
|
@@ -386,6 +416,9 @@ export class SharingProvider extends Component {
|
|
|
386
416
|
}
|
|
387
417
|
|
|
388
418
|
this.dispatch(updateSharing(optimisticSharing))
|
|
419
|
+
this.dispatch(
|
|
420
|
+
updateEffectiveRecipient(sharingId, memberIndex, makeReadOnly)
|
|
421
|
+
)
|
|
389
422
|
|
|
390
423
|
try {
|
|
391
424
|
if (makeReadOnly) {
|
|
@@ -411,12 +444,39 @@ export class SharingProvider extends Component {
|
|
|
411
444
|
}
|
|
412
445
|
|
|
413
446
|
this.dispatch(updateSharing(rollbackSharing))
|
|
447
|
+
this.dispatch(
|
|
448
|
+
updateEffectiveRecipient(sharingId, memberIndex, !makeReadOnly)
|
|
449
|
+
)
|
|
414
450
|
log.error(
|
|
415
451
|
`Failed to change member ${member.email} permission type to ${newType}`,
|
|
416
452
|
error
|
|
417
453
|
)
|
|
418
454
|
throw error
|
|
419
455
|
}
|
|
456
|
+
|
|
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
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
fetchEffectiveRecipients = async (fileId, driveId) => {
|
|
467
|
+
const resp = await this.sharingCol.fetchEffectiveRecipients(fileId, {
|
|
468
|
+
driveId
|
|
469
|
+
})
|
|
470
|
+
this.dispatch(
|
|
471
|
+
receiveEffectiveRecipients(
|
|
472
|
+
fileId,
|
|
473
|
+
mapEffectiveRecipients(resp?.data || [])
|
|
474
|
+
)
|
|
475
|
+
)
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
invalidateEffectiveRecipients = docId => {
|
|
479
|
+
this.dispatch(invalidateEffectiveRecipients(docId))
|
|
420
480
|
}
|
|
421
481
|
|
|
422
482
|
shareByLink = async (document, options) => {
|