Skip to content

Commit adeb1d0

Browse files
committed
fix: leverage shared_link_permission_options instead
1 parent ba65fad commit adeb1d0

File tree

9 files changed

+60
-125
lines changed

9 files changed

+60
-125
lines changed

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export const FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS: 'allowed_shared_l
124124
export const FIELD_SHARED_LINK_FEATURES: 'shared_link_features' = 'shared_link_features';
125125
export const FIELD_ALLOWED_INVITEE_ROLES: 'allowed_invitee_roles' = 'allowed_invitee_roles';
126126
export const FIELD_ALLOWED_SHARED_LINK_ACCESS_LEVELS = 'allowed_shared_link_access_levels';
127+
export const FIELD_SHARED_LINK_PERMISSION_OPTIONS: 'shared_link_permission_options' = 'shared_link_permission_options';
127128
export const FIELD_HAS_COLLABORATIONS = 'has_collaborations';
128129
export const FIELD_IS_EXTERNALLY_OWNED = 'is_externally_owned';
129130
export const FIELD_TOTAL_COUNT = 'total_count';

src/elements/content-sharing/constants.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
import {
2+
FIELD_ALLOWED_INVITEE_ROLES,
3+
FIELD_ALLOWED_SHARED_LINK_ACCESS_LEVELS,
4+
FIELD_CLASSIFICATION,
5+
FIELD_DESCRIPTION,
6+
FIELD_EXTENSION,
7+
FIELD_ID,
8+
FIELD_NAME,
9+
FIELD_OWNED_BY,
10+
FIELD_PERMISSIONS,
11+
FIELD_SHARED_LINK,
12+
FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS,
13+
FIELD_SHARED_LINK_FEATURES,
14+
FIELD_SHARED_LINK_PERMISSION_OPTIONS,
15+
FIELD_TYPE as FIELD_ITEM_TYPE,
16+
} from '../../constants';
117
import {
218
CLASSIFICATION_COLOR_ID_0,
319
CLASSIFICATION_COLOR_ID_1,
@@ -18,21 +34,6 @@ import {
1834
bdlWatermelonRed50,
1935
bdlYellow50,
2036
} from '../../styles/variables';
21-
import {
22-
FIELD_ALLOWED_INVITEE_ROLES,
23-
FIELD_ALLOWED_SHARED_LINK_ACCESS_LEVELS,
24-
FIELD_CLASSIFICATION,
25-
FIELD_EXTENSION,
26-
FIELD_DESCRIPTION,
27-
FIELD_ID,
28-
FIELD_NAME,
29-
FIELD_OWNED_BY,
30-
FIELD_PERMISSIONS,
31-
FIELD_SHARED_LINK,
32-
FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS,
33-
FIELD_SHARED_LINK_FEATURES,
34-
FIELD_TYPE as FIELD_ITEM_TYPE,
35-
} from '../../constants';
3637

3738
export const CONTENT_SHARING_ERRORS = {
3839
400: 'badRequestError',
@@ -56,6 +57,7 @@ export const CONTENT_SHARING_ITEM_FIELDS = [
5657
FIELD_SHARED_LINK,
5758
FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS,
5859
FIELD_SHARED_LINK_FEATURES,
60+
FIELD_SHARED_LINK_PERMISSION_OPTIONS,
5961
];
6062

6163
export const CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS = {

src/elements/content-sharing/types.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import type { CollaborationRole, Collaborator, DateValue, Item, SharedLink } from '@box/unified-share-modal';
33

44
import API from '../../api';
5+
6+
import type { RequestOptions } from '../../common/types/api';
57
import type {
68
Access,
79
BoxItemClassification,
@@ -20,7 +22,6 @@ import type {
2022
item,
2123
sharedLinkType as USMSharedLinkType,
2224
} from '../../features/unified-share-modal/flowTypes';
23-
import type { RequestOptions } from '../../common/types/api';
2425

2526
// "SLS" denotes values that are used in the Shared Link Settings modal
2627
type ContentSharingEnterpriseDataType = {
@@ -88,6 +89,7 @@ export type ContentSharingItemAPIResponse = {
8889
password: boolean,
8990
vanity_name: boolean,
9091
},
92+
shared_link_permission_options?: Array<'can_preview' | 'can_download' | 'can_edit'>,
9193
type: ItemType,
9294
};
9395

src/elements/content-sharing/utils/__mocks__/ContentSharingV2Mocks.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export const DEFAULT_ITEM_API_RESPONSE = {
110110
permissions: MOCK_PERMISSIONS,
111111
shared_link: null,
112112
shared_link_features: { password: true },
113+
shared_link_permission_options: ['can_edit', 'can_download', 'can_preview'],
113114
type: MOCK_ITEM.type,
114115
};
115116

src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
mockOwnerId,
77
mockOwnerName,
88
} from '../__mocks__/ContentSharingV2Mocks';
9+
910
import { convertItemResponse } from '../convertItemResponse';
1011
import { getAllowedPermissionLevels } from '../getAllowedPermissionLevels';
1112

@@ -30,8 +31,8 @@ describe('convertItemResponse', () => {
3031
{ id: 'viewer', isDefault: false },
3132
],
3233
item: {
33-
id: '123456789',
3434
classification: undefined,
35+
id: '123456789',
3536
name: 'Box Development Guide.pdf',
3637
permissions: {
3738
canInviteCollaborator: true,
@@ -80,7 +81,7 @@ describe('convertItemResponse', () => {
8081
accessLevels: ['open', 'company', 'collaborators'],
8182
expiresAt: 1704067200000,
8283
permission: 'can_download',
83-
permissionLevels: ['canDownload', 'canPreview'],
84+
permissionLevels: ['can_edit', 'can_download', 'can_preview'],
8485
settings: {
8586
canChangeDownload: true,
8687
canChangeExpiration: true,
@@ -97,20 +98,19 @@ describe('convertItemResponse', () => {
9798
});
9899
});
99100

100-
test('should pass extension to getAllowedPermissionLevels', () => {
101-
const MOCK_ITEM_WITH_EXTENSION = {
101+
test('should use shared_link_permission_options from API when available', () => {
102+
const result = convertItemResponse(MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK);
103+
expect(result.sharedLink?.permissionLevels).toEqual(['can_edit', 'can_download', 'can_preview']);
104+
expect(getAllowedPermissionLevels).not.toHaveBeenCalled();
105+
});
106+
107+
test('should call getAllowedPermissionLevels when shared_link_permission_options is not available', () => {
108+
const mockItemWithoutPermissionOptions = {
102109
...MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK,
103-
extension: 'pdf',
110+
shared_link_permission_options: undefined,
104111
};
105-
convertItemResponse(MOCK_ITEM_WITH_EXTENSION);
106-
expect(getAllowedPermissionLevels).toHaveBeenCalledWith({
107-
access: 'open',
108-
canChangeAccessLevel: true,
109-
extension: 'pdf',
110-
isDownloadSettingAvailable: true,
111-
itemType: 'file',
112-
permission: 'can_download',
113-
});
112+
convertItemResponse(mockItemWithoutPermissionOptions);
113+
expect(getAllowedPermissionLevels).toHaveBeenCalledWith(true, true, 'can_download');
114114
});
115115

116116
test('should convert shared link settings correctly if user cannot change access level', () => {
Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,29 @@
1-
import {
2-
ACCESS_OPEN,
3-
PERMISSION_CAN_DOWNLOAD,
4-
PERMISSION_CAN_EDIT,
5-
PERMISSION_CAN_PREVIEW,
6-
TYPE_FILE,
7-
} from '../../../../constants';
1+
import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../../constants';
82

93
import { getAllowedPermissionLevels } from '../getAllowedPermissionLevels';
104

115
describe('getAllowedPermissionLevels', () => {
12-
const defaultParams = {
13-
access: ACCESS_OPEN,
14-
canChangeAccessLevel: true,
15-
extension: 'pdf',
16-
isDownloadSettingAvailable: true,
17-
itemType: TYPE_FILE,
18-
permission: PERMISSION_CAN_DOWNLOAD,
19-
};
20-
21-
test('should return all permission levels when all conditions are met', () => {
22-
const result = getAllowedPermissionLevels(defaultParams);
23-
expect(result).toEqual([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]);
6+
test('should return both permission levels when all conditions are met', () => {
7+
const result = getAllowedPermissionLevels(true, true, PERMISSION_CAN_DOWNLOAD);
8+
expect(result).toEqual([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW]);
249
});
2510

26-
test.each([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT])(
11+
test.each([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW])(
2712
'should return only current permission when cannot change access level',
2813
permission => {
29-
const result = getAllowedPermissionLevels({
30-
...defaultParams,
31-
canChangeAccessLevel: false,
32-
permission,
33-
});
14+
const result = getAllowedPermissionLevels(false, true, permission);
3415
expect(result).toEqual([permission]);
3516
},
3617
);
3718

3819
test('should exclude download permission when download setting is not available', () => {
39-
const result = getAllowedPermissionLevels({
40-
...defaultParams,
41-
isDownloadSettingAvailable: false,
42-
});
43-
expect(result).toEqual([PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]);
20+
const result = getAllowedPermissionLevels(true, false, PERMISSION_CAN_DOWNLOAD);
21+
expect(result).toEqual([PERMISSION_CAN_PREVIEW]);
4422
});
4523

4624
test('should return empty array for unknown permission values when cannot change access level', () => {
47-
const result = getAllowedPermissionLevels({
48-
...defaultParams,
49-
canChangeAccessLevel: false,
50-
permission: 'unknown_permission',
51-
});
25+
const unknownPermission = 'unknown_permission';
26+
const result = getAllowedPermissionLevels(false, true, unknownPermission);
5227
expect(result).toEqual([]);
5328
});
54-
55-
test.each([
56-
[true, true, PERMISSION_CAN_PREVIEW],
57-
[true, true, PERMISSION_CAN_DOWNLOAD],
58-
[false, true, PERMISSION_CAN_PREVIEW],
59-
])(
60-
'should exclude edit permission for webdocs when canChangeAccessLevel=%s, isDownloadSettingAvailable=%s, permission=%s',
61-
(canChangeAccessLevel, isDownloadSettingAvailable, permission) => {
62-
const result = getAllowedPermissionLevels({
63-
...defaultParams,
64-
canChangeAccessLevel,
65-
extension: 'webdoc',
66-
isDownloadSettingAvailable,
67-
permission,
68-
});
69-
expect(result).not.toContain(PERMISSION_CAN_EDIT);
70-
},
71-
);
7229
});

src/elements/content-sharing/utils/convertItemResponse.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ACCESS_COLLAB, INVITEE_ROLE_EDITOR, PERMISSION_CAN_DOWNLOAD } from '../../../constants';
1+
import { ACCESS_COLLAB, INVITEE_ROLE_EDITOR, PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_EDIT } from '../../../constants';
2+
23
import { API_TO_USM_CLASSIFICATION_COLORS_MAP } from '../constants';
34
import { getAllowedAccessLevels } from './getAllowedAccessLevels';
45
import { getAllowedPermissionLevels } from './getAllowedPermissionLevels';
@@ -11,13 +12,13 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
1112
allowed_shared_link_access_levels,
1213
allowed_shared_link_access_levels_disabled_reasons,
1314
classification,
14-
extension,
1515
id,
1616
name,
1717
owned_by: ownedBy,
1818
permissions,
1919
shared_link,
2020
shared_link_features,
21+
shared_link_permission_options,
2122
type,
2223
} = itemApiData;
2324

@@ -55,7 +56,7 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
5556
vanity_url: vanityUrl,
5657
} = shared_link;
5758

58-
const isDownloadAllowed = permission === PERMISSION_CAN_DOWNLOAD;
59+
const isDownloadAllowed = permission === PERMISSION_CAN_DOWNLOAD || permission === PERMISSION_CAN_EDIT;
5960
const canChangeDownload = canChangeAccessLevel && isDownloadSettingAvailable && access !== ACCESS_COLLAB; // access must be "company" or "open"
6061
const canChangePassword = canChangeAccessLevel && isPasswordAvailable;
6162
const canChangeExpiration = canChangeAccessLevel && isEditAllowed;
@@ -68,14 +69,9 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
6869
),
6970
expiresAt: expirationTimestamp ? new Date(expirationTimestamp).getTime() : undefined, // convert to milliseconds
7071
permission,
71-
permissionLevels: getAllowedPermissionLevels({
72-
access,
73-
canChangeAccessLevel,
74-
extension,
75-
isDownloadSettingAvailable,
76-
itemType: type,
77-
permission,
78-
}),
72+
permissionLevels:
73+
shared_link_permission_options ??
74+
getAllowedPermissionLevels(canChangeAccessLevel, isDownloadSettingAvailable, permission),
7975
settings: {
8076
canChangeDownload,
8177
canChangeExpiration,
@@ -100,8 +96,8 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
10096
return {
10197
collaborationRoles,
10298
item: {
103-
id,
10499
classification: classificationData,
100+
id,
105101
name,
106102
permissions: {
107103
canInviteCollaborator: !!canInvite,
@@ -110,13 +106,13 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
110106
},
111107
type,
112108
},
109+
ownedBy,
113110
sharedLink,
114111
sharingService: {
115112
can_set_share_access: canChangeAccessLevel,
116113
can_share: canShare,
117114
ownerEmail: ownedBy.login,
118115
ownerId: ownedBy.id,
119116
},
120-
ownedBy,
121117
};
122118
};

src/elements/content-sharing/utils/convertSharingServiceData.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface ConvertSharedLinkSettingsReturnType {
1313
password?: string | null;
1414
permissions?: {
1515
can_download?: boolean;
16+
can_edit?: boolean;
1617
can_preview: boolean;
1718
};
1819
unshared_at: string | null;
Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,11 @@
1-
import {
2-
ACCESS_COMPANY,
3-
ACCESS_OPEN,
4-
PERMISSION_CAN_DOWNLOAD,
5-
PERMISSION_CAN_EDIT,
6-
PERMISSION_CAN_PREVIEW,
7-
TYPE_FOLDER,
8-
} from '../../../constants';
1+
import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../constants';
92

10-
type GetAllowedPermissionLevelsParams = {
11-
access: string;
12-
canChangeAccessLevel: boolean;
13-
extension: string;
14-
isDownloadSettingAvailable: boolean;
15-
itemType: string;
16-
permission: string;
17-
};
18-
19-
export const getAllowedPermissionLevels = ({
20-
access,
3+
export const getAllowedPermissionLevels = (
214
canChangeAccessLevel,
22-
extension,
235
isDownloadSettingAvailable,
24-
itemType,
256
permission,
26-
}: GetAllowedPermissionLevelsParams): Array<string> => {
27-
let allowedPermissionLevels = [PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT];
7+
): Array<string> => {
8+
let allowedPermissionLevels = [PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW];
289

2910
if (!canChangeAccessLevel) {
3011
// remove all but current level
@@ -36,11 +17,5 @@ export const getAllowedPermissionLevels = ({
3617
allowedPermissionLevels = allowedPermissionLevels.filter(level => level !== PERMISSION_CAN_DOWNLOAD);
3718
}
3819

39-
// Can Edit requires ACCESS_OPEN or ACCESS_COMPANY, and must NOT be a folder
40-
const canEditAccessLevels = [ACCESS_OPEN, ACCESS_COMPANY];
41-
if (!canEditAccessLevels.includes(access) || itemType === TYPE_FOLDER || extension?.toLowerCase() === 'webdoc') {
42-
allowedPermissionLevels = allowedPermissionLevels.filter(level => level !== PERMISSION_CAN_EDIT);
43-
}
44-
4520
return allowedPermissionLevels;
4621
};

0 commit comments

Comments
 (0)