diff --git a/lib/types/thread-permission-types.js b/lib/types/thread-permission-types.js --- a/lib/types/thread-permission-types.js +++ b/lib/types/thread-permission-types.js @@ -124,10 +124,7 @@ userSurfacedPermission: userSurfacedPermissions.EDIT_CALENDAR, }; const editEntries = threadPermissions.EDIT_ENTRIES; -const descendantEditEntries = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_ENTRIES; -const editCalendarPermissions = new Set([editEntries, descendantEditEntries]); +const editCalendarPermissions = new Set([editEntries]); const knowOfSecretChannelsPermission = { title: 'Know of secret channels', @@ -170,42 +167,16 @@ userSurfacedPermission: userSurfacedPermissions.CREATE_AND_EDIT_CHANNELS, }; const editThreadName = threadPermissions.EDIT_THREAD_NAME; -const descendantEditThreadName = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_THREAD_NAME; const editThreadDescription = threadPermissions.EDIT_THREAD_DESCRIPTION; -const descendantEditThreadDescription = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_THREAD_DESCRIPTION; const editThreadColor = threadPermissions.EDIT_THREAD_COLOR; -const descendantEditThreadColor = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_THREAD_COLOR; const createSubchannels = threadPermissions.CREATE_SUBCHANNELS; -const descendantCreateSubchannels = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissionFilterPrefixes.TOP_LEVEL + - threadPermissions.CREATE_SUBCHANNELS; const editThreadAvatar = threadPermissions.EDIT_THREAD_AVATAR; -const descendantEditThreadAvatar = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_THREAD_AVATAR; -const descendantTopLevelCreateSidebars = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissionFilterPrefixes.TOP_LEVEL + - threadPermissions.CREATE_SIDEBARS; const createAndEditChannelsPermissions = new Set([ editThreadName, - descendantEditThreadName, editThreadDescription, - descendantEditThreadDescription, editThreadColor, - descendantEditThreadColor, createSubchannels, - descendantCreateSubchannels, editThreadAvatar, - descendantEditThreadAvatar, - descendantTopLevelCreateSidebars, ]); const deleteChannelsPermission = { @@ -214,13 +185,7 @@ userSurfacedPermission: userSurfacedPermissions.DELETE_CHANNELS, }; const deleteThread = threadPermissions.DELETE_THREAD; -const descendantDeleteThread = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.DELETE_THREAD; -const deleteChannelsPermissions = new Set([ - deleteThread, - descendantDeleteThread, -]); +const deleteChannelsPermissions = new Set([deleteThread]); const addMembersPermission = { title: 'Add members', @@ -228,18 +193,11 @@ userSurfacedPermission: userSurfacedPermissions.ADD_MEMBERS, }; const addMembers = threadPermissions.ADD_MEMBERS; -const descendantAddMembers = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.ADD_MEMBERS; const childOpenAddMembers = threadPermissionPropagationPrefixes.CHILD + threadPermissionFilterPrefixes.OPEN + threadPermissions.ADD_MEMBERS; -const addMembersPermissions = new Set([ - addMembers, - descendantAddMembers, - childOpenAddMembers, -]); +const addMembersPermissions = new Set([addMembers, childOpenAddMembers]); const removeMembersPermission = { title: 'Remove members', @@ -247,13 +205,7 @@ userSurfacedPermission: userSurfacedPermissions.REMOVE_MEMBERS, }; const removeMembers = threadPermissions.REMOVE_MEMBERS; -const descendantRemoveMembers = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.REMOVE_MEMBERS; -const removeMembersPermissions = new Set([ - removeMembers, - descendantRemoveMembers, -]); +const removeMembersPermissions = new Set([removeMembers]); const changeRolePermission = { title: 'Change roles', @@ -261,10 +213,7 @@ userSurfacedPermission: userSurfacedPermissions.CHANGE_ROLES, }; const changeRole = threadPermissions.CHANGE_ROLE; -const descendantChangeRole = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.CHANGE_ROLE; -const changeRolePermissions = new Set([changeRole, descendantChangeRole]); +const changeRolePermissions = new Set([changeRole]); const editVisibilityPermission = { title: 'Edit visibility', @@ -272,13 +221,7 @@ userSurfacedPermission: userSurfacedPermissions.EDIT_VISIBILITY, }; const editPermissions = threadPermissions.EDIT_PERMISSIONS; -const descendantEditPermissions = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_PERMISSIONS; -const editVisibilityPermissions = new Set([ - editPermissions, - descendantEditPermissions, -]); +const editVisibilityPermissions = new Set([editPermissions]); const managePinsPermission = { title: 'Manage pins', @@ -286,10 +229,7 @@ userSurfacedPermission: userSurfacedPermissions.MANAGE_PINS, }; const managePins = threadPermissions.MANAGE_PINS; -const descendantManagePins = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.MANAGE_PINS; -const managePinsPermissions = new Set([managePins, descendantManagePins]); +const managePinsPermissions = new Set([managePins]); const reactToMessagePermission = { title: 'React to messages', @@ -297,13 +237,7 @@ userSurfacedPermission: userSurfacedPermissions.REACT_TO_MESSAGES, }; const reactToMessage = threadPermissions.REACT_TO_MESSAGE; -const descendantReactToMessage = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.REACT_TO_MESSAGE; -const reactToMessagePermissions = new Set([ - reactToMessage, - descendantReactToMessage, -]); +const reactToMessagePermissions = new Set([reactToMessage]); const editMessagePermission = { title: 'Edit messages', @@ -311,10 +245,7 @@ userSurfacedPermission: userSurfacedPermissions.EDIT_MESSAGES, }; const editMessage = threadPermissions.EDIT_MESSAGE; -const descendantEditMessage = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.EDIT_MESSAGE; -const editMessagePermissions = new Set([editMessage, descendantEditMessage]); +const editMessagePermissions = new Set([editMessage]); const manageInviteLinksPermission = { title: 'Manage invite links', @@ -322,13 +253,7 @@ userSurfacedPermission: userSurfacedPermissions.MANAGE_INVITE_LINKS, }; const manageInviteLinks = threadPermissions.MANAGE_INVITE_LINKS; -const descendantManageInviteLinks = - threadPermissionPropagationPrefixes.DESCENDANT + - threadPermissions.MANAGE_INVITE_LINKS; -const manageInviteLinksPermissions = new Set([ - manageInviteLinks, - descendantManageInviteLinks, -]); +const manageInviteLinksPermissions = new Set([manageInviteLinks]); export type UserSurfacedPermissionOption = { +title: string, @@ -388,8 +313,7 @@ threadPermissionFilterPrefixes.OPEN + threadPermissions.VISIBLE, - // join_thread | child_open_join_thread | descendant_opentoplevel_join_thread - threadPermissions.JOIN_THREAD, + // child_open_join_thread | descendant_opentoplevel_join_thread threadPermissionPropagationPrefixes.CHILD + threadPermissionFilterPrefixes.OPEN + threadPermissions.JOIN_THREAD, diff --git a/lib/types/thread-permission-types.test.js b/lib/types/thread-permission-types.test.js --- a/lib/types/thread-permission-types.test.js +++ b/lib/types/thread-permission-types.test.js @@ -4,13 +4,54 @@ configurableCommunityPermissions, universalCommunityPermissions, userSurfacedPermissions, - type UserSurfacedPermission, threadPermissions, } from './thread-permission-types.js'; import { getRolePermissionBlobs } from '../permissions/thread-permissions.js'; import { threadTypes } from '../types/thread-types-enum.js'; import { deepDiff, values } from '../utils/objects.js'; +const getUniversalCommunityPermissionsBlob = () => + Object.fromEntries( + universalCommunityPermissions.map(permission => [permission, true]), + ); + +const addAllUniversalCommunityPermissions = ( + permissionsBlob, + universalBlob, +) => ({ + ...permissionsBlob, + ...universalBlob, +}); + +const addAllConfigurableCommunityPermissions = permissionsBlob => ({ + ...permissionsBlob, + ...Object.fromEntries( + values(configurableCommunityPermissions).flatMap(permissions => + [...permissions].map(permission => [permission, true]), + ), + ), +}); + +const removeAllConfigurableCommunityPermissions = permissionsBlob => { + const allConfigurableCommunityPermissions = values( + configurableCommunityPermissions, + ).flatMap(permissions => [...permissions]); + + return Object.fromEntries( + Object.entries(permissionsBlob).filter( + ([key]) => !allConfigurableCommunityPermissions.includes(key), + ), + ); +}; + +const reconstructOriginalPermissionsBlob = ( + permissionsBlob, + permissionsToAdd, +) => ({ + ...permissionsBlob, + ...Object.fromEntries(permissionsToAdd.map(permission => [permission, true])), +}); + describe('Community Announcement Root', () => { it('should find Member permissions from getRolePermissionBlobs and user-surfaced permissions to be equal', () => { const { Members: membersPermissionBlob } = getRolePermissionBlobs( @@ -34,30 +75,70 @@ expect( deepDiff(membersPermissionBlob, membersPermissionsConstructedBlob), ).toEqual({}); + expect( + deepDiff(membersPermissionsConstructedBlob, membersPermissionBlob), + ).toEqual({}); }); - it('should find Admin permissions from getRolePermissionBlobs and user-surfaced permissions to be equal', () => { - const adminsPermissionBlob = - getRolePermissionBlobs(threadTypes.COMMUNITY_ANNOUNCEMENT_ROOT).Admins ?? - {}; - - const adminsPermissionsConstructed = [ - ...values(userSurfacedPermissions) - .map((permission: UserSurfacedPermission) => [ - ...configurableCommunityPermissions[permission], - ]) - .flat(), - ...universalCommunityPermissions, + it('should find Member permissions to be equal before and after adding permissions', () => { + const { Members: membersPermissionBlob } = getRolePermissionBlobs( + threadTypes.COMMUNITY_ANNOUNCEMENT_ROOT, + ); + const universalCommunityPermissionsBlob = + getUniversalCommunityPermissionsBlob(); + + const constructedMembersPermissionsBlob = membersPermissionBlob; + expect( + deepDiff(constructedMembersPermissionsBlob, membersPermissionBlob), + ).toEqual({}); + + // Add all universal community permissions + const constructedBlobWithUniversalPermissions = + addAllUniversalCommunityPermissions( + constructedMembersPermissionsBlob, + universalCommunityPermissionsBlob, + ); + expect( + deepDiff(constructedBlobWithUniversalPermissions, membersPermissionBlob), + ).toEqual({}); + + // Add all configurable community permissions. + const constructedBlobWithConfigurablePermissions = + addAllConfigurableCommunityPermissions( + constructedBlobWithUniversalPermissions, + ); + + // Remove all configurable community permissions + const constructedBlobWithoutConfigurablePermissions = + removeAllConfigurableCommunityPermissions( + constructedBlobWithConfigurablePermissions, + ); + + expect( + deepDiff( + constructedBlobWithoutConfigurablePermissions, + universalCommunityPermissionsBlob, + ), + ).toEqual({}); + + // Add the original user-surfaced permissions back to the Members blob + const originalUserSurfacedPermissions = [ + ...configurableCommunityPermissions[userSurfacedPermissions.ADD_MEMBERS], + ...configurableCommunityPermissions[ + userSurfacedPermissions.REACT_TO_MESSAGES + ], + ...configurableCommunityPermissions[ + userSurfacedPermissions.EDIT_MESSAGES + ], ]; - const adminsPermissionsConstructedBlob = Object.fromEntries( - adminsPermissionsConstructed.map(permission => [permission, true]), + const reconstructedBlob = reconstructOriginalPermissionsBlob( + constructedBlobWithoutConfigurablePermissions, + originalUserSurfacedPermissions, ); - // Context: https://phab.comm.dev/D8478#inline-55680 - expect( - deepDiff(adminsPermissionBlob, adminsPermissionsConstructedBlob), - ).toEqual({ descendant_voiced: true }); + expect(deepDiff(reconstructedBlob, membersPermissionBlob)).toEqual({}); + expect(deepDiff(membersPermissionBlob, reconstructedBlob)).toEqual({}); }); }); @@ -91,5 +172,76 @@ expect( deepDiff(membersPermissionBlob, membersPermissionsConstructedBlob), ).toEqual({}); + expect( + deepDiff(membersPermissionsConstructedBlob, membersPermissionBlob), + ).toEqual({}); + }); + + it('should find Member permissions to be equal before and after adding permissions', () => { + const { Members: membersPermissionBlob } = getRolePermissionBlobs( + threadTypes.COMMUNITY_ROOT, + ); + const universalCommunityPermissionsBlob = + getUniversalCommunityPermissionsBlob(); + + const constructedMembersPermissionsBlob = membersPermissionBlob; + expect( + deepDiff(constructedMembersPermissionsBlob, membersPermissionBlob), + ).toEqual({}); + + // Add all universal community permissions + const constructedBlobWithUniversalPermissions = + addAllUniversalCommunityPermissions( + constructedMembersPermissionsBlob, + universalCommunityPermissionsBlob, + ); + expect( + deepDiff(constructedBlobWithUniversalPermissions, membersPermissionBlob), + ).toEqual({}); + + // Add all configurable community permissions. + const constructedBlobWithConfigurablePermissions = + addAllConfigurableCommunityPermissions( + constructedBlobWithUniversalPermissions, + ); + + // Remove all configurable community permissions + const constructedBlobWithoutConfigurablePermissions = + removeAllConfigurableCommunityPermissions( + constructedBlobWithConfigurablePermissions, + ); + + expect( + deepDiff( + constructedBlobWithoutConfigurablePermissions, + universalCommunityPermissionsBlob, + ), + ).toEqual({}); + + // Add the original user-surfaced permissions back to the Members blob + const originalUserSurfacedPermissions = [ + ...configurableCommunityPermissions[userSurfacedPermissions.ADD_MEMBERS], + ...configurableCommunityPermissions[ + userSurfacedPermissions.REACT_TO_MESSAGES + ], + ...configurableCommunityPermissions[ + userSurfacedPermissions.EDIT_MESSAGES + ], + ...configurableCommunityPermissions[ + userSurfacedPermissions.CREATE_AND_EDIT_CHANNELS + ], + ...configurableCommunityPermissions[ + userSurfacedPermissions.EDIT_CALENDAR + ], + ]; + + const reconstructedBlob = reconstructOriginalPermissionsBlob( + constructedBlobWithoutConfigurablePermissions, + originalUserSurfacedPermissions, + ); + reconstructedBlob[threadPermissions.VOICED] = true; + + expect(deepDiff(reconstructedBlob, membersPermissionBlob)).toEqual({}); + expect(deepDiff(membersPermissionBlob, reconstructedBlob)).toEqual({}); }); }); diff --git a/lib/utils/migration-utils.js b/lib/utils/migration-utils.js --- a/lib/utils/migration-utils.js +++ b/lib/utils/migration-utils.js @@ -130,6 +130,50 @@ threadPermissionPropagationPrefixes.DESCENDANT + threadPermissionFilterPrefixes.OPEN + threadPermissions.VOICED, + + threadPermissions.JOIN_THREAD, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_ENTRIES, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_THREAD_NAME, + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_THREAD_DESCRIPTION, + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_THREAD_COLOR, + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissionFilterPrefixes.TOP_LEVEL + + threadPermissions.CREATE_SUBCHANNELS, + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_THREAD_AVATAR, + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissionFilterPrefixes.TOP_LEVEL + + threadPermissions.CREATE_SIDEBARS, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.ADD_MEMBERS, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.REMOVE_MEMBERS, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.CHANGE_ROLE, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_PERMISSIONS, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.MANAGE_PINS, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.REACT_TO_MESSAGE, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.EDIT_MESSAGE, + + threadPermissionPropagationPrefixes.DESCENDANT + + threadPermissions.MANAGE_INVITE_LINKS, ]; export {