diff --git a/keyserver/src/fetchers/thread-fetchers.js b/keyserver/src/fetchers/thread-fetchers.js --- a/keyserver/src/fetchers/thread-fetchers.js +++ b/keyserver/src/fetchers/thread-fetchers.js @@ -10,7 +10,10 @@ getContainingThreadID, getCommunity, } from 'lib/shared/thread-utils.js'; -import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; +import { + FUTURE_CODE_VERSION, + hasMinCodeVersion, +} from 'lib/shared/version-utils.js'; import type { AvatarDBContent, ClientAvatar } from 'lib/types/avatar-types.js'; import type { RawMessageInfo, MessageInfo } from 'lib/types/message-types.js'; import type { ThinRawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; @@ -305,6 +308,10 @@ web: 88, }, ); + const stripMemberPermissions = !hasMinCodeVersion(viewer.platformDetails, { + native: FUTURE_CODE_VERSION, + web: FUTURE_CODE_VERSION, + }); const threadInfos: { [string]: LegacyThinRawThreadInfo | ThinRawThreadInfo, @@ -324,6 +331,7 @@ allowAddingUsersToCommunityRoot: addingUsersToCommunityRootSupported, filterManageFarcasterChannelTagsPermission: manageFarcasterChannelTagsPermissionUnsupported, + stripMemberPermissions: stripMemberPermissions, }, ); if (threadInfo) { diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -101,6 +101,10 @@ type ThreadEntity, type UserEntity, } from '../utils/entity-text.js'; +import { + stripMemberPermissionsFromRawThreadInfo, + type ThinRawThreadInfoWithPermissions, +} from '../utils/member-info-utils.js'; import { entries, values } from '../utils/objects.js'; import { useSelector } from '../utils/redux-utils.js'; import { usingOlmViaTunnelbrokerForDMs } from '../utils/services-utils.js'; @@ -703,6 +707,7 @@ +includeSpecialRoleFieldInRoles?: boolean, +allowAddingUsersToCommunityRoot?: boolean, +filterManageFarcasterChannelTagsPermission?: boolean, + +stripMemberPermissions?: boolean, }; function rawThreadInfoFromServerThreadInfo( @@ -724,6 +729,7 @@ options?.allowAddingUsersToCommunityRoot; const filterManageFarcasterChannelTagsPermission = options?.filterManageFarcasterChannelTagsPermission; + const stripMemberPermissions = options?.stripMemberPermissions; const filterThreadPermissions = ( innerThreadPermissions: ThreadPermissionsInfo, @@ -859,27 +865,49 @@ return rawThreadInfo; } - const minimallyEncoded = + const minimallyEncodedRawThreadInfoWithMemberPermissions = deprecatedMinimallyEncodeRawThreadInfo(rawThreadInfo); - invariant(!minimallyEncoded.thick, 'ServerThreadInfo should be thin thread'); + invariant( + !minimallyEncodedRawThreadInfoWithMemberPermissions.thick, + 'ServerThreadInfo should be thin thread', + ); if (shouldIncludeSpecialRoleFieldInRoles) { - return minimallyEncoded; + return minimallyEncodedRawThreadInfoWithMemberPermissions; } const minimallyEncodedRolesWithoutSpecialRoleField = Object.fromEntries( - entries(minimallyEncoded.roles).map(([key, role]) => [ - key, - { - ..._omit('specialRole')(role), - isDefault: roleIsDefaultRole(role), - }, - ]), + entries(minimallyEncodedRawThreadInfoWithMemberPermissions.roles).map( + ([key, role]) => [ + key, + { + ..._omit('specialRole')(role), + isDefault: roleIsDefaultRole(role), + }, + ], + ), ); - return { - ...minimallyEncoded, - roles: minimallyEncodedRolesWithoutSpecialRoleField, - }; + if (!stripMemberPermissions) { + return { + ...minimallyEncodedRawThreadInfoWithMemberPermissions, + roles: minimallyEncodedRolesWithoutSpecialRoleField, + }; + } + + // The return value of `deprecatedMinimallyEncodeRawThreadInfo` is typed + // as `RawThreadInfo`, but still includes thread member permissions. + // This was to prevent introducing "Legacy" types that would need to be + // maintained going forward. This `any`-cast allows us to more precisely + // type the obj being passed to `stripMemberPermissionsFromRawThreadInfo`. + const rawThreadInfoWithMemberPermissions: ThinRawThreadInfoWithPermissions = + ({ + ...minimallyEncodedRawThreadInfoWithMemberPermissions, + roles: minimallyEncodedRolesWithoutSpecialRoleField, + }: any); + + return stripMemberPermissionsFromRawThreadInfo( + rawThreadInfoWithMemberPermissions, + ); } function threadUIName(threadInfo: ThreadInfo): string | ThreadEntity { diff --git a/lib/utils/member-info-utils.js b/lib/utils/member-info-utils.js --- a/lib/utils/member-info-utils.js +++ b/lib/utils/member-info-utils.js @@ -1,11 +1,9 @@ // @flow -import invariant from 'invariant'; - import type { MemberInfoSansPermissions, MemberInfoWithPermissions, - RawThreadInfo, + ThinRawThreadInfo, } from '../types/minimally-encoded-thread-permissions-types.js'; function stripPermissionsFromMemberInfo( @@ -15,13 +13,14 @@ return rest; } +export type ThinRawThreadInfoWithPermissions = $ReadOnly<{ + ...ThinRawThreadInfo, + +members: $ReadOnlyArray, +}>; + function stripMemberPermissionsFromRawThreadInfo( - rawThreadInfo: RawThreadInfo, -): RawThreadInfo { - invariant( - !rawThreadInfo.thick, - 'Expect ThinRawThreadInfo in stripMemberPermissionsFromRawThreadInfo', - ); + rawThreadInfo: ThinRawThreadInfoWithPermissions, +): ThinRawThreadInfo { return { ...rawThreadInfo, members: rawThreadInfo.members.map(stripPermissionsFromMemberInfo),