diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index c122737b32..b53b0adacf 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -1297,7 +1297,8 @@ processChatCommand' vr = \case CTContactConnection -> pure $ chatCmdError (Just user) "not supported" CTContactRequest -> pure $ chatCmdError (Just user) "not supported" APIAcceptContact incognito connReqId -> withUser $ \_ -> do - (user@User {userId}, cReq@UserContactRequest {userContactLinkId}) <- withFastStore $ \db -> getContactRequest' db connReqId + (user@User {userId}, cReq) <- withFastStore $ \db -> getContactRequest' db connReqId + let UserContactRequest {agentInvitationId = AgentInvId invId, userContactLinkId, cReqChatVRange, localDisplayName = cName, profileId, profile = cp, xContactId, pqSupport} = cReq withUserContactLock "acceptContact" userContactLinkId $ do -- TODO conn prepare -- add connection_id to contact_requests; read in getContactRequest @@ -1308,11 +1309,21 @@ processChatCommand' vr = \case -- case connection Just: -- use it -- acceptContactRequest to work with prepared connection, pass connId to agent's acceptContact + + incognitoProfile <- if incognito then Just . NewIncognito <$> liftIO generateRandomProfile else pure Nothing + connId <- withAgent $ \a -> prepareConnectionToAccept a True invId pqSupport + let chatV = vr `peerConnChatVersion` cReqChatVRange + subMode <- chatReadVar subscriptionMode + conn <- withFastStore' $ \db -> createContactRequestConn db user connId chatV cReqChatVRange userContactLinkId incognitoProfile subMode pqSupport + ucl <- withFastStore $ \db -> getUserContactLinkById db userId userContactLinkId let contactUsed = (\(_, groupId_, _) -> isNothing groupId_) ucl -- [incognito] generate profile to send, create connection with incognito profile - incognitoProfile <- if incognito then Just . NewIncognito <$> liftIO generateRandomProfile else pure Nothing - ct <- acceptContactRequest user cReq incognitoProfile contactUsed + let profileToSend = profileToSendOnAccept user incognitoProfile False + dm <- encodeConnInfoPQ pqSupport chatV $ XInfo profileToSend + (acId, sqSecured) <- withAgent $ \a -> acceptContact a "" True invId dm pqSupport subMode + let connStatus = if sqSecured then ConnSndReady else ConnNew + ct <- withStore' $ \db -> createAcceptedContact db user acId connStatus chatV cReqChatVRange cName profileId cp userContactLinkId xContactId incognitoProfile subMode pqSupport contactUsed pure $ CRAcceptingContactRequest user ct APIRejectContact connReqId -> withUser $ \user -> do cReq@UserContactRequest {userContactLinkId, agentContactConnId = AgentConnId connId, agentInvitationId = AgentInvId invId} <- @@ -3681,21 +3692,6 @@ getRcvFilePath fileId fPath_ fn keepHandle = case fPath_ of liftIO $ B.hPut h "" >> hFlush h | otherwise = liftIO $ B.writeFile fPath "" -acceptContactRequest :: User -> UserContactRequest -> Maybe IncognitoProfile -> Bool -> CM Contact -acceptContactRequest user UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = cp, userContactLinkId, xContactId, pqSupport} incognitoProfile contactUsed = do - subMode <- chatReadVar subscriptionMode - let pqSup = PQSupportOn - vr <- chatVersionRange - let profileToSend = profileToSendOnAccept user incognitoProfile False - chatV = vr `peerConnChatVersion` cReqChatVRange - pqSup' = pqSup `CR.pqSupportAnd` pqSupport - dm <- encodeConnInfoPQ pqSup' chatV $ XInfo profileToSend - -- TODO conn prepare - -- use prepared conn id - (acId, sqSecured) <- withAgent $ \a -> acceptContact a "" True invId dm pqSup' subMode - let connStatus = if sqSecured then ConnSndReady else ConnNew - withStore' $ \db -> createAcceptedContact db user acId connStatus chatV cReqChatVRange cName profileId cp userContactLinkId xContactId incognitoProfile subMode pqSup' contactUsed - acceptContactRequestAsync :: User -> UserContactRequest -> Maybe IncognitoProfile -> Bool -> PQSupport -> CM Contact acceptContactRequestAsync user UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = p, userContactLinkId, xContactId} incognitoProfile contactUsed pqSup = do subMode <- chatReadVar subscriptionMode diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index c0f007b6ac..cf1cc7f556 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -61,6 +61,7 @@ module Simplex.Chat.Store.Direct getContactRequest, getContactRequestIdByName, deleteContactRequest, + createContactRequestConn, createAcceptedContact, getUserByContactRequestId, getPendingContactConnections, @@ -766,20 +767,30 @@ deleteContactRequest db User {userId} contactRequestId = do (userId, userId, contactRequestId, userId) DB.execute db "DELETE FROM contact_requests WHERE user_id = ? AND contact_request_id = ?" (userId, contactRequestId) -createAcceptedContact :: DB.Connection -> User -> ConnId -> ConnStatus -> VersionChat -> VersionRangeChat -> ContactName -> ProfileId -> Profile -> Int64 -> Maybe XContactId -> Maybe IncognitoProfile -> SubscriptionMode -> PQSupport -> Bool -> IO Contact -createAcceptedContact db user@User {userId, profile = LocalProfile {preferences}} agentConnId connStatus connChatVersion cReqChatVRange localDisplayName profileId profile userContactLinkId xContactId incognitoProfile subMode pqSup contactUsed = do - DB.execute db "DELETE FROM contact_requests WHERE user_id = ? AND local_display_name = ?" (userId, localDisplayName) +createContactRequestConn :: DB.Connection -> User -> ConnId -> VersionChat -> VersionRangeChat -> Int64 -> Maybe IncognitoProfile -> SubscriptionMode -> PQSupport -> IO Connection +createContactRequestConn db User {userId} connId connChatVersion cReqChatVRange userContactLinkId incognitoProfile subMode pqSup = do createdAt <- getCurrentTime customUserProfileId <- forM incognitoProfile $ \case NewIncognito p -> createIncognitoProfile_ db userId createdAt p ExistingIncognito LocalProfile {profileId = pId} -> pure pId + createConnection_ db userId ConnContact Nothing connId ConnNew connChatVersion cReqChatVRange Nothing (Just userContactLinkId) customUserProfileId 0 createdAt subMode pqSup + +createAcceptedContact :: DB.Connection -> User -> ConnStatus -> ContactName -> ProfileId -> Profile -> Maybe XContactId -> Connection -> Bool -> IO Contact +createAcceptedContact db user@User {userId, profile = LocalProfile {preferences}} connStatus localDisplayName profileId profile xContactId conn@Connection {connId, customUserProfileId} contactUsed = do + DB.execute db "DELETE FROM contact_requests WHERE user_id = ? AND local_display_name = ?" (userId, localDisplayName) + createdAt <- getCurrentTime + incognitoProfile <- forM customUserProfileId $ \cupId -> runExceptT $ getProfileById db userId cupId let userPreferences = fromMaybe emptyChatPrefs $ incognitoProfile >> preferences DB.execute db "INSERT INTO contacts (user_id, local_display_name, contact_profile_id, enable_ntfs, user_preferences, created_at, updated_at, chat_ts, xcontact_id, contact_used) VALUES (?,?,?,?,?,?,?,?,?,?)" (userId, localDisplayName, profileId, True, userPreferences, createdAt, createdAt, createdAt, xContactId, contactUsed) contactId <- insertedRowId db - conn <- createConnection_ db userId ConnContact (Just contactId) agentConnId connStatus connChatVersion cReqChatVRange Nothing (Just userContactLinkId) customUserProfileId 0 createdAt subMode pqSup + -- todo update conn: set contact id, update conn status, conn type + DB.execute + db + "UPDATE connections SET contact_id = ?, conn_status = ?, conn_type = ? WHERE connection_id = ?" + (contactId, connStatus, ConnContact, connId) let mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito conn pure $ Contact