diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index c2ac1ba200..354923f44e 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -2821,8 +2821,6 @@ deleteMemberConnection user GroupMember {activeConn} = do deleteAgentConnectionAsync user conn `catchError` \_ -> pure () withStore' $ \db -> updateConnectionStatus db conn ConnDeleted --- withStore $ \db -> deleteGroupMemberConnection db userId m - sendDirectContactMessage :: (MsgEncodingI e, ChatMonad m) => Contact -> ChatMsgEvent e -> m (SndMessage, Int64) sendDirectContactMessage ct@Contact {activeConn = conn@Connection {connId, connStatus}} chatMsgEvent = do if connStatus == ConnReady || connStatus == ConnSndReady diff --git a/src/Simplex/Chat/Store.hs b/src/Simplex/Chat/Store.hs index 3d68df02b6..0100f54be9 100644 --- a/src/Simplex/Chat/Store.hs +++ b/src/Simplex/Chat/Store.hs @@ -1976,8 +1976,9 @@ createNewMember_ pure GroupMember {groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus, invitedBy, localDisplayName, memberProfile = toLocalProfile memberContactProfileId memberProfile "", memberContactId, memberContactProfileId, activeConn} deleteGroupMember :: DB.Connection -> User -> GroupMember -> IO () -deleteGroupMember db user@User {userId} m@GroupMember {groupMemberId, memberContactId, memberContactProfileId} = do +deleteGroupMember db user@User {userId} m@GroupMember {groupMemberId, groupId, memberContactId, memberContactProfileId} = do deleteGroupMemberConnection db user m + DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND group_id = ? AND group_member_id = ?" (userId, groupId, groupMemberId) DB.execute db "DELETE FROM group_members WHERE user_id = ? AND group_member_id = ?" (userId, groupMemberId) unless (isJust memberContactId) $ do sameProfileMember :: (Maybe GroupMemberId) <- maybeFirstRow fromOnly $ DB.query db "SELECT group_member_id FROM group_members WHERE user_id = ? AND contact_profile_id = ? AND group_member_id != ? LIMIT 1" (userId, memberContactProfileId, groupMemberId) diff --git a/tests/ChatTests.hs b/tests/ChatTests.hs index cabc771035..c3208aaeec 100644 --- a/tests/ChatTests.hs +++ b/tests/ChatTests.hs @@ -139,6 +139,7 @@ chatTests = do describe "group links" $ do it "create group link, join via group link" testGroupLink it "create group link, join via group link - incognito membership" testGroupLinkIncognitoMembership + it "deleting invited member does not leave broken chat item" testGroupLinkDeleteInvitedMemberNoBrokenItem versionTestMatrix2 :: (TestCC -> TestCC -> IO ()) -> Spec versionTestMatrix2 runTest = do @@ -3519,6 +3520,64 @@ testGroupLinkIncognitoMembership = cath <# ("#team " <> danIncognito <> "> how is it going?") ] +testGroupLinkDeleteInvitedMemberNoBrokenItem :: IO () +testGroupLinkDeleteInvitedMemberNoBrokenItem = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + alice ##> "/g team" + alice <## "group #team is created" + alice <## "use /a team to add members" + alice ##> "/create link #team" + gLink <- getGroupLink alice "team" True + bob ##> ("/c " <> gLink) + bob <## "connection request sent!" + alice <## "bob (Bob): accepting request to join group #team..." + concurrentlyN_ + [ do + alice <## "bob (Bob): contact is connected" + alice <## "bob invited to group #team via your group link", + do + bob <## "alice (Alice): contact is connected" + bob <## "#team: alice invites you to join the group as member" + bob <## "use /j team to accept" + ] + alice #$> ("/_get chat #1 count=100", chat, [(0, "invited via your group link")]) + alice @@@ [("#team", "invited via your group link")] + -- removing invited member who connected via group link does not leave broken chat item + alice ##> "/rm team bob" + alice <## "#team: you removed bob from the group" + alice #$> ("/_get chat #1 count=100", chat, []) + alice @@@ [("#team", "")] + alice <##> bob + alice @@@ [("@bob", "hey"), ("#team", "")] + bob ##> "/j team" + bob <## "error: connection authorization failed - this could happen if connection was deleted, secured with different credentials, or due to a bug - please re-create the connection" + -- repeat request is prohibited because of the re-used XContactId, until contact is deleted + bob ##> ("/c " <> gLink) + bob <## "alice (Alice): contact already exists" + bob ##> "/d alice" + bob <## "alice: contact is deleted" + bob ##> ("/c " <> gLink) + bob <## "connection request sent!" + alice <## "bob_1 (Bob): accepting request to join group #team..." + concurrentlyN_ + [ do + alice <## "bob_1 (Bob): contact is connected" + alice <## "bob_1 invited to group #team via your group link", + do + bob <## "alice_1 (Alice): contact is connected" + bob <## "#team_1 (team): alice_1 invites you to join the group as member" + bob <## "use /j team_1 to accept" + ] + bob ##> "/j team_1" + concurrently_ + (alice <## "#team: bob_1 joined the group") + (bob <## "#team_1: you joined the group") + alice #> "#team hello" + bob <# "#team_1 alice_1> hello" + bob #> "#team_1 hi there" + alice <# "#team bob_1> hi there" + withTestChatContactConnected :: String -> (TestCC -> IO a) -> IO a withTestChatContactConnected dbPrefix action = withTestChat dbPrefix $ \cc -> do