From e93c048be980e1f94e4356cc046d572d1615a585 Mon Sep 17 00:00:00 2001 From: reneshen0328 Date: Wed, 4 Mar 2026 10:51:01 -0800 Subject: [PATCH 1/2] fix(content-sharing): Add shared link permission can edit option --- .../__tests__/convertItemResponse.test.ts | 21 +++++- .../convertSharingServiceData.test.ts | 17 ++++- .../getAllowedPermissionLevels.test.ts | 64 ++++++++++++++++--- .../utils/convertItemResponse.ts | 10 ++- .../utils/convertSharingServiceData.ts | 13 +++- .../utils/getAllowedPermissionLevels.ts | 33 ++++++++-- 6 files changed, 136 insertions(+), 22 deletions(-) diff --git a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts index efe009b302..76e65257bf 100644 --- a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts +++ b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts @@ -1,12 +1,13 @@ 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']), @@ -96,6 +97,22 @@ describe('convertItemResponse', () => { }); }); + test('should pass extension to getAllowedPermissionLevels', () => { + const MOCK_ITEM_WITH_EXTENSION = { + ...MOCK_ITEM_API_RESPONSE_WITH_SHARED_LINK, + extension: 'pdf', + }; + convertItemResponse(MOCK_ITEM_WITH_EXTENSION); + expect(getAllowedPermissionLevels).toHaveBeenCalledWith({ + access: 'open', + canChangeAccessLevel: true, + extension: 'pdf', + isDownloadSettingAvailable: true, + itemType: 'file', + permission: '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, diff --git a/src/elements/content-sharing/utils/__tests__/convertSharingServiceData.test.ts b/src/elements/content-sharing/utils/__tests__/convertSharingServiceData.test.ts index c03224556d..de150794d4 100644 --- a/src/elements/content-sharing/utils/__tests__/convertSharingServiceData.test.ts +++ b/src/elements/content-sharing/utils/__tests__/convertSharingServiceData.test.ts @@ -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'; @@ -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); }); diff --git a/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts b/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts index 65963a3615..b0e4d857cb 100644 --- a/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts +++ b/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts @@ -1,28 +1,72 @@ -import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../../constants'; +import { + ACCESS_OPEN, + PERMISSION_CAN_DOWNLOAD, + PERMISSION_CAN_EDIT, + PERMISSION_CAN_PREVIEW, + TYPE_FILE, +} from '../../../../constants'; + import { getAllowedPermissionLevels } from '../getAllowedPermissionLevels'; describe('getAllowedPermissionLevels', () => { - test('should return both permission levels when all conditions are met', () => { - const result = getAllowedPermissionLevels(true, true, PERMISSION_CAN_DOWNLOAD); - expect(result).toEqual([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW]); + const defaultParams = { + access: ACCESS_OPEN, + canChangeAccessLevel: true, + extension: 'pdf', + isDownloadSettingAvailable: true, + itemType: TYPE_FILE, + permission: PERMISSION_CAN_DOWNLOAD, + }; + + test('should return all permission levels when all conditions are met', () => { + const result = getAllowedPermissionLevels(defaultParams); + expect(result).toEqual([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]); }); - test.each([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW])( + test.each([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT])( 'should return only current permission when cannot change access level', permission => { - const result = getAllowedPermissionLevels(false, true, permission); + const result = getAllowedPermissionLevels({ + ...defaultParams, + canChangeAccessLevel: false, + permission, + }); expect(result).toEqual([permission]); }, ); test('should exclude download permission when download setting is not available', () => { - const result = getAllowedPermissionLevels(true, false, PERMISSION_CAN_DOWNLOAD); - expect(result).toEqual([PERMISSION_CAN_PREVIEW]); + const result = getAllowedPermissionLevels({ + ...defaultParams, + isDownloadSettingAvailable: false, + }); + expect(result).toEqual([PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]); }); test('should return empty array for unknown permission values when cannot change access level', () => { - const unknownPermission = 'unknown_permission'; - const result = getAllowedPermissionLevels(false, true, unknownPermission); + const result = getAllowedPermissionLevels({ + ...defaultParams, + canChangeAccessLevel: false, + permission: 'unknown_permission', + }); expect(result).toEqual([]); }); + + test.each([ + [true, true, PERMISSION_CAN_PREVIEW], + [true, true, PERMISSION_CAN_DOWNLOAD], + [false, true, PERMISSION_CAN_PREVIEW], + ])( + 'should exclude edit permission for webdocs when canChangeAccessLevel=%s, isDownloadSettingAvailable=%s, permission=%s', + (canChangeAccessLevel, isDownloadSettingAvailable, permission) => { + const result = getAllowedPermissionLevels({ + ...defaultParams, + canChangeAccessLevel, + extension: 'webdoc', + isDownloadSettingAvailable, + permission, + }); + expect(result).not.toContain(PERMISSION_CAN_EDIT); + }, + ); }); diff --git a/src/elements/content-sharing/utils/convertItemResponse.ts b/src/elements/content-sharing/utils/convertItemResponse.ts index ba6c6b36f5..db7882c054 100644 --- a/src/elements/content-sharing/utils/convertItemResponse.ts +++ b/src/elements/content-sharing/utils/convertItemResponse.ts @@ -11,6 +11,7 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): allowed_shared_link_access_levels, allowed_shared_link_access_levels_disabled_reasons, classification, + extension, id, name, owned_by: ownedBy, @@ -67,7 +68,14 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): ), expiresAt: expirationTimestamp ? new Date(expirationTimestamp).getTime() : undefined, // convert to milliseconds permission, - permissionLevels: getAllowedPermissionLevels(canChangeAccessLevel, isDownloadSettingAvailable, permission), + permissionLevels: getAllowedPermissionLevels({ + access, + canChangeAccessLevel, + extension, + isDownloadSettingAvailable, + itemType: type, + permission, + }), settings: { canChangeDownload, canChangeExpiration, diff --git a/src/elements/content-sharing/utils/convertSharingServiceData.ts b/src/elements/content-sharing/utils/convertSharingServiceData.ts index f9eea83c0b..c29aeb689e 100644 --- a/src/elements/content-sharing/utils/convertSharingServiceData.ts +++ b/src/elements/content-sharing/utils/convertSharingServiceData.ts @@ -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'; @@ -18,8 +24,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, }; }; diff --git a/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts b/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts index 2922386832..5806c75907 100644 --- a/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts +++ b/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts @@ -1,11 +1,30 @@ -import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../constants'; +import { + ACCESS_COMPANY, + ACCESS_OPEN, + PERMISSION_CAN_DOWNLOAD, + PERMISSION_CAN_EDIT, + PERMISSION_CAN_PREVIEW, + TYPE_FOLDER, +} from '../../../constants'; -export const getAllowedPermissionLevels = ( +type GetAllowedPermissionLevelsParams = { + access: string; + canChangeAccessLevel: boolean; + extension: string; + isDownloadSettingAvailable: boolean; + itemType: string; + permission: string; +}; + +export const getAllowedPermissionLevels = ({ + access, canChangeAccessLevel, + extension, isDownloadSettingAvailable, + itemType, permission, -): Array => { - let allowedPermissionLevels = [PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW]; +}: GetAllowedPermissionLevelsParams): Array => { + let allowedPermissionLevels = [PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]; if (!canChangeAccessLevel) { // remove all but current level @@ -17,5 +36,11 @@ export const getAllowedPermissionLevels = ( allowedPermissionLevels = allowedPermissionLevels.filter(level => level !== PERMISSION_CAN_DOWNLOAD); } + // Can Edit requires ACCESS_OPEN or ACCESS_COMPANY, and must NOT be a folder + const canEditAccessLevels = [ACCESS_OPEN, ACCESS_COMPANY]; + if (!canEditAccessLevels.includes(access) || itemType === TYPE_FOLDER || extension?.toLowerCase() === 'webdoc') { + allowedPermissionLevels = allowedPermissionLevels.filter(level => level !== PERMISSION_CAN_EDIT); + } + return allowedPermissionLevels; }; From 5c28e59965113b64595749c7f585193d5c9b234e Mon Sep 17 00:00:00 2001 From: reneshen0328 Date: Wed, 4 Mar 2026 12:35:55 -0800 Subject: [PATCH 2/2] fix: leverage shared_link_permission_options instead --- src/constants.js | 1 + src/elements/content-sharing/constants.js | 32 +++++----- src/elements/content-sharing/types.js | 4 +- .../utils/__mocks__/ContentSharingV2Mocks.js | 1 + .../__tests__/convertItemResponse.test.ts | 28 ++++----- .../getAllowedPermissionLevels.test.ts | 63 +++---------------- .../utils/convertItemResponse.ts | 22 +++---- .../utils/convertSharingServiceData.ts | 1 + .../utils/getAllowedPermissionLevels.ts | 33 ++-------- 9 files changed, 60 insertions(+), 125 deletions(-) diff --git a/src/constants.js b/src/constants.js index 9961f2dda6..f689dab270 100644 --- a/src/constants.js +++ b/src/constants.js @@ -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'; diff --git a/src/elements/content-sharing/constants.js b/src/elements/content-sharing/constants.js index eea0b912b9..533577f445 100644 --- a/src/elements/content-sharing/constants.js +++ b/src/elements/content-sharing/constants.js @@ -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, @@ -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', @@ -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 = { diff --git a/src/elements/content-sharing/types.js b/src/elements/content-sharing/types.js index 16acebba5a..89cd2b01d0 100644 --- a/src/elements/content-sharing/types.js +++ b/src/elements/content-sharing/types.js @@ -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, @@ -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 = { @@ -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, }; diff --git a/src/elements/content-sharing/utils/__mocks__/ContentSharingV2Mocks.js b/src/elements/content-sharing/utils/__mocks__/ContentSharingV2Mocks.js index 706fd5201e..21ece1ee88 100644 --- a/src/elements/content-sharing/utils/__mocks__/ContentSharingV2Mocks.js +++ b/src/elements/content-sharing/utils/__mocks__/ContentSharingV2Mocks.js @@ -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, }; diff --git a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts index 76e65257bf..6f5dcdbd04 100644 --- a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts +++ b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts @@ -6,6 +6,7 @@ import { mockOwnerId, mockOwnerName, } from '../__mocks__/ContentSharingV2Mocks'; + import { convertItemResponse } from '../convertItemResponse'; import { getAllowedPermissionLevels } from '../getAllowedPermissionLevels'; @@ -30,8 +31,8 @@ describe('convertItemResponse', () => { { id: 'viewer', isDefault: false }, ], item: { - id: '123456789', classification: undefined, + id: '123456789', name: 'Box Development Guide.pdf', permissions: { canInviteCollaborator: true, @@ -80,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, @@ -97,20 +98,19 @@ describe('convertItemResponse', () => { }); }); - test('should pass extension to getAllowedPermissionLevels', () => { - const MOCK_ITEM_WITH_EXTENSION = { + 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, - extension: 'pdf', + shared_link_permission_options: undefined, }; - convertItemResponse(MOCK_ITEM_WITH_EXTENSION); - expect(getAllowedPermissionLevels).toHaveBeenCalledWith({ - access: 'open', - canChangeAccessLevel: true, - extension: 'pdf', - isDownloadSettingAvailable: true, - itemType: 'file', - permission: 'can_download', - }); + convertItemResponse(mockItemWithoutPermissionOptions); + expect(getAllowedPermissionLevels).toHaveBeenCalledWith(true, true, 'can_download'); }); test('should convert shared link settings correctly if user cannot change access level', () => { diff --git a/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts b/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts index b0e4d857cb..355933c6be 100644 --- a/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts +++ b/src/elements/content-sharing/utils/__tests__/getAllowedPermissionLevels.test.ts @@ -1,72 +1,29 @@ -import { - ACCESS_OPEN, - PERMISSION_CAN_DOWNLOAD, - PERMISSION_CAN_EDIT, - PERMISSION_CAN_PREVIEW, - TYPE_FILE, -} from '../../../../constants'; +import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../../constants'; import { getAllowedPermissionLevels } from '../getAllowedPermissionLevels'; describe('getAllowedPermissionLevels', () => { - const defaultParams = { - access: ACCESS_OPEN, - canChangeAccessLevel: true, - extension: 'pdf', - isDownloadSettingAvailable: true, - itemType: TYPE_FILE, - permission: PERMISSION_CAN_DOWNLOAD, - }; - - test('should return all permission levels when all conditions are met', () => { - const result = getAllowedPermissionLevels(defaultParams); - expect(result).toEqual([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]); + test('should return both permission levels when all conditions are met', () => { + const result = getAllowedPermissionLevels(true, true, PERMISSION_CAN_DOWNLOAD); + expect(result).toEqual([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW]); }); - test.each([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT])( + test.each([PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW])( 'should return only current permission when cannot change access level', permission => { - const result = getAllowedPermissionLevels({ - ...defaultParams, - canChangeAccessLevel: false, - permission, - }); + const result = getAllowedPermissionLevels(false, true, permission); expect(result).toEqual([permission]); }, ); test('should exclude download permission when download setting is not available', () => { - const result = getAllowedPermissionLevels({ - ...defaultParams, - isDownloadSettingAvailable: false, - }); - expect(result).toEqual([PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]); + const result = getAllowedPermissionLevels(true, false, PERMISSION_CAN_DOWNLOAD); + expect(result).toEqual([PERMISSION_CAN_PREVIEW]); }); test('should return empty array for unknown permission values when cannot change access level', () => { - const result = getAllowedPermissionLevels({ - ...defaultParams, - canChangeAccessLevel: false, - permission: 'unknown_permission', - }); + const unknownPermission = 'unknown_permission'; + const result = getAllowedPermissionLevels(false, true, unknownPermission); expect(result).toEqual([]); }); - - test.each([ - [true, true, PERMISSION_CAN_PREVIEW], - [true, true, PERMISSION_CAN_DOWNLOAD], - [false, true, PERMISSION_CAN_PREVIEW], - ])( - 'should exclude edit permission for webdocs when canChangeAccessLevel=%s, isDownloadSettingAvailable=%s, permission=%s', - (canChangeAccessLevel, isDownloadSettingAvailable, permission) => { - const result = getAllowedPermissionLevels({ - ...defaultParams, - canChangeAccessLevel, - extension: 'webdoc', - isDownloadSettingAvailable, - permission, - }); - expect(result).not.toContain(PERMISSION_CAN_EDIT); - }, - ); }); diff --git a/src/elements/content-sharing/utils/convertItemResponse.ts b/src/elements/content-sharing/utils/convertItemResponse.ts index db7882c054..985247fcf9 100644 --- a/src/elements/content-sharing/utils/convertItemResponse.ts +++ b/src/elements/content-sharing/utils/convertItemResponse.ts @@ -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'; @@ -11,13 +12,13 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): allowed_shared_link_access_levels, allowed_shared_link_access_levels_disabled_reasons, classification, - extension, id, name, owned_by: ownedBy, permissions, shared_link, shared_link_features, + shared_link_permission_options, type, } = itemApiData; @@ -55,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; @@ -68,14 +69,9 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): ), expiresAt: expirationTimestamp ? new Date(expirationTimestamp).getTime() : undefined, // convert to milliseconds permission, - permissionLevels: getAllowedPermissionLevels({ - access, - canChangeAccessLevel, - extension, - isDownloadSettingAvailable, - itemType: type, - permission, - }), + permissionLevels: + shared_link_permission_options ?? + getAllowedPermissionLevels(canChangeAccessLevel, isDownloadSettingAvailable, permission), settings: { canChangeDownload, canChangeExpiration, @@ -100,8 +96,8 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): return { collaborationRoles, item: { - id, classification: classificationData, + id, name, permissions: { canInviteCollaborator: !!canInvite, @@ -110,6 +106,7 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): }, type, }, + ownedBy, sharedLink, sharingService: { can_set_share_access: canChangeAccessLevel, @@ -117,6 +114,5 @@ export const convertItemResponse = (itemApiData: ContentSharingItemAPIResponse): ownerEmail: ownedBy.login, ownerId: ownedBy.id, }, - ownedBy, }; }; diff --git a/src/elements/content-sharing/utils/convertSharingServiceData.ts b/src/elements/content-sharing/utils/convertSharingServiceData.ts index c29aeb689e..715e872db6 100644 --- a/src/elements/content-sharing/utils/convertSharingServiceData.ts +++ b/src/elements/content-sharing/utils/convertSharingServiceData.ts @@ -13,6 +13,7 @@ export interface ConvertSharedLinkSettingsReturnType { password?: string | null; permissions?: { can_download?: boolean; + can_edit?: boolean; can_preview: boolean; }; unshared_at: string | null; diff --git a/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts b/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts index 5806c75907..2922386832 100644 --- a/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts +++ b/src/elements/content-sharing/utils/getAllowedPermissionLevels.ts @@ -1,30 +1,11 @@ -import { - ACCESS_COMPANY, - ACCESS_OPEN, - PERMISSION_CAN_DOWNLOAD, - PERMISSION_CAN_EDIT, - PERMISSION_CAN_PREVIEW, - TYPE_FOLDER, -} from '../../../constants'; +import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../constants'; -type GetAllowedPermissionLevelsParams = { - access: string; - canChangeAccessLevel: boolean; - extension: string; - isDownloadSettingAvailable: boolean; - itemType: string; - permission: string; -}; - -export const getAllowedPermissionLevels = ({ - access, +export const getAllowedPermissionLevels = ( canChangeAccessLevel, - extension, isDownloadSettingAvailable, - itemType, permission, -}: GetAllowedPermissionLevelsParams): Array => { - let allowedPermissionLevels = [PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW, PERMISSION_CAN_EDIT]; +): Array => { + let allowedPermissionLevels = [PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW]; if (!canChangeAccessLevel) { // remove all but current level @@ -36,11 +17,5 @@ export const getAllowedPermissionLevels = ({ allowedPermissionLevels = allowedPermissionLevels.filter(level => level !== PERMISSION_CAN_DOWNLOAD); } - // Can Edit requires ACCESS_OPEN or ACCESS_COMPANY, and must NOT be a folder - const canEditAccessLevels = [ACCESS_OPEN, ACCESS_COMPANY]; - if (!canEditAccessLevels.includes(access) || itemType === TYPE_FOLDER || extension?.toLowerCase() === 'webdoc') { - allowedPermissionLevels = allowedPermissionLevels.filter(level => level !== PERMISSION_CAN_EDIT); - } - return allowedPermissionLevels; };