cozy-sharing 40.1.6 → 40.1.8

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/components/FederatedFolder/FederatedFolderModal.js +10 -12
  3. package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +2 -2
  4. package/dist/components/Recipient/DowngradePermissionConfirmDialog.js +3 -12
  5. package/dist/components/Recipient/GroupRecipient.js +1 -4
  6. package/dist/components/Recipient/GroupRecipient.stories.js +3 -1
  7. package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +1 -4
  8. package/dist/components/Recipient/GroupRecipientPermissions.js +5 -8
  9. package/dist/components/Recipient/GroupRecipientPermissions.stories.js +2 -0
  10. package/dist/components/Recipient/LinkRecipient.js +2 -6
  11. package/dist/components/Recipient/LinkRecipient.stories.js +4 -0
  12. package/dist/components/Recipient/LinkRecipientPermissions.js +13 -12
  13. package/dist/components/Recipient/LinkRecipientPermissions.stories.js +5 -1
  14. package/dist/components/Recipient/MemberRecipient.js +7 -6
  15. package/dist/components/Recipient/MemberRecipient.spec.js +7 -12
  16. package/dist/components/Recipient/MemberRecipientPermissions.js +28 -13
  17. package/dist/components/Recipient/MemberRecipientPermissions.spec.js +5 -14
  18. package/dist/components/Recipient/MemberRecipientPermissions.stories.js +2 -1
  19. package/dist/components/Recipient/OwnerRecipient.js +4 -17
  20. package/dist/components/Recipient/OwnerRecipient.stories.js +3 -1
  21. package/dist/components/Recipient/OwnerRecipientDefaultLite.js +1 -1
  22. package/dist/components/Recipient/PermissionTypeMenu.js +32 -155
  23. package/dist/components/Recipient/PermissionTypeMenuWrapper.js +37 -0
  24. package/dist/components/Recipient/{PermissionTypeMenu.spec.js → PermissionTypeMenuWrapper.spec.js} +2 -2
  25. package/dist/components/Recipient/RecipientList.js +10 -0
  26. package/dist/components/Recipient/RecipientList.stories.js +3 -0
  27. package/dist/components/{ShareRecipientsInput.js → ShareAutosuggestWrapper.js} +12 -54
  28. package/dist/components/{ShareRecipientsInput.spec.js → ShareAutosuggestWrapper.spec.js} +3 -3
  29. package/dist/components/ShareByEmail.js +2 -2
  30. package/dist/components/ShareDialogCozyToCozy.js +20 -19
  31. package/dist/components/ShareDialogCozyToCozy.spec.js +3 -0
  32. package/dist/components/ShareDialogOnlyByLink.js +3 -5
  33. package/dist/components/ShareDialogOnlyByLink.spec.js +0 -1
  34. package/dist/components/ShareModal/SharingDetailsModal.js +2 -2
  35. package/dist/components/SharedDrive/EditSharedDriveModal.js +11 -10
  36. package/dist/components/SharedDrive/useSharedDrive.js +8 -11
  37. package/dist/components/SharingBanner/components/PublicBanner.js +8 -6
  38. package/dist/components/SharingBanner/components/PublicBanner.spec.js +1 -9
  39. package/dist/components/SharingBanner/components/SharingBanner.js +3 -0
  40. package/dist/components/SharingBanner/index.js +3 -0
  41. package/dist/components/SharingContent.js +3 -5
  42. package/dist/components/WhoHasAccess.js +27 -11
  43. package/dist/components/WhoHasAccessWrapper.js +122 -0
  44. package/dist/helpers/contacts.js +79 -1
  45. package/dist/helpers/contacts.spec.js +122 -1
  46. package/dist/helpers/recipients.js +46 -0
  47. package/dist/helpers/recipients.spec.js +89 -0
  48. package/dist/hooks/useMemberPermissionType.js +191 -0
  49. package/dist/hooks/useResolveRecipients.js +53 -0
  50. package/dist/hooks/useResolveRecipients.spec.js +140 -0
  51. package/dist/index.js +1 -1
  52. package/docs/share-modal-architecture.md +2 -2
  53. package/package.json +3 -3
  54. package/src/components/FederatedFolder/FederatedFolderModal.jsx +6 -12
  55. package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +1 -0
  56. package/src/components/Recipient/DowngradePermissionConfirmDialog.jsx +3 -10
  57. package/src/components/Recipient/GroupRecipient.jsx +1 -5
  58. package/src/components/Recipient/GroupRecipient.stories.jsx +3 -1
  59. package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +1 -4
  60. package/src/components/Recipient/GroupRecipientPermissions.jsx +5 -5
  61. package/src/components/Recipient/GroupRecipientPermissions.stories.jsx +2 -0
  62. package/src/components/Recipient/LinkRecipient.jsx +2 -4
  63. package/src/components/Recipient/LinkRecipient.stories.jsx +4 -0
  64. package/src/components/Recipient/LinkRecipientPermissions.jsx +16 -12
  65. package/src/components/Recipient/LinkRecipientPermissions.stories.jsx +5 -1
  66. package/src/components/Recipient/MemberRecipient.jsx +4 -4
  67. package/src/components/Recipient/MemberRecipient.spec.jsx +7 -10
  68. package/src/components/Recipient/MemberRecipientPermissions.jsx +29 -13
  69. package/src/components/Recipient/MemberRecipientPermissions.spec.jsx +5 -11
  70. package/src/components/Recipient/MemberRecipientPermissions.stories.jsx +2 -1
  71. package/src/components/Recipient/OwnerRecipient.jsx +4 -17
  72. package/src/components/Recipient/OwnerRecipient.stories.jsx +1 -1
  73. package/src/components/Recipient/OwnerRecipientDefaultLite.jsx +1 -1
  74. package/src/components/Recipient/PermissionTypeMenu.jsx +21 -81
  75. package/src/components/Recipient/PermissionTypeMenuWrapper.jsx +32 -0
  76. package/src/components/Recipient/{PermissionTypeMenu.spec.jsx → PermissionTypeMenuWrapper.spec.jsx} +2 -2
  77. package/src/components/Recipient/RecipientList.jsx +10 -0
  78. package/src/components/Recipient/RecipientList.stories.jsx +3 -0
  79. package/src/components/{ShareRecipientsInput.jsx → ShareAutosuggestWrapper.jsx} +14 -65
  80. package/src/components/{ShareRecipientsInput.spec.jsx → ShareAutosuggestWrapper.spec.jsx} +3 -3
  81. package/src/components/ShareByEmail.jsx +2 -2
  82. package/src/components/ShareDialogCozyToCozy.jsx +10 -11
  83. package/src/components/ShareDialogCozyToCozy.spec.jsx +1 -0
  84. package/src/components/ShareDialogOnlyByLink.jsx +2 -4
  85. package/src/components/ShareDialogOnlyByLink.spec.jsx +0 -1
  86. package/src/components/ShareModal/SharingDetailsModal.jsx +2 -2
  87. package/src/components/SharedDrive/EditSharedDriveModal.jsx +6 -11
  88. package/src/components/SharedDrive/useSharedDrive.js +4 -11
  89. package/src/components/SharingBanner/components/PublicBanner.jsx +6 -6
  90. package/src/components/SharingBanner/components/PublicBanner.spec.jsx +1 -8
  91. package/src/components/SharingBanner/components/SharingBanner.jsx +7 -1
  92. package/src/components/SharingBanner/index.jsx +4 -0
  93. package/src/components/SharingContent.jsx +2 -4
  94. package/src/components/WhoHasAccess.jsx +26 -12
  95. package/src/components/WhoHasAccessWrapper.jsx +117 -0
  96. package/src/helpers/contacts.js +83 -0
  97. package/src/helpers/contacts.spec.js +78 -1
  98. package/src/helpers/recipients.js +44 -0
  99. package/src/helpers/recipients.spec.js +82 -0
  100. package/src/hooks/useMemberPermissionType.js +110 -0
  101. package/src/hooks/useResolveRecipients.js +38 -0
  102. package/src/hooks/useResolveRecipients.spec.js +70 -0
  103. package/src/index.jsx +1 -1
  104. package/dist/components/Recipient/OwnerRecipientDefault.js +0 -27
  105. package/dist/components/Recipient/OwnerRecipientDefault.stories.js +0 -10
  106. package/src/components/Recipient/OwnerRecipientDefault.jsx +0 -37
  107. package/src/components/Recipient/OwnerRecipientDefault.stories.jsx +0 -13
