cozy-sharing 40.1.6 → 40.1.7
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 +4 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +10 -12
- package/dist/components/Recipient/DowngradePermissionConfirmDialog.js +3 -12
- package/dist/components/Recipient/GroupRecipient.js +1 -4
- package/dist/components/Recipient/GroupRecipient.stories.js +3 -1
- package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +1 -4
- package/dist/components/Recipient/GroupRecipientPermissions.js +5 -8
- package/dist/components/Recipient/GroupRecipientPermissions.stories.js +2 -0
- package/dist/components/Recipient/LinkRecipient.js +2 -6
- package/dist/components/Recipient/LinkRecipient.stories.js +4 -0
- package/dist/components/Recipient/LinkRecipientPermissions.js +13 -12
- package/dist/components/Recipient/LinkRecipientPermissions.stories.js +5 -1
- package/dist/components/Recipient/MemberRecipient.js +7 -6
- package/dist/components/Recipient/MemberRecipient.spec.js +7 -12
- package/dist/components/Recipient/MemberRecipientPermissions.js +28 -13
- package/dist/components/Recipient/MemberRecipientPermissions.spec.js +5 -14
- package/dist/components/Recipient/MemberRecipientPermissions.stories.js +2 -1
- package/dist/components/Recipient/OwnerRecipient.js +4 -17
- package/dist/components/Recipient/OwnerRecipient.stories.js +3 -1
- package/dist/components/Recipient/OwnerRecipientDefaultLite.js +1 -1
- package/dist/components/Recipient/PermissionTypeMenu.js +32 -155
- package/dist/components/Recipient/PermissionTypeMenuWrapper.js +37 -0
- package/dist/components/Recipient/{PermissionTypeMenu.spec.js → PermissionTypeMenuWrapper.spec.js} +2 -2
- package/dist/components/Recipient/RecipientList.js +10 -0
- package/dist/components/Recipient/RecipientList.stories.js +3 -0
- package/dist/components/ShareDialogCozyToCozy.js +20 -19
- package/dist/components/ShareDialogCozyToCozy.spec.js +3 -0
- package/dist/components/ShareDialogOnlyByLink.js +3 -5
- package/dist/components/ShareDialogOnlyByLink.spec.js +0 -1
- package/dist/components/ShareModal/SharingDetailsModal.js +2 -2
- package/dist/components/SharedDrive/EditSharedDriveModal.js +11 -10
- package/dist/components/SharedDrive/useSharedDrive.js +8 -11
- package/dist/components/SharingContent.js +3 -5
- package/dist/components/WhoHasAccess.js +27 -11
- package/dist/components/WhoHasAccessWrapper.js +122 -0
- package/dist/helpers/recipients.js +46 -0
- package/dist/helpers/recipients.spec.js +89 -0
- package/dist/hooks/useMemberPermissionType.js +191 -0
- package/dist/hooks/useResolveRecipients.js +53 -0
- package/dist/hooks/useResolveRecipients.spec.js +140 -0
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +6 -12
- package/src/components/Recipient/DowngradePermissionConfirmDialog.jsx +3 -10
- package/src/components/Recipient/GroupRecipient.jsx +1 -5
- package/src/components/Recipient/GroupRecipient.stories.jsx +3 -1
- package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +1 -4
- package/src/components/Recipient/GroupRecipientPermissions.jsx +5 -5
- package/src/components/Recipient/GroupRecipientPermissions.stories.jsx +2 -0
- package/src/components/Recipient/LinkRecipient.jsx +2 -4
- package/src/components/Recipient/LinkRecipient.stories.jsx +4 -0
- package/src/components/Recipient/LinkRecipientPermissions.jsx +16 -12
- package/src/components/Recipient/LinkRecipientPermissions.stories.jsx +5 -1
- package/src/components/Recipient/MemberRecipient.jsx +4 -4
- package/src/components/Recipient/MemberRecipient.spec.jsx +7 -10
- package/src/components/Recipient/MemberRecipientPermissions.jsx +29 -13
- package/src/components/Recipient/MemberRecipientPermissions.spec.jsx +5 -11
- package/src/components/Recipient/MemberRecipientPermissions.stories.jsx +2 -1
- package/src/components/Recipient/OwnerRecipient.jsx +4 -17
- package/src/components/Recipient/OwnerRecipient.stories.jsx +1 -1
- package/src/components/Recipient/OwnerRecipientDefaultLite.jsx +1 -1
- package/src/components/Recipient/PermissionTypeMenu.jsx +21 -81
- package/src/components/Recipient/PermissionTypeMenuWrapper.jsx +32 -0
- package/src/components/Recipient/{PermissionTypeMenu.spec.jsx → PermissionTypeMenuWrapper.spec.jsx} +2 -2
- package/src/components/Recipient/RecipientList.jsx +10 -0
- package/src/components/Recipient/RecipientList.stories.jsx +3 -0
- package/src/components/ShareDialogCozyToCozy.jsx +10 -11
- package/src/components/ShareDialogCozyToCozy.spec.jsx +1 -0
- package/src/components/ShareDialogOnlyByLink.jsx +2 -4
- package/src/components/ShareDialogOnlyByLink.spec.jsx +0 -1
- package/src/components/ShareModal/SharingDetailsModal.jsx +2 -2
- package/src/components/SharedDrive/EditSharedDriveModal.jsx +6 -11
- package/src/components/SharedDrive/useSharedDrive.js +4 -11
- package/src/components/SharingContent.jsx +2 -4
- package/src/components/WhoHasAccess.jsx +26 -12
- package/src/components/WhoHasAccessWrapper.jsx +117 -0
- package/src/helpers/recipients.js +44 -0
- package/src/helpers/recipients.spec.js +82 -0
- package/src/hooks/useMemberPermissionType.js +110 -0
- package/src/hooks/useResolveRecipients.js +38 -0
- package/src/hooks/useResolveRecipients.spec.js +70 -0
- package/src/index.jsx +1 -1
- package/dist/components/Recipient/OwnerRecipientDefault.js +0 -27
- package/dist/components/Recipient/OwnerRecipientDefault.stories.js +0 -10
- package/src/components/Recipient/OwnerRecipientDefault.jsx +0 -37
- package/src/components/Recipient/OwnerRecipientDefault.stories.jsx +0 -13
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
4
|
+
|
|
5
|
+
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
|
+
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
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
10
|
+
|
|
11
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
12
|
+
|
|
13
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
14
|
+
|
|
15
|
+
import { useCallback } from 'react';
|
|
16
|
+
import { useClient } from 'cozy-client';
|
|
17
|
+
import flag from 'cozy-flags';
|
|
18
|
+
import { useFetchDocumentPath } from './useFetchDocumentPath';
|
|
19
|
+
import { useResolveRecipients } from './useResolveRecipients';
|
|
20
|
+
import { useSharingContext } from './useSharingContext';
|
|
21
|
+
import { getSharingDocIds } from '../state';
|
|
22
|
+
/**
|
|
23
|
+
* Gives what is needed to change the permission type of the members
|
|
24
|
+
* of a document's sharing
|
|
25
|
+
*
|
|
26
|
+
* @param {object} document - Shared document
|
|
27
|
+
* @param {object} [options]
|
|
28
|
+
* @param {boolean} [options.shouldFetchPath] - Whether to fetch the document
|
|
29
|
+
* path, needed to know the shared parent
|
|
30
|
+
* @returns {{ isInsideSharedParent: boolean, sharedParentName: string|null, setMemberType: Function }}
|
|
31
|
+
* `setMemberType({ sharingId, memberIndex, type, recipient }, newType, { withAncestors })`
|
|
32
|
+
* also downgrades the member on the read-write ancestor sharings when `withAncestors` is set
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
export var useMemberPermissionType = function useMemberPermissionType(document) {
|
|
36
|
+
var _sharedParentPath$spl;
|
|
37
|
+
|
|
38
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
39
|
+
_ref$shouldFetchPath = _ref.shouldFetchPath,
|
|
40
|
+
shouldFetchPath = _ref$shouldFetchPath === void 0 ? true : _ref$shouldFetchPath;
|
|
41
|
+
|
|
42
|
+
var client = useClient();
|
|
43
|
+
|
|
44
|
+
var _useSharingContext = useSharingContext(),
|
|
45
|
+
hasSharedParent = _useSharingContext.hasSharedParent,
|
|
46
|
+
getSharedParentPath = _useSharingContext.getSharedParentPath,
|
|
47
|
+
updateSharingMemberType = _useSharingContext.updateSharingMemberType,
|
|
48
|
+
getSharingById = _useSharingContext.getSharingById,
|
|
49
|
+
share = _useSharingContext.share;
|
|
50
|
+
|
|
51
|
+
var resolveRecipients = useResolveRecipients();
|
|
52
|
+
var documentPath = useFetchDocumentPath(client, shouldFetchPath ? document : null);
|
|
53
|
+
var isInsideSharedParent = Boolean(documentPath) && Boolean(hasSharedParent === null || hasSharedParent === void 0 ? void 0 : hasSharedParent(documentPath));
|
|
54
|
+
var sharedParentPath = documentPath ? getSharedParentPath === null || getSharedParentPath === void 0 ? void 0 : getSharedParentPath(documentPath) : null;
|
|
55
|
+
var setMemberType = useCallback( /*#__PURE__*/function () {
|
|
56
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref2, newType) {
|
|
57
|
+
var sharingId,
|
|
58
|
+
memberIndex,
|
|
59
|
+
type,
|
|
60
|
+
recipient,
|
|
61
|
+
_ref4,
|
|
62
|
+
_ref4$withAncestors,
|
|
63
|
+
withAncestors,
|
|
64
|
+
ancestors,
|
|
65
|
+
_iterator,
|
|
66
|
+
_step,
|
|
67
|
+
ancestor,
|
|
68
|
+
documentId,
|
|
69
|
+
sourceSharing,
|
|
70
|
+
_yield$resolveRecipie2,
|
|
71
|
+
recipients,
|
|
72
|
+
_args = arguments;
|
|
73
|
+
|
|
74
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
75
|
+
while (1) switch (_context.prev = _context.next) {
|
|
76
|
+
case 0:
|
|
77
|
+
sharingId = _ref2.sharingId, memberIndex = _ref2.memberIndex, type = _ref2.type, recipient = _ref2.recipient;
|
|
78
|
+
_ref4 = _args.length > 2 && _args[2] !== undefined ? _args[2] : {}, _ref4$withAncestors = _ref4.withAncestors, withAncestors = _ref4$withAncestors === void 0 ? false : _ref4$withAncestors;
|
|
79
|
+
|
|
80
|
+
if (!withAncestors) {
|
|
81
|
+
_context.next = 21;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Ancestors first: only the target's own update refetches its
|
|
86
|
+
// effective recipients, which must already see them downgraded.
|
|
87
|
+
ancestors = ((recipient === null || recipient === void 0 ? void 0 : recipient.sources) || []).filter(function (s) {
|
|
88
|
+
return s.kind === 'ancestor' && !s.read_only;
|
|
89
|
+
});
|
|
90
|
+
_iterator = _createForOfIteratorHelper(ancestors);
|
|
91
|
+
_context.prev = 5;
|
|
92
|
+
|
|
93
|
+
_iterator.s();
|
|
94
|
+
|
|
95
|
+
case 7:
|
|
96
|
+
if ((_step = _iterator.n()).done) {
|
|
97
|
+
_context.next = 13;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
ancestor = _step.value;
|
|
102
|
+
_context.next = 11;
|
|
103
|
+
return updateSharingMemberType(ancestor.sharing_id, ancestor.member_index, newType);
|
|
104
|
+
|
|
105
|
+
case 11:
|
|
106
|
+
_context.next = 7;
|
|
107
|
+
break;
|
|
108
|
+
|
|
109
|
+
case 13:
|
|
110
|
+
_context.next = 18;
|
|
111
|
+
break;
|
|
112
|
+
|
|
113
|
+
case 15:
|
|
114
|
+
_context.prev = 15;
|
|
115
|
+
_context.t0 = _context["catch"](5);
|
|
116
|
+
|
|
117
|
+
_iterator.e(_context.t0);
|
|
118
|
+
|
|
119
|
+
case 18:
|
|
120
|
+
_context.prev = 18;
|
|
121
|
+
|
|
122
|
+
_iterator.f();
|
|
123
|
+
|
|
124
|
+
return _context.finish(18);
|
|
125
|
+
|
|
126
|
+
case 21:
|
|
127
|
+
documentId = (document === null || document === void 0 ? void 0 : document._id) || (document === null || document === void 0 ? void 0 : document.id);
|
|
128
|
+
|
|
129
|
+
if (!(flag('drive.federated-shared-folder.enabled') && type === 'one-way' && newType === 'two-way' && documentId)) {
|
|
130
|
+
_context.next = 34;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
sourceSharing = getSharingById(sharingId);
|
|
135
|
+
|
|
136
|
+
if (!(sourceSharing && !getSharingDocIds(sourceSharing).includes(documentId))) {
|
|
137
|
+
_context.next = 34;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
_context.next = 27;
|
|
142
|
+
return resolveRecipients([recipient]);
|
|
143
|
+
|
|
144
|
+
case 27:
|
|
145
|
+
_yield$resolveRecipie2 = _context.sent;
|
|
146
|
+
recipients = _yield$resolveRecipie2.recipients;
|
|
147
|
+
|
|
148
|
+
if (recipients[0]) {
|
|
149
|
+
_context.next = 31;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
throw new Error('Recipient contact not found');
|
|
154
|
+
|
|
155
|
+
case 31:
|
|
156
|
+
_context.next = 33;
|
|
157
|
+
return share({
|
|
158
|
+
document: _objectSpread(_objectSpread({}, document), {}, {
|
|
159
|
+
id: documentId
|
|
160
|
+
}),
|
|
161
|
+
description: document.name,
|
|
162
|
+
recipients: recipients,
|
|
163
|
+
readOnlyRecipients: [],
|
|
164
|
+
sharedDrive: true,
|
|
165
|
+
openSharing: false
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
case 33:
|
|
169
|
+
return _context.abrupt("return");
|
|
170
|
+
|
|
171
|
+
case 34:
|
|
172
|
+
_context.next = 36;
|
|
173
|
+
return updateSharingMemberType(sharingId, memberIndex, newType, document);
|
|
174
|
+
|
|
175
|
+
case 36:
|
|
176
|
+
case "end":
|
|
177
|
+
return _context.stop();
|
|
178
|
+
}
|
|
179
|
+
}, _callee, null, [[5, 15, 18, 21]]);
|
|
180
|
+
}));
|
|
181
|
+
|
|
182
|
+
return function (_x, _x2) {
|
|
183
|
+
return _ref3.apply(this, arguments);
|
|
184
|
+
};
|
|
185
|
+
}(), [document, getSharingById, resolveRecipients, share, updateSharingMemberType]);
|
|
186
|
+
return {
|
|
187
|
+
isInsideSharedParent: isInsideSharedParent,
|
|
188
|
+
sharedParentName: (_sharedParentPath$spl = sharedParentPath === null || sharedParentPath === void 0 ? void 0 : sharedParentPath.split('/').pop()) !== null && _sharedParentPath$spl !== void 0 ? _sharedParentPath$spl : null,
|
|
189
|
+
setMemberType: setMemberType
|
|
190
|
+
};
|
|
191
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { useClient } from 'cozy-client';
|
|
5
|
+
import { getOrCreateFromArray } from '../helpers/contacts';
|
|
6
|
+
import { DOCTYPE_CONTACTS } from '../models';
|
|
7
|
+
/**
|
|
8
|
+
* Turns the recipients picked in a sharing form into contacts, creating the
|
|
9
|
+
* missing ones, and splits them by the selected sharing right.
|
|
10
|
+
*
|
|
11
|
+
* @returns {Function} `resolveRecipients(pendingRecipients, selectedOption, createContact?)`
|
|
12
|
+
* resolving to `{ recipients, readOnlyRecipients }`, ready to be passed to `share`
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export var useResolveRecipients = function useResolveRecipients() {
|
|
16
|
+
var client = useClient();
|
|
17
|
+
return useCallback( /*#__PURE__*/function () {
|
|
18
|
+
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(pendingRecipients) {
|
|
19
|
+
var selectedOption,
|
|
20
|
+
createContact,
|
|
21
|
+
contacts,
|
|
22
|
+
isReadOnly,
|
|
23
|
+
_args = arguments;
|
|
24
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
25
|
+
while (1) switch (_context.prev = _context.next) {
|
|
26
|
+
case 0:
|
|
27
|
+
selectedOption = _args.length > 1 && _args[1] !== undefined ? _args[1] : 'readWrite';
|
|
28
|
+
createContact = _args.length > 2 && _args[2] !== undefined ? _args[2] : function (contact) {
|
|
29
|
+
return client.create(DOCTYPE_CONTACTS, contact);
|
|
30
|
+
};
|
|
31
|
+
_context.next = 4;
|
|
32
|
+
return getOrCreateFromArray(client, pendingRecipients, createContact);
|
|
33
|
+
|
|
34
|
+
case 4:
|
|
35
|
+
contacts = _context.sent;
|
|
36
|
+
isReadOnly = selectedOption === 'readOnly';
|
|
37
|
+
return _context.abrupt("return", {
|
|
38
|
+
recipients: isReadOnly ? [] : contacts,
|
|
39
|
+
readOnlyRecipients: isReadOnly ? contacts : []
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
case 7:
|
|
43
|
+
case "end":
|
|
44
|
+
return _context.stop();
|
|
45
|
+
}
|
|
46
|
+
}, _callee);
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
return function (_x) {
|
|
50
|
+
return _ref.apply(this, arguments);
|
|
51
|
+
};
|
|
52
|
+
}(), [client]);
|
|
53
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
4
|
+
import { useResolveRecipients } from './useResolveRecipients';
|
|
5
|
+
import { getOrCreateFromArray } from '../helpers/contacts';
|
|
6
|
+
var mockClient = {
|
|
7
|
+
create: jest.fn()
|
|
8
|
+
};
|
|
9
|
+
jest.mock('cozy-client', function () {
|
|
10
|
+
return {
|
|
11
|
+
useClient: function useClient() {
|
|
12
|
+
return mockClient;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
jest.mock('../helpers/contacts', function () {
|
|
17
|
+
return {
|
|
18
|
+
getOrCreateFromArray: jest.fn()
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
var contacts = [{
|
|
22
|
+
_id: 'alice'
|
|
23
|
+
}, {
|
|
24
|
+
_id: 'bob'
|
|
25
|
+
}];
|
|
26
|
+
describe('useResolveRecipients', function () {
|
|
27
|
+
beforeEach(function () {
|
|
28
|
+
jest.clearAllMocks();
|
|
29
|
+
getOrCreateFromArray.mockResolvedValue(contacts);
|
|
30
|
+
});
|
|
31
|
+
it('gives read-write rights by default', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
32
|
+
var _renderHook, result, resolved;
|
|
33
|
+
|
|
34
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
35
|
+
while (1) switch (_context.prev = _context.next) {
|
|
36
|
+
case 0:
|
|
37
|
+
_renderHook = renderHook(function () {
|
|
38
|
+
return useResolveRecipients();
|
|
39
|
+
}), result = _renderHook.result;
|
|
40
|
+
_context.next = 3;
|
|
41
|
+
return result.current([{
|
|
42
|
+
email: 'alice@cozy.cc'
|
|
43
|
+
}]);
|
|
44
|
+
|
|
45
|
+
case 3:
|
|
46
|
+
resolved = _context.sent;
|
|
47
|
+
expect(resolved).toEqual({
|
|
48
|
+
recipients: contacts,
|
|
49
|
+
readOnlyRecipients: []
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
case 5:
|
|
53
|
+
case "end":
|
|
54
|
+
return _context.stop();
|
|
55
|
+
}
|
|
56
|
+
}, _callee);
|
|
57
|
+
})));
|
|
58
|
+
it('gives read-only rights when the read-only option is selected', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
59
|
+
var _renderHook2, result, resolved;
|
|
60
|
+
|
|
61
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
62
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
63
|
+
case 0:
|
|
64
|
+
_renderHook2 = renderHook(function () {
|
|
65
|
+
return useResolveRecipients();
|
|
66
|
+
}), result = _renderHook2.result;
|
|
67
|
+
_context2.next = 3;
|
|
68
|
+
return result.current([], 'readOnly');
|
|
69
|
+
|
|
70
|
+
case 3:
|
|
71
|
+
resolved = _context2.sent;
|
|
72
|
+
expect(resolved).toEqual({
|
|
73
|
+
recipients: [],
|
|
74
|
+
readOnlyRecipients: contacts
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
case 5:
|
|
78
|
+
case "end":
|
|
79
|
+
return _context2.stop();
|
|
80
|
+
}
|
|
81
|
+
}, _callee2);
|
|
82
|
+
})));
|
|
83
|
+
it('creates missing contacts with the client by default', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
84
|
+
var _renderHook3, result, pendingRecipients, createContact;
|
|
85
|
+
|
|
86
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
87
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
88
|
+
case 0:
|
|
89
|
+
_renderHook3 = renderHook(function () {
|
|
90
|
+
return useResolveRecipients();
|
|
91
|
+
}), result = _renderHook3.result;
|
|
92
|
+
pendingRecipients = [{
|
|
93
|
+
email: 'alice@cozy.cc'
|
|
94
|
+
}];
|
|
95
|
+
_context3.next = 4;
|
|
96
|
+
return result.current(pendingRecipients);
|
|
97
|
+
|
|
98
|
+
case 4:
|
|
99
|
+
createContact = getOrCreateFromArray.mock.calls[0][2];
|
|
100
|
+
createContact({
|
|
101
|
+
email: [{
|
|
102
|
+
address: 'alice@cozy.cc'
|
|
103
|
+
}]
|
|
104
|
+
});
|
|
105
|
+
expect(getOrCreateFromArray).toHaveBeenCalledWith(mockClient, pendingRecipients, expect.any(Function));
|
|
106
|
+
expect(mockClient.create).toHaveBeenCalledWith('io.cozy.contacts', {
|
|
107
|
+
email: [{
|
|
108
|
+
address: 'alice@cozy.cc'
|
|
109
|
+
}]
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
case 8:
|
|
113
|
+
case "end":
|
|
114
|
+
return _context3.stop();
|
|
115
|
+
}
|
|
116
|
+
}, _callee3);
|
|
117
|
+
})));
|
|
118
|
+
it('creates missing contacts with the given function', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
|
|
119
|
+
var _renderHook4, result, createContact;
|
|
120
|
+
|
|
121
|
+
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
122
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
123
|
+
case 0:
|
|
124
|
+
_renderHook4 = renderHook(function () {
|
|
125
|
+
return useResolveRecipients();
|
|
126
|
+
}), result = _renderHook4.result;
|
|
127
|
+
createContact = jest.fn();
|
|
128
|
+
_context4.next = 4;
|
|
129
|
+
return result.current([], 'readWrite', createContact);
|
|
130
|
+
|
|
131
|
+
case 4:
|
|
132
|
+
expect(getOrCreateFromArray).toHaveBeenCalledWith(mockClient, [], createContact);
|
|
133
|
+
|
|
134
|
+
case 5:
|
|
135
|
+
case "end":
|
|
136
|
+
return _context4.stop();
|
|
137
|
+
}
|
|
138
|
+
}, _callee4);
|
|
139
|
+
})));
|
|
140
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ export { ShareButtonWithRecipients } from './ShareButtonWithRecipients';
|
|
|
32
32
|
export { DOCUMENT_TYPE } from './helpers/documentType';
|
|
33
33
|
export { getRecipientsFromSharing } from './state';
|
|
34
34
|
export { default as OpenSharingLinkButton } from './OpenSharingLinkButton';
|
|
35
|
-
export { PermissionTypeMenu } from './components/Recipient/
|
|
35
|
+
export { default as PermissionTypeMenu } from './components/Recipient/PermissionTypeMenuWrapper';
|
|
36
36
|
export { default as OpenSharingLinkFabButton } from './OpenSharingLinkFabButton';
|
|
37
37
|
export { NativeFileSharingProvider, useNativeFileSharing } from './providers/NativeFileSharingProvider';
|
|
38
38
|
export { createCozySharingLink } from './actions/createCozySharingLink';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "40.1.
|
|
3
|
+
"version": "40.1.7",
|
|
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.1.
|
|
61
|
+
"cozy-ui-plus": "^14.1.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": "
|
|
87
|
+
"gitHead": "ff9d90f0000f5446b91840dbb4237b48336c3997"
|
|
88
88
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
2
|
import React, { useCallback, useEffect, useState } from 'react'
|
|
3
3
|
|
|
4
|
-
import { useClient } from 'cozy-client'
|
|
5
4
|
import minilog from 'cozy-minilog'
|
|
6
5
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
7
6
|
import { FixedDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
|
|
@@ -12,15 +11,15 @@ import ConfirmDialogProvider, {
|
|
|
12
11
|
} from 'cozy-ui/transpiled/react/providers/ConfirmDialog'
|
|
13
12
|
import { useI18n } from 'twake-i18n'
|
|
14
13
|
|
|
15
|
-
import { getOrCreateFromArray } from '../../helpers/contacts'
|
|
16
14
|
import withLocales from '../../hoc/withLocales'
|
|
17
15
|
import { usePendingRecipients } from '../../hooks/usePendingRecipients'
|
|
16
|
+
import { useResolveRecipients } from '../../hooks/useResolveRecipients'
|
|
18
17
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
19
18
|
import styles from '../../styles/share.styl'
|
|
20
19
|
import AntivirusAlert from '../AntivirusAlert'
|
|
21
20
|
import { default as DumbShareByEmail } from '../ShareByEmail'
|
|
22
21
|
import ShareByLink from '../ShareByLink'
|
|
23
|
-
import
|
|
22
|
+
import WhoHasAccessWrapper from '../WhoHasAccessWrapper'
|
|
24
23
|
|
|
25
24
|
const log = minilog('FederatedFolderModal')
|
|
26
25
|
|
|
@@ -38,7 +37,7 @@ const FederatedFolderModalContent = ({
|
|
|
38
37
|
// we close the popup and we do not want to see briefly the new contacts added
|
|
39
38
|
// in members before the modal closes. That's why when clicking on "Share"
|
|
40
39
|
// we do not use the reactive existingDocument and existingRecipients.
|
|
41
|
-
const
|
|
40
|
+
const resolveRecipients = useResolveRecipients()
|
|
42
41
|
const { t } = useI18n()
|
|
43
42
|
const {
|
|
44
43
|
canReshare,
|
|
@@ -162,13 +161,8 @@ const FederatedFolderModalContent = ({
|
|
|
162
161
|
setFrozenRecipients(recipients)
|
|
163
162
|
|
|
164
163
|
try {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
pendingRecipients,
|
|
168
|
-
contact => client.create('io.cozy.contacts', contact)
|
|
169
|
-
)
|
|
170
|
-
const readWriteRecipients = selectedOption === 'readOnly' ? [] : contacts
|
|
171
|
-
const readOnlyRecipients = selectedOption === 'readOnly' ? contacts : []
|
|
164
|
+
const { recipients: readWriteRecipients, readOnlyRecipients } =
|
|
165
|
+
await resolveRecipients(pendingRecipients, selectedOption)
|
|
172
166
|
|
|
173
167
|
await share({
|
|
174
168
|
description: folderName,
|
|
@@ -275,7 +269,7 @@ const FederatedFolderModalContent = ({
|
|
|
275
269
|
</>
|
|
276
270
|
)}
|
|
277
271
|
</div>
|
|
278
|
-
<
|
|
272
|
+
<WhoHasAccessWrapper
|
|
279
273
|
isOwner={isCurrentUserOwner}
|
|
280
274
|
canManageSharing={canManageSharing}
|
|
281
275
|
isSharedDrive
|
|
@@ -3,7 +3,6 @@ import React from 'react'
|
|
|
3
3
|
import snarkdown from 'snarkdown'
|
|
4
4
|
|
|
5
5
|
import { Icon, FolderOutlined, ArrowUp } from '@linagora/twake-icons'
|
|
6
|
-
import { useClient } from 'cozy-client'
|
|
7
6
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
8
7
|
import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
|
|
9
8
|
import Timeline from 'cozy-ui/transpiled/react/Timeline'
|
|
@@ -17,23 +16,16 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
|
17
16
|
import { useI18n } from 'twake-i18n'
|
|
18
17
|
|
|
19
18
|
import { DEFAULT_DISPLAY_NAME } from '../../helpers/recipients'
|
|
20
|
-
import { useFetchDocumentPath } from '../../hooks/useFetchDocumentPath'
|
|
21
|
-
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
22
19
|
import { getDisplayName } from '../../models'
|
|
23
20
|
|
|
24
21
|
const DowngradePermissionConfirmDialog = ({
|
|
25
22
|
document,
|
|
26
23
|
recipient,
|
|
24
|
+
sharedParentName,
|
|
27
25
|
onCancel,
|
|
28
26
|
onConfirm
|
|
29
27
|
}) => {
|
|
30
28
|
const { t } = useI18n()
|
|
31
|
-
const client = useClient()
|
|
32
|
-
const { getSharedParentPath } = useSharingContext()
|
|
33
|
-
|
|
34
|
-
const documentPath = useFetchDocumentPath(client, document)
|
|
35
|
-
const sharedParentPath = documentPath && getSharedParentPath(documentPath)
|
|
36
|
-
const parentFolderName = sharedParentPath?.split('/').pop()
|
|
37
29
|
const contactName = getDisplayName(recipient, t(DEFAULT_DISPLAY_NAME))
|
|
38
30
|
const [before, afterOpen] = snarkdown(
|
|
39
31
|
t('DowngradePermissionConfirmDialog.content', { contactName })
|
|
@@ -68,7 +60,7 @@ const DowngradePermissionConfirmDialog = ({
|
|
|
68
60
|
<TimelineConnector />
|
|
69
61
|
</TimelineSeparator>
|
|
70
62
|
<TimelineContent>
|
|
71
|
-
<Typography variant="body2">{
|
|
63
|
+
<Typography variant="body2">{sharedParentName}</Typography>
|
|
72
64
|
<div>
|
|
73
65
|
<s>
|
|
74
66
|
<Typography display="inline" variant="caption">
|
|
@@ -147,6 +139,7 @@ const DowngradePermissionConfirmDialog = ({
|
|
|
147
139
|
DowngradePermissionConfirmDialog.propTypes = {
|
|
148
140
|
document: PropTypes.object.isRequired,
|
|
149
141
|
recipient: PropTypes.object.isRequired,
|
|
142
|
+
sharedParentName: PropTypes.string,
|
|
150
143
|
onCancel: PropTypes.func.isRequired,
|
|
151
144
|
onConfirm: PropTypes.func.isRequired
|
|
152
145
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import { useClient } from 'cozy-client'
|
|
4
3
|
import Fade from 'cozy-ui/transpiled/react/Fade'
|
|
5
4
|
import ListItem from 'cozy-ui/transpiled/react/ListItem'
|
|
6
5
|
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
|
|
@@ -21,7 +20,6 @@ import { GroupAvatar } from '../Avatar/GroupAvatar'
|
|
|
21
20
|
const GroupRecipient = props => {
|
|
22
21
|
const { name, color, members, fadeIn, isOwner } = props
|
|
23
22
|
const { t } = useI18n()
|
|
24
|
-
const client = useClient()
|
|
25
23
|
const { isMobile } = useBreakpoints()
|
|
26
24
|
|
|
27
25
|
const [isDetailOpened, setDetailOpened] = useState(false)
|
|
@@ -30,9 +28,7 @@ const GroupRecipient = props => {
|
|
|
30
28
|
const nbMemberReady = members.filter(
|
|
31
29
|
member => !['revoked', 'mail-not-sent'].includes(member.status)
|
|
32
30
|
).length
|
|
33
|
-
const isUserInsideMembers = members.some(
|
|
34
|
-
member => member.instance === client.options.uri
|
|
35
|
-
)
|
|
31
|
+
const isUserInsideMembers = members.some(member => member.isCurrentUser)
|
|
36
32
|
|
|
37
33
|
const toogleDetailOpened = () => {
|
|
38
34
|
setDetailOpened(!isDetailOpened)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
|
|
3
|
-
import { useClient } from 'cozy-client'
|
|
4
3
|
import Avatar from 'cozy-ui/transpiled/react/Avatar'
|
|
5
4
|
import List from 'cozy-ui/transpiled/react/List'
|
|
6
5
|
import ListItem from 'cozy-ui/transpiled/react/ListItem'
|
|
@@ -14,7 +13,6 @@ import { getInitials, getDisplayName } from '../../models'
|
|
|
14
13
|
|
|
15
14
|
const GroupRecipientDetailWithAccess = ({ withAccess }) => {
|
|
16
15
|
const { t } = useI18n()
|
|
17
|
-
const client = useClient()
|
|
18
16
|
|
|
19
17
|
return (
|
|
20
18
|
<div>
|
|
@@ -24,7 +22,6 @@ const GroupRecipientDetailWithAccess = ({ withAccess }) => {
|
|
|
24
22
|
<List>
|
|
25
23
|
{withAccess.map(recipient => {
|
|
26
24
|
const name = getDisplayName(recipient)
|
|
27
|
-
const isMe = recipient.instance === client.options.uri
|
|
28
25
|
|
|
29
26
|
return (
|
|
30
27
|
<ListItem disableGutters key={recipient.index} size="small">
|
|
@@ -36,7 +33,7 @@ const GroupRecipientDetailWithAccess = ({ withAccess }) => {
|
|
|
36
33
|
secondary={
|
|
37
34
|
<MemberRecipientStatus
|
|
38
35
|
status={recipient.status}
|
|
39
|
-
isMe={
|
|
36
|
+
isMe={Boolean(recipient.isCurrentUser)}
|
|
40
37
|
instance={recipient.instance}
|
|
41
38
|
email={recipient.email}
|
|
42
39
|
name={recipient.name || recipient.public_name}
|
|
@@ -13,7 +13,6 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
|
13
13
|
import { useI18n } from 'twake-i18n'
|
|
14
14
|
|
|
15
15
|
import { permission } from './actions/permission'
|
|
16
|
-
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
17
16
|
import { GroupAvatar } from '../Avatar/GroupAvatar'
|
|
18
17
|
|
|
19
18
|
const GroupRecipientPermissions = ({
|
|
@@ -26,11 +25,12 @@ const GroupRecipientPermissions = ({
|
|
|
26
25
|
read_only = false,
|
|
27
26
|
className,
|
|
28
27
|
isUserInsideMembers,
|
|
29
|
-
document
|
|
28
|
+
document,
|
|
29
|
+
onRevokeGroup,
|
|
30
|
+
onLeaveGroup
|
|
30
31
|
}) => {
|
|
31
32
|
const { t } = useI18n()
|
|
32
33
|
const buttonRef = useRef()
|
|
33
|
-
const { revokeGroup, revokeSelf } = useSharingContext()
|
|
34
34
|
|
|
35
35
|
const [isMenuDisplayed, setMenuDisplayed] = useState(false)
|
|
36
36
|
const [revoking, setRevoking] = useState(false)
|
|
@@ -44,9 +44,9 @@ const GroupRecipientPermissions = ({
|
|
|
44
44
|
const handleRevocation = async () => {
|
|
45
45
|
setRevoking(true)
|
|
46
46
|
if (isOwner) {
|
|
47
|
-
await
|
|
47
|
+
await onRevokeGroup(document, sharingId, groupIndex)
|
|
48
48
|
} else {
|
|
49
|
-
await
|
|
49
|
+
await onLeaveGroup(document)
|
|
50
50
|
}
|
|
51
51
|
setRevoking(false)
|
|
52
52
|
}
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
getPermissionExpiresDate
|
|
20
20
|
} from '../../helpers/permissions'
|
|
21
21
|
import { FADE_IN_DURATION } from '../../helpers/recipients'
|
|
22
|
-
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
23
22
|
import { ShareRestrictionModal } from '../ShareRestrictionModal/ShareRestrictionModal'
|
|
24
23
|
|
|
25
24
|
const LinkRecipientTextReadOnly = ({ textPrimary, textSecondary }) => {
|
|
@@ -55,19 +54,18 @@ const LinkRecipientText = ({ onClick, textPrimary, textSecondary }) => {
|
|
|
55
54
|
const LinkRecipient = props => {
|
|
56
55
|
const { t, f, lang } = useI18n()
|
|
57
56
|
const { isMobile } = useBreakpoints()
|
|
58
|
-
const { getDocumentPermissions } = useSharingContext()
|
|
59
57
|
|
|
60
58
|
const {
|
|
61
59
|
recipientConfirmationData,
|
|
62
60
|
verifyRecipient,
|
|
63
61
|
fadeIn,
|
|
64
62
|
document,
|
|
65
|
-
isReadOnly
|
|
63
|
+
isReadOnly,
|
|
64
|
+
permissions
|
|
66
65
|
} = props
|
|
67
66
|
|
|
68
67
|
const [openShareRestrictionModal, setOpenShareRestrictionModal] =
|
|
69
68
|
useState(false)
|
|
70
|
-
const permissions = getDocumentPermissions(document?._id)
|
|
71
69
|
const hasPassword = checkIsPermissionHasPassword(permissions)
|
|
72
70
|
const expiresDate = getPermissionExpiresDate(permissions)
|
|
73
71
|
const dateFormatted = expiresDate
|