cozy-sharing 28.4.4 → 28.5.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 +10 -0
- package/dist/SharingProvider.js +192 -58
- package/dist/SharingProvider.spec.js +180 -2
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.js +7 -4
- package/dist/components/FederatedFolder/FederatedFolderModal.js +79 -23
- package/dist/components/ShareByLink.js +5 -1
- 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/helpers/shortcodes.js +24 -0
- package/dist/state.js +3 -10
- package/package.json +4 -4
- package/src/SharingProvider.jsx +77 -8
- package/src/SharingProvider.spec.jsx +130 -1
- package/src/components/FederatedFolder/DumbFederatedFolderModal.jsx +6 -3
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +39 -6
- package/src/components/ShareByLink.jsx +3 -1
- 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/helpers/shortcodes.js +28 -0
- package/src/state.js +3 -14
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,
|
|
@@ -336,11 +340,66 @@ export class SharingProvider extends Component {
|
|
|
336
340
|
}
|
|
337
341
|
|
|
338
342
|
shareByLink = async (document, options) => {
|
|
339
|
-
const resp =
|
|
343
|
+
const resp = document.driveId
|
|
344
|
+
? await this.createSharedDriveSharingLink(document, options)
|
|
345
|
+
: await this.permissionCol.createSharingLink(document, options)
|
|
340
346
|
this.dispatch(addSharingLink(resp.data))
|
|
341
347
|
return resp
|
|
342
348
|
}
|
|
343
349
|
|
|
350
|
+
getFederatedShareLink = document => {
|
|
351
|
+
if (!document.driveId) return null
|
|
352
|
+
|
|
353
|
+
const permissions = getDocumentPermissions(this.state, document._id)
|
|
354
|
+
const perm = permissions.find(p => getShortcode(p))
|
|
355
|
+
if (!perm) return null
|
|
356
|
+
|
|
357
|
+
const code = getShortcode(perm)
|
|
358
|
+
if (!code) return null
|
|
359
|
+
|
|
360
|
+
const { client } = this.props
|
|
361
|
+
return generateShareLinkFromFile({
|
|
362
|
+
client,
|
|
363
|
+
file: document,
|
|
364
|
+
sharecode: code,
|
|
365
|
+
getOwner: this.state.getOwner,
|
|
366
|
+
getSharingById: this.state.getSharingById,
|
|
367
|
+
documentType: this.state.documentType
|
|
368
|
+
})
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
createSharedDriveSharingLink = async (document, options) => {
|
|
372
|
+
const { client } = this.props
|
|
373
|
+
const drivePermissionCollection = client.collection('io.cozy.permissions', {
|
|
374
|
+
driveId: document.driveId
|
|
375
|
+
})
|
|
376
|
+
const resp = await drivePermissionCollection.createSharingLink(
|
|
377
|
+
document,
|
|
378
|
+
options
|
|
379
|
+
)
|
|
380
|
+
return resp
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
updateSharedDrivePermissions = async (
|
|
384
|
+
document,
|
|
385
|
+
permissionDocument,
|
|
386
|
+
updatedPermissions,
|
|
387
|
+
options
|
|
388
|
+
) => {
|
|
389
|
+
const { client } = this.props
|
|
390
|
+
const { expiresAt, password } = options
|
|
391
|
+
const drivePermissionCollection = client.collection('io.cozy.permissions', {
|
|
392
|
+
driveId: document.driveId
|
|
393
|
+
})
|
|
394
|
+
const resp = await drivePermissionCollection.add(
|
|
395
|
+
permissionDocument,
|
|
396
|
+
updatedPermissions,
|
|
397
|
+
{ expiresAt, password }
|
|
398
|
+
)
|
|
399
|
+
this.dispatch(updateSharingLink(resp.data))
|
|
400
|
+
return resp
|
|
401
|
+
}
|
|
402
|
+
|
|
344
403
|
/**
|
|
345
404
|
* updateDocumentPermissions - Description
|
|
346
405
|
*
|
|
@@ -356,19 +415,29 @@ export class SharingProvider extends Component {
|
|
|
356
415
|
const { verbs, expiresAt, password } = options
|
|
357
416
|
const permissions = getDocumentPermissions(this.state, document.id)
|
|
358
417
|
|
|
418
|
+
if (!permissions || permissions.length === 0) {
|
|
419
|
+
return []
|
|
420
|
+
}
|
|
421
|
+
|
|
359
422
|
const responses = await Promise.all(
|
|
360
423
|
permissions.map(async permissionDocument => {
|
|
361
424
|
const updatedPermissions = permissionDocument.attributes.permissions
|
|
362
|
-
Object.keys(updatedPermissions).
|
|
425
|
+
Object.keys(updatedPermissions).forEach(permType => {
|
|
363
426
|
updatedPermissions[permType].verbs = verbs
|
|
364
427
|
})
|
|
365
428
|
|
|
366
|
-
const resp =
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
429
|
+
const resp = document.driveId
|
|
430
|
+
? await this.updateSharedDrivePermissions(
|
|
431
|
+
document,
|
|
432
|
+
permissionDocument,
|
|
433
|
+
updatedPermissions,
|
|
434
|
+
options
|
|
435
|
+
)
|
|
436
|
+
: await this.permissionCol.add(
|
|
437
|
+
permissionDocument,
|
|
438
|
+
updatedPermissions,
|
|
439
|
+
{ expiresAt, password }
|
|
440
|
+
)
|
|
372
441
|
return resp
|
|
373
442
|
})
|
|
374
443
|
)
|
|
@@ -5,7 +5,7 @@ import { createMockClient } from 'cozy-client'
|
|
|
5
5
|
|
|
6
6
|
import { SharingProvider } from './SharingProvider'
|
|
7
7
|
import SharingContext from './context'
|
|
8
|
-
|
|
8
|
+
import reducer, { addSharingLink, getDocumentPermissions } from './state'
|
|
9
9
|
import AppLike from '../test/AppLike'
|
|
10
10
|
|
|
11
11
|
const AppWrapper = ({ children, client, isPublic }) => {
|
|
@@ -105,6 +105,135 @@ describe('SharingProvider', () => {
|
|
|
105
105
|
})
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
+
describe('shareByLink', () => {
|
|
109
|
+
const PERM_DRIVE_FILE = {
|
|
110
|
+
type: 'io.cozy.permissions',
|
|
111
|
+
id: 'perm_drive_file',
|
|
112
|
+
attributes: {
|
|
113
|
+
type: 'share',
|
|
114
|
+
permissions: {
|
|
115
|
+
rule0: {
|
|
116
|
+
type: 'io.cozy.files',
|
|
117
|
+
verbs: ['GET'],
|
|
118
|
+
values: ['file_in_drive']
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
shortcodes: { code: 'shortcode123' }
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const driveFile = {
|
|
126
|
+
_id: 'file_in_drive',
|
|
127
|
+
id: 'file_in_drive',
|
|
128
|
+
driveId: 'drive_123'
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
it('dispatches addSharingLink exactly once for a shared drive file', async () => {
|
|
132
|
+
const mockCreateSharingLink = jest
|
|
133
|
+
.fn()
|
|
134
|
+
.mockResolvedValue({ data: PERM_DRIVE_FILE })
|
|
135
|
+
const mockClient = createMockClient({})
|
|
136
|
+
mockClient.collection = jest.fn().mockReturnValue({
|
|
137
|
+
createSharingLink: mockCreateSharingLink
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
const provider = new SharingProvider({ client: mockClient })
|
|
141
|
+
provider.state = reducer()
|
|
142
|
+
provider.dispatch = jest.fn(action => {
|
|
143
|
+
provider.state = reducer(provider.state, action)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
await provider.shareByLink(driveFile, { verbs: ['GET'] })
|
|
147
|
+
|
|
148
|
+
expect(provider.dispatch).toHaveBeenCalledTimes(1)
|
|
149
|
+
const permissions = getDocumentPermissions(provider.state, driveFile._id)
|
|
150
|
+
expect(permissions).toHaveLength(1)
|
|
151
|
+
expect(permissions[0].id).toBe(PERM_DRIVE_FILE.id)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('dispatches addSharingLink once for a regular file (non shared drive)', async () => {
|
|
155
|
+
const PERM_REGULAR_FILE = {
|
|
156
|
+
type: 'io.cozy.permissions',
|
|
157
|
+
id: 'perm_regular_file',
|
|
158
|
+
attributes: {
|
|
159
|
+
type: 'share',
|
|
160
|
+
permissions: {
|
|
161
|
+
rule0: {
|
|
162
|
+
type: 'io.cozy.files',
|
|
163
|
+
verbs: ['GET'],
|
|
164
|
+
values: ['regular_file_id']
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
shortcodes: { code: 'shortcode456' }
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const regularFile = { _id: 'regular_file_id', id: 'regular_file_id' }
|
|
171
|
+
const mockCreateSharingLink = jest
|
|
172
|
+
.fn()
|
|
173
|
+
.mockResolvedValue({ data: PERM_REGULAR_FILE })
|
|
174
|
+
const mockClient = createMockClient({})
|
|
175
|
+
mockClient.collection = jest.fn().mockReturnValue({
|
|
176
|
+
createSharingLink: mockCreateSharingLink
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const provider = new SharingProvider({ client: mockClient })
|
|
180
|
+
provider.state = reducer()
|
|
181
|
+
provider.permissionCol = { createSharingLink: mockCreateSharingLink }
|
|
182
|
+
provider.dispatch = jest.fn(action => {
|
|
183
|
+
provider.state = reducer(provider.state, action)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
await provider.shareByLink(regularFile, { verbs: ['GET'] })
|
|
187
|
+
|
|
188
|
+
expect(provider.dispatch).toHaveBeenCalledTimes(1)
|
|
189
|
+
const permissions = getDocumentPermissions(provider.state, regularFile._id)
|
|
190
|
+
expect(permissions).toHaveLength(1)
|
|
191
|
+
expect(permissions[0].id).toBe(PERM_REGULAR_FILE.id)
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
describe('updateDocumentPermissions', () => {
|
|
196
|
+
const PERM_DRIVE_FILE = {
|
|
197
|
+
type: 'io.cozy.permissions',
|
|
198
|
+
id: 'perm_drive_file',
|
|
199
|
+
attributes: {
|
|
200
|
+
type: 'share',
|
|
201
|
+
permissions: {
|
|
202
|
+
rule0: {
|
|
203
|
+
type: 'io.cozy.files',
|
|
204
|
+
verbs: ['GET'],
|
|
205
|
+
values: ['file_in_drive']
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
shortcodes: { code: 'shortcode123' }
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
it('sends only one PATCH request for a shared drive file', async () => {
|
|
213
|
+
const driveFile = {
|
|
214
|
+
_id: 'file_in_drive',
|
|
215
|
+
id: 'file_in_drive',
|
|
216
|
+
driveId: 'drive_123'
|
|
217
|
+
}
|
|
218
|
+
const mockAdd = jest.fn().mockResolvedValue({ data: PERM_DRIVE_FILE })
|
|
219
|
+
const mockClient = createMockClient({})
|
|
220
|
+
mockClient.collection = jest.fn().mockReturnValue({ add: mockAdd })
|
|
221
|
+
|
|
222
|
+
const provider = new SharingProvider({ client: mockClient })
|
|
223
|
+
// Seed the state with exactly one permission (as it would be after a correct shareByLink)
|
|
224
|
+
provider.state = reducer(undefined, addSharingLink(PERM_DRIVE_FILE))
|
|
225
|
+
provider.dispatch = jest.fn()
|
|
226
|
+
|
|
227
|
+
await provider.updateDocumentPermissions(driveFile, {
|
|
228
|
+
verbs: ['GET'],
|
|
229
|
+
expiresAt: '',
|
|
230
|
+
password: ''
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
expect(mockAdd).toHaveBeenCalledTimes(1)
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
|
|
108
237
|
// TODO Convert with react-testing-library
|
|
109
238
|
// describe('hasWriteAccess', () => {
|
|
110
239
|
// it('tells if a doc is writtable', () => {
|
|
@@ -3,7 +3,7 @@ import React from 'react'
|
|
|
3
3
|
import { useI18n } from 'twake-i18n'
|
|
4
4
|
|
|
5
5
|
import withLocales from '../../hoc/withLocales'
|
|
6
|
-
import DumbBatchSharedFolderModal from '../SharedFolder/DumbBatchSharedFolderModal'
|
|
6
|
+
import { DumbBatchSharedFolderModal } from '../SharedFolder/DumbBatchSharedFolderModal'
|
|
7
7
|
|
|
8
8
|
export const DumbFederatedFolderModal = withLocales(
|
|
9
9
|
({
|
|
@@ -18,7 +18,8 @@ export const DumbFederatedFolderModal = withLocales(
|
|
|
18
18
|
onSend,
|
|
19
19
|
onClose,
|
|
20
20
|
onShare,
|
|
21
|
-
sharingLink
|
|
21
|
+
sharingLink,
|
|
22
|
+
showShareByEmail
|
|
22
23
|
}) => {
|
|
23
24
|
const { t } = useI18n()
|
|
24
25
|
return (
|
|
@@ -39,6 +40,7 @@ export const DumbFederatedFolderModal = withLocales(
|
|
|
39
40
|
addPeopleLabel={t('FederatedFolder.addPeople')}
|
|
40
41
|
addButtonLabel={t('FederatedFolder.add')}
|
|
41
42
|
shareLabel={t('FederatedFolder.share')}
|
|
43
|
+
showShareByEmail={showShareByEmail}
|
|
42
44
|
/>
|
|
43
45
|
)
|
|
44
46
|
}
|
|
@@ -56,7 +58,8 @@ DumbFederatedFolderModal.propTypes = {
|
|
|
56
58
|
onSend: PropTypes.func.isRequired,
|
|
57
59
|
onClose: PropTypes.func.isRequired,
|
|
58
60
|
onShare: PropTypes.func.isRequired,
|
|
59
|
-
sharingLink: PropTypes.string
|
|
61
|
+
sharingLink: PropTypes.string,
|
|
62
|
+
showShareByEmail: PropTypes.bool
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
export default DumbFederatedFolderModal
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
|
-
import React, { useState } from 'react'
|
|
2
|
+
import React, { useState, useEffect } from 'react'
|
|
3
3
|
import { useI18n } from 'twake-i18n'
|
|
4
4
|
|
|
5
5
|
import { useClient } from 'cozy-client'
|
|
@@ -19,13 +19,43 @@ export const FederatedFolderModal = withLocales(
|
|
|
19
19
|
({ onClose, document: existingDocument }) => {
|
|
20
20
|
const client = useClient()
|
|
21
21
|
const { t } = useI18n()
|
|
22
|
-
const {
|
|
22
|
+
const {
|
|
23
|
+
share,
|
|
24
|
+
getSharingLink,
|
|
25
|
+
getFederatedShareLink,
|
|
26
|
+
getDocumentPermissions,
|
|
27
|
+
getOwner,
|
|
28
|
+
getSharingById
|
|
29
|
+
} = useSharingContext()
|
|
23
30
|
const { showAlert } = useAlert()
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
const [sharingLink, setSharingLink] = useState(null)
|
|
33
|
+
|
|
34
|
+
const documentPermissions = existingDocument
|
|
35
|
+
? getDocumentPermissions(existingDocument._id)
|
|
36
|
+
: []
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const fetchSharingLink = async () => {
|
|
40
|
+
if (!existingDocument) return
|
|
41
|
+
|
|
42
|
+
if (existingDocument.driveId) {
|
|
43
|
+
const link = await getFederatedShareLink(existingDocument)
|
|
44
|
+
setSharingLink(link)
|
|
45
|
+
} else {
|
|
46
|
+
setSharingLink(getSharingLink(existingDocument._id))
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fetchSharingLink()
|
|
51
|
+
}, [
|
|
52
|
+
existingDocument,
|
|
53
|
+
documentPermissions,
|
|
54
|
+
getFederatedShareLink,
|
|
55
|
+
getSharingLink,
|
|
56
|
+
getOwner,
|
|
57
|
+
getSharingById
|
|
58
|
+
]) // eslint-disable-line react-hooks/exhaustive-deps
|
|
29
59
|
|
|
30
60
|
const [federatedRecipients, setFederatedRecipients] = useState({
|
|
31
61
|
recipients: [],
|
|
@@ -92,6 +122,8 @@ export const FederatedFolderModal = withLocales(
|
|
|
92
122
|
|
|
93
123
|
const modalTitle = t('FederatedFolder.shareTitle', { name: folderName })
|
|
94
124
|
|
|
125
|
+
const isSharedDrive = Boolean(existingDocument?.driveId)
|
|
126
|
+
|
|
95
127
|
return (
|
|
96
128
|
<DumbFederatedFolderModal
|
|
97
129
|
title={modalTitle}
|
|
@@ -106,6 +138,7 @@ export const FederatedFolderModal = withLocales(
|
|
|
106
138
|
onClose={onClose}
|
|
107
139
|
onShare={onShare}
|
|
108
140
|
sharingLink={sharingLink}
|
|
141
|
+
showShareByEmail={!isSharedDrive}
|
|
109
142
|
/>
|
|
110
143
|
)
|
|
111
144
|
}
|
|
@@ -23,7 +23,7 @@ const ShareByLink = ({ link, document, documentType }) => {
|
|
|
23
23
|
const { isMobile } = useBreakpoints()
|
|
24
24
|
const { showAlert } = useAlert()
|
|
25
25
|
const client = useClient()
|
|
26
|
-
const { shareByLink } = useSharingContext()
|
|
26
|
+
const { shareByLink, getOwner, getSharingById } = useSharingContext()
|
|
27
27
|
const [isGenerating, setIsGenerating] = useState(false)
|
|
28
28
|
|
|
29
29
|
const canShare = typeof navigator?.share === 'function'
|
|
@@ -44,6 +44,8 @@ const ShareByLink = ({ link, document, documentType }) => {
|
|
|
44
44
|
file: document,
|
|
45
45
|
documentType,
|
|
46
46
|
shareByLink,
|
|
47
|
+
getOwner,
|
|
48
|
+
getSharingById,
|
|
47
49
|
t,
|
|
48
50
|
showAlert,
|
|
49
51
|
password: '',
|
|
@@ -2,6 +2,7 @@ import { generateWebLink } from 'cozy-client'
|
|
|
2
2
|
import minilog from 'cozy-minilog'
|
|
3
3
|
|
|
4
4
|
import { getAppSlugFromDocumentType } from '../../helpers/link'
|
|
5
|
+
import { getShortcode } from '../../helpers/shortcodes'
|
|
5
6
|
|
|
6
7
|
const log = minilog('ShareRestrictionModal/helpers')
|
|
7
8
|
|
|
@@ -28,6 +29,8 @@ export const createSharingLink = async ({
|
|
|
28
29
|
file,
|
|
29
30
|
documentType,
|
|
30
31
|
shareByLink,
|
|
32
|
+
getOwner,
|
|
33
|
+
getSharingById,
|
|
31
34
|
t,
|
|
32
35
|
ttl,
|
|
33
36
|
editingRights = 'readOnly',
|
|
@@ -44,13 +47,48 @@ export const createSharingLink = async ({
|
|
|
44
47
|
shareByLink,
|
|
45
48
|
showAlert
|
|
46
49
|
})
|
|
47
|
-
|
|
50
|
+
const code = getShortcode(permsResult?.data)
|
|
51
|
+
if (!code) {
|
|
48
52
|
return null
|
|
49
53
|
}
|
|
50
|
-
|
|
54
|
+
return generateShareLinkFromFile({
|
|
55
|
+
client,
|
|
56
|
+
file,
|
|
57
|
+
sharecode: code,
|
|
58
|
+
getOwner,
|
|
59
|
+
getSharingById,
|
|
60
|
+
documentType
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Generate a sharing link from a file and sharecode
|
|
66
|
+
* @param {object} options
|
|
67
|
+
* @param {object} options.client - CozyClient instance
|
|
68
|
+
* @param {object} options.file - File to share
|
|
69
|
+
* @param {string} options.sharecode - Share code
|
|
70
|
+
* @param {Function} options.getOwner - Function to get the owner of a sharing
|
|
71
|
+
* @param {Function} options.getSharingById - Function to get a sharing by ID
|
|
72
|
+
* @param {string} options.documentType - Type of the document
|
|
73
|
+
* @returns {string} - The generated web link
|
|
74
|
+
*/
|
|
75
|
+
export const generateShareLinkFromFile = ({
|
|
76
|
+
client,
|
|
77
|
+
file,
|
|
78
|
+
sharecode,
|
|
79
|
+
getOwner,
|
|
80
|
+
getSharingById,
|
|
81
|
+
documentType
|
|
82
|
+
}) => {
|
|
83
|
+
let cozyUrl = client.getStackClient().uri
|
|
84
|
+
if (file.driveId) {
|
|
85
|
+
const sharing = getSharingById(file.driveId)
|
|
86
|
+
const owner = getOwner(sharing?.rules?.[0]?.values?.[0])
|
|
87
|
+
cozyUrl = owner?.instance || client.getStackClient().uri
|
|
88
|
+
}
|
|
51
89
|
return generateWebLink({
|
|
52
|
-
cozyUrl
|
|
53
|
-
searchParams: [['sharecode',
|
|
90
|
+
cozyUrl,
|
|
91
|
+
searchParams: [['sharecode', sharecode]],
|
|
54
92
|
pathname: '/public',
|
|
55
93
|
slug: getAppSlugFromDocumentType({ documentType }),
|
|
56
94
|
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
@@ -3,7 +3,7 @@ import React from 'react'
|
|
|
3
3
|
import { useI18n } from 'twake-i18n'
|
|
4
4
|
|
|
5
5
|
import withLocales from '../../hoc/withLocales'
|
|
6
|
-
import DumbBatchSharedFolderModal from '../SharedFolder/DumbBatchSharedFolderModal'
|
|
6
|
+
import { DumbBatchSharedFolderModal } from '../SharedFolder/DumbBatchSharedFolderModal'
|
|
7
7
|
|
|
8
8
|
export const DumbSharedDriveModal = withLocales(
|
|
9
9
|
({
|
|
@@ -37,7 +37,8 @@ export const DumbBatchSharedFolderModal = withLocales(
|
|
|
37
37
|
createLabel,
|
|
38
38
|
shareLabel,
|
|
39
39
|
saveLabel,
|
|
40
|
-
sharingDesc
|
|
40
|
+
sharingDesc,
|
|
41
|
+
showShareByEmail = true
|
|
41
42
|
}) => {
|
|
42
43
|
const hasRecipients = Boolean(recipients?.length)
|
|
43
44
|
|
|
@@ -52,6 +53,16 @@ export const DumbBatchSharedFolderModal = withLocales(
|
|
|
52
53
|
)
|
|
53
54
|
}
|
|
54
55
|
|
|
56
|
+
if (!showShareByEmail) {
|
|
57
|
+
return (
|
|
58
|
+
<ShareByLink
|
|
59
|
+
link={sharingLink}
|
|
60
|
+
document={document}
|
|
61
|
+
documentType="Files"
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
55
66
|
if (!showNameField) {
|
|
56
67
|
return (
|
|
57
68
|
<>
|
|
@@ -111,19 +122,21 @@ export const DumbBatchSharedFolderModal = withLocales(
|
|
|
111
122
|
<Typography variant="h6" className="u-mt-1-half u-mb-half">
|
|
112
123
|
{addPeopleLabel}
|
|
113
124
|
</Typography>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
onShare
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
{showShareByEmail && (
|
|
126
|
+
<DumbShareByEmail
|
|
127
|
+
createContact={createContact}
|
|
128
|
+
currentRecipients={currentRecipients}
|
|
129
|
+
document={document}
|
|
130
|
+
documentType="Files"
|
|
131
|
+
sharedDrive
|
|
132
|
+
sharingDesc={sharingDesc}
|
|
133
|
+
onShare={params => {
|
|
134
|
+
onShare(params)
|
|
135
|
+
}}
|
|
136
|
+
submitLabel={addButtonLabel}
|
|
137
|
+
showNotifications={false}
|
|
138
|
+
/>
|
|
139
|
+
)}
|
|
127
140
|
</div>
|
|
128
141
|
<WhoHasAccess
|
|
129
142
|
isOwner
|
|
@@ -168,7 +181,10 @@ DumbBatchSharedFolderModal.propTypes = {
|
|
|
168
181
|
createLabel: PropTypes.string,
|
|
169
182
|
shareLabel: PropTypes.string,
|
|
170
183
|
saveLabel: PropTypes.string,
|
|
171
|
-
sharingDesc: PropTypes.string
|
|
184
|
+
sharingDesc: PropTypes.string,
|
|
185
|
+
showShareByEmail: PropTypes.bool
|
|
172
186
|
}
|
|
173
187
|
|
|
174
|
-
|
|
188
|
+
DumbBatchSharedFolderModal.defaultProps = {
|
|
189
|
+
sharingDesc: ''
|
|
190
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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 const getShortcode = permission => {
|
|
21
|
+
return (
|
|
22
|
+
permission?.attributes?.shortcodes?.email ||
|
|
23
|
+
permission?.attributes?.shortcodes?.code ||
|
|
24
|
+
permission?.attributes?.codes?.email ||
|
|
25
|
+
permission?.attributes?.codes?.code ||
|
|
26
|
+
null
|
|
27
|
+
)
|
|
28
|
+
}
|
package/src/state.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import get from 'lodash/get'
|
|
2
|
-
|
|
3
1
|
import flag from 'cozy-flags'
|
|
4
2
|
|
|
3
|
+
import { getShortcode } from './helpers/shortcodes'
|
|
4
|
+
|
|
5
5
|
const RECEIVE_SHARINGS = 'RECEIVE_SHARINGS'
|
|
6
6
|
const ADD_SHARING = 'ADD_SHARING'
|
|
7
7
|
const UPDATE_SHARING = 'UPDATE_SHARING'
|
|
@@ -423,18 +423,7 @@ export const getSharingLink = (state, docId, documentType) => {
|
|
|
423
423
|
const perms = getDocumentPermissions(state, docId)
|
|
424
424
|
if (perms.length === 0) return null
|
|
425
425
|
const perm = perms[0]
|
|
426
|
-
|
|
427
|
-
// But when we use cozy-client to create a Permission, by default
|
|
428
|
-
// the codes attribute is set to `code`. MesPapiers app is using this
|
|
429
|
-
// default behavior... So the sharing by link created by mes papiers
|
|
430
|
-
// didn't appear correctly in cozy-sharing.
|
|
431
|
-
// This is a bit ugly, we should have a better way to know if this is
|
|
432
|
-
// a sharing by link or not.
|
|
433
|
-
const code =
|
|
434
|
-
get(perm, 'attributes.shortcodes.email') ||
|
|
435
|
-
get(perm, 'attributes.shortcodes.code') ||
|
|
436
|
-
get(perm, 'attributes.codes.email') ||
|
|
437
|
-
get(perm, 'attributes.codes.code')
|
|
426
|
+
const code = getShortcode(perm)
|
|
438
427
|
if (code) {
|
|
439
428
|
return buildSharingLink(state, documentType, code)
|
|
440
429
|
} else {
|