cozy-sharing 17.0.0 → 19.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/SharingProvider.spec.js +84 -80
  3. package/dist/components/Recipient/LinkRecipientPermissions.js +18 -129
  4. package/dist/components/Recipient/actions/editPermissionLink.js +71 -0
  5. package/dist/components/Recipient/actions/readOnlyPermissionLink.js +63 -0
  6. package/dist/components/ShareByLink.js +45 -185
  7. package/dist/components/ShareDialogCozyToCozy.js +2 -6
  8. package/dist/components/ShareDialogOnlyByLink.js +2 -8
  9. package/dist/components/ShareDialogTwoStepsConfirmationContainer.js +1 -3
  10. package/dist/components/ShareModal/EditableSharingModal.js +1 -7
  11. package/dist/components/ShareModal/EditableSharingModal.spec.js +49 -52
  12. package/dist/components/ShareModal/SharingDetailsModal.js +1 -1
  13. package/dist/components/ShareModal.js +0 -12
  14. package/dist/components/ShareRestrictionModal/BoxDate.js +77 -0
  15. package/dist/components/ShareRestrictionModal/BoxEditingRights.js +83 -0
  16. package/dist/components/ShareRestrictionModal/BoxPassword.js +138 -0
  17. package/dist/components/ShareRestrictionModal/ShareRestrictionContentModal.js +94 -0
  18. package/dist/components/ShareRestrictionModal/ShareRestrictionModal.js +260 -0
  19. package/dist/components/ShareRestrictionModal/helpers.js +275 -0
  20. package/dist/components/ShareRestrictionModal/helpers.spec.js +110 -0
  21. package/dist/components/SharedStatus.spec.js +20 -21
  22. package/dist/components/WhoHasAccess.js +1 -5
  23. package/jest.config.js +8 -3
  24. package/jestHelpers/setup.js +1 -8
  25. package/locales/en.json +28 -0
  26. package/locales/fr.json +29 -0
  27. package/package.json +13 -11
  28. package/src/SharingProvider.spec.jsx +88 -88
  29. package/src/components/Recipient/LinkRecipientPermissions.jsx +28 -137
  30. package/src/components/Recipient/actions/editPermissionLink.js +63 -0
  31. package/src/components/Recipient/actions/readOnlyPermissionLink.js +59 -0
  32. package/src/components/ShareByLink.jsx +20 -96
  33. package/src/components/ShareDialogCozyToCozy.jsx +1 -5
  34. package/src/components/ShareDialogOnlyByLink.jsx +0 -6
  35. package/src/components/ShareDialogTwoStepsConfirmationContainer.jsx +0 -2
  36. package/src/components/ShareModal/EditableSharingModal.jsx +1 -7
  37. package/src/components/ShareModal/EditableSharingModal.spec.jsx +50 -44
  38. package/src/components/ShareModal/SharingDetailsModal.jsx +1 -1
  39. package/src/components/ShareModal.jsx +0 -12
  40. package/src/components/ShareRestrictionModal/BoxDate.jsx +76 -0
  41. package/src/components/ShareRestrictionModal/BoxEditingRights.jsx +91 -0
  42. package/src/components/ShareRestrictionModal/BoxPassword.jsx +112 -0
  43. package/src/components/ShareRestrictionModal/ShareRestrictionContentModal.jsx +102 -0
  44. package/src/components/ShareRestrictionModal/ShareRestrictionModal.jsx +177 -0
  45. package/src/components/ShareRestrictionModal/helpers.js +193 -0
  46. package/src/components/ShareRestrictionModal/helpers.spec.js +78 -0
  47. package/src/components/SharedStatus.spec.js +32 -31
  48. package/src/components/WhoHasAccess.jsx +1 -5
  49. package/src/components/__snapshots__/SharedStatus.spec.js.snap +59 -129
  50. package/dist/RefreshableSharings.spec.js +0 -40
  51. package/dist/components/EditLinkPermissionDialog.js +0 -72
  52. package/dist/components/EditLinkPermissionDialog.spec.js +0 -48
  53. package/src/RefreshableSharings.spec.jsx +0 -43
  54. package/src/components/EditLinkPermissionDialog.jsx +0 -89
  55. package/src/components/EditLinkPermissionDialog.spec.jsx +0 -53