@@ -0,0 +1,122 @@
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 React from 'react';
8
+ import { useClient, useQuery, hasQueryBeenLoaded } from 'cozy-client';
9
+ import WhoHasAccess from './WhoHasAccess';
10
+ import { hasMemberActions, markCurrentUser } from '../helpers/recipients';
11
+ import { useMemberPermissionType } from '../hooks/useMemberPermissionType';
12
+ import { useSharingContext } from '../hooks/useSharingContext';
13
+ import { buildInstanceSettingsQuery } from '../queries/queries'; // When the owner is not part of a sharing's members (eg. the folder only has
14
+ // a link), there is no per-sharing avatar to reference. The instance's public
15
+ // avatar still holds the owner's picture. fallback=initials makes the stack
16
+ // serve a generated initials avatar (instead of the app icon) when no picture
17
+ // has been uploaded, matching how avatars are rendered everywhere else.
18
+
19
+ var OWNER_PUBLIC_AVATAR_PATH = '/public/avatar?fallback=initials';
20
+
21
+ var WhoHasAccessWrapper = function WhoHasAccessWrapper(_ref) {
22
+ var _instanceSettingsResu;
23
+
24
+ var _ref$isOwner = _ref.isOwner,
25
+ isOwner = _ref$isOwner === void 0 ? false : _ref$isOwner,
26
+ _ref$canManageSharing = _ref.canManageSharing,
27
+ canManageSharing = _ref$canManageSharing === void 0 ? isOwner : _ref$canManageSharing,
28
+ isSharedDrive = _ref.isSharedDrive,
29
+ isReadOnly = _ref.isReadOnly,
30
+ _ref$canManageMembers = _ref.canManageMembers,
31
+ canManageMembers = _ref$canManageMembers === void 0 ? !isReadOnly : _ref$canManageMembers,
32
+ canManageLink = _ref.canManageLink,
33
+ _ref$showOwner = _ref.showOwner,
34
+ showOwner = _ref$showOwner === void 0 ? true : _ref$showOwner,
35
+ recipients = _ref.recipients,
36
+ _ref$recipientsToBeCo = _ref.recipientsToBeConfirmed,
37
+ recipientsToBeConfirmed = _ref$recipientsToBeCo === void 0 ? [] : _ref$recipientsToBeCo,
38
+ document = _ref.document,
39
+ documentType = _ref.documentType,
40
+ className = _ref.className,
41
+ onRevoke = _ref.onRevoke,
42
+ onRevokeSelf = _ref.onRevokeSelf,
43
+ verifyRecipient = _ref.verifyRecipient,
44
+ link = _ref.link;
45
+ var client = useClient();
46
+
47
+ var _useSharingContext = useSharingContext(),
48
+ isOrgSharedDrive = _useSharingContext.isOrgSharedDrive,
49
+ getDocumentPermissions = _useSharingContext.getDocumentPermissions,
50
+ updateDocumentPermissions = _useSharingContext.updateDocumentPermissions,
51
+ revokeSharingLink = _useSharingContext.revokeSharingLink,
52
+ revokeGroup = _useSharingContext.revokeGroup,
53
+ revokeSelf = _useSharingContext.revokeSelf;
54
+
55
+ var instanceUri = client.options.uri;
56
+ var markedRecipients = markCurrentUser(recipients, instanceUri);
57
+ var hasMemberMenus = markedRecipients.some(function (recipient) {
58
+ return !recipient.members && !recipientsToBeConfirmed.some(function (user) {
59
+ return user.email === recipient.email;
60
+ }) && hasMemberActions({
61
+ status: recipient.status,
62
+ isCurrentUser: recipient.isCurrentUser,
63
+ isOwner: isOwner,
64
+ canManageSharing: canManageSharing,
65
+ canManageMembers: canManageMembers
66
+ });
67
+ });
68
+
69
+ var _useMemberPermissionT = useMemberPermissionType(document, {
70
+ shouldFetchPath: hasMemberMenus
71
+ }),
72
+ isInsideSharedParent = _useMemberPermissionT.isInsideSharedParent,
73
+ sharedParentName = _useMemberPermissionT.sharedParentName,
74
+ setMemberType = _useMemberPermissionT.setMemberType;
75
+
76
+ var ownerRecipient = markedRecipients.find(function (recipient) {
77
+ return recipient.status === 'owner';
78
+ });
79
+ var instanceSettingsQuery = buildInstanceSettingsQuery();
80
+ var instanceSettingsResult = useQuery(instanceSettingsQuery.definition, _objectSpread(_objectSpread({}, instanceSettingsQuery.options), {}, {
81
+ enabled: showOwner && !ownerRecipient
82
+ }));
83
+ var defaultOwner = hasQueryBeenLoaded(instanceSettingsResult) ? {
84
+ isOwner: true,
85
+ status: 'owner',
86
+ instance: instanceUri,
87
+ avatarPath: OWNER_PUBLIC_AVATAR_PATH,
88
+ public_name: (_instanceSettingsResu = instanceSettingsResult.data) === null || _instanceSettingsResu === void 0 || (_instanceSettingsResu = _instanceSettingsResu.attributes) === null || _instanceSettingsResu === void 0 ? void 0 : _instanceSettingsResu.public_name
89
+ } : null;
90
+ var owner = ownerRecipient ? _objectSpread(_objectSpread({}, ownerRecipient), {}, {
91
+ isOrgSharedDrive: isOrgSharedDrive(document === null || document === void 0 ? void 0 : document._id)
92
+ }) : defaultOwner;
93
+ return /*#__PURE__*/React.createElement(WhoHasAccess, {
94
+ isOwner: isOwner,
95
+ canManageSharing: canManageSharing,
96
+ isSharedDrive: isSharedDrive,
97
+ isReadOnly: isReadOnly,
98
+ canManageMembers: canManageMembers,
99
+ canManageLink: canManageLink,
100
+ showOwner: showOwner,
101
+ owner: owner,
102
+ isInsideSharedParent: isInsideSharedParent,
103
+ sharedParentName: sharedParentName,
104
+ recipients: markedRecipients,
105
+ recipientsToBeConfirmed: recipientsToBeConfirmed,
106
+ document: document,
107
+ documentType: documentType,
108
+ className: className,
109
+ onRevoke: onRevoke,
110
+ onRevokeSelf: onRevokeSelf,
111
+ onRevokeGroup: revokeGroup,
112
+ onLeaveGroup: revokeSelf,
113
+ onSetMemberType: setMemberType,
114
+ onUpdateLinkPermissions: updateDocumentPermissions,
115
+ onRevokeLink: revokeSharingLink,
116
+ verifyRecipient: verifyRecipient,
117
+ link: link,
118
+ permissions: getDocumentPermissions(document === null || document === void 0 ? void 0 : document._id)
119
+ });
120
+ };
121
+
122
+ export default WhoHasAccessWrapper;
@@ -1,6 +1,16 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
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
+
2
9
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
- import { validateEmail } from '../helpers/email'; // Return the contact object if present
10
+ import { models } from 'cozy-client';
11
+ import flag from 'cozy-flags';
12
+ import { validateEmail } from '../helpers/email';
13
+ var ContactModel = models.contact; // Return the contact object if present
4
14
  // Else check if a contact exist with this email address, if yes return it
