cozy-sharing 28.4.4 → 28.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 +18 -0
- package/dist/SharingProvider.js +296 -66
- package/dist/SharingProvider.spec.js +332 -2
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.js +7 -4
- package/dist/components/FederatedFolder/FederatedFolderModal.js +79 -23
- package/dist/components/Recipient/LinkRecipient.js +6 -3
- package/dist/components/Recipient/LinkRecipient.stories.js +0 -1
- package/dist/components/Recipient/MemberRecipient.spec.js +13 -0
- package/dist/components/Recipient/MemberRecipientPermissions.js +80 -20
- package/dist/components/Recipient/MemberRecipientPermissions.spec.js +214 -0
- package/dist/components/Recipient/actions/setReadOnlySharedPermission.js +0 -1
- package/dist/components/Recipient/actions/setReadOnlySharedPermission.spec.js +72 -0
- package/dist/components/Recipient/actions/setReadWriteSharedPermission.js +0 -1
- package/dist/components/Recipient/actions/setReadWriteSharedPermission.spec.js +72 -0
- package/dist/components/ShareByLink.js +5 -1
- package/dist/components/ShareDialogCozyToCozy.spec.js +9 -0
- package/dist/components/ShareRestrictionModal/helpers.js +66 -29
- package/dist/components/SharedDrive/DumbSharedDriveModal.js +1 -1
- package/dist/components/SharedFolder/DumbBatchSharedFolderModal.js +17 -4
- package/dist/components/WhoHasAccess.js +0 -1
- package/dist/helpers/shortcodes.js +24 -0
- package/dist/state.js +3 -10
- package/locales/en.json +4 -1
- package/locales/fr.json +4 -1
- package/locales/ru.json +4 -1
- package/locales/vi.json +4 -1
- package/package.json +4 -4
- package/src/SharingProvider.jsx +128 -9
- package/src/SharingProvider.spec.jsx +224 -1
- package/src/components/FederatedFolder/DumbFederatedFolderModal.jsx +6 -3
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +39 -6
- package/src/components/Recipient/LinkRecipient.jsx +10 -4
- package/src/components/Recipient/LinkRecipient.stories.jsx +0 -1
- package/src/components/Recipient/MemberRecipient.spec.jsx +11 -0
- package/src/components/Recipient/MemberRecipientPermissions.jsx +69 -16
- package/src/components/Recipient/MemberRecipientPermissions.spec.jsx +165 -0
- package/src/components/Recipient/actions/setReadOnlySharedPermission.js +1 -1
- package/src/components/Recipient/actions/setReadOnlySharedPermission.spec.jsx +95 -0
- package/src/components/Recipient/actions/setReadWriteSharedPermission.js +1 -1
- package/src/components/Recipient/actions/setReadWriteSharedPermission.spec.jsx +95 -0
- package/src/components/ShareByLink.jsx +3 -1
- package/src/components/ShareDialogCozyToCozy.spec.jsx +6 -0
- package/src/components/ShareRestrictionModal/helpers.js +42 -4
- package/src/components/SharedDrive/DumbSharedDriveModal.jsx +1 -1
- package/src/components/SharedFolder/DumbBatchSharedFolderModal.jsx +32 -16
- package/src/components/WhoHasAccess.jsx +0 -1
- package/src/helpers/shortcodes.js +28 -0
- package/src/state.js +3 -14
|
@@ -3,6 +3,7 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
|
3
3
|
import { generateWebLink } from 'cozy-client';
|
|
4
4
|
import minilog from 'cozy-minilog';
|
|
5
5
|
import { getAppSlugFromDocumentType } from '../../helpers/link';
|
|
6
|
+
import { getShortcode } from '../../helpers/shortcodes';
|
|
6
7
|
var log = minilog('ShareRestrictionModal/helpers');
|
|
7
8
|
export var WRITE_PERMS = ['GET', 'POST', 'PUT', 'PATCH'];
|
|
8
9
|
export var READ_ONLY_PERMS = ['GET'];
|
|
@@ -24,14 +25,12 @@ export var READ_ONLY_PERMS = ['GET'];
|
|
|
24
25
|
|
|
25
26
|
export var createSharingLink = /*#__PURE__*/function () {
|
|
26
27
|
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
var client, file, documentType, shareByLink, t, ttl, _ref$editingRights, editingRights, password, showAlert, permsResult, perms;
|
|
28
|
+
var client, file, documentType, shareByLink, getOwner, getSharingById, t, ttl, _ref$editingRights, editingRights, password, showAlert, permsResult, code;
|
|
30
29
|
|
|
31
30
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
32
31
|
while (1) switch (_context.prev = _context.next) {
|
|
33
32
|
case 0:
|
|
34
|
-
client = _ref.client, file = _ref.file, documentType = _ref.documentType, shareByLink = _ref.shareByLink, t = _ref.t, ttl = _ref.ttl, _ref$editingRights = _ref.editingRights, editingRights = _ref$editingRights === void 0 ? 'readOnly' : _ref$editingRights, password = _ref.password, showAlert = _ref.showAlert;
|
|
33
|
+
client = _ref.client, file = _ref.file, documentType = _ref.documentType, shareByLink = _ref.shareByLink, getOwner = _ref.getOwner, getSharingById = _ref.getSharingById, t = _ref.t, ttl = _ref.ttl, _ref$editingRights = _ref.editingRights, editingRights = _ref$editingRights === void 0 ? 'readOnly' : _ref$editingRights, password = _ref.password, showAlert = _ref.showAlert;
|
|
35
34
|
_context.next = 3;
|
|
36
35
|
return createPermissions({
|
|
37
36
|
file: file,
|
|
@@ -46,24 +45,23 @@ export var createSharingLink = /*#__PURE__*/function () {
|
|
|
46
45
|
|
|
47
46
|
case 3:
|
|
48
47
|
permsResult = _context.sent;
|
|
48
|
+
code = getShortcode(permsResult === null || permsResult === void 0 ? void 0 : permsResult.data);
|
|
49
49
|
|
|
50
|
-
if (
|
|
51
|
-
_context.next =
|
|
50
|
+
if (code) {
|
|
51
|
+
_context.next = 7;
|
|
52
52
|
break;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
return _context.abrupt("return", null);
|
|
56
56
|
|
|
57
|
-
case
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}),
|
|
66
|
-
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
57
|
+
case 7:
|
|
58
|
+
return _context.abrupt("return", generateShareLinkFromFile({
|
|
59
|
+
client: client,
|
|
60
|
+
file: file,
|
|
61
|
+
sharecode: code,
|
|
62
|
+
getOwner: getOwner,
|
|
63
|
+
getSharingById: getSharingById,
|
|
64
|
+
documentType: documentType
|
|
67
65
|
}));
|
|
68
66
|
|
|
69
67
|
case 8:
|
|
@@ -77,6 +75,45 @@ export var createSharingLink = /*#__PURE__*/function () {
|
|
|
77
75
|
return _ref2.apply(this, arguments);
|
|
78
76
|
};
|
|
79
77
|
}();
|
|
78
|
+
/**
|
|
79
|
+
* Generate a sharing link from a file and sharecode
|
|
80
|
+
* @param {object} options
|
|
81
|
+
* @param {object} options.client - CozyClient instance
|
|
82
|
+
* @param {object} options.file - File to share
|
|
83
|
+
* @param {string} options.sharecode - Share code
|
|
84
|
+
* @param {Function} options.getOwner - Function to get the owner of a sharing
|
|
85
|
+
* @param {Function} options.getSharingById - Function to get a sharing by ID
|
|
86
|
+
* @param {string} options.documentType - Type of the document
|
|
87
|
+
* @returns {string} - The generated web link
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
export var generateShareLinkFromFile = function generateShareLinkFromFile(_ref3) {
|
|
91
|
+
var client = _ref3.client,
|
|
92
|
+
file = _ref3.file,
|
|
93
|
+
sharecode = _ref3.sharecode,
|
|
94
|
+
getOwner = _ref3.getOwner,
|
|
95
|
+
getSharingById = _ref3.getSharingById,
|
|
96
|
+
documentType = _ref3.documentType;
|
|
97
|
+
var cozyUrl = client.getStackClient().uri;
|
|
98
|
+
|
|
99
|
+
if (file.driveId) {
|
|
100
|
+
var _sharing$rules;
|
|
101
|
+
|
|
102
|
+
var sharing = getSharingById(file.driveId);
|
|
103
|
+
var owner = getOwner(sharing === null || sharing === void 0 || (_sharing$rules = sharing.rules) === null || _sharing$rules === void 0 || (_sharing$rules = _sharing$rules[0]) === null || _sharing$rules === void 0 || (_sharing$rules = _sharing$rules.values) === null || _sharing$rules === void 0 ? void 0 : _sharing$rules[0]);
|
|
104
|
+
cozyUrl = (owner === null || owner === void 0 ? void 0 : owner.instance) || client.getStackClient().uri;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return generateWebLink({
|
|
108
|
+
cozyUrl: cozyUrl,
|
|
109
|
+
searchParams: [['sharecode', sharecode]],
|
|
110
|
+
pathname: '/public',
|
|
111
|
+
slug: getAppSlugFromDocumentType({
|
|
112
|
+
documentType: documentType
|
|
113
|
+
}),
|
|
114
|
+
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
115
|
+
});
|
|
116
|
+
};
|
|
80
117
|
/**
|
|
81
118
|
* Copy a string to the clipboard
|
|
82
119
|
*
|
|
@@ -87,8 +124,8 @@ export var createSharingLink = /*#__PURE__*/function () {
|
|
|
87
124
|
*/
|
|
88
125
|
|
|
89
126
|
export var copyToClipboard = /*#__PURE__*/function () {
|
|
90
|
-
var
|
|
91
|
-
var
|
|
127
|
+
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(value) {
|
|
128
|
+
var _ref5,
|
|
92
129
|
t,
|
|
93
130
|
showAlert,
|
|
94
131
|
_args2 = arguments;
|
|
@@ -96,7 +133,7 @@ export var copyToClipboard = /*#__PURE__*/function () {
|
|
|
96
133
|
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
97
134
|
while (1) switch (_context2.prev = _context2.next) {
|
|
98
135
|
case 0:
|
|
99
|
-
|
|
136
|
+
_ref5 = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : {}, t = _ref5.t, showAlert = _ref5.showAlert;
|
|
100
137
|
|
|
101
138
|
if (value) {
|
|
102
139
|
_context2.next = 3;
|
|
@@ -137,7 +174,7 @@ export var copyToClipboard = /*#__PURE__*/function () {
|
|
|
137
174
|
}));
|
|
138
175
|
|
|
139
176
|
return function copyToClipboard(_x2) {
|
|
140
|
-
return
|
|
177
|
+
return _ref4.apply(this, arguments);
|
|
141
178
|
};
|
|
142
179
|
}();
|
|
143
180
|
/**
|
|
@@ -188,12 +225,12 @@ export var makeTTL = function makeTTL(selectedDate) {
|
|
|
188
225
|
*/
|
|
189
226
|
|
|
190
227
|
export var createPermissions = /*#__PURE__*/function () {
|
|
191
|
-
var
|
|
228
|
+
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref6) {
|
|
192
229
|
var file, t, ttl, password, editingRights, documentType, shareByLink, showAlert, verbs;
|
|
193
230
|
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
194
231
|
while (1) switch (_context3.prev = _context3.next) {
|
|
195
232
|
case 0:
|
|
196
|
-
file =
|
|
233
|
+
file = _ref6.file, t = _ref6.t, ttl = _ref6.ttl, password = _ref6.password, editingRights = _ref6.editingRights, documentType = _ref6.documentType, shareByLink = _ref6.shareByLink, showAlert = _ref6.showAlert;
|
|
197
234
|
_context3.prev = 1;
|
|
198
235
|
verbs = editingRights === 'readOnly' ? READ_ONLY_PERMS : WRITE_PERMS;
|
|
199
236
|
return _context3.abrupt("return", shareByLink(file, {
|
|
@@ -220,7 +257,7 @@ export var createPermissions = /*#__PURE__*/function () {
|
|
|
220
257
|
}));
|
|
221
258
|
|
|
222
259
|
return function createPermissions(_x3) {
|
|
223
|
-
return
|
|
260
|
+
return _ref7.apply(this, arguments);
|
|
224
261
|
};
|
|
225
262
|
}();
|
|
226
263
|
/**
|
|
@@ -239,12 +276,12 @@ export var createPermissions = /*#__PURE__*/function () {
|
|
|
239
276
|
*/
|
|
240
277
|
|
|
241
278
|
export var updatePermissions = /*#__PURE__*/function () {
|
|
242
|
-
var
|
|
279
|
+
var _ref9 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref8) {
|
|
243
280
|
var file, t, dateToggle, selectedDate, passwordToggle, password, editingRights, documentType, updateDocumentPermissions, showAlert, expiresAt, ensurePassword, verbs;
|
|
244
281
|
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
245
282
|
while (1) switch (_context4.prev = _context4.next) {
|
|
246
283
|
case 0:
|
|
247
|
-
file =
|
|
284
|
+
file = _ref8.file, t = _ref8.t, dateToggle = _ref8.dateToggle, selectedDate = _ref8.selectedDate, passwordToggle = _ref8.passwordToggle, password = _ref8.password, editingRights = _ref8.editingRights, documentType = _ref8.documentType, updateDocumentPermissions = _ref8.updateDocumentPermissions, showAlert = _ref8.showAlert;
|
|
248
285
|
_context4.prev = 1;
|
|
249
286
|
expiresAt = dateToggle ? (selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.toISOString()) || undefined : '';
|
|
250
287
|
ensurePassword = passwordToggle ? password || undefined : '';
|
|
@@ -273,7 +310,7 @@ export var updatePermissions = /*#__PURE__*/function () {
|
|
|
273
310
|
}));
|
|
274
311
|
|
|
275
312
|
return function updatePermissions(_x4) {
|
|
276
|
-
return
|
|
313
|
+
return _ref9.apply(this, arguments);
|
|
277
314
|
};
|
|
278
315
|
}();
|
|
279
316
|
/**
|
|
@@ -287,12 +324,12 @@ export var updatePermissions = /*#__PURE__*/function () {
|
|
|
287
324
|
*/
|
|
288
325
|
|
|
289
326
|
export var revokePermissions = /*#__PURE__*/function () {
|
|
290
|
-
var
|
|
327
|
+
var _ref11 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref10) {
|
|
291
328
|
var file, t, documentType, revokeSharingLink, showAlert;
|
|
292
329
|
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
|
|
293
330
|
while (1) switch (_context5.prev = _context5.next) {
|
|
294
331
|
case 0:
|
|
295
|
-
file =
|
|
332
|
+
file = _ref10.file, t = _ref10.t, documentType = _ref10.documentType, revokeSharingLink = _ref10.revokeSharingLink, showAlert = _ref10.showAlert;
|
|
296
333
|
_context5.prev = 1;
|
|
297
334
|
return _context5.abrupt("return", revokeSharingLink(file));
|
|
298
335
|
|
|
@@ -314,6 +351,6 @@ export var revokePermissions = /*#__PURE__*/function () {
|
|
|
314
351
|
}));
|
|
315
352
|
|
|
316
353
|
return function revokePermissions(_x5) {
|
|
317
|
-
return
|
|
354
|
+
return _ref11.apply(this, arguments);
|
|
318
355
|
};
|
|
319
356
|
}();
|
|
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useI18n } from 'twake-i18n';
|
|
4
4
|
import withLocales from '../../hoc/withLocales';
|
|
5
|
-
import DumbBatchSharedFolderModal from '../SharedFolder/DumbBatchSharedFolderModal';
|
|
5
|
+
import { DumbBatchSharedFolderModal } from '../SharedFolder/DumbBatchSharedFolderModal';
|
|
6
6
|
export var DumbSharedDriveModal = withLocales(function (_ref) {
|
|
7
7
|
var title = _ref.title,
|
|
8
8
|
document = _ref.document,
|
|
@@ -34,7 +34,9 @@ export var DumbBatchSharedFolderModal = withLocales(function (_ref) {
|
|
|
34
34
|
createLabel = _ref.createLabel,
|
|
35
35
|
shareLabel = _ref.shareLabel,
|
|
36
36
|
saveLabel = _ref.saveLabel,
|
|
37
|
-
sharingDesc = _ref.sharingDesc
|
|
37
|
+
sharingDesc = _ref.sharingDesc,
|
|
38
|
+
_ref$showShareByEmail = _ref.showShareByEmail,
|
|
39
|
+
showShareByEmail = _ref$showShareByEmail === void 0 ? true : _ref$showShareByEmail;
|
|
38
40
|
var hasRecipients = Boolean(recipients === null || recipients === void 0 ? void 0 : recipients.length); // Determine action buttons based on modal mode
|
|
39
41
|
|
|
40
42
|
var actionButtons = function () {
|
|
@@ -50,6 +52,14 @@ export var DumbBatchSharedFolderModal = withLocales(function (_ref) {
|
|
|
50
52
|
}));
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
if (!showShareByEmail) {
|
|
56
|
+
return /*#__PURE__*/React.createElement(ShareByLink, {
|
|
57
|
+
link: sharingLink,
|
|
58
|
+
document: document,
|
|
59
|
+
documentType: "Files"
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
if (!showNameField) {
|
|
54
64
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ShareByLink, {
|
|
55
65
|
link: sharingLink,
|
|
@@ -104,7 +114,7 @@ export var DumbBatchSharedFolderModal = withLocales(function (_ref) {
|
|
|
104
114
|
}), /*#__PURE__*/React.createElement(Typography, {
|
|
105
115
|
variant: "h6",
|
|
106
116
|
className: "u-mt-1-half u-mb-half"
|
|
107
|
-
}, addPeopleLabel), /*#__PURE__*/React.createElement(DumbShareByEmail, {
|
|
117
|
+
}, addPeopleLabel), showShareByEmail && /*#__PURE__*/React.createElement(DumbShareByEmail, {
|
|
108
118
|
createContact: createContact,
|
|
109
119
|
currentRecipients: currentRecipients,
|
|
110
120
|
document: document,
|
|
@@ -154,6 +164,9 @@ DumbBatchSharedFolderModal.propTypes = {
|
|
|
154
164
|
createLabel: PropTypes.string,
|
|
155
165
|
shareLabel: PropTypes.string,
|
|
156
166
|
saveLabel: PropTypes.string,
|
|
157
|
-
sharingDesc: PropTypes.string
|
|
167
|
+
sharingDesc: PropTypes.string,
|
|
168
|
+
showShareByEmail: PropTypes.bool
|
|
158
169
|
};
|
|
159
|
-
|
|
170
|
+
DumbBatchSharedFolderModal.defaultProps = {
|
|
171
|
+
sharingDesc: ''
|
|
172
|
+
};
|
|
@@ -55,7 +55,6 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
55
55
|
documentType: documentType,
|
|
56
56
|
onRevoke: onRevoke,
|
|
57
57
|
onRevokeSelf: onRevokeSelf,
|
|
58
|
-
link: link,
|
|
59
58
|
permissions: permissions,
|
|
60
59
|
fadeIn: linkHasBeenJustCreated
|
|
61
60
|
}), /*#__PURE__*/React.createElement(OwnerRecipient, {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the shortcode from a permission object
|
|
3
|
+
* The shortcode can be in different places depending on how the sharing was created:
|
|
4
|
+
* - attributes.shortcodes.email
|
|
5
|
+
* - attributes.shortcodes.code
|
|
6
|
+
* - attributes.codes.email
|
|
7
|
+
* - attributes.codes.code
|
|
8
|
+
*
|
|
9
|
+
* We used to use `email` as `codes` attribute for a sharingByLink.
|
|
10
|
+
* But when we use cozy-client to create a Permission, by default
|
|
11
|
+
* the codes attribute is set to `code`. MesPapiers app is using this
|
|
12
|
+
* default behavior... So the sharing by link created by mes papiers
|
|
13
|
+
* didn't appear correctly in cozy-sharing.
|
|
14
|
+
* This is a bit ugly, we should have a better way to know if this is
|
|
15
|
+
* a sharing by link or not.
|
|
16
|
+
*
|
|
17
|
+
* @param {object} permission - The permission object
|
|
18
|
+
* @returns {string|null} The shortcode or null if not found
|
|
19
|
+
*/
|
|
20
|
+
export var getShortcode = function getShortcode(permission) {
|
|
21
|
+
var _permission$attribute, _permission$attribute2, _permission$attribute3, _permission$attribute4;
|
|
22
|
+
|
|
23
|
+
return (permission === null || permission === void 0 || (_permission$attribute = permission.attributes) === null || _permission$attribute === void 0 || (_permission$attribute = _permission$attribute.shortcodes) === null || _permission$attribute === void 0 ? void 0 : _permission$attribute.email) || (permission === null || permission === void 0 || (_permission$attribute2 = permission.attributes) === null || _permission$attribute2 === void 0 || (_permission$attribute2 = _permission$attribute2.shortcodes) === null || _permission$attribute2 === void 0 ? void 0 : _permission$attribute2.code) || (permission === null || permission === void 0 || (_permission$attribute3 = permission.attributes) === null || _permission$attribute3 === void 0 || (_permission$attribute3 = _permission$attribute3.codes) === null || _permission$attribute3 === void 0 ? void 0 : _permission$attribute3.email) || (permission === null || permission === void 0 || (_permission$attribute4 = permission.attributes) === null || _permission$attribute4 === void 0 || (_permission$attribute4 = _permission$attribute4.codes) === null || _permission$attribute4 === void 0 ? void 0 : _permission$attribute4.code) || null;
|
|
24
|
+
};
|
package/dist/state.js
CHANGED
|
@@ -10,8 +10,8 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
10
10
|
|
|
11
11
|
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; }
|
|
12
12
|
|
|
13
|
-
import get from 'lodash/get';
|
|
14
13
|
import flag from 'cozy-flags';
|
|
14
|
+
import { getShortcode } from './helpers/shortcodes';
|
|
15
15
|
var RECEIVE_SHARINGS = 'RECEIVE_SHARINGS';
|
|
16
16
|
var ADD_SHARING = 'ADD_SHARING';
|
|
17
17
|
var UPDATE_SHARING = 'UPDATE_SHARING';
|
|
@@ -521,15 +521,8 @@ export var getSharingLink = function getSharingLink(state, docId, documentType)
|
|
|
521
521
|
// This shouldn't have happened, but unfortunately some duplicate sharing links have been created in the past
|
|
522
522
|
var perms = getDocumentPermissions(state, docId);
|
|
523
523
|
if (perms.length === 0) return null;
|
|
524
|
-
var perm = perms[0];
|
|
525
|
-
|
|
526
|
-
// the codes attribute is set to `code`. MesPapiers app is using this
|
|
527
|
-
// default behavior... So the sharing by link created by mes papiers
|
|
528
|
-
// didn't appear correctly in cozy-sharing.
|
|
529
|
-
// This is a bit ugly, we should have a better way to know if this is
|
|
530
|
-
// a sharing by link or not.
|
|
531
|
-
|
|
532
|
-
var code = get(perm, 'attributes.shortcodes.email') || get(perm, 'attributes.shortcodes.code') || get(perm, 'attributes.codes.email') || get(perm, 'attributes.codes.code');
|
|
524
|
+
var perm = perms[0];
|
|
525
|
+
var code = getShortcode(perm);
|
|
533
526
|
|
|
534
527
|
if (code) {
|
|
535
528
|
return buildSharingLink(state, documentType, code);
|
package/locales/en.json
CHANGED
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"members": {
|
|
35
35
|
"count": "%{smart_count} member |||| %{smart_count} members",
|
|
36
36
|
"others": "and 1 other… |||| and %{smart_count} others…",
|
|
37
|
-
"otherContacts": "other contact |||| other contacts"
|
|
37
|
+
"otherContacts": "other contact |||| other contacts",
|
|
38
|
+
"error": {
|
|
39
|
+
"changePermission": "An error occurred while changing the permissions. Please try again."
|
|
40
|
+
}
|
|
38
41
|
},
|
|
39
42
|
"contacts": {
|
|
40
43
|
"whoHasAccess": "Who has access?",
|
package/locales/fr.json
CHANGED
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"members": {
|
|
35
35
|
"count": "%{smart_count} membre |||| %{smart_count} membres",
|
|
36
36
|
"others": "et 1 autre… |||| et %{smart_count} autres…",
|
|
37
|
-
"otherContacts": "autre contact |||| autres contacts"
|
|
37
|
+
"otherContacts": "autre contact |||| autres contacts",
|
|
38
|
+
"error": {
|
|
39
|
+
"changePermission": "Une erreur s'est produite lors du changement des permissions. Veuillez réessayer."
|
|
40
|
+
}
|
|
38
41
|
},
|
|
39
42
|
"contacts": {
|
|
40
43
|
"whoHasAccess": "Qui a accès ?",
|
package/locales/ru.json
CHANGED
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"members": {
|
|
35
35
|
"count": "%{smart_count} участник |||| %{smart_count} участника |||| %{smart_count} участников",
|
|
36
36
|
"others": "и 1 другой… |||| и %{smart_count} других…",
|
|
37
|
-
"otherContacts": "другой контакт |||| других контакта"
|
|
37
|
+
"otherContacts": "другой контакт |||| других контакта",
|
|
38
|
+
"error": {
|
|
39
|
+
"changePermission": "Произошла ошибка при изменении разрешений. Пожалуйста, попробуйте снова."
|
|
40
|
+
}
|
|
38
41
|
},
|
|
39
42
|
"contacts": {
|
|
40
43
|
"whoHasAccess": "У кого есть доступ?",
|
package/locales/vi.json
CHANGED
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"members": {
|
|
35
35
|
"count": "%{smart_count} thành viên |||| %{smart_count} thành viên",
|
|
36
36
|
"others": "và 1 người khác… |||| và %{smart_count} người khác…",
|
|
37
|
-
"otherContacts": "người liên hệ khác |||| người liên hệ khác"
|
|
37
|
+
"otherContacts": "người liên hệ khác |||| người liên hệ khác",
|
|
38
|
+
"error": {
|
|
39
|
+
"changePermission": "Đã xảy ra lỗi khi thay đổi quyền. Vui lòng thử lại."
|
|
40
|
+
}
|
|
38
41
|
},
|
|
39
42
|
"contacts": {
|
|
40
43
|
"whoHasAccess": "Ai có quyền truy cập?",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "28.
|
|
3
|
+
"version": "28.6.0",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"babel-jest": "27.5.1",
|
|
55
55
|
"babel-plugin-css-modules-transform": "1.6.2",
|
|
56
56
|
"babel-plugin-inline-react-svg": "1.1.2",
|
|
57
|
-
"cozy-client": "^60.
|
|
57
|
+
"cozy-client": "^60.22.0",
|
|
58
58
|
"cozy-device-helper": "^3.7.1",
|
|
59
59
|
"cozy-intent": "^2.30.3",
|
|
60
60
|
"cozy-minilog": "^3.10.0",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"twake-i18n": "^0.3.2"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
|
-
"cozy-client": ">=60.
|
|
72
|
+
"cozy-client": ">=60.22.0",
|
|
73
73
|
"cozy-device-helper": ">=3.7.1",
|
|
74
74
|
"cozy-intent": ">=2.29.1",
|
|
75
75
|
"cozy-minilog": ">=3.9.1",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"sideEffects": [
|
|
84
84
|
"*.css"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "64311a9d08372224b5214cbf49f7d658d93f9af9"
|
|
87
87
|
}
|
package/src/SharingProvider.jsx
CHANGED
|
@@ -3,6 +3,7 @@ import React, { Component } from 'react'
|
|
|
3
3
|
import { withClient } from 'cozy-client'
|
|
4
4
|
import minilog from 'cozy-minilog'
|
|
5
5
|
|
|
6
|
+
import { generateShareLinkFromFile } from './components/ShareRestrictionModal/helpers'
|
|
6
7
|
import SharingContext from './context'
|
|
7
8
|
import { fetchNextPermissions } from './fetchNextPermissions'
|
|
8
9
|
import { fetchFilesPaths } from './helpers/files'
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
createSharingInStore,
|
|
12
13
|
updateSharingInStore
|
|
13
14
|
} from './helpers/sharings'
|
|
15
|
+
import { getShortcode } from './helpers/shortcodes'
|
|
14
16
|
import { SynchronousJobQueue } from './helpers/synchronousJobQueue'
|
|
15
17
|
import { fetchApps } from './queries/queries'
|
|
16
18
|
import reducer, {
|
|
@@ -67,6 +69,7 @@ export class SharingProvider extends Component {
|
|
|
67
69
|
canReshare: docId => canReshare(this.state, docId, instanceUri),
|
|
68
70
|
getOwner: docId => getOwner(this.state, docId),
|
|
69
71
|
getSharingType: docId => getSharingType(this.state, docId, instanceUri),
|
|
72
|
+
getSharingById: docId => getSharingById(this.state, docId),
|
|
70
73
|
getSharingForSelf: docId => getSharingForSelf(this.state, docId),
|
|
71
74
|
getRecipients: docId => getRecipients(this.state, docId),
|
|
72
75
|
getSharedParentPath: documentPath =>
|
|
@@ -83,6 +86,7 @@ export class SharingProvider extends Component {
|
|
|
83
86
|
revokeGroup: this.revokeGroup,
|
|
84
87
|
revokeSelf: this.revokeSelf,
|
|
85
88
|
shareByLink: this.shareByLink,
|
|
89
|
+
getFederatedShareLink: this.getFederatedShareLink,
|
|
86
90
|
updateDocumentPermissions: this.updateDocumentPermissions,
|
|
87
91
|
revokeSharingLink: this.revokeSharingLink,
|
|
88
92
|
hasLoadedAtLeastOnePage: false,
|
|
@@ -90,7 +94,8 @@ export class SharingProvider extends Component {
|
|
|
90
94
|
revokeAllRecipients: this.revokeAllRecipients,
|
|
91
95
|
refresh: this.fetchAllSharings,
|
|
92
96
|
hasWriteAccess: this.hasWriteAccess,
|
|
93
|
-
renameSharedDrive: this.renameSharedDrive
|
|
97
|
+
renameSharedDrive: this.renameSharedDrive,
|
|
98
|
+
updateSharingMemberType: this.updateSharingMemberType
|
|
94
99
|
}
|
|
95
100
|
this.isPublic = props.isPublic ?? false
|
|
96
101
|
this.realtime = null
|
|
@@ -335,12 +340,116 @@ export class SharingProvider extends Component {
|
|
|
335
340
|
this.dispatch(revokeSelf(sharing))
|
|
336
341
|
}
|
|
337
342
|
|
|
343
|
+
/**
|
|
344
|
+
* Update a sharing member's read_only field to change permission type
|
|
345
|
+
* @param {string} sharingId - The ID of the sharing
|
|
346
|
+
* @param {number} memberIndex - The index of the member in the sharing members array
|
|
347
|
+
* @param {string} newType - 'one-way' for read-only, 'two-way' for read-write
|
|
348
|
+
*/
|
|
349
|
+
updateSharingMemberType = async (sharingId, memberIndex, newType) => {
|
|
350
|
+
const sharing = getSharingById(this.state, sharingId)
|
|
351
|
+
if (!sharing) throw new Error('Sharing not found')
|
|
352
|
+
|
|
353
|
+
const member = sharing.attributes.members[memberIndex]
|
|
354
|
+
if (!member) throw new Error('Member not found')
|
|
355
|
+
|
|
356
|
+
// Find the contact by email (same pattern as helpers/contacts.js)
|
|
357
|
+
const matchedContacts = await this.props.client
|
|
358
|
+
.collection('io.cozy.contacts')
|
|
359
|
+
.find(
|
|
360
|
+
{
|
|
361
|
+
email: { $elemMatch: { address: member.email } },
|
|
362
|
+
_id: { $gt: null }
|
|
363
|
+
},
|
|
364
|
+
{ indexedFields: ['_id'] }
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
if (!matchedContacts.data.length) {
|
|
368
|
+
throw new Error(`Contact not found for member ${member.email}`)
|
|
369
|
+
}
|
|
370
|
+
const contact = matchedContacts.data[0]
|
|
371
|
+
|
|
372
|
+
// Revoke (API call only, no state dispatch to avoid UI flickering)
|
|
373
|
+
await this.sharingCol.revokeRecipient(sharing, memberIndex)
|
|
374
|
+
|
|
375
|
+
// Re-add with the new permission type
|
|
376
|
+
const readOnly = newType === 'one-way'
|
|
377
|
+
try {
|
|
378
|
+
await this.addRecipients({
|
|
379
|
+
document: sharing,
|
|
380
|
+
recipients: readOnly ? [] : [contact],
|
|
381
|
+
readOnlyRecipients: readOnly ? [contact] : []
|
|
382
|
+
})
|
|
383
|
+
} catch (error) {
|
|
384
|
+
log.error(
|
|
385
|
+
`Failed to re-add member ${member.email} after revocation. The member has been revoked but could not be re-added with the new permission type.`,
|
|
386
|
+
error
|
|
387
|
+
)
|
|
388
|
+
throw error
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
338
392
|
shareByLink = async (document, options) => {
|
|
339
|
-
const resp =
|
|
393
|
+
const resp = document.driveId
|
|
394
|
+
? await this.createSharedDriveSharingLink(document, options)
|
|
395
|
+
: await this.permissionCol.createSharingLink(document, options)
|
|
340
396
|
this.dispatch(addSharingLink(resp.data))
|
|
341
397
|
return resp
|
|
342
398
|
}
|
|
343
399
|
|
|
400
|
+
getFederatedShareLink = document => {
|
|
401
|
+
if (!document.driveId) return null
|
|
402
|
+
|
|
403
|
+
const permissions = getDocumentPermissions(this.state, document._id)
|
|
404
|
+
const perm = permissions.find(p => getShortcode(p))
|
|
405
|
+
if (!perm) return null
|
|
406
|
+
|
|
407
|
+
const code = getShortcode(perm)
|
|
408
|
+
if (!code) return null
|
|
409
|
+
|
|
410
|
+
const { client } = this.props
|
|
411
|
+
return generateShareLinkFromFile({
|
|
412
|
+
client,
|
|
413
|
+
file: document,
|
|
414
|
+
sharecode: code,
|
|
415
|
+
getOwner: this.state.getOwner,
|
|
416
|
+
getSharingById: this.state.getSharingById,
|
|
417
|
+
documentType: this.state.documentType
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
createSharedDriveSharingLink = async (document, options) => {
|
|
422
|
+
const { client } = this.props
|
|
423
|
+
const drivePermissionCollection = client.collection('io.cozy.permissions', {
|
|
424
|
+
driveId: document.driveId
|
|
425
|
+
})
|
|
426
|
+
const resp = await drivePermissionCollection.createSharingLink(
|
|
427
|
+
document,
|
|
428
|
+
options
|
|
429
|
+
)
|
|
430
|
+
return resp
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
updateSharedDrivePermissions = async (
|
|
434
|
+
document,
|
|
435
|
+
permissionDocument,
|
|
436
|
+
updatedPermissions,
|
|
437
|
+
options
|
|
438
|
+
) => {
|
|
439
|
+
const { client } = this.props
|
|
440
|
+
const { expiresAt, password } = options
|
|
441
|
+
const drivePermissionCollection = client.collection('io.cozy.permissions', {
|
|
442
|
+
driveId: document.driveId
|
|
443
|
+
})
|
|
444
|
+
const resp = await drivePermissionCollection.add(
|
|
445
|
+
permissionDocument,
|
|
446
|
+
updatedPermissions,
|
|
447
|
+
{ expiresAt, password }
|
|
448
|
+
)
|
|
449
|
+
this.dispatch(updateSharingLink(resp.data))
|
|
450
|
+
return resp
|
|
451
|
+
}
|
|
452
|
+
|
|
344
453
|
/**
|
|
345
454
|
* updateDocumentPermissions - Description
|
|
346
455
|
*
|
|
@@ -356,19 +465,29 @@ export class SharingProvider extends Component {
|
|
|
356
465
|
const { verbs, expiresAt, password } = options
|
|
357
466
|
const permissions = getDocumentPermissions(this.state, document.id)
|
|
358
467
|
|
|
468
|
+
if (!permissions || permissions.length === 0) {
|
|
469
|
+
return []
|
|
470
|
+
}
|
|
471
|
+
|
|
359
472
|
const responses = await Promise.all(
|
|
360
473
|
permissions.map(async permissionDocument => {
|
|
361
474
|
const updatedPermissions = permissionDocument.attributes.permissions
|
|
362
|
-
Object.keys(updatedPermissions).
|
|
475
|
+
Object.keys(updatedPermissions).forEach(permType => {
|
|
363
476
|
updatedPermissions[permType].verbs = verbs
|
|
364
477
|
})
|
|
365
478
|
|
|
366
|
-
const resp =
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
479
|
+
const resp = document.driveId
|
|
480
|
+
? await this.updateSharedDrivePermissions(
|
|
481
|
+
document,
|
|
482
|
+
permissionDocument,
|
|
483
|
+
updatedPermissions,
|
|
484
|
+
options
|
|
485
|
+
)
|
|
486
|
+
: await this.permissionCol.add(
|
|
487
|
+
permissionDocument,
|
|
488
|
+
updatedPermissions,
|
|
489
|
+
{ expiresAt, password }
|
|
490
|
+
)
|
|
372
491
|
return resp
|
|
373
492
|
})
|
|
374
493
|
)
|