mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-23 06:22:43 +00:00
core: report an invitation the agent already used
Accepting a contact request that was already accepted reached the user as error agent CMD PROHIBITED SEInvitationNotFound acceptContact, invitationId = "..." The chat layer cannot tell that case from an accept that failed: the contact connection is committed at ConnNew before acceptContact is called, and a successful accept leaves it at ConnNew as well, until the peer's CONF arrives. A guard on the connection would reject retrying an accept that failed with a network error - covered by "retry connecting via contact link". The agent can tell, because it owns the invitation and clears it in the right order: getInvitation requires accepted = 0, joinConn can fail, and only then does acceptInvitation set accepted = 1. So SEInvitationNotFound means the request was accepted, while a join that failed leaves the invitation for the retry to find. Its CMD PROHIBITED is translated rather than re-derived; within acceptContact' that error has no other source.
This commit is contained in:
1 parent
66d6466a9e
commit
226c43f395
1 file changed
+8
-5
@@ -914,16 +914,19 @@ acceptContactRequest nm user@User {userId} UserContactRequest {agentInvitationId
|
||||
forM_ xContactId $ \xcId -> setContactAcceptedXContactId db ct xcId
|
||||
createAcceptedContactConn db user userContactLinkId_ contactId connId chatV cReqChatVRange pqSup' incognitoProfile subMode currentTs
|
||||
pure (ct {activeConn = Just conn} :: Contact, conn, incognitoProfile)
|
||||
-- contact connection in any status other than prepared is created when the request is accepted
|
||||
-- (see createAcceptedContactConn), so the request was already accepted -
|
||||
-- accepting it again would fail in the agent, as the invitation is already used.
|
||||
Just Connection {connStatus} | connStatus /= ConnPrepared -> throwCmdError "contact request already accepted"
|
||||
Just conn@Connection {customUserProfileId} -> do
|
||||
incognitoProfile <- forM customUserProfileId $ \pId -> withFastStore $ \db -> getProfileById db userId pId
|
||||
pure (ct, conn, ExistingIncognito <$> incognitoProfile)
|
||||
profileToSend <- presentUserBadge user incognitoProfile $ userProfileDirect user (fromIncognitoProfile <$> incognitoProfile) (Just ct) True
|
||||
dm <- encodeConnInfoPQ pqSup' chatV $ XInfo profileToSend
|
||||
(ct,conn,) <$> withAgent (\a -> acceptContact a nm (aUserId user) (aConnId conn) True invId dm pqSup' subMode)
|
||||
sqSecured <-
|
||||
withAgent (\a -> acceptContact a nm (aUserId user) (aConnId conn) True invId dm pqSup' subMode)
|
||||
-- the agent marks the invitation accepted only once joining succeeded (see acceptContact'),
|
||||
-- so not finding it is what tells an accepted request from an accept that failed and can be retried
|
||||
`catchAllErrors` \case
|
||||
ChatErrorAgent {agentError = CMD PROHIBITED _} -> throwCmdError "contact request already accepted"
|
||||
e -> throwError e
|
||||
pure (ct, conn, sqSecured)
|
||||
|
||||
acceptContactRequestAsync :: User -> Int64 -> Contact -> UserContactRequest -> Maybe IncognitoProfile -> CM Contact
|
||||
acceptContactRequestAsync
|
||||
|
||||
Reference in new issue
Block a user