5
15
  // if not create it
6
16
 
@@ -114,4 +124,72 @@ export var getContactsFromGroupId = function getContactsFromGroupId() {
114
124
 
115
125
  export var isContactToBeCreated = function isContactToBeCreated(contact) {
116
126
  return !contact._id;
127
+ };
128
+
129
+ var isCurrentUser = function isCurrentUser(contact) {
130
+ return contact.me === true;
131
+ };
132
+ /**
133
+ * Computes the contacts and groups to suggest when adding recipients to a
134
+ * sharing. The unreachable contacts only count in the members of the groups,
135
+ * when flag sharing.show-recipient-groups is enabled.
136
+ *
137
+ * @param {object} params
138
+ * @param {object[]} params.reachableContacts - Contacts that can be shared with
139
+ * @param {object[]} params.unreachableContactsWithGroups - Contacts that cannot be shared with but belong to a group
140
+ * @param {object[]} params.contactGroups - Groups of contacts
141
+ * @param {object[]} params.currentRecipients - Recipients already in the sharing
142
+ * @param {object[]} params.pendingRecipients - Recipients picked but not yet shared with
143
+ * @returns {object[]} The contacts, then the groups with their members
144
+ */
145
+
146
+
147
+ export var computeContactsAndGroups = function computeContactsAndGroups(_ref3) {
148
+ var reachableContacts = _ref3.reachableContacts,
149
+ unreachableContactsWithGroups = _ref3.unreachableContactsWithGroups,
150
+ contactGroups = _ref3.contactGroups,
151
+ currentRecipients = _ref3.currentRecipients,
152
+ pendingRecipients = _ref3.pendingRecipients;
153
+ var suggestedContacts = reachableContacts.filter(function (contact) {
154
+ return !isCurrentUser(contact) && // We do not want contact already in the sharing
155
+ !currentRecipients.find(function (r) {
156
+ return r.email === ContactModel.getPrimaryEmail(contact);
157
+ }) && // We do not want contact currently in pending contacts (in chips)
158
+ !pendingRecipients.find(function (r) {
159
+ return r._id === contact._id;
160
+ });
161
+ });
162
+ var unreachableContacts = unreachableContactsWithGroups.filter(function (contact) {
163
+ return !isCurrentUser(contact);
164
+ });
165
+ var currentRecipientGroups = currentRecipients.map(function (_ref4) {
166
+ var id = _ref4.id;
167
+ return id;
168
+ }).filter(Boolean);
169
+ var suggestedGroups = contactGroups.filter(function (_ref5) {
170
+ var _id = _ref5._id;
171
+ return !flag('sharing.show-recipient-groups') || !currentRecipientGroups.includes(_id);
172
+ }).map(function (contactGroup) {
173
+ var reachableMembers = getContactsFromGroupId(suggestedContacts, contactGroup.id).map(function (contact) {
174
+ return _objectSpread(_objectSpread({}, contact), {}, {
175
+ isReachable: true
176
+ });
177
+ });
178
+
179
+ if (flag('sharing.show-recipient-groups') !== true) {
180
+ return _objectSpread(_objectSpread({}, contactGroup), {}, {
181
+ members: reachableMembers
182
+ });
183
+ }
184
+
185
+ var unreachableMembers = getContactsFromGroupId(unreachableContacts, contactGroup.id).map(function (contact) {
186
+ return _objectSpread(_objectSpread({}, contact), {}, {
187
+ isReachable: false
188
+ });
189
+ });
190
+ return _objectSpread(_objectSpread({}, contactGroup), {}, {
191
+ members: [].concat(_toConsumableArray(reachableMembers), _toConsumableArray(unreachableMembers))
192
+ });
193
+ });
194
+ return [].concat(_toConsumableArray(suggestedContacts), _toConsumableArray(suggestedGroups));
117
195
  };
@@ -1,6 +1,22 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
1
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
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
+
2
9
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
- import { getOrCreateFromArray } from './contacts';
10
+ import flag from 'cozy-flags';
11
+ import { computeContactsAndGroups, getOrCreateFromArray } from './contacts';
12
+ jest.mock('cozy-flags', function () {
13
+ return {
14
+ __esModule: true,
15
+ default: jest.fn(function () {
16
+ return null;
17
+ })
18
+ };
19
+ });
4
20
  var findMock = jest.fn().mockReturnValueOnce({
5
21
  data: [{
6
22
  id: 2,
@@ -63,4 +79,109 @@ describe('getOrCreateFromArray', function () {
63
79
  }
64
80
  }, _callee);
65
81
  })));