@@ -0,0 +1,112 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useState } from 'react'
3
+
4
+ import Box from 'cozy-ui/transpiled/react/Box'
5
+ import Icon from 'cozy-ui/transpiled/react/Icon'
6
+ import IconButton from 'cozy-ui/transpiled/react/IconButton'
7
+ import List from 'cozy-ui/transpiled/react/List'
8
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
9
+ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
10
+ import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
11
+ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
12
+ import Switch from 'cozy-ui/transpiled/react/Switch'
13
+ import TextField from 'cozy-ui/transpiled/react/TextField'
14
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
15
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
16
+
17
+ import { copyToClipboard } from './helpers'
18
+
19
+ export const BoxPassword = ({
20
+ onChange,
21
+ password,
22
+ onToggle,
23
+ toggle,
24
+ helperText,
25
+ inputProps
26
+ }) => {
27
+ const { t } = useI18n()
28
+ const { showAlert } = useAlert()
29
+ const [displayHelper, setDisplayHelper] = useState(false)
30
+ const inputRef = React.useRef()
31
+
32
+ const handlePasswordToggle = val => {
33
+ const value = val?.target?.checked ?? val
34
+ onToggle(value)
35
+ }
36
+
37
+ const handleChange = val => {
38
+ const value = val?.target?.value ?? val
39
+ onChange(value)
40
+ }
41
+ const handleOnFocus = () => {
42
+ setDisplayHelper(false)
43
+ }
44
+ const handleOnBlur = () => {
45
+ handleChange(inputRef.current.value.trim())
46
+ setDisplayHelper(true)
47
+ }
48
+
49
+ const handleCopy = async () => {
50
+ await copyToClipboard(password, { t, showAlert })
51
+ }
52
+
53
+ return (
54
+ <Box borderRadius="0.5rem" border="1px solid var(--borderMainColor)">
55
+ <List className="u-p-0">
56
+ <ListItem
57
+ button
58
+ size="large"
59
+ ellipsis={false}
60
+ onClick={() => handlePasswordToggle(!toggle)}
61
+ >
62
+ <ListItemIcon>
63
+ <Icon icon="password" />
64
+ </ListItemIcon>
65
+ <ListItemText primary={t('BoxPassword.text')} />
66
+ <ListItemSecondaryAction>
67
+ <Switch
68
+ edge="end"
69
+ color="primary"
70
+ checked={toggle}
71
+ onChange={handlePasswordToggle}
72
+ />
73
+ </ListItemSecondaryAction>
74
+ </ListItem>
75
+ </List>
76
+ {toggle && (
77
+ <div className="u-pt-half u-ph-1 u-pb-1">
78
+ <TextField
79
+ inputRef={inputRef}
80
+ label={t('BoxPassword.label')}
81
+ value={password}
82
+ error={displayHelper && !!helperText}
83
+ helperText={displayHelper && helperText}
84
+ onChange={handleChange}
85
+ onFocus={handleOnFocus}
86
+ onBlur={handleOnBlur}
87
+ fullWidth
88
+ type="text"
89
+ variant="outlined"
90
+ InputProps={{
91
+ endAdornment: (
92
+ <IconButton onClick={handleCopy}>
93
+ <Icon icon="copy" />
94
+ </IconButton>
95
+ )
96
+ }}
97
+ inputProps={inputProps}
98
+ />
99
+ </div>
100
+ )}
101
+ </Box>
102
+ )
103
+ }
104
+
105
+ BoxPassword.propTypes = {
106
+ onChange: PropTypes.func.isRequired,
107
+ password: PropTypes.string,
108
+ onToggle: PropTypes.func.isRequired,
109
+ toggle: PropTypes.bool.isRequired,
110
+ helperText: PropTypes.string,
111
+ inputProps: PropTypes.object
112
+ }
@@ -0,0 +1,102 @@
1
+ import { addDays } from 'date-fns'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ import Box from 'cozy-ui/transpiled/react/Box'
6
+ import Typography from 'cozy-ui/transpiled/react/Typography'
7
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
8
+
9
+ import { BoxDate } from './BoxDate'
10
+ import { BoxEditingRights } from './BoxEditingRights'
11
+ import { BoxPassword } from './BoxPassword'
12
+
13
+ const PASSWORD_MIN_LENGTH = 4
14
+
15
+ export const ShareRestrictionContentModal = ({
16
+ file,
17
+ // Date
18
+ selectedDate,
19
+ setSelectedDate,
20
+ dateToggle,
21
+ setDateToggle,
22
+ setIsValidDate,
23
+ // Password
24
+ helperTextPassword,
25
+ password,
26
+ setPassword,
27
+ passwordToggle,
28
+ setPasswordToggle,
29
+ setIsValidPassword,
30
+ // Editing rights
31
+ editingRights,
32
+ setEditingRights
33
+ }) => {
34
+ const { t } = useI18n()
35
+
36
+ const handlePasswordToggle = val => {
37
+ setPasswordToggle(val)
38
+ }
39
+ const handlePassword = value => {
40
+ setPassword(value)
41
+ setIsValidPassword(
42
+ value.trim().length === 0 || value.trim().length >= PASSWORD_MIN_LENGTH
43
+ )
44
+ }
45
+
46
+ const handleDateToggle = val => {
47
+ if (!val) {
48
+ setIsValidDate(true)
49
+ }
50
+ const defaultValue = val ? addDays(new Date(), 30) : null
51
+ setSelectedDate(defaultValue, true)
52
+ setDateToggle(val)
53
+ }
54
+
55
+ return (
56
+ <Box display="flex" flexDirection="column" gridGap="1rem">
57
+ <Typography variant="h4" className="u-mb-half u-ml-half">
58
+ {t('ShareRestrictionModal.title')}
59
+ </Typography>
60
+
61
+ <BoxEditingRights
62
+ file={file}
63
+ editingRights={editingRights}
64
+ setEditingRights={setEditingRights}
65
+ />
66
+ <BoxDate
67
+ onChange={setSelectedDate}
68
+ date={selectedDate}
69
+ onToggle={handleDateToggle}
70
+ toggle={dateToggle}
71
+ />
72
+ <BoxPassword
73
+ onChange={handlePassword}
74
+ password={password}
75
+ onToggle={handlePasswordToggle}
76
+ toggle={passwordToggle}
77
+ helperText={helperTextPassword}
78
+ inputProps={{ minLength: PASSWORD_MIN_LENGTH }}
79
+ />
80
+ </Box>
81
+ )
82
+ }
83
+
84
+ ShareRestrictionContentModal.propTypes = {
85
+ file: PropTypes.object.isRequired,
86
+ // Date
87
+ selectedDate: PropTypes.object,
88
+ setSelectedDate: PropTypes.func.isRequired,
89
+ dateToggle: PropTypes.bool,
90
+ setDateToggle: PropTypes.func.isRequired,
91
+ setIsValidDate: PropTypes.func.isRequired,
92
+ // Password
93
+ helperTextPassword: PropTypes.string,
94
+ password: PropTypes.string,
95
+ setPassword: PropTypes.func.isRequired,
96
+ passwordToggle: PropTypes.bool.isRequired,
97
+ setPasswordToggle: PropTypes.func.isRequired,
98
+ setIsValidPassword: PropTypes.func.isRequired,
99
+ // Editing rights
100
+ editingRights: PropTypes.oneOf(['readOnly', 'write']),
101
+ setEditingRights: PropTypes.func.isRequired
102
+ }
@@ -0,0 +1,177 @@
1
+ import { addDays } from 'date-fns'
2
+ import PropTypes from 'prop-types'
3
+ import React, { useState } from 'react'
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'
8
+ import Button from 'cozy-ui/transpiled/react/Buttons'
9
+ import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
10
+ import Icon from 'cozy-ui/transpiled/react/Icon'
11
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
12
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
13
+
14
+ import { ShareRestrictionContentModal } from './ShareRestrictionContentModal'
15
+ import {
16
+ copyToClipboard,
17
+ forwardFile,
18
+ updatePermissions,
19
+ makeTTL,
20
+ READ_ONLY_PERMS,
21
+ WRITE_PERMS,
22
+ revokePermissions
23
+ } from './helpers'
24
+ import { checkIsReadOnlyPermissions } from '../../helpers/permissions'
25
+ import { useSharingContext } from '../../hooks/useSharingContext'
26
+
27
+ const PASSWORD_MIN_LENGTH = 4
28
+
29
+ export const ShareRestrictionModal = ({ file, onClose }) => {
30
+ const client = useClient()
31
+ const { t } = useI18n()
32
+ const { showAlert } = useAlert()
33
+ const [password, setPassword] = useState('')
34
+ const [selectedDate, setSelectedDate] = useState(addDays(new Date(), 30))
35
+ const [isValidDate, setIsValidDate] = useState(true)
36
+ const [isValidPassword, setIsValidPassword] = useState(true)
37
+ const [dateToggle, setDateToggle] = useState(true)
38
+ const [passwordToggle, setPasswordToggle] = useState(false)
39
+ const [loading, setLoading] = useState(false)
40
+
41
+ const {
42
+ documentType,
43
+ getDocumentPermissions,
44
+ updateDocumentPermissions,
45
+ shareByLink,
46
+ getSharingLink,
47
+ revokeSharingLink
48
+ } = useSharingContext()
49
+
50
+ const hasSharingLink = getSharingLink(file._id) !== null
51
+ const permissions = getDocumentPermissions(file._id)
52
+ const isReadOnlyPermissions = checkIsReadOnlyPermissions(permissions)
53
+
54
+ const [editingRights, setEditingRights] = useState(
55
+ isReadOnlyPermissions || permissions.length === 0 ? 'readOnly' : 'write'
56
+ )
57
+
58
+ const isDesktopOrMobileWithoutShareAPI =
59
+ (isMobile() && !navigator.share) || !isMobile()
60
+
61
+ const helperTextPassword = !isValidPassword
62
+ ? t('ShareRestrictionModal.invalidPasswordMessage', {
63
+ smart_count: PASSWORD_MIN_LENGTH - password.length
64
+ })
65
+ : null
66
+
67
+ const handleDateChange = (date, isValid) => {
68
+ setSelectedDate(date)
69
+ setIsValidDate(isValid)
70
+ }
71
+
72
+ const handleClick = async () => {
73
+ setLoading(true)
74
+ // If the file is not shared, we create a new sharing link
75
+ if (!hasSharingLink) {
76
+ const verbs = editingRights === 'readOnly' ? READ_ONLY_PERMS : WRITE_PERMS
77
+ await shareByLink(file, { verbs })
78
+ const url = getSharingLink(file._id)
79
+ await copyToClipboard(url, { t, showAlert })
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], {
96
+ ttl,
97
+ password
98
+ })
99
+ await copyToClipboard(url, { t, showAlert })
100
+ } else {
101
+ await forwardFile({
102
+ client,
103
+ file,
104
+ t,
105
+ ttl,
106
+ password,
107
+ showAlert
108
+ })
109
+ }
110
+ onClose()
111
+ }
112
+
113
+ const handleRevokeLink = async () => {
114
+ setLoading(true)
115
+ await revokePermissions({
116
+ file,
117
+ t,
118
+ documentType,
119
+ revokeSharingLink,
120
+ showAlert
121
+ })
122
+ onClose()
123
+ }
124
+
125
+ return (
126
+ <ConfirmDialog
127
+ open
128
+ onClose={onClose}
129
+ content={
130
+ <ShareRestrictionContentModal
131
+ file={file}
132
+ // Date
133
+ dateToggle={dateToggle}
134
+ setDateToggle={setDateToggle}
135
+ setSelectedDate={handleDateChange}
136
+ selectedDate={selectedDate}
137
+ setIsValidDate={setIsValidDate}
138
+ // Password
139
+ helperTextPassword={helperTextPassword}
140
+ passwordToggle={passwordToggle}
141
+ setPasswordToggle={setPasswordToggle}
142
+ password={password}
143
+ setPassword={setPassword}
144
+ setIsValidPassword={setIsValidPassword}
145
+ // Editing rights
146
+ editingRights={editingRights}
147
+ setEditingRights={setEditingRights}
148
+ />
149
+ }
150
+ actions={
151
+ <>
152
+ {hasSharingLink && (
153
+ <Button
154
+ label={t('Share.permissionLink.deactivate')}
155
+ variant="secondary"
156
+ color="error"
157
+ startIcon={<Icon icon="trash" />}
158
+ onClick={handleRevokeLink}
159
+ busy={loading}
160
+ />
161
+ )}
162
+ <Button
163
+ label={t('ShareRestrictionModal.action.confirm')}
164
+ onClick={handleClick}
165
+ disabled={!isValidDate || !isValidPassword}
166
+ busy={loading}
167
+ />
168
+ </>
169
+ }
170
+ />
171
+ )
172
+ }
173
+
174
+ ShareRestrictionModal.propTypes = {
175
+ file: PropTypes.object.isRequired,
176
+ onClose: PropTypes.func
177
+ }
@@ -0,0 +1,193 @@
1
+ import { getSharingLink } from 'cozy-client/dist/models/sharing'
2
+ import minilog from 'cozy-minilog'
3
+
4
+ const log = minilog('ShareRestrictionModal/helpers')
5
+
6
+ export const WRITE_PERMS = ['GET', 'POST', 'PUT', 'PATCH']
7
+ export const READ_ONLY_PERMS = ['GET']
8
+
9
+ /**
10
+ * Copy a string to the clipboard
11
+ *
12
+ * @param {string} value - The string saved to the clipboard
13
+ * @param {object} [options]
14
+ * @param {number} options.t - Translation function
15
+ * @param {Function} options.showAlert - Function to display an alert
16
+ */
17
+ export const copyToClipboard = async (value, { t, showAlert } = {}) => {
18
+ if (!value) return false
19
+ try {
20
+ await navigator.clipboard.writeText(value)
21
+ showAlert({
22
+ message: t('copyReminderContent.success'),
23
+ severity: 'success',
24
+ variant: 'filled'
25
+ })
26
+ } catch (error) {
27
+ showAlert({
28
+ message: t('copyReminderContent.error'),
29
+ severity: 'error',
30
+ variant: 'filled'
31
+ })
32
+ log.error(
33
+ "Error in 'copyToClipboard' function when trying to copy to clipboard",
34
+ error
35
+ )
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Make a TTL string from a date
41
+ * @param {Date|string} selectedDate
42
+ * @returns {string} - TTL string in seconds (e.g. '1234s')
43
+ */
44
+ export const makeTTL = selectedDate => {
45
+ if (!selectedDate) return
46
+ try {
47
+ let selectedDateConverted = selectedDate
48
+ if (typeof selectedDate === 'string') {
49
+ selectedDateConverted = new Date(selectedDate)
50
+ if (selectedDateConverted?.toString() === 'Invalid Date') {
51
+ throw new Error(`Invalid date: ${selectedDate}`)
52
+ }
53
+ }
54
+ if (selectedDateConverted instanceof Date) {
55
+ const now = new Date()
56
+ const ttl =
57
+ selectedDateConverted > now
58
+ ? `${Math.round((selectedDateConverted - now) / 1000)}s`
59
+ : undefined
60
+ return ttl
61
+ }
62
+ throw new Error(`Invalid date: ${selectedDate}`)
63
+ } catch (error) {
64
+ log.error(error)
65
+ return
66
+ }
67
+ }
68
+
69
+ /**
70
+ * forwardFile - Triggers the download of one or multiple files by the browser
71
+ * @param {object} options
72
+ * @param {import('cozy-client/types/CozyClient').default} options.client
73
+ * @param {import('cozy-client/types/types').IOCozyFile} options.file File to download
74
+ * @param {Function} options.t i18n function
75
+ * @param {string} options.ttl Time to live of the sharing link
76
+ * @param {string} options.password Password of the sharing link
77
+ * @param {Function} options.showAlert - Function to display an alert
78
+ */
79
+ export const forwardFile = async ({
80
+ client,
81
+ file,
82
+ t,
83
+ ttl,
84
+ password,
85
+ showAlert
86
+ }) => {
87
+ try {
88
+ // We currently support only one file at a time
89
+ const url = await getSharingLink(client, [file._id], { ttl, password })
90
+ const isZipFile = file.class === 'zip'
91
+ const shareData = {
92
+ title: t('shareFile.title', {
93
+ name: file.name,
94
+ smart_count: isZipFile ? 2 : 1
95
+ }),
96
+ text: t('shareFile.text', {
97
+ name: file.name,
98
+ smart_count: isZipFile ? 2 : 1
99
+ }),
100
+ url
101
+ }
102
+ navigator.share(shareData)
103
+ } catch (error) {
104
+ showAlert({
105
+ message: t('shareFile.error'),
106
+ severity: 'error',
107
+ variant: 'filled'
108
+ })
109
+ }
110
+ }
111
+
112
+ /**
113
+ * updatePermissions - Updates 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 {string} options.documentType - Type of the document
118
+ * @param {'readOnly'|'write'} options.editingRights - Editing rights
119
+ * @param {Function} options.updateDocumentPermissions - Function to update permissions
120
+ * @param {Function} options.showAlert - Function to display an alert
121
+ */
122
+ export const updatePermissions = async ({
123
+ file,
124
+ t,
125
+ editingRights,
126
+ documentType,
127
+ updateDocumentPermissions,
128
+ showAlert
129
+ }) => {
130
+ switch (editingRights) {
131
+ case 'readOnly':
132
+ try {
133
+ return updateDocumentPermissions(file, READ_ONLY_PERMS)
134
+ } catch (err) {
135
+ showAlert({
136
+ message: t(`${documentType}.share.shareByLink.permserror`),
137
+ severity: 'error',
138
+ variant: 'filled'
139
+ })
140
+ log.error(
141
+ "Error in 'readOnlyPermissionLink' function when trying to change permission",
142
+ err
143
+ )
144
+ }
145
+ break
146
+ case 'write':
147
+ try {
148
+ return updateDocumentPermissions(file, WRITE_PERMS)
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
161
+ }
162
+ }
163
+
164
+ /**
165
+ * revokePermissions - Revokes the permissions of a file
166
+ * @param {object} options
167
+ * @param {import('cozy-client/types/types').IOCozyFile} options.file File to revoke permissions
168
+ * @param {Function} options.t i18n function
169
+ * @param {string} options.documentType - Type of the document
170
+ * @param {Function} options.revokeSharingLink - Function to revoke permissions
171
+ * @param {Function} options.showAlert - Function to display an alert
172
+ */
173
+ export const revokePermissions = async ({
174
+ file,
175
+ t,
176
+ documentType,
177
+ revokeSharingLink,
178
+ showAlert
179
+ }) => {
180
+ try {
181
+ return revokeSharingLink(file)
182
+ } catch (err) {
183
+ showAlert({
184
+ message: t(`${documentType}.share.error.revoke`),
185
+ severity: 'error',
186
+ variant: 'filled'
187
+ })
188
+ log.error(
189
+ "Error in 'revokePermissions' function when trying to revoke sharing link",
190
+ err
191
+ )
192
+ }
193
+ }
@@ -0,0 +1,78 @@
1
+ import { makeTTL, revokePermissions, updatePermissions } from './helpers'
2
+
3
+ describe('ShareRestrictionModal/helpers', () => {
4
+ describe('makeTTL', () => {
5
+ it('sould return undefined', () => {
6
+ expect(makeTTL()).toBeUndefined()
7
+ expect(makeTTL(123)).toBeUndefined()
8
+ expect(makeTTL('abc')).toBeUndefined()
9
+ expect(makeTTL(new Date('2023-01-01T00:00:00.000Z'))).toBeUndefined()
10
+ expect(makeTTL(new Date('abc'))).toBeUndefined()
11
+ expect(makeTTL('2023-01-01T00:00:00.000Z')).toBeUndefined()
12
+ })
13
+ it('sould return TTL in seconds', () => {
14
+ expect(makeTTL(new Date('2100-01-01T00:00:00.000Z'))).toBeDefined()
15
+ expect(makeTTL('2100-01-01T00:00:00.000Z')).toBeDefined()
16
+ })
17
+ })
18
+
19
+ describe('updatePermissions', () => {
20
+ const documentType = 'Files'
21
+ it('should call updateDocumentPermissions with "readOnly" permission', async () => {
22
+ const updateDocumentPermissions = jest.fn()
23
+ const file = { _id: '123' }
24
+ const editingRights = 'readOnly'
25
+
26
+ await updatePermissions({
27
+ file,
28
+ t: jest.fn(),
29
+ editingRights,
30
+ documentType,
31
+ updateDocumentPermissions,
32
+ showAlert: jest.fn()
33
+ })
34
+
35
+ expect(updateDocumentPermissions).toHaveBeenCalledWith(file, ['GET'])
36
+ })
37
+
38
+ it('should call updateDocumentPermissions with "write" permissions', async () => {
39
+ const updateDocumentPermissions = jest.fn()
40
+ const file = { _id: '123' }
41
+ const editingRights = 'write'
42
+
43
+ await updatePermissions({
44
+ file,
45
+ t: jest.fn(),
46
+ editingRights,
47
+ documentType,
48
+ updateDocumentPermissions,
49
+ showAlert: jest.fn()
50
+ })
51
+
52
+ expect(updateDocumentPermissions).toHaveBeenCalledWith(file, [
53
+ 'GET',
54
+ 'POST',
55
+ 'PUT',
56
+ 'PATCH'
57
+ ])
58
+ })
59
+ })
60
+
61
+ describe('revokePermissions', () => {
62
+ const documentType = 'Files'
63
+ it('should call revokeSharingLink', async () => {
64
+ const revokeSharingLink = jest.fn()
65
+ const file = { _id: '123' }
66
+
67
+ await revokePermissions({
68
+ file,
69
+ t: jest.fn(),
70
+ documentType,
71
+ revokeSharingLink,
72
+ showAlert: jest.fn()
73
+ })
74
+
75
+ expect(revokeSharingLink).toHaveBeenCalledWith(file)
76
+ })
77
+ })
78
+ })