cozy-sharing 37.2.10 → 37.2.12
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/AGENTS.md +21 -0
- package/CHANGELOG.md +10 -0
- package/README.md +203 -41
- package/dist/components/FederatedFolder/FederatedFolderModal.js +5 -2
- package/dist/components/Recipient/GroupRecipientPermissions.js +3 -2
- package/dist/components/Recipient/MemberRecipientPermissions.js +3 -2
- package/dist/components/Recipient/RecipientList.js +3 -3
- package/dist/components/ShareModal/ShareModal.js +2 -3
- package/dist/components/ShareModal/SharingDetailsModal.js +22 -5
- package/dist/components/WhoHasAccess.js +8 -2
- package/package.json +3 -3
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +8 -1
- package/src/components/Recipient/GroupRecipientPermissions.jsx +2 -2
- package/src/components/Recipient/MemberRecipientPermissions.jsx +2 -2
- package/src/components/Recipient/RecipientList.jsx +3 -3
- package/src/components/ShareModal/ShareModal.jsx +2 -3
- package/src/components/ShareModal/SharingDetailsModal.jsx +25 -4
- package/src/components/WhoHasAccess.jsx +6 -2
package/AGENTS.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# cozy-sharing — agent rules
|
|
2
|
+
|
|
3
|
+
## Keep README.md in sync with the code
|
|
4
|
+
|
|
5
|
+
The implementation is the behavioral source of truth. `README.md` documents the implemented behavior and usage, and MUST be updated in the same commit/PR whenever the behavior or usage changes.
|
|
6
|
+
|
|
7
|
+
### When to update the README
|
|
8
|
+
|
|
9
|
+
- **Feature flags** — a flag is added, removed, renamed, or its default changes → update the "Feature flags" table.
|
|
10
|
+
- **Feature behavior or conditions** — a permission rule, a restriction (e.g. `hasSharedParent` / `hasSharedChild`), a link lifecycle step, or a gating condition changes → update the matching "Feature conditions" table.
|
|
11
|
+
- **Architecture** — the `ShareModal` routing, a new modal/dialog, or the `SharingProvider` context shape changes → update "Architecture".
|
|
12
|
+
|
|
13
|
+
### When NOT to update
|
|
14
|
+
|
|
15
|
+
- Pure refactors with no behavior change.
|
|
16
|
+
- Bug fixes that don't change documented behavior.
|
|
17
|
+
- Test-only or style-only changes.
|
|
18
|
+
|
|
19
|
+
### Rule of thumb
|
|
20
|
+
|
|
21
|
+
If the code and the README disagree after your change, the change is incomplete — fix the README before committing.
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [37.2.12](https://github.com/cozy/cozy-libs/compare/cozy-sharing@37.2.11...cozy-sharing@37.2.12) (2026-07-30)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **sharing:** Make shared-drive member modals consistent and correct ([9dcf67d](https://github.com/cozy/cozy-libs/commit/9dcf67d375600a1a02298dc3036880ae37d08aef))
|
|
11
|
+
|
|
12
|
+
## [37.2.11](https://github.com/cozy/cozy-libs/compare/cozy-sharing@37.2.10...cozy-sharing@37.2.11) (2026-07-30)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package cozy-sharing
|
|
15
|
+
|
|
6
16
|
## [37.2.10](https://github.com/cozy/cozy-libs/compare/cozy-sharing@37.2.9...cozy-sharing@37.2.10) (2026-07-30)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package cozy-sharing
|
package/README.md
CHANGED
|
@@ -1,83 +1,231 @@
|
|
|
1
|
-
#
|
|
1
|
+
# cozy-sharing
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React library that provides sharing UI and logic for Cozy / Twake Drive applications.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It wraps the Cozy Stack sharing API and exposes ready-to-use components (modal, button, banners), hooks, and context for building sharing experiences.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
***
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- import the stylesheet.css: `import 'cozy-sharing/dist/stylesheet.css'`
|
|
9
|
+
## Installation
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
```bash
|
|
12
|
+
yarn add cozy-sharing
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
In your app, you must:
|
|
16
|
+
|
|
17
|
+
- wrap the component tree with `SharingProvider`
|
|
18
|
+
- import the stylesheet: `import 'cozy-sharing/dist/stylesheet.css'`
|
|
19
|
+
|
|
20
|
+
***
|
|
13
21
|
|
|
14
|
-
|
|
22
|
+
## Usage
|
|
15
23
|
|
|
24
|
+
### Provider
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
import SharingProvider from 'cozy-sharing'
|
|
28
|
+
|
|
29
|
+
<SharingProvider doctype="io.cozy.files" documentType="Files">
|
|
30
|
+
<App />
|
|
31
|
+
</SharingProvider>
|
|
16
32
|
```
|
|
33
|
+
|
|
34
|
+
**Props:**
|
|
35
|
+
|
|
36
|
+
| Prop | Required | Description |
|
|
37
|
+
|------|----------|-------------|
|
|
38
|
+
| `doctype` | yes | The cozy doctype (e.g. `io.cozy.files`) |
|
|
39
|
+
| `documentType` | no | Human-readable type for i18n keys (default `'Document'`) |
|
|
40
|
+
| `onShared` | no | Callback fired after a share is created |
|
|
41
|
+
| `isPublic` | no | Set to `true` when rendering a public page (disables fetching) |
|
|
42
|
+
| `previewPath` | no | Custom preview path sent to the share creation |
|
|
43
|
+
|
|
44
|
+
### Built-in components
|
|
45
|
+
|
|
46
|
+
Surrounding application code (imports, state, props) is omitted for brevity.
|
|
47
|
+
|
|
48
|
+
```jsx
|
|
17
49
|
import { ShareModal } from 'cozy-sharing'
|
|
18
50
|
|
|
19
51
|
const ToggleModal = () => {
|
|
20
|
-
const [
|
|
21
|
-
|
|
52
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
22
53
|
return (
|
|
23
54
|
<div>
|
|
24
|
-
<Button onClick={() =>
|
|
25
|
-
{
|
|
55
|
+
<Button onClick={() => setIsOpen(true)}>Share</Button>
|
|
56
|
+
{isOpen && <ShareModal document={doc} onClose={() => setIsOpen(false)} />}
|
|
26
57
|
</div>
|
|
27
58
|
)
|
|
28
59
|
}
|
|
29
60
|
```
|
|
30
61
|
|
|
31
|
-
|
|
62
|
+
### Render-prop components
|
|
32
63
|
|
|
33
|
-
```
|
|
64
|
+
```jsx
|
|
34
65
|
import { SharedDocument } from 'cozy-sharing'
|
|
35
66
|
|
|
67
|
+
const MyComp = () => (
|
|
68
|
+
<SharedDocument docId="123">
|
|
69
|
+
{({ isShared, link }) => (isShared ? link : 'Not shared yet')}
|
|
70
|
+
</SharedDocument>
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Hooks
|
|
75
|
+
|
|
76
|
+
```jsx
|
|
77
|
+
import { useSharingContext } from 'cozy-sharing'
|
|
78
|
+
|
|
36
79
|
const MyComp = () => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{({ isShared, link }) => (
|
|
40
|
-
{isShared ? link : 'Not shared yet'}
|
|
41
|
-
)}
|
|
42
|
-
</SharedDocument>
|
|
43
|
-
)
|
|
80
|
+
const { share } = useSharingContext()
|
|
81
|
+
return <Button onClick={() => share({ document, recipients, ... })}>Share</Button>
|
|
44
82
|
}
|
|
45
83
|
```
|
|
46
84
|
|
|
47
|
-
|
|
85
|
+
***
|
|
48
86
|
|
|
49
|
-
|
|
87
|
+
## How it works
|
|
50
88
|
|
|
51
|
-
|
|
52
|
-
import { SharingContext } from 'cozy-sharing'
|
|
89
|
+
### Permission model
|
|
53
90
|
|
|
54
|
-
|
|
55
|
-
const { share } = useContext(SharingContext)
|
|
91
|
+
The UI exposes two roles, but the stack has more granular verb control:
|
|
56
92
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
93
|
+
| Role | Verbs | Description |
|
|
94
|
+
|------|-------|-------------|
|
|
95
|
+
| **Viewer** | `GET` | Read-only access |
|
|
96
|
+
| **Editor** | `GET, POST, PUT, PATCH` | Read + write + share management |
|
|
97
|
+
|
|
98
|
+
The `write` permission allows editing content, uploading files, deleting files (to the owner's trash), and managing share members (add/remove members, change permissions, view/manage link).
|
|
99
|
+
|
|
100
|
+
### Link sharing (public URL)
|
|
101
|
+
|
|
102
|
+
Creates a public URL accessible without a Twake account. One link per resource at any time.
|
|
103
|
+
|
|
104
|
+
**Options (set in `ShareRestrictionModal` or `ShareLinkAccessModal`):**
|
|
105
|
+
|
|
106
|
+
| Option | Default | Details |
|
|
107
|
+
|--------|---------|---------|
|
|
108
|
+
| Permission | `readOnly` | Can be changed to `write` |
|
|
109
|
+
| Expiration date | Off | Toggle; defaults to 30 days ahead when enabled; expires at end of that day |
|
|
110
|
+
| Password | Off | Minimum 4 characters; owner communicates it out-of-band |
|
|
111
|
+
|
|
112
|
+
**Lifecycle:**
|
|
113
|
+
|
|
114
|
+
- Deactivating a link revokes the current permissions. Reactivating generates a **new URL** — the old one stays invalid.
|
|
115
|
+
- Deleting the root resource revokes all associated shares (link and email).
|
|
116
|
+
- Link sharing coexists with email sharing on the same resource.
|
|
60
117
|
|
|
61
|
-
|
|
118
|
+
### Email sharing (cozy-to-cozy)
|
|
119
|
+
|
|
120
|
+
Invites specific users or groups with individualized permissions. Two technical modes:
|
|
121
|
+
|
|
122
|
+
- **Cozy-to-cozy sharing** (classic) — data is **replicated** to each recipient's Cozy.
|
|
123
|
+
- **Shared drives** (shared folders, team drives) — recipients access files at the **owner's instance** (no replication).
|
|
124
|
+
|
|
125
|
+
In both cases, content appears in the recipient's **Sharing tab**.
|
|
126
|
+
|
|
127
|
+
**By recipient status:**
|
|
128
|
+
|
|
129
|
+
| Recipient status | Behavior |
|
|
130
|
+
|-----------------|----------|
|
|
131
|
+
| Trusted contact (same org or previously accepted) | Content appears directly in the Sharing tab; notification sent |
|
|
132
|
+
| Has Twake account, not in contacts | Invitation email → login → Sharing tab |
|
|
133
|
+
| **No Twake account** | ❌ Not supported today |
|
|
134
|
+
| **Different SSO** | ❌ Not supported today |
|
|
135
|
+
| Not trusted (guest in org) | ❌ Only if added manually; not automated today |
|
|
136
|
+
|
|
137
|
+
### Cohabitation
|
|
138
|
+
|
|
139
|
+
Link and email sharing can coexist on the same resource. The recipient's permission is the most permissive when both apply.
|
|
140
|
+
|
|
141
|
+
***
|
|
142
|
+
|
|
143
|
+
## Feature conditions
|
|
144
|
+
|
|
145
|
+
### Link sharing
|
|
146
|
+
|
|
147
|
+
| Condition | Rule | Source |
|
|
148
|
+
|-----------|------|--------|
|
|
149
|
+
| Who can create/manage | Owner or Editor (`canReshare` = owner, or `open_sharing && !read_only`) | `canReshare()` in `state.js` |
|
|
150
|
+
| Document type restriction | Hidden when `documentType === 'Organizations'` | `ShareModal.jsx:33` |
|
|
151
|
+
| Albums | Link-only, read-only permissions only | `ShareModal.jsx:30`, `link.js:3` |
|
|
152
|
+
| Editing rights box | Hidden when `drive.federated-shared-folder.enabled` flag is true | `BoxEditingRights.jsx:54` |
|
|
153
|
+
| Expiration date toggle default | Controlled by `sharing.date-toggle.enabled` flag (default: false) | `ShareRestrictionModal.jsx:62` |
|
|
154
|
+
| Link deactivation | Revokes the permission document; regenerates a new URL on reactivation | `SharingProvider.jsx:635` |
|
|
155
|
+
| Password | 4+ characters; no limit on attempts | `ShareLinkSettings.jsx:10` |
|
|
156
|
+
| Guest access | Via `/public` URL with `sharecode`; no auth required | `helpers.js:106` |
|
|
157
|
+
|
|
158
|
+
### Email sharing
|
|
159
|
+
|
|
160
|
+
| Condition | Rule | Source |
|
|
161
|
+
|-----------|------|--------|
|
|
162
|
+
| Who can share | Owner or Editor (`canReshare`) | `SharingProvider.jsx` |
|
|
163
|
+
| **Core constraint** | Disabled if `hasSharedParent` OR `hasSharedChild` — a subfolder of an email-shared folder cannot be shared by email independently | `ShareModal.jsx:32`, `state.js:508-523` |
|
|
164
|
+
| Recipients limit | Default 100; overridable via `sharing.recipients-limit` flag | `helpers/recipients.js:33` |
|
|
165
|
+
| Recipient display mode | `sharing.show-recipient-groups` flag: `true` = groups as units, `false` = spread group members | `ShareByEmail.jsx:31` |
|
|
166
|
+
| Read-only sharing | If the existing sharing is read-only, only the `readOnly` option is offered | `ShareByEmail.jsx:46-57` |
|
|
167
|
+
| Contacts shown | Only contacts with a defined `email` or `cozy` URL | `helpers/recipients.js:72-73` |
|
|
168
|
+
| Group sharing | All members get the same permission; dynamic membership (add/remove) propagates | `state.js:414-451` |
|
|
169
|
+
|
|
170
|
+
### Shared drives & federated folders
|
|
171
|
+
|
|
172
|
+
| Condition | Rule | Source |
|
|
173
|
+
|-----------|------|--------|
|
|
174
|
+
| Org shared drive | `isOrgSharedDrive` = `sharing.drive === true && sharing.org_drive === true` | `state.js:324` |
|
|
175
|
+
| `canLeave` | `false` for org shared drives | `state.js:335` |
|
|
176
|
+
| `canReshare` | `!org_drive && !read_only` for drives; `open_sharing && !read_only` for folders | `state.js:342` |
|
|
177
|
+
| Federated folder modal | Enabled by `drive.federated-shared-folder.enabled` flag and `document.driveId` | `ShareModal.jsx:39` |
|
|
178
|
+
| Email sharing in federated folder | Disabled for files inside a federated shared folder (has `driveId` but is not the root) | `FederatedFolderModal.jsx:122-126` |
|
|
179
|
+
| Link sharing in federated folder | Uses `getFederatedShareLink` which resolves the owner's instance URL | `FederatedFolderModal.jsx:108-110` |
|
|
180
|
+
| Member view inside shared drive | Subfolder members see link management only (no member cross/perm). Root members with `canReshare` see full member management; read-only root members see link management only. | `FederatedFolderModal.jsx:118-133`, `SharingDetailsModal.jsx:38-39` |
|
|
181
|
+
|
|
182
|
+
### Share management
|
|
183
|
+
|
|
184
|
+
| Condition | Rule | Source |
|
|
185
|
+
|-----------|------|--------|
|
|
186
|
+
| Editable modal | `isEditable = !byDocId[doc] \|\| isOwner(doc) \|\| canReshare(doc)` | `ShareModal.jsx:35-36` |
|
|
187
|
+
| Non-editable view | `SharingDetailsModal` — read-only members (no cross/perm menu), with link management (gear + copy link) for shared drives | `ShareModal.jsx:53-62` |
|
|
188
|
+
| Updating member type | `updateSharingMemberType` calls `setReadOnly` / `setReadWrite` on the stack | `SharingProvider.jsx:361-420` |
|
|
189
|
+
| Revoke self | Available to all recipients | `SharingProvider.jsx:349-353` |
|
|
190
|
+
| Revoke group | Available to owner/editor; removes all group members at once | `SharingProvider.jsx:336-347` |
|
|
191
|
+
|
|
192
|
+
### Native mobile sharing
|
|
193
|
+
|
|
194
|
+
| Condition | Rule | Source |
|
|
195
|
+
|-----------|------|--------|
|
|
196
|
+
| Availability | Only in flagship app (`isFlagshipApp()`) when `shareFiles` intent is available | `NativeFileSharingProvider.jsx:26-27` |
|
|
197
|
+
| Restriction | Files only (not directories) | `shareNative.js:42` |
|
|
198
|
+
|
|
199
|
+
***
|
|
200
|
+
|
|
201
|
+
## Feature flags
|
|
202
|
+
|
|
203
|
+
| Flag | Default | Effect |
|
|
204
|
+
|------|---------|--------|
|
|
205
|
+
| `cozy.hide-sharing-cozy-to-cozy` | `false` | When `true`, hides cozy-to-cozy sharing entirely; only link sharing is available |
|
|
206
|
+
| `drive.federated-shared-folder.enabled` | `false` | Enables federated folder modal (shared drives across instances) |
|
|
207
|
+
| `sharing.date-toggle.enabled` | `false` | Default state of the expiration date toggle when creating a new link |
|
|
208
|
+
| `sharing.show-recipient-groups` | `false` | When `true`, groups are shown as distinct recipients; when `false`, group members are spread |
|
|
209
|
+
| `sharing.recipients-limit` | `100` | Maximum number of recipients per document |
|
|
210
|
+
| `signup-url` / `signup.url` | `https://sign-up.twake.app` | URL used for the sharing banner "create account" call-to-action |
|
|
211
|
+
|
|
212
|
+
## Development
|
|
213
|
+
|
|
214
|
+
### Share and send mail in development
|
|
62
215
|
|
|
63
216
|
Cozy apps let users [share documents from cozy to cozy](https://github.com/cozy/cozy-stack/blob/master/docs/sharing.md#cozy-to-cozy-sharing).
|
|
64
217
|
|
|
65
|
-
Meet Alice and Bob.
|
|
66
|
-
Alice wants to share a folder with Bob.
|
|
67
|
-
Alice clicks on the share button and fills in the email input with Bob's email address.
|
|
68
|
-
Bob receives an email with a *« Accept the sharing »* button.
|
|
69
|
-
Bob clicks on that button and is redirected to Alice's cozy to enter his own cozy url to link both cozys.
|
|
70
|
-
Bob sees Alice's shared folder in his own cozy.
|
|
218
|
+
Meet Alice and Bob. Alice wants to share a folder with Bob. Alice clicks on the share button and fills in the email input with Bob's email address. Bob receives an email with a *"Accept the sharing"* button. Bob clicks on that button and is redirected to Alice's cozy to enter his own cozy url to link both cozys. Bob sees Alice's shared folder in his own cozy.
|
|
71
219
|
|
|
72
|
-
|
|
220
|
+
But how could we do this scenario on development environment?
|
|
73
221
|
|
|
74
|
-
|
|
222
|
+
#### With the docker image
|
|
75
223
|
|
|
76
224
|
If you develop with the [cozy-app-dev docker image](https://github.com/cozy/cozy-stack/blob/master/docs/client-app-dev.md#with-docker), [MailHog](https://github.com/mailhog/MailHog) is running inside it to catch emails.
|
|
77
225
|
|
|
78
226
|
If cozy-stack has to send an email, MailHog catches it and exposes it on its web interface on <http://cozy.tools:8025/>.
|
|
79
227
|
|
|
80
|
-
|
|
228
|
+
#### With the binary cozy-stack
|
|
81
229
|
|
|
82
230
|
If you develop with the [cozy-stack CLI](https://github.com/cozy/cozy-stack/blob/master/docs/cli/cozy-stack.md), you have to run [MailHog](https://github.com/mailhog/MailHog) on your computer and tell `cozy-stack serve` where to find the mail server with some [options](https://github.com/cozy/cozy-stack/blob/master/docs/cli/cozy-stack_serve.md#options):
|
|
83
231
|
|
|
@@ -89,6 +237,20 @@ If you develop with the [cozy-stack CLI](https://github.com/cozy/cozy-stack/blob
|
|
|
89
237
|
|
|
90
238
|
Then simply run `mailhog` and open <http://cozy.tools:8025/>.
|
|
91
239
|
|
|
92
|
-
|
|
240
|
+
#### Retrieve sent emails
|
|
93
241
|
|
|
94
242
|
With MailHog, **every email** sent by cozy-stack is caught. That means the email address *does not have to be a real one*, ie. `bob@cozy`, `bob@cozy.tools` are perfectly fine. It *could be a real one*, but the email will not reach the real recipient's inbox, say `contact@cozycloud.cc`.
|
|
243
|
+
|
|
244
|
+
***
|
|
245
|
+
|
|
246
|
+
## Architecture
|
|
247
|
+
|
|
248
|
+
The share modal's component tree is documented in [`docs/share-modal-architecture.md`](docs/share-modal-architecture.md).
|
|
249
|
+
|
|
250
|
+
Key decisions:
|
|
251
|
+
|
|
252
|
+
- `ShareModal` checks `isEditable` → `EditableSharingModal` (editable) or `SharingDetailsModal` (read-only).
|
|
253
|
+
- `EditableSharingModal` renders `ShareModal` (the dumb component), which decides `ShareDialogCozyToCozy` vs `ShareDialogOnlyByLink` based on flags and context.
|
|
254
|
+
- `ShareDialogTwoStepsConfirmationContainer` wraps the cozy-to-cozy dialog when recipients need confirmation (untrusted contacts).
|
|
255
|
+
- Federated mode: when `drive.federated-shared-folder.enabled` is true, `FederatedFolderModal` replaces the standard `EditableSharingModal`.
|
|
256
|
+
- `WhoHasAccess` accepts an independent `canManageLink` prop to control link management (gear + perm dropdown) separately from `canManageMembers` which controls member management. This allows shared-drive members to see the link gear without the member cross/perm menu.
|
|
@@ -41,7 +41,7 @@ import WhoHasAccess from '../WhoHasAccess';
|
|
|
41
41
|
var log = minilog('FederatedFolderModal');
|
|
42
42
|
|
|
43
43
|
var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
44
|
-
var _sharedDriveSharing$a, _sharedDriveSharing$a2;
|
|
44
|
+
var _sharedDriveSharing$a, _sharedDriveSharing$a2, _sharedDriveSharing$a3;
|
|
45
45
|
|
|
46
46
|
var onClose = _ref.onClose,
|
|
47
47
|
onRevokeSuccess = _ref.onRevokeSuccess,
|
|
@@ -137,7 +137,8 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
137
137
|
return id === (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument._id) || id === (existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.id);
|
|
138
138
|
}));
|
|
139
139
|
var isInsideSharedDrive = Boolean((existingDocument === null || existingDocument === void 0 ? void 0 : existingDocument.driveId) && !isSharedDriveRoot);
|
|
140
|
-
var isCurrentUserOwner = documentId ? isOwner(documentId) : false;
|
|
140
|
+
var isCurrentUserOwner = existingDocument !== null && existingDocument !== void 0 && existingDocument.driveId ? Boolean(sharedDriveSharing === null || sharedDriveSharing === void 0 || (_sharedDriveSharing$a3 = sharedDriveSharing.attributes) === null || _sharedDriveSharing$a3 === void 0 ? void 0 : _sharedDriveSharing$a3.owner) : documentId ? isOwner(documentId) : false;
|
|
141
|
+
var isMemberReadOnly = isInsideSharedDrive && !isCurrentUserOwner;
|
|
141
142
|
var hasParentRestriction = isInsideSharedDrive || hasSharedParentByPath;
|
|
142
143
|
var hasChildRestriction = Boolean(documentPath && hasSharedChild(documentPath));
|
|
143
144
|
var canShareByEmail = !hasParentRestriction && !hasChildRestriction;
|
|
@@ -391,6 +392,8 @@ var FederatedFolderModalContent = function FederatedFolderModalContent(_ref) {
|
|
|
391
392
|
isOwner: isCurrentUserOwner,
|
|
392
393
|
canManageSharing: canManageSharing,
|
|
393
394
|
isSharedDrive: true,
|
|
395
|
+
canManageMembers: !isMemberReadOnly,
|
|
396
|
+
canManageLink: true,
|
|
394
397
|
recipients: isSending ? frozenRecipients : existingRecipients,
|
|
395
398
|
document: isSending ? frozenDoc : existingDocument,
|
|
396
399
|
documentType: "Files",
|
|
@@ -21,7 +21,8 @@ var GroupRecipientPermissions = function GroupRecipientPermissions(_ref) {
|
|
|
21
21
|
var name = _ref.name,
|
|
22
22
|
color = _ref.color,
|
|
23
23
|
isOwner = _ref.isOwner,
|
|
24
|
-
|
|
24
|
+
_ref$canManageMembers = _ref.canManageMembers,
|
|
25
|
+
canManageMembers = _ref$canManageMembers === void 0 ? true : _ref$canManageMembers,
|
|
25
26
|
sharingId = _ref.sharingId,
|
|
26
27
|
groupIndex = _ref.groupIndex,
|
|
27
28
|
_ref$read_only = _ref.read_only,
|
|
@@ -49,7 +50,7 @@ var GroupRecipientPermissions = function GroupRecipientPermissions(_ref) {
|
|
|
49
50
|
revoking = _useState4[0],
|
|
50
51
|
setRevoking = _useState4[1];
|
|
51
52
|
|
|
52
|
-
var shouldShowMenu =
|
|
53
|
+
var shouldShowMenu = canManageMembers && !revoking && (isOwner || isUserInsideMembers);
|
|
53
54
|
|
|
54
55
|
var toggleMenu = function toggleMenu() {
|
|
55
56
|
return setMenuDisplayed(!isMenuDisplayed);
|
|
@@ -14,7 +14,8 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
|
14
14
|
var isOwner = _ref.isOwner,
|
|
15
15
|
_ref$canManageSharing = _ref.canManageSharing,
|
|
16
16
|
canManageSharing = _ref$canManageSharing === void 0 ? isOwner : _ref$canManageSharing,
|
|
17
|
-
|
|
17
|
+
_ref$canManageMembers = _ref.canManageMembers,
|
|
18
|
+
canManageMembers = _ref$canManageMembers === void 0 ? true : _ref$canManageMembers,
|
|
18
19
|
status = _ref.status,
|
|
19
20
|
instance = _ref.instance,
|
|
20
21
|
type = _ref.type,
|
|
@@ -36,7 +37,7 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
|
|
|
36
37
|
|
|
37
38
|
var instanceMatchesClient = instance !== undefined && instance === client.options.uri;
|
|
38
39
|
var contactIsOwner = status === 'owner';
|
|
39
|
-
var shouldShowMenu =
|
|
40
|
+
var shouldShowMenu = canManageMembers && !revoking && !contactIsOwner && (instanceMatchesClient && !isOwner || canManageSharing);
|
|
40
41
|
var handleRevocation = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
41
42
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
42
43
|
while (1) switch (_context.prev = _context.next) {
|
|
@@ -10,8 +10,8 @@ var RecipientList = function RecipientList(_ref) {
|
|
|
10
10
|
recipientsToBeConfirmed = _ref.recipientsToBeConfirmed,
|
|
11
11
|
isOwner = _ref.isOwner,
|
|
12
12
|
canManageSharing = _ref.canManageSharing,
|
|
13
|
+
canManageMembers = _ref.canManageMembers,
|
|
13
14
|
isSharedDrive = _ref.isSharedDrive,
|
|
14
|
-
isReadOnly = _ref.isReadOnly,
|
|
15
15
|
document = _ref.document,
|
|
16
16
|
documentType = _ref.documentType,
|
|
17
17
|
onRevoke = _ref.onRevoke,
|
|
@@ -28,7 +28,7 @@ var RecipientList = function RecipientList(_ref) {
|
|
|
28
28
|
if (isGroupRecipient) {
|
|
29
29
|
return /*#__PURE__*/React.createElement(GroupRecipient, _extends({}, recipient, {
|
|
30
30
|
isOwner: isOwner,
|
|
31
|
-
|
|
31
|
+
canManageMembers: canManageMembers,
|
|
32
32
|
key: recipient.index,
|
|
33
33
|
document: document,
|
|
34
34
|
documentType: documentType,
|
|
@@ -42,8 +42,8 @@ var RecipientList = function RecipientList(_ref) {
|
|
|
42
42
|
key: recipient.index,
|
|
43
43
|
isOwner: isOwner,
|
|
44
44
|
canManageSharing: canManageSharing,
|
|
45
|
+
canManageMembers: canManageMembers,
|
|
45
46
|
isSharedDrive: isSharedDrive,
|
|
46
|
-
isReadOnly: isReadOnly,
|
|
47
47
|
document: document,
|
|
48
48
|
documentType: documentType,
|
|
49
49
|
onRevoke: onRevoke,
|
|
@@ -30,8 +30,7 @@ export var ShareModal = withLocales(function (props) {
|
|
|
30
30
|
canReshare = _useSharingContext.canReshare,
|
|
31
31
|
documentType = _useSharingContext.documentType,
|
|
32
32
|
getRecipients = _useSharingContext.getRecipients,
|
|
33
|
-
revokeSelf = _useSharingContext.revokeSelf
|
|
34
|
-
allLoaded = _useSharingContext.allLoaded;
|
|
33
|
+
revokeSelf = _useSharingContext.revokeSelf;
|
|
35
34
|
|
|
36
35
|
var handleRevokeSelf = /*#__PURE__*/function () {
|
|
37
36
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(document) {
|
|
@@ -61,7 +60,7 @@ export var ShareModal = withLocales(function (props) {
|
|
|
61
60
|
if (isEditable) {
|
|
62
61
|
var isFederatedMode = flag('drive.federated-shared-folder.enabled');
|
|
63
62
|
|
|
64
|
-
if (isFederatedMode &&
|
|
63
|
+
if (isFederatedMode && document.driveId) {
|
|
65
64
|
return /*#__PURE__*/React.createElement(FederatedFolderModal, _extends({
|
|
66
65
|
document: document,
|
|
67
66
|
onRevokeSuccess: onRevokeSuccess
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { FixedDialog } from 'cozy-ui/transpiled/react/CozyDialogs';
|
|
4
4
|
import { useI18n } from 'twake-i18n';
|
|
5
|
+
import { useSharingContext } from '../../hooks/useSharingContext';
|
|
5
6
|
var styles = {
|
|
6
7
|
"share-modal-content": "share__share-modal-content___1iqEq",
|
|
7
8
|
"coz-form": "share__coz-form___1ICST",
|
|
@@ -20,6 +21,7 @@ var styles = {
|
|
|
20
21
|
"share-byemail-onlybylink": "share__share-byemail-onlybylink___29W-t",
|
|
21
22
|
"aligned-dropdown-button": "share__aligned-dropdown-button___3crgG"
|
|
22
23
|
};
|
|
24
|
+
import ShareByLink from '../ShareByLink';
|
|
23
25
|
import WhoHasAccess from '../WhoHasAccess';
|
|
24
26
|
export var SharingDetailsModal = function SharingDetailsModal(_ref) {
|
|
25
27
|
var recipients = _ref.recipients,
|
|
@@ -33,7 +35,13 @@ export var SharingDetailsModal = function SharingDetailsModal(_ref) {
|
|
|
33
35
|
var _useI18n = useI18n(),
|
|
34
36
|
t = _useI18n.t;
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
var _useSharingContext = useSharingContext(),
|
|
39
|
+
getSharingLink = _useSharingContext.getSharingLink,
|
|
40
|
+
getFederatedShareLink = _useSharingContext.getFederatedShareLink;
|
|
41
|
+
|
|
42
|
+
var isSharedDrive = Boolean(document === null || document === void 0 ? void 0 : document.driveId);
|
|
43
|
+
var displayedLink = isSharedDrive ? getFederatedShareLink(document) : getSharingLink(document === null || document === void 0 ? void 0 : document._id);
|
|
44
|
+
return /*#__PURE__*/React.createElement(FixedDialog, {
|
|
37
45
|
disableGutters: true,
|
|
38
46
|
open: true,
|
|
39
47
|
onClose: onClose,
|
|
@@ -42,14 +50,23 @@ export var SharingDetailsModal = function SharingDetailsModal(_ref) {
|
|
|
42
50
|
content: /*#__PURE__*/React.createElement("div", {
|
|
43
51
|
className: styles['share-modal-content']
|
|
44
52
|
}, /*#__PURE__*/React.createElement(WhoHasAccess, {
|
|
45
|
-
|
|
53
|
+
canManageMembers: false,
|
|
54
|
+
canManageLink: isSharedDrive,
|
|
55
|
+
isSharedDrive: isSharedDrive,
|
|
46
56
|
recipients: recipients,
|
|
47
57
|
document: document,
|
|
48
58
|
documentType: documentType,
|
|
49
59
|
onRevoke: onRevoke,
|
|
50
60
|
onRevokeSelf: onRevokeSelf,
|
|
51
|
-
link:
|
|
52
|
-
}))
|
|
61
|
+
link: displayedLink
|
|
62
|
+
})),
|
|
63
|
+
actions: isSharedDrive && /*#__PURE__*/React.createElement(ShareByLink, {
|
|
64
|
+
link: displayedLink,
|
|
65
|
+
document: document,
|
|
66
|
+
documentType: "Files",
|
|
67
|
+
showGenerateLinkButton: true,
|
|
68
|
+
autoOpenShareRestriction: false
|
|
69
|
+
})
|
|
53
70
|
});
|
|
54
71
|
};
|
|
55
72
|
SharingDetailsModal.propTypes = {
|
|
@@ -37,6 +37,10 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
37
37
|
isSharedDrive = _ref2$isSharedDrive === void 0 ? false : _ref2$isSharedDrive,
|
|
38
38
|
_ref2$isReadOnly = _ref2.isReadOnly,
|
|
39
39
|
isReadOnly = _ref2$isReadOnly === void 0 ? false : _ref2$isReadOnly,
|
|
40
|
+
_ref2$canManageMember = _ref2.canManageMembers,
|
|
41
|
+
canManageMembers = _ref2$canManageMember === void 0 ? !isReadOnly : _ref2$canManageMember,
|
|
42
|
+
_ref2$canManageLink = _ref2.canManageLink,
|
|
43
|
+
canManageLink = _ref2$canManageLink === void 0 ? canManageMembers : _ref2$canManageLink,
|
|
40
44
|
_ref2$showOwner = _ref2.showOwner,
|
|
41
45
|
showOwner = _ref2$showOwner === void 0 ? true : _ref2$showOwner,
|
|
42
46
|
recipients = _ref2.recipients,
|
|
@@ -63,7 +67,7 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
63
67
|
}, /*#__PURE__*/React.createElement(RecipientWaitingForConfirmationAlert, {
|
|
64
68
|
recipientsToBeConfirmed: recipientsToBeConfirmed
|
|
65
69
|
}), /*#__PURE__*/React.createElement(List, null, link && /*#__PURE__*/React.createElement(LinkRecipient, {
|
|
66
|
-
isReadOnly:
|
|
70
|
+
isReadOnly: !canManageLink,
|
|
67
71
|
document: document,
|
|
68
72
|
documentType: documentType,
|
|
69
73
|
onRevoke: onRevoke,
|
|
@@ -78,8 +82,8 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
78
82
|
recipientsToBeConfirmed: recipientsToBeConfirmed,
|
|
79
83
|
isOwner: isOwner,
|
|
80
84
|
canManageSharing: canManageSharing,
|
|
85
|
+
canManageMembers: canManageMembers,
|
|
81
86
|
isSharedDrive: isSharedDrive,
|
|
82
|
-
isReadOnly: isReadOnly,
|
|
83
87
|
document: document,
|
|
84
88
|
documentType: documentType,
|
|
85
89
|
onRevoke: onRevoke,
|
|
@@ -92,6 +96,8 @@ var WhoHasAccess = function WhoHasAccess(_ref2) {
|
|
|
92
96
|
WhoHasAccess.propTypes = {
|
|
93
97
|
isOwner: PropTypes.bool,
|
|
94
98
|
canManageSharing: PropTypes.bool,
|
|
99
|
+
canManageMembers: PropTypes.bool,
|
|
100
|
+
canManageLink: PropTypes.bool,
|
|
95
101
|
showOwner: PropTypes.bool,
|
|
96
102
|
recipients: PropTypes.array.isRequired,
|
|
97
103
|
recipientsToBeConfirmed: PropTypes.arrayOf(PropTypes.shape({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "37.2.
|
|
3
|
+
"version": "37.2.12",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"cozy-intent": "^2.31.1",
|
|
60
60
|
"cozy-minilog": "^3.10.1",
|
|
61
61
|
"cozy-ui": "^140.5.0",
|
|
62
|
-
"cozy-ui-plus": "^12.3.
|
|
62
|
+
"cozy-ui-plus": "^12.3.6",
|
|
63
63
|
"jest": "30.3.0",
|
|
64
64
|
"jest-environment-jsdom": "30.3.0",
|
|
65
65
|
"react": "16.12.0",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"sideEffects": [
|
|
86
86
|
"*.css"
|
|
87
87
|
],
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "8dbc03f6ef437764cfec18a0b2a6e1b44102f7c3"
|
|
89
89
|
}
|
|
@@ -118,7 +118,12 @@ const FederatedFolderModalContent = ({
|
|
|
118
118
|
const isInsideSharedDrive = Boolean(
|
|
119
119
|
existingDocument?.driveId && !isSharedDriveRoot
|
|
120
120
|
)
|
|
121
|
-
const isCurrentUserOwner =
|
|
121
|
+
const isCurrentUserOwner = existingDocument?.driveId
|
|
122
|
+
? Boolean(sharedDriveSharing?.attributes?.owner)
|
|
123
|
+
: documentId
|
|
124
|
+
? isOwner(documentId)
|
|
125
|
+
: false
|
|
126
|
+
const isMemberReadOnly = isInsideSharedDrive && !isCurrentUserOwner
|
|
122
127
|
const hasParentRestriction = isInsideSharedDrive || hasSharedParentByPath
|
|
123
128
|
const hasChildRestriction = Boolean(
|
|
124
129
|
documentPath && hasSharedChild(documentPath)
|
|
@@ -322,6 +327,8 @@ const FederatedFolderModalContent = ({
|
|
|
322
327
|
isOwner={isCurrentUserOwner}
|
|
323
328
|
canManageSharing={canManageSharing}
|
|
324
329
|
isSharedDrive
|
|
330
|
+
canManageMembers={!isMemberReadOnly}
|
|
331
|
+
canManageLink={true}
|
|
325
332
|
recipients={isSending ? frozenRecipients : existingRecipients}
|
|
326
333
|
document={isSending ? frozenDoc : existingDocument}
|
|
327
334
|
documentType="Files"
|
|
@@ -20,7 +20,7 @@ const GroupRecipientPermissions = ({
|
|
|
20
20
|
name,
|
|
21
21
|
color,
|
|
22
22
|
isOwner,
|
|
23
|
-
|
|
23
|
+
canManageMembers = true,
|
|
24
24
|
sharingId,
|
|
25
25
|
groupIndex,
|
|
26
26
|
read_only = false,
|
|
@@ -36,7 +36,7 @@ const GroupRecipientPermissions = ({
|
|
|
36
36
|
const [revoking, setRevoking] = useState(false)
|
|
37
37
|
|
|
38
38
|
const shouldShowMenu =
|
|
39
|
-
|
|
39
|
+
canManageMembers && !revoking && (isOwner || isUserInsideMembers)
|
|
40
40
|
|
|
41
41
|
const toggleMenu = () => setMenuDisplayed(!isMenuDisplayed)
|
|
42
42
|
const hideMenu = () => setMenuDisplayed(false)
|
|
@@ -12,7 +12,7 @@ import { PermissionTypeMenu } from './PermissionTypeMenu'
|
|
|
12
12
|
const MemberRecipientPermissions = ({
|
|
13
13
|
isOwner,
|
|
14
14
|
canManageSharing = isOwner,
|
|
15
|
-
|
|
15
|
+
canManageMembers = true,
|
|
16
16
|
status,
|
|
17
17
|
instance,
|
|
18
18
|
type,
|
|
@@ -31,7 +31,7 @@ const MemberRecipientPermissions = ({
|
|
|
31
31
|
instance !== undefined && instance === client.options.uri
|
|
32
32
|
const contactIsOwner = status === 'owner'
|
|
33
33
|
const shouldShowMenu =
|
|
34
|
-
|
|
34
|
+
canManageMembers &&
|
|
35
35
|
!revoking &&
|
|
36
36
|
!contactIsOwner &&
|
|
37
37
|
((instanceMatchesClient && !isOwner) || canManageSharing)
|
|
@@ -10,8 +10,8 @@ const RecipientList = ({
|
|
|
10
10
|
recipientsToBeConfirmed,
|
|
11
11
|
isOwner,
|
|
12
12
|
canManageSharing,
|
|
13
|
+
canManageMembers,
|
|
13
14
|
isSharedDrive,
|
|
14
|
-
isReadOnly,
|
|
15
15
|
document,
|
|
16
16
|
documentType,
|
|
17
17
|
onRevoke,
|
|
@@ -35,7 +35,7 @@ const RecipientList = ({
|
|
|
35
35
|
<GroupRecipient
|
|
36
36
|
{...recipient}
|
|
37
37
|
isOwner={isOwner}
|
|
38
|
-
|
|
38
|
+
canManageMembers={canManageMembers}
|
|
39
39
|
key={recipient.index}
|
|
40
40
|
document={document}
|
|
41
41
|
documentType={documentType}
|
|
@@ -52,8 +52,8 @@ const RecipientList = ({
|
|
|
52
52
|
key={recipient.index}
|
|
53
53
|
isOwner={isOwner}
|
|
54
54
|
canManageSharing={canManageSharing}
|
|
55
|
+
canManageMembers={canManageMembers}
|
|
55
56
|
isSharedDrive={isSharedDrive}
|
|
56
|
-
isReadOnly={isReadOnly}
|
|
57
57
|
document={document}
|
|
58
58
|
documentType={documentType}
|
|
59
59
|
onRevoke={onRevoke}
|
|
@@ -23,8 +23,7 @@ export const ShareModal = withLocales(props => {
|
|
|
23
23
|
canReshare,
|
|
24
24
|
documentType,
|
|
25
25
|
getRecipients,
|
|
26
|
-
revokeSelf
|
|
27
|
-
allLoaded
|
|
26
|
+
revokeSelf
|
|
28
27
|
} = useSharingContext()
|
|
29
28
|
|
|
30
29
|
const handleRevokeSelf = async document => {
|
|
@@ -37,7 +36,7 @@ export const ShareModal = withLocales(props => {
|
|
|
37
36
|
|
|
38
37
|
if (isEditable) {
|
|
39
38
|
const isFederatedMode = flag('drive.federated-shared-folder.enabled')
|
|
40
|
-
if (isFederatedMode &&
|
|
39
|
+
if (isFederatedMode && document.driveId) {
|
|
41
40
|
return (
|
|
42
41
|
<FederatedFolderModal
|
|
43
42
|
document={document}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { FixedDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
|
|
5
5
|
import { useI18n } from 'twake-i18n'
|
|
6
6
|
|
|
7
|
+
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
7
8
|
import styles from '../../styles/share.styl'
|
|
9
|
+
import ShareByLink from '../ShareByLink'
|
|
8
10
|
import WhoHasAccess from '../WhoHasAccess'
|
|
9
11
|
|
|
10
12
|
export const SharingDetailsModal = ({
|
|
@@ -16,9 +18,15 @@ export const SharingDetailsModal = ({
|
|
|
16
18
|
onClose
|
|
17
19
|
}) => {
|
|
18
20
|
const { t } = useI18n()
|
|
21
|
+
const { getSharingLink, getFederatedShareLink } = useSharingContext()
|
|
22
|
+
|
|
23
|
+
const isSharedDrive = Boolean(document?.driveId)
|
|
24
|
+
const displayedLink = isSharedDrive
|
|
25
|
+
? getFederatedShareLink(document)
|
|
26
|
+
: getSharingLink(document?._id)
|
|
19
27
|
|
|
20
28
|
return (
|
|
21
|
-
<
|
|
29
|
+
<FixedDialog
|
|
22
30
|
disableGutters
|
|
23
31
|
open={true}
|
|
24
32
|
onClose={onClose}
|
|
@@ -27,16 +35,29 @@ export const SharingDetailsModal = ({
|
|
|
27
35
|
content={
|
|
28
36
|
<div className={styles['share-modal-content']}>
|
|
29
37
|
<WhoHasAccess
|
|
30
|
-
|
|
38
|
+
canManageMembers={false}
|
|
39
|
+
canManageLink={isSharedDrive}
|
|
40
|
+
isSharedDrive={isSharedDrive}
|
|
31
41
|
recipients={recipients}
|
|
32
42
|
document={document}
|
|
33
43
|
documentType={documentType}
|
|
34
44
|
onRevoke={onRevoke}
|
|
35
45
|
onRevokeSelf={onRevokeSelf}
|
|
36
|
-
link=
|
|
46
|
+
link={displayedLink}
|
|
37
47
|
/>
|
|
38
48
|
</div>
|
|
39
49
|
}
|
|
50
|
+
actions={
|
|
51
|
+
isSharedDrive && (
|
|
52
|
+
<ShareByLink
|
|
53
|
+
link={displayedLink}
|
|
54
|
+
document={document}
|
|
55
|
+
documentType="Files"
|
|
56
|
+
showGenerateLinkButton={true}
|
|
57
|
+
autoOpenShareRestriction={false}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
40
61
|
/>
|
|
41
62
|
)
|
|
42
63
|
}
|
|
@@ -32,6 +32,8 @@ const WhoHasAccess = ({
|
|
|
32
32
|
canManageSharing = isOwner,
|
|
33
33
|
isSharedDrive = false,
|
|
34
34
|
isReadOnly = false,
|
|
35
|
+
canManageMembers = !isReadOnly,
|
|
36
|
+
canManageLink = canManageMembers,
|
|
35
37
|
showOwner = true,
|
|
36
38
|
recipients,
|
|
37
39
|
recipientsToBeConfirmed = [],
|
|
@@ -58,7 +60,7 @@ const WhoHasAccess = ({
|
|
|
58
60
|
<List>
|
|
59
61
|
{link && (
|
|
60
62
|
<LinkRecipient
|
|
61
|
-
isReadOnly={
|
|
63
|
+
isReadOnly={!canManageLink}
|
|
62
64
|
document={document}
|
|
63
65
|
documentType={documentType}
|
|
64
66
|
onRevoke={onRevoke}
|
|
@@ -80,8 +82,8 @@ const WhoHasAccess = ({
|
|
|
80
82
|
recipientsToBeConfirmed={recipientsToBeConfirmed}
|
|
81
83
|
isOwner={isOwner}
|
|
82
84
|
canManageSharing={canManageSharing}
|
|
85
|
+
canManageMembers={canManageMembers}
|
|
83
86
|
isSharedDrive={isSharedDrive}
|
|
84
|
-
isReadOnly={isReadOnly}
|
|
85
87
|
document={document}
|
|
86
88
|
documentType={documentType}
|
|
87
89
|
onRevoke={onRevoke}
|
|
@@ -97,6 +99,8 @@ const WhoHasAccess = ({
|
|
|
97
99
|
WhoHasAccess.propTypes = {
|
|
98
100
|
isOwner: PropTypes.bool,
|
|
99
101
|
canManageSharing: PropTypes.bool,
|
|
102
|
+
canManageMembers: PropTypes.bool,
|
|
103
|
+
canManageLink: PropTypes.bool,
|
|
100
104
|
showOwner: PropTypes.bool,
|
|
101
105
|
recipients: PropTypes.array.isRequired,
|
|
102
106
|
recipientsToBeConfirmed: PropTypes.arrayOf(
|