82
+ });
83
+ describe('computeContactsAndGroups', function () {
84
+ var group = {
85
+ id: 'friends',
86
+ _id: 'friends',
87
+ name: 'Friends'
88
+ };
89
+ var inGroup = {
90
+ relationships: {
91
+ groups: {
92
+ data: [{
93
+ _id: 'friends'
94
+ }]
95
+ }
96
+ }
97
+ };
98
+
99
+ var alice = _objectSpread({
100
+ _id: 'alice',
101
+ email: [{
102
+ address: 'alice@cozy.cc',
103
+ primary: true
104
+ }]
105
+ }, inGroup);
106
+
107
+ var bob = _objectSpread({
108
+ _id: 'bob',
109
+ email: [{
110
+ address: 'bob@cozy.cc'
111
+ }]
112
+ }, inGroup);
113
+
114
+ var me = _objectSpread({
115
+ _id: 'me',
116
+ me: true
117
+ }, inGroup);
118
+
119
+ var carol = _objectSpread({
120
+ _id: 'carol'
121
+ }, inGroup);
122
+
123
+ var setup = function setup() {
124
+ var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
125
+ _ref2$currentRecipien = _ref2.currentRecipients,
126
+ currentRecipients = _ref2$currentRecipien === void 0 ? [] : _ref2$currentRecipien,
127
+ _ref2$pendingRecipien = _ref2.pendingRecipients,
128
+ pendingRecipients = _ref2$pendingRecipien === void 0 ? [] : _ref2$pendingRecipien,
129
+ _ref2$showRecipientGr = _ref2.showRecipientGroups,
130
+ showRecipientGroups = _ref2$showRecipientGr === void 0 ? null : _ref2$showRecipientGr;
131
+
132
+ flag.mockReturnValue(showRecipientGroups);
133
+ return computeContactsAndGroups({
134
+ reachableContacts: [alice, bob, me],
135
+ unreachableContactsWithGroups: [carol, me],
136
+ contactGroups: [group],
137
+ currentRecipients: currentRecipients,
138
+ pendingRecipients: pendingRecipients
139
+ });
140
+ };
141
+
142
+ it('suggests the contacts, then the groups with their reachable members', function () {
143
+ var _setup = setup(),
144
+ _setup2 = _slicedToArray(_setup, 3),
145
+ first = _setup2[0],
146
+ second = _setup2[1],
147
+ friends = _setup2[2];
148
+
149
+ expect([first._id, second._id, friends._id]).toEqual(['alice', 'bob', 'friends']);
150
+ expect(friends.members.map(function (m) {
151
+ return [m._id, m.isReachable];
152
+ })).toEqual([['alice', true], ['bob', true]]);
153
+ });
154
+ it('does not suggest the recipients already shared with or picked', function () {
155
+ var contactsAndGroups = setup({
156
+ currentRecipients: [{
157
+ email: 'alice@cozy.cc'
158
+ }],
159
+ pendingRecipients: [bob]
160
+ });
161
+ expect(contactsAndGroups.map(function (c) {
162
+ return c._id;
163
+ })).toEqual(['friends']);
164
+ });
165
+ it('adds the unreachable members when flag sharing.show-recipient-groups is enabled', function () {
166
+ var _setup3 = setup({
167
+ showRecipientGroups: true
168
+ }),
169
+ _setup4 = _slicedToArray(_setup3, 3),
170
+ friends = _setup4[2];
171
+
172
+ expect(friends.members.map(function (m) {
173
+ return [m._id, m.isReachable];
174
+ })).toEqual([['alice', true], ['bob', true], ['carol', false]]);
175
+ });
176
+ it('does not suggest the groups already in the sharing when flag sharing.show-recipient-groups is enabled', function () {
177
+ var contactsAndGroups = setup({
178
+ currentRecipients: [{
179
+ id: 'friends'
180
+ }],
181
+ showRecipientGroups: true
182
+ });
183
+ expect(contactsAndGroups.map(function (c) {
184
+ return c._id;
185
+ })).toEqual(['alice', 'bob']);
186
+ });
66
187
  });
