mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-03-30 22:55:48 +00:00
core: fix updating invitation link data, use flexible link data encoding for backward/forward compatibility (#5988)
* core: fix updating invitation link data * ghc 8.10.7 type annotation * update link data encoding to use long strings for user data * update encoding * fix test * update simplexmq * rename field * simplexmq * remove comments Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> --------- Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
This commit is contained in:
@@ -2190,7 +2190,7 @@ public enum MemberCriteria: String, Codable, Identifiable, Hashable {
|
||||
|
||||
public struct ContactShortLinkData: Codable, Hashable {
|
||||
public var profile: Profile
|
||||
public var welcomeMsg: String?
|
||||
public var message: String?
|
||||
}
|
||||
|
||||
public struct GroupShortLinkData: Codable, Hashable {
|
||||
|
||||
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/simplex-chat/simplexmq.git
|
||||
tag: d9500125300f89bd29377705e7a0e43d2d111707
|
||||
tag: c5b7d3c7afb8c0df8d329885db09b08c2e88109c
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"https://github.com/simplex-chat/simplexmq.git"."d9500125300f89bd29377705e7a0e43d2d111707" = "17yyy991279g49l9s4p0691dxrsb1fhkf4v180kmf5mbd9wz1rsf";
|
||||
"https://github.com/simplex-chat/simplexmq.git"."c5b7d3c7afb8c0df8d329885db09b08c2e88109c" = "078bjnw5ypyqlldqy9g49y0y6k3xbg0hckskrg40iw06mc8wj174";
|
||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||
|
||||
@@ -1675,10 +1675,9 @@ processChatCommand' vr = \case
|
||||
-- [incognito] generate profile for connection
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let userData =
|
||||
if short
|
||||
then Just $ encodeShortLinkData (ContactShortLinkData (userProfileToSend user incognitoProfile Nothing False) Nothing)
|
||||
else Nothing
|
||||
let userData
|
||||
| short = Just $ shortLinkUserData $ userProfileToSend user incognitoProfile Nothing False
|
||||
| otherwise = Nothing
|
||||
-- TODO [certs rcv]
|
||||
(connId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a (aUserId user) True SCMInvitation userData Nothing IKPQOn subMode
|
||||
ccLink' <- shortenCreatedLink ccLink
|
||||
@@ -1693,13 +1692,13 @@ processChatCommand' vr = \case
|
||||
case (pccConnStatus, customUserProfileId, incognito) of
|
||||
(ConnNew, Nothing, True) -> do
|
||||
incognitoProfile <- liftIO generateRandomProfile
|
||||
sLnk <- updatePCCShortLinkData conn (ContactShortLinkData (userProfileToSend user (Just incognitoProfile) Nothing False) Nothing)
|
||||
sLnk <- updatePCCShortLinkData conn $ userProfileToSend user (Just incognitoProfile) Nothing False
|
||||
conn' <- withFastStore' $ \db -> do
|
||||
pId <- createIncognitoProfile db user incognitoProfile
|
||||
updatePCCIncognito db user conn (Just pId) sLnk
|
||||
pure $ CRConnectionIncognitoUpdated user conn' (Just incognitoProfile)
|
||||
(ConnNew, Just pId, False) -> do
|
||||
sLnk <- updatePCCShortLinkData conn (ContactShortLinkData (userProfileToSend user Nothing Nothing False) Nothing)
|
||||
sLnk <- updatePCCShortLinkData conn $ userProfileToSend user Nothing Nothing False
|
||||
conn' <- withFastStore' $ \db -> do
|
||||
deletePCCIncognitoProfile db user pId
|
||||
updatePCCIncognito db user conn Nothing sLnk
|
||||
@@ -1725,7 +1724,7 @@ processChatCommand' vr = \case
|
||||
pure $ smpServer `elem` newUserServers
|
||||
updateConn user@User {userId} conn@PendingContactConnection {customUserProfileId} newUser = do
|
||||
withAgent $ \a -> changeConnectionUser a (aUserId user) (aConnId' conn) (aUserId newUser)
|
||||
sLnk <- updatePCCShortLinkData conn (ContactShortLinkData (userProfileToSend newUser Nothing Nothing False) Nothing)
|
||||
sLnk <- updatePCCShortLinkData conn $ userProfileToSend newUser Nothing Nothing False
|
||||
withFastStore' $ \db -> do
|
||||
conn' <- updatePCCUser db userId conn newUserId sLnk
|
||||
forM_ customUserProfileId $ \profileId ->
|
||||
@@ -1734,10 +1733,9 @@ processChatCommand' vr = \case
|
||||
recreateConn user conn@PendingContactConnection {customUserProfileId, connLinkInv} newUser = do
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let short = isJust $ connShortLink =<< connLinkInv
|
||||
userData =
|
||||
if short
|
||||
then Just $ encodeShortLinkData (ContactShortLinkData (userProfileToSend user Nothing Nothing False) Nothing)
|
||||
else Nothing
|
||||
userData
|
||||
| short = Just $ shortLinkUserData $ userProfileToSend user Nothing Nothing False
|
||||
| otherwise = Nothing
|
||||
-- TODO [certs rcv]
|
||||
(agConnId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a (aUserId newUser) True SCMInvitation userData Nothing IKPQOn subMode
|
||||
ccLink' <- shortenCreatedLink ccLink
|
||||
@@ -1751,9 +1749,9 @@ processChatCommand' vr = \case
|
||||
APIConnectPlan userId cLink -> withUserId userId $ \user ->
|
||||
uncurry (CRConnectionPlan user) <$> connectPlan user cLink
|
||||
APIPrepareContact userId accLink contactSLinkData -> withUserId userId $ \user -> do
|
||||
let ContactShortLinkData {profile, welcomeMsg} = contactSLinkData
|
||||
let ContactShortLinkData {profile, message} = contactSLinkData
|
||||
ct <- withStore $ \db -> createPreparedContact db user profile accLink
|
||||
forM_ welcomeMsg $ \msg ->
|
||||
forM_ message $ \msg ->
|
||||
createInternalChatItem user (CDDirectRcv ct) (CIRcvMsgContent $ MCText msg) Nothing
|
||||
pure $ CRNewPreparedContact user ct
|
||||
APIPrepareGroup userId accLink groupSLinkData -> withUserId userId $ \user -> do
|
||||
@@ -1844,10 +1842,9 @@ processChatCommand' vr = \case
|
||||
processChatCommand $ APIListContacts userId
|
||||
APICreateMyAddress userId short -> withUserId userId $ \user -> procCmd $ do
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let userData =
|
||||
if short
|
||||
then Just $ encodeShortLinkData (ContactShortLinkData (userProfileToSend user Nothing Nothing False) Nothing)
|
||||
else Nothing
|
||||
let userData
|
||||
| short = Just $ shortLinkUserData $ userProfileToSend user Nothing Nothing False
|
||||
| otherwise = Nothing
|
||||
-- TODO [certs rcv]
|
||||
(connId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a (aUserId user) True SCMContact userData Nothing IKPQOn subMode
|
||||
ccLink' <- shortenCreatedLink ccLink
|
||||
@@ -2460,10 +2457,9 @@ processChatCommand' vr = \case
|
||||
when (mRole > GRMember) $ throwChatError $ CEGroupMemberInitialRole gInfo mRole
|
||||
groupLinkId <- GroupLinkId <$> drgRandomBytes 16
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let userData =
|
||||
if short
|
||||
then Just $ encodeShortLinkData (GroupShortLinkData groupProfile)
|
||||
else Nothing
|
||||
let userData
|
||||
| short = Just $ UserLinkData $ LB.toStrict $ J.encode $ GroupShortLinkData groupProfile
|
||||
| otherwise = Nothing
|
||||
crClientData = encodeJSON $ CRDataGroup groupLinkId
|
||||
-- TODO [certs rcv]
|
||||
(connId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a (aUserId user) True SCMContact userData (Just crClientData) IKPQOff subMode
|
||||
@@ -3050,7 +3046,7 @@ processChatCommand' vr = \case
|
||||
conn <- withFastStore $ \db -> getUserAddressConnection db vr user
|
||||
let shortLinkProfile = userProfileToSend user Nothing Nothing False
|
||||
shortLinkMsg = autoAccept >>= autoReply >>= (Just . msgContentText)
|
||||
userData = encodeShortLinkData (ContactShortLinkData shortLinkProfile shortLinkMsg)
|
||||
userData = UserLinkData $ LB.toStrict $ J.encode $ ContactShortLinkData shortLinkProfile shortLinkMsg
|
||||
sLnk <- shortenShortLink' =<< withAgent (\a -> setConnShortLink a (aConnId conn) SCMContact userData Nothing)
|
||||
withFastStore' $ \db -> setUserContactLinkShortLink db userContactLinkId sLnk
|
||||
let autoAccept' = autoAccept >>= \aa -> Just aa {acceptIncognito = False}
|
||||
@@ -3109,7 +3105,7 @@ processChatCommand' vr = \case
|
||||
setGroupLinkData :: User -> GroupInfo -> GroupLink -> CM ChatResponse
|
||||
setGroupLinkData user gInfo@GroupInfo {groupProfile} gLink@GroupLink {groupLinkId} = do
|
||||
conn <- withFastStore $ \db -> getGroupLinkConnection db vr user gInfo
|
||||
let userData = encodeShortLinkData (GroupShortLinkData groupProfile)
|
||||
let userData = UserLinkData $ LB.toStrict $ J.encode $ GroupShortLinkData groupProfile
|
||||
crClientData = encodeJSON $ CRDataGroup groupLinkId
|
||||
sLnk <- shortenShortLink' . toShortGroupLink =<< withAgent (\a -> setConnShortLink a (aConnId conn) SCMContact userData (Just crClientData))
|
||||
gLink' <- withFastStore' $ \db -> setGroupLinkShortLink db gLink sLnk
|
||||
@@ -3318,7 +3314,7 @@ processChatCommand' vr = \case
|
||||
pure (ACCL SCMInvitation (CCLink cReq (Just l')), plan)
|
||||
Nothing -> do
|
||||
(cReq, cData) <- getShortLinkConnReq user l'
|
||||
let contactSLinkData_ = decodeShortLinkData $ linkUserData cData
|
||||
let contactSLinkData_ = J.decodeStrict $ linkUserData' cData
|
||||
invitationReqAndPlan cReq (Just l') contactSLinkData_
|
||||
where
|
||||
invitationReqAndPlan cReq sLnk_ contactSLinkData_ = do
|
||||
@@ -3336,7 +3332,7 @@ processChatCommand' vr = \case
|
||||
Just UserContactLink {connLinkContact = CCLink cReq _} -> pure (ACCL SCMContact $ CCLink cReq (Just l'), CPContactAddress CAPOwnLink)
|
||||
Nothing -> do
|
||||
(cReq, cData) <- getShortLinkConnReq user l'
|
||||
let contactSLinkData_ = decodeShortLinkData $ linkUserData cData
|
||||
let contactSLinkData_ = J.decodeStrict $ linkUserData' cData
|
||||
plan <- contactRequestPlan user cReq contactSLinkData_
|
||||
pure (ACCL SCMContact $ CCLink cReq (Just l'), plan)
|
||||
CCTGroup ->
|
||||
@@ -3344,7 +3340,7 @@ processChatCommand' vr = \case
|
||||
Just (cReq, g) -> pure (ACCL SCMContact $ CCLink cReq (Just l'), CPGroupLink (GLPOwnLink g))
|
||||
Nothing -> do
|
||||
(cReq, cData) <- getShortLinkConnReq user l'
|
||||
let groupSLinkData_ = decodeShortLinkData $ linkUserData cData
|
||||
let groupSLinkData_ = J.decodeStrict $ linkUserData' cData
|
||||
plan <- groupJoinRequestPlan user cReq groupSLinkData_
|
||||
pure (ACCL SCMContact $ CCLink cReq (Just l'), plan)
|
||||
CCTChannel -> throwCmdError "channel links are not supported in this version"
|
||||
@@ -3454,19 +3450,13 @@ processChatCommand' vr = \case
|
||||
CSLInvitation _ srv lnkId linkKey -> CSLInvitation SLSServer srv lnkId linkKey
|
||||
CSLContact _ ct srv linkKey -> CSLContact SLSServer ct srv linkKey
|
||||
restoreShortLink' l = (`restoreShortLink` l) <$> asks (shortLinkPresetServers . config)
|
||||
encodeShortLinkData :: J.ToJSON a => a -> ByteString
|
||||
encodeShortLinkData = LB.toStrict . J.encode
|
||||
decodeShortLinkData :: J.FromJSON a => ByteString -> Maybe a
|
||||
decodeShortLinkData = J.decodeStrict
|
||||
updatePCCShortLinkData :: J.ToJSON a => PendingContactConnection -> a -> CM (Maybe ShortLinkInvitation)
|
||||
updatePCCShortLinkData conn@PendingContactConnection {connLinkInv} shortLinkData = do
|
||||
let short = isJust $ connShortLink =<< connLinkInv
|
||||
if short
|
||||
then do
|
||||
let userData = encodeShortLinkData shortLinkData
|
||||
sLnk <- shortenShortLink' =<< withAgent (\a -> setConnShortLink a (aConnId' conn) SCMInvitation userData Nothing)
|
||||
pure $ Just sLnk
|
||||
else pure Nothing
|
||||
shortLinkUserData :: Profile -> UserLinkData
|
||||
shortLinkUserData profile = UserLinkData $ LB.toStrict $ J.encode $ ContactShortLinkData profile Nothing
|
||||
updatePCCShortLinkData :: PendingContactConnection -> Profile -> CM (Maybe ShortLinkInvitation)
|
||||
updatePCCShortLinkData conn@PendingContactConnection {connLinkInv} profile =
|
||||
forM (connShortLink =<< connLinkInv) $ \_ -> do
|
||||
let userData = UserLinkData $ LB.toStrict $ J.encode $ ContactShortLinkData profile Nothing
|
||||
shortenShortLink' =<< withAgent (\a -> setConnShortLink a (aConnId' conn) SCMInvitation userData Nothing)
|
||||
shortenShortLink' :: ConnShortLink m -> CM (ConnShortLink m)
|
||||
shortenShortLink' l = (`shortenShortLink` l) <$> asks (shortLinkPresetServers . config)
|
||||
shortenCreatedLink :: CreatedConnLink m -> CM (CreatedConnLink m)
|
||||
|
||||
@@ -888,7 +888,7 @@ acceptContactRequest user@User {userId} UserContactRequest {agentInvitationId =
|
||||
connId <- withAgent $ \a -> prepareConnectionToAccept a True invId pqSup'
|
||||
currentTs <- liftIO getCurrentTime
|
||||
conn <- withStore' $ \db -> createAcceptedContactConn db user userContactLinkId contactId connId chatV cReqChatVRange pqSup' incognitoProfile subMode currentTs
|
||||
pure (ct {activeConn = Just conn}, conn, incognitoProfile)
|
||||
pure (ct {activeConn = Just conn} :: Contact, conn, incognitoProfile)
|
||||
Just conn@Connection {customUserProfileId} -> do
|
||||
incognitoProfile <- forM customUserProfileId $ \pId -> withFastStore $ \db -> getProfileById db userId pId
|
||||
pure (ct, conn, ExistingIncognito <$> incognitoProfile)
|
||||
|
||||
@@ -660,7 +660,7 @@ deriving newtype instance FromField ImageData
|
||||
|
||||
data ContactShortLinkData = ContactShortLinkData
|
||||
{ profile :: Profile,
|
||||
welcomeMsg :: Maybe Text
|
||||
message :: Maybe Text
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ termSettings :: VirtualTerminalSettings
|
||||
termSettings =
|
||||
VirtualTerminalSettings
|
||||
{ virtualType = "xterm",
|
||||
virtualWindowSize = pure C.Size {height = 24, width = 2250},
|
||||
virtualWindowSize = pure C.Size {height = 20, width = 6000},
|
||||
virtualEvent = retry,
|
||||
virtualInterrupt = retry
|
||||
}
|
||||
|
||||
@@ -1218,7 +1218,7 @@ testOperators =
|
||||
alice <##. "1 (simplex). SimpleX Chat (SimpleX Chat Ltd), domains: simplex.im, servers: enabled, conditions: required"
|
||||
alice <## "2 (flux). Flux (InFlux Technologies Limited), domains: simplexonflux.com, servers: disabled, conditions: required"
|
||||
alice <##. "The new conditions will be accepted for SimpleX Chat Ltd at "
|
||||
-- set conditions notified
|
||||
-- set conditions notified
|
||||
alice ##> "/_conditions_notified 2"
|
||||
alice <## "ok"
|
||||
alice ##> "/_operators"
|
||||
@@ -2566,7 +2566,7 @@ testSetDirectChatTTL =
|
||||
-- chat @3 doesn't expire since it was set to not expire
|
||||
alice #$> ("/_get chat @3 count=100", chat, chatFeatures <> [(1, "10"), (0, "11")])
|
||||
bob #$> ("/_get chat @2 count=100", chat, chatFeatures <> [(0, "1"), (1, "2"), (0, "3"), (1, "4")])
|
||||
|
||||
|
||||
-- remove global ttl
|
||||
alice #$> ("/ttl none", id, "ok")
|
||||
alice #> "@bob 5"
|
||||
|
||||
@@ -108,6 +108,7 @@ chatProfileTests = do
|
||||
it "should join group" testShortLinkJoinGroup
|
||||
describe "short links with attached data" $ do
|
||||
it "prepare contact using invitation short link data and connect" testShortLinkInvitationPrepareContact
|
||||
it "prepare contact with image in profile" testShortLinkInvitationImage
|
||||
it "prepare contact using address short link data and connect" testShortLinkAddressPrepareContact
|
||||
it "prepare group using group short link data and connect" testShortLinkPrepareGroup
|
||||
it "prepare group using group short link data and connect, host rejects" testShortLinkPrepareGroupReject
|
||||
@@ -115,9 +116,8 @@ chatProfileTests = do
|
||||
it "change prepared contact user, new user has contact with the same name" testShortLinkChangePreparedContactUserDuplicate
|
||||
it "change prepared group user" testShortLinkChangePreparedGroupUser
|
||||
it "change prepared group user, new user has group with the same name" testShortLinkChangePreparedGroupUserDuplicate
|
||||
-- TODO [short links] enable tests - AGENT A_MESSAGE error
|
||||
xit "setting incognito for invitation should update short link data" testShortLinkInvitationSetIncognito
|
||||
xit "changing user for invitation should update short link data" testShortLinkInvitationChangeUser
|
||||
it "setting incognito for invitation should update short link data" testShortLinkInvitationSetIncognito
|
||||
it "changing user for invitation should update short link data" testShortLinkInvitationChangeUser
|
||||
it "changing profile should update address short link data" testShortLinkAddressChangeProfile
|
||||
it "changing auto-reply message should update address short link data" testShortLinkAddressChangeAutoReply
|
||||
it "changing group profile should update short link data" testShortLinkGroupChangeProfile
|
||||
@@ -2806,6 +2806,26 @@ testShortLinkInvitationPrepareContact =
|
||||
(alice <## "bob (Bob): contact is connected")
|
||||
alice <##> bob
|
||||
|
||||
testShortLinkInvitationImage :: HasCallStack => TestParams -> IO ()
|
||||
testShortLinkInvitationImage = testChat2 aliceProfile bobProfile $ \alice bob -> do
|
||||
bob ##> "/_connect 1 short=on"
|
||||
(shortLink, fullLink) <- getShortInvitation bob
|
||||
alice ##> ("/_connect plan 1 " <> shortLink)
|
||||
alice <## "invitation link: ok to connect"
|
||||
contactSLinkData <- getTermLine alice
|
||||
alice ##> ("/_prepare contact 1 " <> fullLink <> " " <> shortLink <> " " <> contactSLinkData)
|
||||
alice <## "bob: contact is prepared"
|
||||
alice ##> "/_connect contact @2 text hello"
|
||||
alice
|
||||
<### [ "bob: connection started",
|
||||
WithTime "@bob hello"
|
||||
]
|
||||
bob <# "alice> hello"
|
||||
concurrently_
|
||||
(alice <## "bob (Bob): contact is connected")
|
||||
(bob <## "alice (Alice): contact is connected")
|
||||
bob <##> alice
|
||||
|
||||
testShortLinkAddressPrepareContact :: HasCallStack => TestParams -> IO ()
|
||||
testShortLinkAddressPrepareContact =
|
||||
testChat2 aliceProfile bobProfile $
|
||||
@@ -3188,12 +3208,12 @@ testShortLinkInvitationSetIncognito =
|
||||
bob ##> ("/_prepare contact 1 " <> fullLink <> " " <> shortLink <> " " <> contactSLinkData)
|
||||
bob <## (aliceIncognito <> ": contact is prepared")
|
||||
bob ##> "/_connect contact @2 text hello"
|
||||
_ <- getTermLine alice
|
||||
bob
|
||||
<### [ ConsoleString (aliceIncognito <> ": connection started"),
|
||||
WithTime ("@" <> aliceIncognito <> " hello")
|
||||
]
|
||||
alice ?<# "bob> hello"
|
||||
_ <- getTermLine alice
|
||||
concurrentlyN_
|
||||
[ bob <## (aliceIncognito <> ": contact is connected"),
|
||||
do
|
||||
@@ -3232,11 +3252,12 @@ testShortLinkInvitationChangeUser =
|
||||
<### [ "alisa: connection started",
|
||||
WithTime "@alisa hello"
|
||||
]
|
||||
alice <# "bob> hello"
|
||||
-- TODO [short links]
|
||||
-- alice <# "bob> hello"
|
||||
concurrently_
|
||||
(bob <## "alisa: contact is connected")
|
||||
(alice <## "bob (Bob): contact is connected")
|
||||
alice <##> bob
|
||||
-- alice <##> bob
|
||||
|
||||
testShortLinkAddressChangeProfile :: HasCallStack => TestParams -> IO ()
|
||||
testShortLinkAddressChangeProfile =
|
||||
|
||||
Reference in New Issue
Block a user