diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index ed6874324b..286ae555c8 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -4209,10 +4209,10 @@ processChatCommand cxt nm = \case where knownLinkPlans = withFastStore $ \db -> liftIO (getUserContactLinkViaTarget db user nameOrLink') >>= \case - Just UserContactLink {connLinkContact = CCLink cReq _} -> pure $ Just (knownCon cReq, CPContactAddress CAPOwnLink) + Just UserContactLink {connLinkContact} -> pure $ Just (ACCL SCMContact connLinkContact, CPContactAddress CAPOwnLink) Nothing -> getContactToConnect db cxt user nameOrLink' >>= \case - Just (cReq, ct') -> pure $ if contactDeleted ct' then Nothing else Just (knownCon cReq, CPContactAddress (CAPKnown ct')) + Just (ccl, ct') -> pure $ if contactDeleted ct' then Nothing else Just (ACCL SCMContact ccl, CPContactAddress (CAPKnown ct')) Nothing -> (gPlan =<<) <$> getGroupToConnect db cxt user nameOrLink' CCTGroup -> groupShortLinkPlan CCTChannel -> groupShortLinkPlan @@ -4229,10 +4229,7 @@ processChatCommand cxt nm = \case CTLink sl -> pure sl CTName ni -> serverShortLink <$> resolveNameLink user ni con sl cReq = ACCL SCMContact $ CCLink cReq (Just sl) - knownCon cReq = ACCL SCMContact $ CCLink cReq $ case nameOrLink' of - CTLink sl -> Just sl - CTName _ -> Nothing - gPlan (cReq, g) = if memberRemoved (membership g) then Nothing else Just (knownCon cReq, CPGroupLink (GLPKnown g (BoolDef False) Nothing (ListDef []))) + gPlan (ccl, g) = if memberRemoved (membership g) then Nothing else Just (ACCL SCMContact ccl, CPGroupLink (GLPKnown g (BoolDef False) Nothing (ListDef []))) verified r = case nameOrLink of CTName ni -> verifyConnectedName user ni (fst r) (snd r) CTLink _ -> pure r @@ -4266,7 +4263,7 @@ processChatCommand cxt nm = \case _ -> False knownLinkPlans = withFastStore $ \db -> liftIO (getGroupInfoViaUserTarget db cxt user nameOrLink') >>= \case - Just (cReq, g) -> pure $ Just (knownCon cReq, CPGroupLink (GLPOwnLink g)) + Just (ccl, g) -> pure $ Just (ACCL SCMContact ccl, CPGroupLink (GLPOwnLink g)) Nothing -> (gPlan =<<) <$> getGroupToConnect db cxt user nameOrLink' resolveKnownGroup g = do sl <- resolveSLink diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index 72acb0da27..c8fc09c515 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -798,19 +798,18 @@ getContactByName db cxt user localDisplayName = do cId <- getContactIdByName db user localDisplayName getContact db cxt user cId --- a contact to connect to, found by the target: by its address short link, or by its verified name -getContactToConnect :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> ExceptT StoreError IO (Maybe (ConnReqContact, Contact)) +getContactToConnect :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> ExceptT StoreError IO (Maybe (CreatedLinkContact, Contact)) getContactToConnect db cxt user@User {userId} = \case - CTLink sl -> getContactViaShortLinkToConnect db cxt user sl + CTLink sl -> fmap (fmap (\(cReq, ct) -> (CCLink cReq (Just sl), ct))) (getContactViaShortLinkToConnect db cxt user sl) CTName ni -> liftIO (maybeFirstRow id $ DB.query db byNameQuery (userId, ni)) >>= \case - Just (ctId :: Int64, Just (ACR cMode cReq)) | Just Refl <- testEquality cMode SCMContact -> - Just . (cReq,) <$> getContact db cxt user ctId + Just (ctId :: Int64, Just (ACR cMode cReq), Just (sLnk :: ShortLinkContact)) | Just Refl <- testEquality cMode SCMContact -> + Just . (CCLink cReq (Just sLnk),) <$> getContact db cxt user ctId _ -> pure Nothing where byNameQuery = [sql| - SELECT ct.contact_id, ct.conn_full_link_to_connect FROM contacts ct + SELECT ct.contact_id, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect FROM contacts ct JOIN contact_profiles cp ON cp.contact_profile_id = ct.contact_profile_id WHERE ct.user_id = ? AND cp.contact_domain = ? AND cp.contact_domain_verification = 1 AND ct.deleted = 0 |] diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index aabf047e27..a8516e587a 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -1074,18 +1074,17 @@ getGroupInfoByName db cxt user gName = do gId <- getGroupIdByName db user gName getGroupInfo db cxt user gId --- a group to connect to, found by the target: by its address short link, or by its verified name -getGroupToConnect :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> ExceptT StoreError IO (Maybe (ConnReqContact, GroupInfo)) +getGroupToConnect :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> ExceptT StoreError IO (Maybe (CreatedLinkContact, GroupInfo)) getGroupToConnect db cxt user@User {userId} = \case - CTLink sl -> getGroupViaShortLinkToConnect db cxt user sl + CTLink sl -> fmap (fmap (\(cReq, g) -> (CCLink cReq (Just sl), g))) (getGroupViaShortLinkToConnect db cxt user sl) CTName ni -> liftIO (maybeFirstRow id $ DB.query db byNameQuery (userId, ni)) >>= \case - Just (gId :: Int64, Just cReq) -> Just . (cReq,) <$> getGroupInfo db cxt user gId + Just (gId :: Int64, Just cReq, Just (sLnk :: ShortLinkContact)) -> Just . (CCLink cReq (Just sLnk),) <$> getGroupInfo db cxt user gId _ -> pure Nothing where byNameQuery = [sql| - SELECT g.group_id, g.conn_full_link_to_connect FROM groups g + SELECT g.group_id, g.conn_full_link_to_connect, g.conn_short_link_to_connect FROM groups g JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id WHERE g.user_id = ? AND gp.group_domain = ? AND g.group_domain_verification = 1 |] @@ -2753,11 +2752,10 @@ getGroupInfoByUserContactLinkConnReq db cxt user@User {userId} (cReqSchema1, cRe (userId, cReqSchema1, cReqSchema2) maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getGroupInfo db cxt user) groupId_ --- own hosted group found by the target: by its address short link, or (for a name) by the group's registered name -getGroupInfoViaUserTarget :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> IO (Maybe (ConnReqContact, GroupInfo)) +getGroupInfoViaUserTarget :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> IO (Maybe (CreatedLinkContact, GroupInfo)) getGroupInfoViaUserTarget db cxt user@User {userId} target = fmap eitherToMaybe $ runExceptT $ do - (cReq, groupId) <- ExceptT getConnReqGroup - (cReq,) <$> getGroupInfo db cxt user groupId + (cReq, sLnk, groupId) <- ExceptT getConnReqGroup + (CCLink cReq (Just sLnk),) <$> getGroupInfo db cxt user groupId where getConnReqGroup = firstRow' toConnReqGroupId (SEInternalError "group link not found") $ case target of @@ -2765,7 +2763,7 @@ getGroupInfoViaUserTarget db cxt user@User {userId} target = fmap eitherToMaybe DB.query db [sql| - SELECT conn_req_contact, group_id + SELECT conn_req_contact, short_link_contact, group_id FROM user_contact_links WHERE user_id = ? AND short_link_contact = ? |] @@ -2774,7 +2772,7 @@ getGroupInfoViaUserTarget db cxt user@User {userId} target = fmap eitherToMaybe DB.query db [sql| - SELECT ucl.conn_req_contact, ucl.group_id + SELECT ucl.conn_req_contact, ucl.short_link_contact, ucl.group_id FROM user_contact_links ucl JOIN groups g ON g.group_id = ucl.group_id JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id @@ -2783,7 +2781,7 @@ getGroupInfoViaUserTarget db cxt user@User {userId} target = fmap eitherToMaybe (userId, ni) toConnReqGroupId = \case -- cReq is "not null", group_id is nullable - (cReq, Just groupId) -> Right (cReq, groupId) + (cReq, Just (sLnk :: ShortLinkContact), Just groupId) -> Right (cReq, sLnk, groupId) _ -> Left $ SEInternalError "no conn req or group ID" getGroupViaShortLinkToConnect :: DB.Connection -> StoreCxt -> User -> ShortLinkContact -> ExceptT StoreError IO (Maybe (ConnReqContact, GroupInfo)) diff --git a/src/Simplex/Chat/Store/Profiles.hs b/src/Simplex/Chat/Store/Profiles.hs index 6dee102ce9..63caa5ffcd 100644 --- a/src/Simplex/Chat/Store/Profiles.hs +++ b/src/Simplex/Chat/Store/Profiles.hs @@ -562,7 +562,6 @@ getUserContactLinkByConnReq db User {userId} (cReqSchema1, cReqSchema2) = maybeFirstRow toUserContactLink $ DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND conn_req_contact IN (?,?)") (userId, cReqSchema1, cReqSchema2) --- own contact address found by the target: by its short link, or (for a name) when it is this user's own registered address name getUserContactLinkViaTarget :: DB.Connection -> User -> ContactNameOrLink -> IO (Maybe UserContactLink) getUserContactLinkViaTarget db User {userId, profile = LocalProfile {contactDomain}} = \case CTLink shortLink -> @@ -571,7 +570,7 @@ getUserContactLinkViaTarget db User {userId, profile = LocalProfile {contactDoma CTName ni | contactDomain == Just ni -> maybeFirstRow toUserContactLink $ - DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND group_id IS NULL") (Only userId) + DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND group_id IS NULL AND short_link_contact IS NOT NULL") (Only userId) | otherwise -> pure Nothing userContactLinkQuery :: Query diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index ac49ffb7a4..e8cba67d40 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -1787,14 +1787,11 @@ type ConnReqInvitation = ConnectionRequestUri 'CMInvitation type ConnReqContact = ConnectionRequestUri 'CMContact --- what the user is connecting to: a contact/group by full address link, by short address link or registered name, or a one-time invitation link --- CTFullContact is its own case because full address links are legacy; keeping them separate makes dropping them later a localized change (remove the constructor, its connectPlan branch, and the parser alternative) data ConnectTarget (m :: ConnectionMode) where CTFullContact :: ConnectionRequestUri 'CMContact -> ConnectTarget 'CMContact CTShortContact :: ContactNameOrLink -> ConnectTarget 'CMContact CTInv :: ConnectionLink 'CMInvitation -> ConnectTarget 'CMInvitation --- a short contact address link or a registered name; resolving a name produces a short link, i.e. turns CTName into CTLink data ContactNameOrLink = CTName SimplexNameInfo | CTLink (ConnShortLink 'CMContact) deriving (Eq, Show)