@@ -95,4 +95,50 @@ export var getGroupRecipientSecondaryText = function getGroupRecipientSecondaryT
95
95
  smart_count: nbMember
96
96
  });
97
97
  return secondary + (isUserInsideMembers ? " (".concat(t('GroupRecipient.secondary_you'), ")") : '');
98
+ };
99
+
100
+ var isInstance = function isInstance(recipient, instanceUri) {
101
+ return recipient.instance !== undefined && recipient.instance === instanceUri;
102
+ };
103
+ /**
104
+ * Flags with `isCurrentUser` the recipients, and the members of group
105
+ * recipients, whose instance is the current user's one
106
+ *
107
+ * @param {object[]} recipients - Recipients of a sharing
108
+ * @param {string} instanceUri - URI of the current user's instance
109
+ * @returns {object[]} The recipients with their `isCurrentUser` flag
110
+ */
111
+
112
+
113
+ export var markCurrentUser = function markCurrentUser(recipients, instanceUri) {
114
+ return recipients.map(function (recipient) {
115
+ return _objectSpread(_objectSpread({}, recipient), {}, {
116
+ isCurrentUser: isInstance(recipient, instanceUri)
117
+ }, recipient.members && {
118
+ members: recipient.members.map(function (member) {
119
+ return _objectSpread(_objectSpread({}, member), {}, {
120
+ isCurrentUser: isInstance(member, instanceUri)
121
+ });
122
+ })
123
+ });
124
+ });
125
+ };
126
+ /**
127
+ * @param {object} params
128
+ * @param {string} params.status - Status of the member in the sharing
129
+ * @param {boolean} params.isCurrentUser - Whether the member is the current user
130
+ * @param {boolean} params.isOwner - Whether the current user owns the sharing
131
+ * @param {boolean} params.canManageSharing - Whether the current user can manage the sharing
132
+ * @param {boolean} params.canManageMembers - Whether the members can be managed
133
+ * @returns {boolean} Whether the current user can change the member's
134
+ * permission type or revoke them
135
+ */
136
+
137
+ export var hasMemberActions = function hasMemberActions(_ref2) {
138
+ var status = _ref2.status,
139
+ isCurrentUser = _ref2.isCurrentUser,
140
+ isOwner = _ref2.isOwner,
141
+ canManageSharing = _ref2.canManageSharing,
142
+ canManageMembers = _ref2.canManageMembers;
143
+ return canManageMembers && status !== 'owner' && (isCurrentUser && !isOwner || canManageSharing);
98
144
  };
