From fd14739faf4b4ccad615c0df17517865710244da Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Wed, 29 Apr 2026 09:40:05 +0000 Subject: [PATCH] directory: fix /invite not re-inviting member who left owners' group (#6866) * directory: re-invite owner who left owners' group The /invite command's alreadyMember check treated any GroupMember row as a current member, including rows with status GSMemLeft or GSMemRemoved. Owners who had left the owners' group could therefore not be re-invited. Use memberCurrent to only block re-invite when the member is actually in the group. * directory tests: account for admin notification and renamed group on re-invite The owners' group has no GroupReg by design, so when an owner leaves it the directory service notifies admins with "Error: contact left, group: N owners, group registration not found" - expected behavior, but the test for re-inviting an owner who left the owners' group did not consume this DM and failed at bracket cleanup. The test also assumed bob's new invitation would land in #owners, but the chat client disambiguates it to #owners_1 because bob's old left membership of #owners is still present locally. Consume the admin DM explicitly and update the invitation assertions to #owners_1 / /j owners_1. --------- Co-authored-by: Evgeny Poberezkin --- .../src/Directory/Service.hs | 2 +- tests/Bots/DirectoryTests.hs | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/simplex-directory-service/src/Directory/Service.hs b/apps/simplex-directory-service/src/Directory/Service.hs index 400f250979..6e414ef011 100644 --- a/apps/simplex-directory-service/src/Directory/Service.hs +++ b/apps/simplex-directory-service/src/Directory/Service.hs @@ -1395,7 +1395,7 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName r -> contErr r r -> contErr r where - alreadyMember = isJust . find ((Just ctId ==) . memberContactId) + alreadyMember = any (\m -> memberContactId m == Just ctId && memberCurrent m) contErr r = do let err = "error inviting contact ID " <> tshow ctId <> " to owners' group: " <> tshow r putStrLn $ T.unpack err diff --git a/tests/Bots/DirectoryTests.hs b/tests/Bots/DirectoryTests.hs index b57127eced..9961fa4c1a 100644 --- a/tests/Bots/DirectoryTests.hs +++ b/tests/Bots/DirectoryTests.hs @@ -44,6 +44,7 @@ directoryServiceTests = do it "should support group names with spaces" testGroupNameWithSpaces it "should return more groups in search, all and recent groups" testSearchGroups it "should invite to owners' group if specified" testInviteToOwnersGroup + it "should re-invite owner who left owners' group" testInviteOwnerAfterLeavingOwnersGroup describe "de-listing the group" $ do it "should de-list if owner leaves the group" testDelistedOwnerLeaves it "should de-list if owner is removed from the group" testDelistedOwnerRemoved @@ -577,6 +578,32 @@ testInviteToOwnersGroup ps = registerGroupId superUser bob "security" "Security" 3 2 superUser <## "Owner is already a member of owners' group" +testInviteOwnerAfterLeavingOwnersGroup :: HasCallStack => TestParams -> IO () +testInviteOwnerAfterLeavingOwnersGroup ps = + withDirectoryServiceCfgOwnersGroup ps testCfg True Nothing $ \superUser dsLink -> + withNewTestChatCfg ps testCfg "bob" bobProfile $ \bob -> do + bob `connectVia` dsLink + registerGroupId superUser bob "privacy" "Privacy" 2 1 + bob <## "#owners: 'SimpleX Directory' invites you to join the group as member" + bob <## "use /j owners to accept" + superUser <## "Invited @bob, the owner of the group ID 2 (privacy) to owners' group owners" + bob ##> "/j owners" + bob <## "#owners: you joined the group" + bob <## "#owners: member alice (Alice) is connected" + superUser <## "#owners: 'SimpleX Directory' added bob (Bob) to the group (connecting...)" + superUser <## "#owners: new member bob is connected" + -- owner leaves owners' group; GroupMember row keeps status GSMemLeft + leaveGroup "owners" bob + superUser <## "#owners: bob left the group" + -- owners' group has no GroupReg, so directory service notifies admins on contact left + superUser <# "'SimpleX Directory'> Error: contact left, group: 1 owners, group registration not found" + -- super-user re-invites via /invite — must send a fresh invitation, not "already a member" + superUser #> "@'SimpleX Directory' /invite 2:privacy" + superUser <# "'SimpleX Directory'> > /invite 2:privacy" + superUser <## " you invited @bob, the owner of the group ID 2 (privacy) to owners' group owners" + bob <## "#owners_1: 'SimpleX Directory' invites you to join the group as member" + bob <## "use /j owners_1 to accept" + testDelistedOwnerLeaves :: HasCallStack => TestParams -> IO () testDelistedOwnerLeaves ps = withDirectoryService ps $ \superUser dsLink ->