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 <evgeny@poberezkin.com>
This commit is contained in:
Narasimha-sc
2026-04-29 09:40:05 +00:00
committed by GitHub
parent 976f5efaf5
commit fd14739faf
2 changed files with 28 additions and 1 deletions
@@ -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
+27
View File
@@ -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 ->