@@ -0,0 +1,89 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+
4
+ 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; }
5
+
6
+ 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; }
7
+
8
+ import { hasMemberActions, markCurrentUser } from './recipients';
9
+ var instanceUri = 'https://alice.cozy.cc';
10
+ describe('markCurrentUser', function () {
11
+ it('flags the recipient whose instance is the current one', function () {
12
+ var recipients = [{
13
+ email: 'alice@cozy.cc',
14
+ instance: instanceUri
15
+ }, {
16
+ email: 'bob@cozy.cc',
17
+ instance: 'https://bob.cozy.cc'
18
+ }, {
19
+ email: 'carol@cozy.cc'
20
+ }];
21
+ expect(markCurrentUser(recipients, instanceUri).map(function (r) {
22
+ return r.isCurrentUser;
23
+ })).toEqual([true, false, false]);
24
+ });
25
+ it('does not flag a recipient without instance when the instance is unknown', function () {
26
+ expect(markCurrentUser([{
27
+ email: 'carol@cozy.cc'
28
+ }], undefined)).toEqual([{
29
+ email: 'carol@cozy.cc',
30
+ isCurrentUser: false
31
+ }]);
32
+ });
33
+ it('flags the members of group recipients', function () {
34
+ var recipients = [{
35
+ name: 'Team',
36
+ members: [{
37
+ instance: 'https://bob.cozy.cc'
38
+ }, {
39
+ instance: instanceUri
40
+ }]
41
+ }];
42
+
43
+ var _markCurrentUser = markCurrentUser(recipients, instanceUri),
44
+ _markCurrentUser2 = _slicedToArray(_markCurrentUser, 1),
45
+ group = _markCurrentUser2[0];
46
+
47
+ expect(group.isCurrentUser).toBe(false);
48
+ expect(group.members.map(function (m) {
49
+ return m.isCurrentUser;
50
+ })).toEqual([false, true]);
51
+ });
52
+ });
53
+ describe('hasMemberActions', function () {
54
+ var ownerRights = {
55
+ isOwner: true,
56
+ canManageSharing: true,
57
+ canManageMembers: true
58
+ };
59
+ var memberRights = {
60
+ isOwner: false,
61
+ canManageSharing: false,
62
+ canManageMembers: true
63
+ };
64
+ it('gives actions on the members to whom can manage the sharing', function () {
65
+ expect(hasMemberActions(_objectSpread(_objectSpread({}, ownerRights), {}, {
66
+ status: 'ready'
67
+ }))).toBe(true);
68
+ });
69
+ it('gives no action on the owner', function () {
70
+ expect(hasMemberActions(_objectSpread(_objectSpread({}, ownerRights), {}, {
71
+ status: 'owner'
72
+ }))).toBe(false);
73
+ });
74
+ it('gives no action when the members cannot be managed', function () {
75
+ expect(hasMemberActions(_objectSpread(_objectSpread({}, ownerRights), {}, {
76
+ canManageMembers: false,
77
+ status: 'ready'
78
+ }))).toBe(false);
79
+ });
80
+ it('gives actions on themselves to a member who cannot manage the sharing', function () {
81
+ expect(hasMemberActions(_objectSpread(_objectSpread({}, memberRights), {}, {
82
+ status: 'ready',
83
+ isCurrentUser: true
84
+ }))).toBe(true);
85
+ expect(hasMemberActions(_objectSpread(_objectSpread({}, memberRights), {}, {
86
+ status: 'ready'
87
+ }))).toBe(false);
88
+ });
89
+ });
@@ -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
+ };