From 1e73eb512a8e51fa71f43bac186ec1c4d54464b3 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Mon, 14 Jul 2025 22:37:39 +0100 Subject: [PATCH] core: fix connection plans to allow re-connecting to address after the contact with address in profile was deleted (#6073) --- src/Simplex/Chat/Library/Commands.hs | 8 +++--- tests/ChatTests/Profiles.hs | 41 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index fc2ffe5025..328b59769f 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -3412,8 +3412,8 @@ processChatCommand vr nm = \case Nothing -> do (cReq, cData) <- getShortLinkConnReq user l' withFastStore' (\db -> getContactWithoutConnViaShortAddress db vr user l') >>= \case - Just ct' -> pure (con cReq, CPContactAddress (CAPContactViaAddress ct')) - Nothing -> do + Just ct' | not (contactDeleted ct') -> pure (con cReq, CPContactAddress (CAPContactViaAddress ct')) + _ -> do contactSLinkData_ <- liftIO $ decodeShortLinkData cData plan <- contactRequestPlan user cReq contactSLinkData_ pure (con cReq, plan) @@ -3486,8 +3486,8 @@ processChatCommand vr nm = \case withFastStore' (\db -> getContactConnEntityByConnReqHash db vr user cReqHashes) >>= \case Nothing -> withFastStore' (\db -> getContactWithoutConnViaAddress db vr user cReqSchemas) >>= \case - Nothing -> pure $ CPContactAddress (CAPOk contactSLinkData_) - Just ct -> pure $ CPContactAddress (CAPContactViaAddress ct) + Just ct | not (contactDeleted ct) -> pure $ CPContactAddress (CAPContactViaAddress ct) + _ -> pure $ CPContactAddress (CAPOk contactSLinkData_) Just (RcvDirectMsgConnection Connection {connStatus} Nothing) | connStatus == ConnPrepared -> pure $ CPContactAddress (CAPOk contactSLinkData_) | otherwise -> pure $ CPContactAddress CAPConnectingConfirmReconnect diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs index 90160a3e51..c59f06c473 100644 --- a/tests/ChatTests/Profiles.hs +++ b/tests/ChatTests/Profiles.hs @@ -124,6 +124,7 @@ shortLinkTests largeLinkData = do else it "prepare contact with a long name in profile" testShortLinkInvitationLongName it "prepare contact via invitation and retry connecting" testShortLinkInvitationConnectRetry it "prepare contact using address short link data and connect" testShortLinkAddressPrepareContact + it "address connect plan after contact is deleted but conversation kept" testShortLinkAddressDeleteContact it "prepare contact via invitation and connect after it is deleted" testShortLinkDeletedInvitation it "prepare contact via address and connect after it is deleted" testShortLinkDeletedAddress it "prepare contact via address and connect with retry after error" testShortLinkAddressConnectRetry @@ -3138,6 +3139,46 @@ testShortLinkAddressPrepareContact ps@TestParams {largeLinkData} = testChatCfg2 bob <## "contact address: ok to connect" void $ getTermLine bob +testShortLinkAddressDeleteContact :: HasCallStack => TestParams -> IO () +testShortLinkAddressDeleteContact ps@TestParams {largeLinkData} = testChatCfg2 testCfg {largeLinkData} aliceProfile bobProfile test ps + where + test alice bob = do + alice ##> "/ad" + (shortLink, fullLink) <- getContactLinks alice True + alice ##> "/pa on" + alice <## "new contact address set" + bob ##> ("/_connect plan 1 " <> shortLink) + bob <## "contact address: ok to connect" + contactSLinkData <- getTermLine bob + bob ##> ("/_prepare contact 1 " <> fullLink <> " " <> shortLink <> " " <> contactSLinkData) + bob <## "alice: contact is prepared" + bob ##> "/_connect contact @2 text hello" + bob + <### [ "alice: connection started", + WithTime "@alice hello" + ] + alice + <### [ "bob (Bob) wants to connect to you!", + WithTime "bob> hello" + ] + alice <## "to accept: /ac bob" + alice <## "to reject: /rc bob (the sender will NOT be notified)" + alice ##> "/ac bob" + alice <## "bob (Bob): accepting contact request, you can send messages to contact" + unless largeLinkData $ + bob <## "contact alice updated bio: Alice" + concurrently_ + (bob <## "alice (Alice): contact is connected") + (alice <## "bob (Bob): contact is connected") + alice <##> bob + threadDelay 250000 + bob ##> "/d alice entity" + bob <## "alice: contact is deleted" + alice <## "bob (Bob) deleted contact with you" + bob ##> ("/_connect plan 1 " <> shortLink) + bob <## "contact address: ok to connect" + void $ getTermLine bob + testShortLinkDeletedInvitation :: HasCallStack => TestParams -> IO () testShortLinkDeletedInvitation ps@TestParams {largeLinkData} = testChatCfg2 testCfg {largeLinkData} aliceProfile bobProfile test ps where