cozy-sharing 19.0.0 → 21.0.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 +68 -0
- package/dist/SharingProvider.js +16 -9
- package/dist/actions/{openSharingLink.js → addToCozySharingLink.js} +12 -16
- package/dist/actions/createCozySharingLink.js +51 -0
- package/dist/actions/syncToCozySharingLink.js +51 -0
- package/dist/components/Recipient/LinkRecipient.js +20 -4
- package/dist/components/ShareRestrictionModal/BoxPassword.js +21 -4
- package/dist/components/ShareRestrictionModal/ShareRestrictionContentModal.js +33 -9
- package/dist/components/ShareRestrictionModal/ShareRestrictionModal.js +74 -78
- package/dist/components/ShareRestrictionModal/helpers.js +82 -47
- package/dist/components/ShareRestrictionModal/helpers.spec.js +142 -20
- package/dist/components/SharingBanner/components/PublicBanner.js +3 -3
- package/dist/components/SharingBanner/components/PublicBanner.spec.js +1 -1
- package/dist/components/SharingBanner/components/SharingBanner.js +3 -3
- package/dist/components/SharingBanner/hooks/useSharingInfos.js +37 -25
- package/dist/components/SharingBanner/hooks/useSharingInfos.spec.js +9 -9
- package/dist/helpers/permissions.js +15 -0
- package/dist/index.js +3 -1
- package/locales/en.json +2 -0
- package/locales/fr.json +2 -0
- package/package.json +4 -4
- package/src/SharingProvider.jsx +10 -5
- package/src/actions/addToCozySharingLink.js +51 -0
- package/src/actions/createCozySharingLink.js +47 -0
- package/src/actions/{openSharingLink.js → syncToCozySharingLink.js} +10 -12
- package/src/components/Recipient/LinkRecipient.jsx +28 -4
- package/src/components/ShareRestrictionModal/BoxPassword.jsx +14 -0
- package/src/components/ShareRestrictionModal/ShareRestrictionContentModal.jsx +31 -9
- package/src/components/ShareRestrictionModal/ShareRestrictionModal.jsx +55 -46
- package/src/components/ShareRestrictionModal/helpers.js +65 -31
- package/src/components/ShareRestrictionModal/helpers.spec.js +92 -11
- package/src/components/SharingBanner/components/PublicBanner.jsx +3 -3
- package/src/components/SharingBanner/components/PublicBanner.spec.jsx +1 -1
- package/src/components/SharingBanner/components/SharingBanner.jsx +3 -3
- package/src/components/SharingBanner/hooks/useSharingInfos.jsx +12 -3
- package/src/components/SharingBanner/hooks/useSharingInfos.spec.js +7 -7
- package/src/helpers/permissions.js +12 -0
- package/src/index.jsx +3 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addDays } from 'date-fns'
|
|
1
|
+
import { addDays, isValid } from 'date-fns'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
|
|
@@ -9,6 +9,8 @@ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
|
|
|
9
9
|
import { BoxDate } from './BoxDate'
|
|
10
10
|
import { BoxEditingRights } from './BoxEditingRights'
|
|
11
11
|
import { BoxPassword } from './BoxPassword'
|
|
12
|
+
import { checkIsPermissionHasPassword } from '../../helpers/permissions'
|
|
13
|
+
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
12
14
|
|
|
13
15
|
const PASSWORD_MIN_LENGTH = 4
|
|
14
16
|
|
|
@@ -32,24 +34,43 @@ export const ShareRestrictionContentModal = ({
|
|
|
32
34
|
setEditingRights
|
|
33
35
|
}) => {
|
|
34
36
|
const { t } = useI18n()
|
|
37
|
+
const { getDocumentPermissions } = useSharingContext()
|
|
38
|
+
const permissions = getDocumentPermissions(file._id)
|
|
39
|
+
const hasPassword = checkIsPermissionHasPassword(permissions)
|
|
35
40
|
|
|
36
|
-
const handlePasswordToggle = val => {
|
|
37
|
-
setPasswordToggle(val)
|
|
38
|
-
}
|
|
39
41
|
const handlePassword = value => {
|
|
40
42
|
setPassword(value)
|
|
41
43
|
setIsValidPassword(
|
|
42
|
-
value.trim().length === 0 ||
|
|
44
|
+
(hasPassword && value.trim().length === 0) ||
|
|
45
|
+
value.trim().length >= PASSWORD_MIN_LENGTH
|
|
43
46
|
)
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
const handlePasswordToggle = val => {
|
|
50
|
+
setPasswordToggle(val)
|
|
51
|
+
setPassword('')
|
|
52
|
+
if (val && !password) {
|
|
53
|
+
setIsValidPassword(hasPassword)
|
|
54
|
+
} else {
|
|
55
|
+
setIsValidPassword(true)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const handleDate = date => {
|
|
60
|
+
setSelectedDate(date)
|
|
61
|
+
setIsValidDate(isValid(date))
|
|
62
|
+
}
|
|
63
|
+
|
|
46
64
|
const handleDateToggle = val => {
|
|
65
|
+
setDateToggle(val)
|
|
47
66
|
if (!val) {
|
|
67
|
+
setSelectedDate(null)
|
|
68
|
+
setIsValidDate(true)
|
|
69
|
+
} else {
|
|
70
|
+
const defaultValue = val ? addDays(new Date(), 30) : null
|
|
71
|
+
setSelectedDate(defaultValue)
|
|
48
72
|
setIsValidDate(true)
|
|
49
73
|
}
|
|
50
|
-
const defaultValue = val ? addDays(new Date(), 30) : null
|
|
51
|
-
setSelectedDate(defaultValue, true)
|
|
52
|
-
setDateToggle(val)
|
|
53
74
|
}
|
|
54
75
|
|
|
55
76
|
return (
|
|
@@ -64,12 +85,13 @@ export const ShareRestrictionContentModal = ({
|
|
|
64
85
|
setEditingRights={setEditingRights}
|
|
65
86
|
/>
|
|
66
87
|
<BoxDate
|
|
67
|
-
onChange={
|
|
88
|
+
onChange={handleDate}
|
|
68
89
|
date={selectedDate}
|
|
69
90
|
onToggle={handleDateToggle}
|
|
70
91
|
toggle={dateToggle}
|
|
71
92
|
/>
|
|
72
93
|
<BoxPassword
|
|
94
|
+
file={file}
|
|
73
95
|
onChange={handlePassword}
|
|
74
96
|
password={password}
|
|
75
97
|
onToggle={handlePasswordToggle}
|
|
@@ -2,9 +2,7 @@ import { addDays } from 'date-fns'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import React, { useState } from 'react'
|
|
4
4
|
|
|
5
|
-
import { useClient } from 'cozy-client'
|
|
6
|
-
import { getSharingLink as makeSharingLink } from 'cozy-client/dist/models/sharing'
|
|
7
|
-
import { isMobile } from 'cozy-device-helper'
|
|
5
|
+
import { generateWebLink, useClient } from 'cozy-client'
|
|
8
6
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
9
7
|
import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
|
|
10
8
|
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
@@ -14,14 +12,17 @@ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
|
|
|
14
12
|
import { ShareRestrictionContentModal } from './ShareRestrictionContentModal'
|
|
15
13
|
import {
|
|
16
14
|
copyToClipboard,
|
|
17
|
-
forwardFile,
|
|
18
15
|
updatePermissions,
|
|
19
16
|
makeTTL,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
revokePermissions
|
|
17
|
+
revokePermissions,
|
|
18
|
+
createPermissions
|
|
23
19
|
} from './helpers'
|
|
24
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
checkIsPermissionHasExpiresDate,
|
|
22
|
+
checkIsPermissionHasPassword,
|
|
23
|
+
checkIsReadOnlyPermissions,
|
|
24
|
+
getPermissionExpiresDate
|
|
25
|
+
} from '../../helpers/permissions'
|
|
25
26
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
26
27
|
|
|
27
28
|
const PASSWORD_MIN_LENGTH = 4
|
|
@@ -31,11 +32,8 @@ export const ShareRestrictionModal = ({ file, onClose }) => {
|
|
|
31
32
|
const { t } = useI18n()
|
|
32
33
|
const { showAlert } = useAlert()
|
|
33
34
|
const [password, setPassword] = useState('')
|
|
34
|
-
const [selectedDate, setSelectedDate] = useState(addDays(new Date(), 30))
|
|
35
35
|
const [isValidDate, setIsValidDate] = useState(true)
|
|
36
36
|
const [isValidPassword, setIsValidPassword] = useState(true)
|
|
37
|
-
const [dateToggle, setDateToggle] = useState(true)
|
|
38
|
-
const [passwordToggle, setPasswordToggle] = useState(false)
|
|
39
37
|
const [loading, setLoading] = useState(false)
|
|
40
38
|
|
|
41
39
|
const {
|
|
@@ -50,64 +48,75 @@ export const ShareRestrictionModal = ({ file, onClose }) => {
|
|
|
50
48
|
const hasSharingLink = getSharingLink(file._id) !== null
|
|
51
49
|
const permissions = getDocumentPermissions(file._id)
|
|
52
50
|
const isReadOnlyPermissions = checkIsReadOnlyPermissions(permissions)
|
|
53
|
-
|
|
51
|
+
const hasPassword = checkIsPermissionHasPassword(permissions)
|
|
52
|
+
const hasExpiresDate = checkIsPermissionHasExpiresDate(permissions)
|
|
53
|
+
const expiresDate = getPermissionExpiresDate(permissions)
|
|
54
|
+
const defaultDate = expiresDate
|
|
55
|
+
? new Date(expiresDate)
|
|
56
|
+
: addDays(new Date(), 30)
|
|
57
|
+
|
|
58
|
+
const [selectedDate, setSelectedDate] = useState(defaultDate)
|
|
59
|
+
const [dateToggle, setDateToggle] = useState(
|
|
60
|
+
permissions.length > 0 ? hasExpiresDate : true
|
|
61
|
+
)
|
|
62
|
+
const [passwordToggle, setPasswordToggle] = useState(hasPassword)
|
|
54
63
|
const [editingRights, setEditingRights] = useState(
|
|
55
64
|
isReadOnlyPermissions || permissions.length === 0 ? 'readOnly' : 'write'
|
|
56
65
|
)
|
|
57
66
|
|
|
58
|
-
const isDesktopOrMobileWithoutShareAPI =
|
|
59
|
-
(isMobile() && !navigator.share) || !isMobile()
|
|
60
|
-
|
|
61
67
|
const helperTextPassword = !isValidPassword
|
|
62
68
|
? t('ShareRestrictionModal.invalidPasswordMessage', {
|
|
63
69
|
smart_count: PASSWORD_MIN_LENGTH - password.length
|
|
64
70
|
})
|
|
65
71
|
: null
|
|
66
72
|
|
|
67
|
-
const handleDateChange = (date, isValid) => {
|
|
68
|
-
setSelectedDate(date)
|
|
69
|
-
setIsValidDate(isValid)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
73
|
const handleClick = async () => {
|
|
73
74
|
setLoading(true)
|
|
74
75
|
// If the file is not shared, we create a new sharing link
|
|
75
76
|
if (!hasSharingLink) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
onClose()
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
await updatePermissions({
|
|
85
|
-
file,
|
|
86
|
-
t,
|
|
87
|
-
editingRights,
|
|
88
|
-
documentType,
|
|
89
|
-
updateDocumentPermissions,
|
|
90
|
-
showAlert
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const ttl = makeTTL(dateToggle && selectedDate)
|
|
94
|
-
if (isDesktopOrMobileWithoutShareAPI) {
|
|
95
|
-
const url = await makeSharingLink(client, [file._id], {
|
|
77
|
+
const ttl = makeTTL(dateToggle && selectedDate)
|
|
78
|
+
const { data: perms } = await createPermissions({
|
|
79
|
+
file,
|
|
80
|
+
t,
|
|
96
81
|
ttl,
|
|
97
|
-
password
|
|
82
|
+
password,
|
|
83
|
+
editingRights,
|
|
84
|
+
documentType,
|
|
85
|
+
shareByLink,
|
|
86
|
+
showAlert
|
|
87
|
+
})
|
|
88
|
+
const url = generateWebLink({
|
|
89
|
+
cozyUrl: client.getStackClient().uri,
|
|
90
|
+
searchParams: [['sharecode', perms.attributes.shortcodes.code]],
|
|
91
|
+
pathname: '/public',
|
|
92
|
+
slug: 'drive',
|
|
93
|
+
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
98
94
|
})
|
|
99
95
|
await copyToClipboard(url, { t, showAlert })
|
|
96
|
+
onClose()
|
|
100
97
|
} else {
|
|
101
|
-
await
|
|
102
|
-
client,
|
|
98
|
+
const [{ data: perms }] = await updatePermissions({
|
|
103
99
|
file,
|
|
104
100
|
t,
|
|
105
|
-
|
|
101
|
+
dateToggle,
|
|
102
|
+
selectedDate,
|
|
103
|
+
passwordToggle,
|
|
106
104
|
password,
|
|
105
|
+
editingRights,
|
|
106
|
+
documentType,
|
|
107
|
+
updateDocumentPermissions,
|
|
107
108
|
showAlert
|
|
108
109
|
})
|
|
110
|
+
const url = generateWebLink({
|
|
111
|
+
cozyUrl: client.getStackClient().uri,
|
|
112
|
+
searchParams: [['sharecode', perms.attributes.shortcodes.code]],
|
|
113
|
+
pathname: '/public',
|
|
114
|
+
slug: 'drive',
|
|
115
|
+
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
116
|
+
})
|
|
117
|
+
await copyToClipboard(url, { t, showAlert })
|
|
118
|
+
onClose()
|
|
109
119
|
}
|
|
110
|
-
onClose()
|
|
111
120
|
}
|
|
112
121
|
|
|
113
122
|
const handleRevokeLink = async () => {
|
|
@@ -132,7 +141,7 @@ export const ShareRestrictionModal = ({ file, onClose }) => {
|
|
|
132
141
|
// Date
|
|
133
142
|
dateToggle={dateToggle}
|
|
134
143
|
setDateToggle={setDateToggle}
|
|
135
|
-
setSelectedDate={
|
|
144
|
+
setSelectedDate={setSelectedDate}
|
|
136
145
|
selectedDate={selectedDate}
|
|
137
146
|
setIsValidDate={setIsValidDate}
|
|
138
147
|
// Password
|
|
@@ -109,11 +109,53 @@ export const forwardFile = async ({
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* createPermissions - Create the permissions of a file
|
|
114
|
+
* @param {object} options
|
|
115
|
+
* @param {import('cozy-client/types/types').IOCozyFile} options.file File to update permissions
|
|
116
|
+
* @param {Function} options.t i18n function
|
|
117
|
+
* @param {Date|string} options.ttl - Time to live of the sharing link
|
|
118
|
+
* @param {string} options.password - Password
|
|
119
|
+
* @param {'readOnly'|'write'} options.editingRights - Editing rights
|
|
120
|
+
* @param {string} options.documentType - Type of the document
|
|
121
|
+
* @param {Function} options.shareByLink - Function to create permissions
|
|
122
|
+
* @param {Function} options.showAlert - Function to display an alert
|
|
123
|
+
*/
|
|
124
|
+
export const createPermissions = async ({
|
|
125
|
+
file,
|
|
126
|
+
t,
|
|
127
|
+
ttl,
|
|
128
|
+
password,
|
|
129
|
+
editingRights,
|
|
130
|
+
documentType,
|
|
131
|
+
shareByLink,
|
|
132
|
+
showAlert
|
|
133
|
+
}) => {
|
|
134
|
+
try {
|
|
135
|
+
const verbs = editingRights === 'readOnly' ? READ_ONLY_PERMS : WRITE_PERMS
|
|
136
|
+
return shareByLink(file, { verbs, ttl, password })
|
|
137
|
+
} catch (err) {
|
|
138
|
+
showAlert({
|
|
139
|
+
message: t(`${documentType}.share.shareByLink.permserror`),
|
|
140
|
+
severity: 'error',
|
|
141
|
+
variant: 'filled'
|
|
142
|
+
})
|
|
143
|
+
log.error(
|
|
144
|
+
"Error in 'readOnlyPermissionLink' function when trying to change permission",
|
|
145
|
+
err
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
112
150
|
/**
|
|
113
151
|
* updatePermissions - Updates the permissions of a file
|
|
114
152
|
* @param {object} options
|
|
115
153
|
* @param {import('cozy-client/types/types').IOCozyFile} options.file File to update permissions
|
|
116
154
|
* @param {Function} options.t i18n function
|
|
155
|
+
* @param {boolean} options.dateToggle - Expiration date toggle
|
|
156
|
+
* @param {Date|null} options.selectedDate - Expiration date
|
|
157
|
+
* @param {boolean} options.passwordToggle - Password toggle
|
|
158
|
+
* @param {string} options.password - Password
|
|
117
159
|
* @param {string} options.documentType - Type of the document
|
|
118
160
|
* @param {'readOnly'|'write'} options.editingRights - Editing rights
|
|
119
161
|
* @param {Function} options.updateDocumentPermissions - Function to update permissions
|
|
@@ -122,42 +164,34 @@ export const forwardFile = async ({
|
|
|
122
164
|
export const updatePermissions = async ({
|
|
123
165
|
file,
|
|
124
166
|
t,
|
|
167
|
+
dateToggle,
|
|
168
|
+
selectedDate,
|
|
169
|
+
passwordToggle,
|
|
170
|
+
password,
|
|
125
171
|
editingRights,
|
|
126
172
|
documentType,
|
|
127
173
|
updateDocumentPermissions,
|
|
128
174
|
showAlert
|
|
129
175
|
}) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
} catch (err) {
|
|
150
|
-
showAlert({
|
|
151
|
-
message: t(`${documentType}.share.shareByLink.permserror`),
|
|
152
|
-
severity: 'error',
|
|
153
|
-
variant: 'filled'
|
|
154
|
-
})
|
|
155
|
-
log.error(
|
|
156
|
-
"Error in 'editPermissionLink' function when trying to change permission",
|
|
157
|
-
err
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
break
|
|
176
|
+
try {
|
|
177
|
+
const expiresAt = dateToggle ? selectedDate?.toISOString() || undefined : ''
|
|
178
|
+
const ensurePassword = passwordToggle ? password || undefined : ''
|
|
179
|
+
const verbs = editingRights === 'readOnly' ? READ_ONLY_PERMS : WRITE_PERMS
|
|
180
|
+
return updateDocumentPermissions(file, {
|
|
181
|
+
verbs,
|
|
182
|
+
expiresAt,
|
|
183
|
+
password: ensurePassword
|
|
184
|
+
})
|
|
185
|
+
} catch (err) {
|
|
186
|
+
showAlert({
|
|
187
|
+
message: t(`${documentType}.share.shareByLink.permserror`),
|
|
188
|
+
severity: 'error',
|
|
189
|
+
variant: 'filled'
|
|
190
|
+
})
|
|
191
|
+
log.error(
|
|
192
|
+
"Error in 'updateDocumentPermissions' function when trying to change permission",
|
|
193
|
+
err
|
|
194
|
+
)
|
|
161
195
|
}
|
|
162
196
|
}
|
|
163
197
|
|
|
@@ -21,40 +21,121 @@ describe('ShareRestrictionModal/helpers', () => {
|
|
|
21
21
|
it('should call updateDocumentPermissions with "readOnly" permission', async () => {
|
|
22
22
|
const updateDocumentPermissions = jest.fn()
|
|
23
23
|
const file = { _id: '123' }
|
|
24
|
-
const editingRights = 'readOnly'
|
|
25
24
|
|
|
26
25
|
await updatePermissions({
|
|
27
26
|
file,
|
|
28
27
|
t: jest.fn(),
|
|
29
|
-
|
|
28
|
+
dateToggle: false,
|
|
29
|
+
selectedDate: null,
|
|
30
|
+
passwordToggle: false,
|
|
31
|
+
password: '',
|
|
32
|
+
editingRights: 'readOnly',
|
|
30
33
|
documentType,
|
|
31
34
|
updateDocumentPermissions,
|
|
32
35
|
showAlert: jest.fn()
|
|
33
36
|
})
|
|
34
37
|
|
|
35
|
-
expect(updateDocumentPermissions).toHaveBeenCalledWith(file,
|
|
38
|
+
expect(updateDocumentPermissions).toHaveBeenCalledWith(file, {
|
|
39
|
+
expiresAt: '',
|
|
40
|
+
password: '',
|
|
41
|
+
verbs: ['GET']
|
|
42
|
+
})
|
|
36
43
|
})
|
|
37
44
|
|
|
38
45
|
it('should call updateDocumentPermissions with "write" permissions', async () => {
|
|
39
46
|
const updateDocumentPermissions = jest.fn()
|
|
40
47
|
const file = { _id: '123' }
|
|
41
|
-
const editingRights = 'write'
|
|
42
48
|
|
|
43
49
|
await updatePermissions({
|
|
44
50
|
file,
|
|
45
51
|
t: jest.fn(),
|
|
46
|
-
|
|
52
|
+
dateToggle: false,
|
|
53
|
+
selectedDate: null,
|
|
54
|
+
passwordToggle: false,
|
|
55
|
+
password: '',
|
|
56
|
+
editingRights: 'write',
|
|
57
|
+
documentType,
|
|
58
|
+
updateDocumentPermissions,
|
|
59
|
+
showAlert: jest.fn()
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
expect(updateDocumentPermissions).toHaveBeenCalledWith(file, {
|
|
63
|
+
expiresAt: '',
|
|
64
|
+
password: '',
|
|
65
|
+
verbs: ['GET', 'POST', 'PUT', 'PATCH']
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should call updateDocumentPermissions with empty date & password if their switches are false', async () => {
|
|
70
|
+
const updateDocumentPermissions = jest.fn()
|
|
71
|
+
const file = { _id: '123' }
|
|
72
|
+
|
|
73
|
+
await updatePermissions({
|
|
74
|
+
file,
|
|
75
|
+
t: jest.fn(),
|
|
76
|
+
dateToggle: false,
|
|
77
|
+
selectedDate: null,
|
|
78
|
+
passwordToggle: false,
|
|
79
|
+
password: '',
|
|
80
|
+
editingRights: 'readOnly',
|
|
81
|
+
documentType,
|
|
82
|
+
updateDocumentPermissions,
|
|
83
|
+
showAlert: jest.fn()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
expect(updateDocumentPermissions).toHaveBeenCalledWith(file, {
|
|
87
|
+
expiresAt: '',
|
|
88
|
+
password: '',
|
|
89
|
+
verbs: ['GET']
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('should call updateDocumentPermissions with "undefined" date & password if their switches are true but the permission doesn\'t yet have these values', async () => {
|
|
94
|
+
const updateDocumentPermissions = jest.fn()
|
|
95
|
+
const file = { _id: '123' }
|
|
96
|
+
|
|
97
|
+
await updatePermissions({
|
|
98
|
+
file,
|
|
99
|
+
t: jest.fn(),
|
|
100
|
+
dateToggle: true,
|
|
101
|
+
selectedDate: null,
|
|
102
|
+
passwordToggle: true,
|
|
103
|
+
password: '',
|
|
104
|
+
editingRights: 'readOnly',
|
|
105
|
+
documentType,
|
|
106
|
+
updateDocumentPermissions,
|
|
107
|
+
showAlert: jest.fn()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
expect(updateDocumentPermissions).toHaveBeenCalledWith(file, {
|
|
111
|
+
expiresAt: undefined,
|
|
112
|
+
password: undefined,
|
|
113
|
+
verbs: ['GET']
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('should call updateDocumentPermissions with expected date & password if their switches are true', async () => {
|
|
118
|
+
const updateDocumentPermissions = jest.fn()
|
|
119
|
+
const file = { _id: '123' }
|
|
120
|
+
|
|
121
|
+
await updatePermissions({
|
|
122
|
+
file,
|
|
123
|
+
t: jest.fn(),
|
|
124
|
+
dateToggle: true,
|
|
125
|
+
selectedDate: new Date('2100-01-01T00:00:00.000Z'),
|
|
126
|
+
passwordToggle: true,
|
|
127
|
+
password: '1234',
|
|
128
|
+
editingRights: 'readOnly',
|
|
47
129
|
documentType,
|
|
48
130
|
updateDocumentPermissions,
|
|
49
131
|
showAlert: jest.fn()
|
|
50
132
|
})
|
|
51
133
|
|
|
52
|
-
expect(updateDocumentPermissions).toHaveBeenCalledWith(file,
|
|
53
|
-
'
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
|
|
57
|
-
])
|
|
134
|
+
expect(updateDocumentPermissions).toHaveBeenCalledWith(file, {
|
|
135
|
+
expiresAt: '2100-01-01T00:00:00.000Z',
|
|
136
|
+
password: '1234',
|
|
137
|
+
verbs: ['GET']
|
|
138
|
+
})
|
|
58
139
|
})
|
|
59
140
|
})
|
|
60
141
|
|
|
@@ -49,12 +49,12 @@ const openExternalLink = url => (window.location = url)
|
|
|
49
49
|
const SharingBannerCozyToCozy = ({
|
|
50
50
|
sharing,
|
|
51
51
|
isSharingShortcutCreated,
|
|
52
|
-
|
|
52
|
+
addSharingLink,
|
|
53
53
|
onClose
|
|
54
54
|
}) => {
|
|
55
55
|
const { t } = useI18n()
|
|
56
56
|
|
|
57
|
-
const action = () => openExternalLink(
|
|
57
|
+
const action = () => openExternalLink(addSharingLink)
|
|
58
58
|
const buttonOne = isSharingShortcutCreated
|
|
59
59
|
? {
|
|
60
60
|
label: t('Share.banner.sync_to_mine', { smart_count: 2 }),
|
|
@@ -139,7 +139,7 @@ const SharingBannerByLink = ({ onClose }) => {
|
|
|
139
139
|
SharingBannerCozyToCozy.propTypes = {
|
|
140
140
|
sharing: PropTypes.object.isRequired,
|
|
141
141
|
isSharingShortcutCreated: PropTypes.bool.isRequired,
|
|
142
|
-
|
|
142
|
+
addToCozySharingLink: PropTypes.string.isRequired,
|
|
143
143
|
onClose: PropTypes.func.isRequired
|
|
144
144
|
}
|
|
145
145
|
export { SharingBannerCozyToCozy, SharingBannerByLink }
|
|
@@ -7,19 +7,19 @@ export const SharingBanner = ({ sharingInfos }) => {
|
|
|
7
7
|
const [isOpened, setIsOpened] = useState(true)
|
|
8
8
|
const onClose = useCallback(() => setIsOpened(false), [setIsOpened])
|
|
9
9
|
|
|
10
|
-
const { loading,
|
|
10
|
+
const { loading, addSharingLink, sharing, isSharingShortcutCreated } =
|
|
11
11
|
sharingInfos
|
|
12
12
|
|
|
13
13
|
if (loading) return null
|
|
14
14
|
return (
|
|
15
15
|
isOpened &&
|
|
16
|
-
(!
|
|
16
|
+
(!addSharingLink ? (
|
|
17
17
|
<SharingBannerByLink onClose={onClose} />
|
|
18
18
|
) : (
|
|
19
19
|
<SharingBannerCozyToCozy
|
|
20
20
|
isSharingShortcutCreated={isSharingShortcutCreated}
|
|
21
21
|
sharing={sharing}
|
|
22
|
-
|
|
22
|
+
addSharingLink={addSharingLink}
|
|
23
23
|
onClose={onClose}
|
|
24
24
|
/>
|
|
25
25
|
))
|
|
@@ -12,10 +12,13 @@ const getSharingId = permission => {
|
|
|
12
12
|
return sharingId
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
const CREATE_COZY_LINK = 'https://manager.cozycloud.cc/cozy/create'
|
|
16
|
+
|
|
15
17
|
export const useSharingInfos = (previewPath = '/preview') => {
|
|
16
18
|
const client = useClient()
|
|
17
19
|
|
|
18
|
-
const [
|
|
20
|
+
const [addSharingLink, setAddSharingLink] = useState()
|
|
21
|
+
const [syncSharingLink, setSyncSharingLink] = useState()
|
|
19
22
|
const [isSharingShortcutCreated, setIsSharingSharingcutCreated] =
|
|
20
23
|
useState(false)
|
|
21
24
|
const [sharing, setSharing] = useState()
|
|
@@ -35,6 +38,9 @@ export const useSharingInfos = (previewPath = '/preview') => {
|
|
|
35
38
|
const { sharecode } = getQueryParameter()
|
|
36
39
|
|
|
37
40
|
const link = client
|
|
41
|
+
.collection('io.cozy.sharings')
|
|
42
|
+
.getDiscoveryLink(sharingId, sharecode, { shortcut: true })
|
|
43
|
+
const linkSync = client
|
|
38
44
|
.collection('io.cozy.sharings')
|
|
39
45
|
.getDiscoveryLink(sharingId, sharecode)
|
|
40
46
|
const sharingsByIdQuery = buildSharingsByIdQuery(sharingId)
|
|
@@ -42,7 +48,8 @@ export const useSharingInfos = (previewPath = '/preview') => {
|
|
|
42
48
|
sharingsByIdQuery.definition
|
|
43
49
|
)
|
|
44
50
|
|
|
45
|
-
|
|
51
|
+
setAddSharingLink(link)
|
|
52
|
+
setSyncSharingLink(linkSync)
|
|
46
53
|
setIsSharingSharingcutCreated(isSharingShortcutCreated)
|
|
47
54
|
setSharing(sharing)
|
|
48
55
|
} catch (e) {
|
|
@@ -62,7 +69,9 @@ export const useSharingInfos = (previewPath = '/preview') => {
|
|
|
62
69
|
return {
|
|
63
70
|
sharing,
|
|
64
71
|
loading,
|
|
65
|
-
|
|
72
|
+
addSharingLink,
|
|
73
|
+
syncSharingLink,
|
|
74
|
+
createCozyLink: CREATE_COZY_LINK,
|
|
66
75
|
isSharingShortcutCreated
|
|
67
76
|
}
|
|
68
77
|
}
|
|
@@ -81,8 +81,8 @@ describe('useSharingInfos', () => {
|
|
|
81
81
|
})
|
|
82
82
|
|
|
83
83
|
it('returns the right infos when using useSharingInfo', async () => {
|
|
84
|
-
const
|
|
85
|
-
getDiscoveryLinkMock.mockReturnValue(
|
|
84
|
+
const addSharingLink = '/addSharingLink'
|
|
85
|
+
getDiscoveryLinkMock.mockReturnValue(addSharingLink)
|
|
86
86
|
fetchOwnPermissionsMock.mockResolvedValue(mockedPermissionsWithInstance)
|
|
87
87
|
queryMock.mockResolvedValue(mockSharing)
|
|
88
88
|
const { result, waitForNextUpdate } = setup()
|
|
@@ -93,12 +93,12 @@ describe('useSharingInfos', () => {
|
|
|
93
93
|
expect(result.current.loading).toEqual(false)
|
|
94
94
|
expect(result.current.isSharingShortcutCreated).toEqual(true)
|
|
95
95
|
expect(result.current.sharing).toEqual(mockSharing.data)
|
|
96
|
-
expect(result.current.
|
|
96
|
+
expect(result.current.addSharingLink).toEqual(addSharingLink)
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
-
it('returns the right infos when using useSharingInfo without
|
|
100
|
-
const
|
|
101
|
-
getDiscoveryLinkMock.mockReturnValue(
|
|
99
|
+
it('returns the right infos when using useSharingInfo without addSharingLink', async () => {
|
|
100
|
+
const addSharingLink = undefined
|
|
101
|
+
getDiscoveryLinkMock.mockReturnValue(addSharingLink)
|
|
102
102
|
fetchOwnPermissionsMock.mockResolvedValue(mockedPermissionsWithoutInstance)
|
|
103
103
|
queryMock.mockResolvedValue(mockSharing)
|
|
104
104
|
const { result, waitForNextUpdate } = setup()
|
|
@@ -109,7 +109,7 @@ describe('useSharingInfos', () => {
|
|
|
109
109
|
expect(result.current.loading).toEqual(false)
|
|
110
110
|
expect(result.current.isSharingShortcutCreated).toEqual(false)
|
|
111
111
|
expect(result.current.sharing).toEqual(mockSharing.data)
|
|
112
|
-
expect(result.current.
|
|
112
|
+
expect(result.current.addSharingLink).toEqual(addSharingLink)
|
|
113
113
|
})
|
|
114
114
|
|
|
115
115
|
it('returns loading false if there is nothing to do aka sharing by link', () => {
|
|
@@ -14,3 +14,15 @@ export const checkIsReadOnlyPermissions = permissions => {
|
|
|
14
14
|
).length > 0
|
|
15
15
|
)
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
export const checkIsPermissionHasExpiresDate = permissions => {
|
|
19
|
+
return Boolean(permissions?.[0]?.attributes?.expires_at)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const getPermissionExpiresDate = permissions => {
|
|
23
|
+
return permissions?.[0]?.attributes?.expires_at
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const checkIsPermissionHasPassword = permissions => {
|
|
27
|
+
return Boolean(permissions?.[0]?.attributes?.password)
|
|
28
|
+
}
|
package/src/index.jsx
CHANGED
|
@@ -33,5 +33,7 @@ export {
|
|
|
33
33
|
NativeFileSharingProvider,
|
|
34
34
|
useNativeFileSharing
|
|
35
35
|
} from './providers/NativeFileSharingProvider'
|
|
36
|
-
export {
|
|
36
|
+
export { createCozySharingLink } from './actions/createCozySharingLink'
|
|
37
|
+
export { addToCozySharingLink } from './actions/addToCozySharingLink'
|
|
38
|
+
export { syncToCozySharingLink } from './actions/syncToCozySharingLink'
|
|
37
39
|
export { shareNative } from './actions/shareNative'
|