Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS: 'allowed_shared_l
export const FIELD_SHARED_LINK_FEATURES: 'shared_link_features' = 'shared_link_features';
export const FIELD_ALLOWED_INVITEE_ROLES: 'allowed_invitee_roles' = 'allowed_invitee_roles';
export const FIELD_ALLOWED_SHARED_LINK_ACCESS_LEVELS = 'allowed_shared_link_access_levels';
export const FIELD_SHARED_LINK_PERMISSION_OPTIONS: 'shared_link_permission_options' = 'shared_link_permission_options';
export const FIELD_HAS_COLLABORATIONS = 'has_collaborations';
export const FIELD_IS_EXTERNALLY_OWNED = 'is_externally_owned';
export const FIELD_TOTAL_COUNT = 'total_count';
Expand Down
32 changes: 17 additions & 15 deletions src/elements/content-sharing/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
import {
FIELD_ALLOWED_INVITEE_ROLES,
FIELD_ALLOWED_SHARED_LINK_ACCESS_LEVELS,
FIELD_CLASSIFICATION,
FIELD_DESCRIPTION,
FIELD_EXTENSION,
FIELD_ID,
FIELD_NAME,
FIELD_OWNED_BY,
FIELD_PERMISSIONS,
FIELD_SHARED_LINK,
FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS,
FIELD_SHARED_LINK_FEATURES,
FIELD_SHARED_LINK_PERMISSION_OPTIONS,
FIELD_TYPE as FIELD_ITEM_TYPE,
} from '../../constants';
import {
CLASSIFICATION_COLOR_ID_0,
CLASSIFICATION_COLOR_ID_1,
Expand All @@ -18,21 +34,6 @@ import {
bdlWatermelonRed50,
bdlYellow50,
} from '../../styles/variables';
import {
FIELD_ALLOWED_INVITEE_ROLES,
FIELD_ALLOWED_SHARED_LINK_ACCESS_LEVELS,
FIELD_CLASSIFICATION,
FIELD_EXTENSION,
FIELD_DESCRIPTION,
FIELD_ID,
FIELD_NAME,
FIELD_OWNED_BY,
FIELD_PERMISSIONS,
FIELD_SHARED_LINK,
FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS,
FIELD_SHARED_LINK_FEATURES,
FIELD_TYPE as FIELD_ITEM_TYPE,
} from '../../constants';

export const CONTENT_SHARING_ERRORS = {
400: 'badRequestError',
Expand All @@ -56,6 +57,7 @@ export const CONTENT_SHARING_ITEM_FIELDS = [
FIELD_SHARED_LINK,
FIELD_SHARED_LINK_ACCESS_LEVELS_DISABLED_REASONS,
FIELD_SHARED_LINK_FEATURES,
FIELD_SHARED_LINK_PERMISSION_OPTIONS,
];

export const CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS = {
Expand Down
4 changes: 3 additions & 1 deletion src/elements/content-sharing/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import type { CollaborationRole, Collaborator, DateValue, Item, SharedLink } from '@box/unified-share-modal';

import API from '../../api';

import type { RequestOptions } from '../../common/types/api';
import type {
Access,
BoxItemClassification,
Expand All @@ -20,7 +22,6 @@ import type {
item,
sharedLinkType as USMSharedLinkType,
} from '../../features/unified-share-modal/flowTypes';
import type { RequestOptions } from '../../common/types/api';

// "SLS" denotes values that are used in the Shared Link Settings modal
type ContentSharingEnterpriseDataType = {
Expand Down Expand Up @@ -88,6 +89,7 @@ export type ContentSharingItemAPIResponse = {
password: boolean,
vanity_name: boolean,
},
shared_link_permission_options?: Array<'can_preview' | 'can_download' | 'can_edit'>,
type: ItemType,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const DEFAULT_ITEM_API_RESPONSE = {
permissions: MOCK_PERMISSIONS,
shared_link: null,
shared_link_features: { password: true },
shared_link_permission_options: ['can_edit', 'can_download', 'can_preview'],
type: MOCK_ITEM.type,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {
DEFAULT_ITEM_API_RESPONSE,
MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK,
MOCK_ITEM_API_RESPONSE_WITH_CLASSIFICATION,
mockOwnerId,
MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK,
mockOwnerEmail,
mockOwnerId,
mockOwnerName,
} from '../__mocks__/ContentSharingV2Mocks';

import { convertItemResponse } from '../convertItemResponse';
import { getAllowedPermissionLevels } from '../getAllowedPermissionLevels';

jest.mock('../getAllowedAccessLevels', () => ({
getAllowedAccessLevels: jest.fn().mockReturnValue(['open', 'company', 'collaborators']),
Expand All @@ -29,8 +31,8 @@ describe('convertItemResponse', () => {
{ id: 'viewer', isDefault: false },
],
item: {
id: '123456789',
classification: undefined,
id: '123456789',
name: 'Box Development Guide.pdf',
permissions: {
canInviteCollaborator: true,
Expand Down Expand Up @@ -79,7 +81,7 @@ describe('convertItemResponse', () => {
accessLevels: ['open', 'company', 'collaborators'],
expiresAt: 1704067200000,
permission: 'can_download',
permissionLevels: ['canDownload', 'canPreview'],
permissionLevels: ['can_edit', 'can_download', 'can_preview'],
settings: {
canChangeDownload: true,
canChangeExpiration: true,
Expand All @@ -96,6 +98,21 @@ describe('convertItemResponse', () => {
});
});

test('should use shared_link_permission_options from API when available', () => {
const result = convertItemResponse(MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK);
expect(result.sharedLink?.permissionLevels).toEqual(['can_edit', 'can_download', 'can_preview']);
expect(getAllowedPermissionLevels).not.toHaveBeenCalled();
});

test('should call getAllowedPermissionLevels when shared_link_permission_options is not available', () => {
const mockItemWithoutPermissionOptions = {
...MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK,
shared_link_permission_options: undefined,
};
convertItemResponse(mockItemWithoutPermissionOptions);
expect(getAllowedPermissionLevels).toHaveBeenCalledWith(true, true, 'can_download');
});

test('should convert shared link settings correctly if user cannot change access level', () => {
const MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK_WITH_PERMISSIONS = {
...MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ACCESS_COMPANY,
ACCESS_OPEN,
PERMISSION_CAN_DOWNLOAD,
PERMISSION_CAN_EDIT,
PERMISSION_CAN_PREVIEW,
} from '../../../../constants';
import { convertISOStringToUTCDate } from '../../../../utils/datetime';
Expand All @@ -22,9 +23,19 @@ describe('elements/content-sharing/utils/convertSharingServiceData', () => {

describe('convertSharedLinkPermissions', () => {
test.each([
[PERMISSION_CAN_DOWNLOAD, { [PERMISSION_CAN_DOWNLOAD]: true, [PERMISSION_CAN_PREVIEW]: false }],
[PERMISSION_CAN_PREVIEW, { [PERMISSION_CAN_DOWNLOAD]: false, [PERMISSION_CAN_PREVIEW]: true }],
])('should return correct permissions for download permission level', (permissionLevel, expected) => {
[
PERMISSION_CAN_DOWNLOAD,
{ [PERMISSION_CAN_DOWNLOAD]: true, [PERMISSION_CAN_EDIT]: false, [PERMISSION_CAN_PREVIEW]: false },
],
[
PERMISSION_CAN_EDIT,
{ [PERMISSION_CAN_DOWNLOAD]: true, [PERMISSION_CAN_EDIT]: true, [PERMISSION_CAN_PREVIEW]: false },
],
[
PERMISSION_CAN_PREVIEW,
{ [PERMISSION_CAN_DOWNLOAD]: false, [PERMISSION_CAN_EDIT]: false, [PERMISSION_CAN_PREVIEW]: true },
],
])('should return correct permissions for %s permission level', (permissionLevel, expected) => {
const result = convertSharedLinkPermissions(permissionLevel);
expect(result).toEqual(expected);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../../constants';

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

describe('getAllowedPermissionLevels', () => {
Expand Down
14 changes: 9 additions & 5 deletions src/elements/content-sharing/utils/convertItemResponse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ACCESS_COLLAB, INVITEE_ROLE_EDITOR, PERMISSION_CAN_DOWNLOAD } from '../../../constants';
import { ACCESS_COLLAB, INVITEE_ROLE_EDITOR, PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_EDIT } from '../../../constants';

import { API_TO_USM_CLASSIFICATION_COLORS_MAP } from '../constants';
import { getAllowedAccessLevels } from './getAllowedAccessLevels';
import { getAllowedPermissionLevels } from './getAllowedPermissionLevels';
Expand All @@ -17,6 +18,7 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
permissions,
shared_link,
shared_link_features,
shared_link_permission_options,
type,
} = itemApiData;

Expand Down Expand Up @@ -54,7 +56,7 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
vanity_url: vanityUrl,
} = shared_link;

const isDownloadAllowed = permission === PERMISSION_CAN_DOWNLOAD;
const isDownloadAllowed = permission === PERMISSION_CAN_DOWNLOAD || permission === PERMISSION_CAN_EDIT;
const canChangeDownload = canChangeAccessLevel && isDownloadSettingAvailable && access !== ACCESS_COLLAB; // access must be "company" or "open"
const canChangePassword = canChangeAccessLevel && isPasswordAvailable;
const canChangeExpiration = canChangeAccessLevel && isEditAllowed;
Expand All @@ -67,7 +69,9 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
),
expiresAt: expirationTimestamp ? new Date(expirationTimestamp).getTime() : undefined, // convert to milliseconds
permission,
permissionLevels: getAllowedPermissionLevels(canChangeAccessLevel, isDownloadSettingAvailable, permission),
permissionLevels:
shared_link_permission_options ??
getAllowedPermissionLevels(canChangeAccessLevel, isDownloadSettingAvailable, permission),
settings: {
canChangeDownload,
canChangeExpiration,
Expand All @@ -92,8 +96,8 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
return {
collaborationRoles,
item: {
id,
classification: classificationData,
id,
name,
permissions: {
canInviteCollaborator: !!canInvite,
Expand All @@ -102,13 +106,13 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse):
},
type,
},
ownedBy,
sharedLink,
sharingService: {
can_set_share_access: canChangeAccessLevel,
can_share: canShare,
ownerEmail: ownedBy.login,
ownerId: ownedBy.id,
},
ownedBy,
};
};
14 changes: 12 additions & 2 deletions src/elements/content-sharing/utils/convertSharingServiceData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { ACCESS_COLLAB, ACCESS_OPEN, PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../constants';
import {
ACCESS_COLLAB,
ACCESS_OPEN,
PERMISSION_CAN_DOWNLOAD,
PERMISSION_CAN_EDIT,
PERMISSION_CAN_PREVIEW,
} from '../../../constants';
import { convertISOStringToUTCDate } from '../../../utils/datetime';

import type { SharedLinkSettings } from '../types';
Expand All @@ -7,6 +13,7 @@ export interface ConvertSharedLinkSettingsReturnType {
password?: string | null;
permissions?: {
can_download?: boolean;
can_edit?: boolean;
can_preview: boolean;
};
unshared_at: string | null;
Expand All @@ -18,8 +25,11 @@ export const convertSharedLinkPermissions = (permissionLevel: string) => {
return {};
}

const isEdit = permissionLevel === PERMISSION_CAN_EDIT;

return {
[PERMISSION_CAN_DOWNLOAD]: permissionLevel === PERMISSION_CAN_DOWNLOAD,
[PERMISSION_CAN_DOWNLOAD]: isEdit || permissionLevel === PERMISSION_CAN_DOWNLOAD,
[PERMISSION_CAN_EDIT]: isEdit,
[PERMISSION_CAN_PREVIEW]: permissionLevel === PERMISSION_CAN_PREVIEW,
};
};
Expand Down