diff --git a/keyserver/src/creators/thread-creator.js b/keyserver/src/creators/thread-creator.js --- a/keyserver/src/creators/thread-creator.js +++ b/keyserver/src/creators/thread-creator.js @@ -41,6 +41,7 @@ import { determineThreadAncestry, personalThreadQuery, + determineThreadAncestryForPossibleMemberResolution, } from '../fetchers/thread-fetchers.js'; import { checkThreadPermission, @@ -161,7 +162,11 @@ ); const validateMembersPromise = (async () => { - const threadAncestry = await determineThreadAncestryPromise; + const threadAncestry = + await determineThreadAncestryForPossibleMemberResolution( + parentThreadID, + threadType, + ); const defaultRolePermissions = getRolePermissionBlobs(threadType).Members; const { initialMemberIDs, ghostMemberIDs } = await validateCandidateMembers( viewer, @@ -174,6 +179,7 @@ parentThreadID, containingThreadID: threadAncestry.containingThreadID, defaultRolePermissions, + communityID: threadAncestry.community, }, { requireRelationship: !shouldCreateRelationships }, ); 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 @@ -2,6 +2,7 @@ import invariant from 'invariant'; +import genesis from 'lib/facts/genesis.js'; import { specialRoles } from 'lib/permissions/special-roles.js'; import { getAllThreadPermissions } from 'lib/permissions/thread-permissions.js'; import { @@ -382,6 +383,21 @@ return { containingThreadID, community, depth }; } +async function determineThreadAncestryForPossibleMemberResolution( + parentThreadID: ?string, + threadType: ThreadType, +): Promise { + const { containingThreadID, community, depth } = + await determineThreadAncestry(parentThreadID, threadType); + + let resolvedContainingThreadID = containingThreadID; + if (resolvedContainingThreadID === genesis().id) { + resolvedContainingThreadID = + parentThreadID === genesis().id ? null : parentThreadID; + } + return { containingThreadID: resolvedContainingThreadID, community, depth }; +} + function personalThreadQuery( firstMemberID: string, secondMemberID: string, @@ -442,6 +458,7 @@ verifyThreadIDs, verifyThreadID, determineThreadAncestry, + determineThreadAncestryForPossibleMemberResolution, personalThreadQuery, fetchPersonalThreadID, serverThreadInfoFromMessageInfo, diff --git a/keyserver/src/fetchers/thread-permission-fetchers.js b/keyserver/src/fetchers/thread-permission-fetchers.js --- a/keyserver/src/fetchers/thread-permission-fetchers.js +++ b/keyserver/src/fetchers/thread-permission-fetchers.js @@ -274,6 +274,7 @@ +parentThreadID: ?string, +containingThreadID: ?string, +defaultRolePermissions: ThreadRolePermissionsBlob, + +communityID: ?string, }; type ValidateCandidateMembersOptions = { +requireRelationship?: boolean }; async function validateCandidateMembers( @@ -370,14 +371,17 @@ continue; } const permissionsFromParent = parentPermissions[memberID]; - if (memberOfContainingThread.get(memberID) === 'non-member') { + if ( + memberOfContainingThread.get(memberID) === 'non-member' && + (params.communityID !== genesis().id || + (relationshipStatus !== userRelationshipStatus.FRIEND && + requireRelationship)) + ) { ignoreMembers.add(memberID); continue; } - const isParentThreadGenesis = params.parentThreadID === genesis().id; if ( - (memberOfContainingThread.get(memberID) === 'no-containing-thread' || - isParentThreadGenesis) && + memberOfContainingThread.get(memberID) === 'no-containing-thread' && relationshipStatus !== userRelationshipStatus.FRIEND && requireRelationship ) { diff --git a/keyserver/src/updaters/thread-updaters.js b/keyserver/src/updaters/thread-updaters.js --- a/keyserver/src/updaters/thread-updaters.js +++ b/keyserver/src/updaters/thread-updaters.js @@ -53,6 +53,7 @@ fetchServerThreadInfos, determineThreadAncestry, rawThreadInfosFromServerThreadInfos, + determineThreadAncestryForPossibleMemberResolution, } from '../fetchers/thread-fetchers.js'; import { checkThreadPermission, @@ -583,7 +584,10 @@ const [defaultRolePermissions, nextThreadAncestry] = await Promise.all([ defaultRolePermissionsPromise, - determineThreadAncestryPromise, + determineThreadAncestryForPossibleMemberResolution( + nextParentThreadID, + nextThreadType, + ), ]); const { newMemberIDs: validatedIDs } = await validateCandidateMembers( @@ -594,6 +598,7 @@ parentThreadID: nextParentThreadID, containingThreadID: nextThreadAncestry.containingThreadID, defaultRolePermissions, + communityID: nextThreadAncestry.community, }, { requireRelationship: !forceAddMembers }, );