mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-28 07:34:16 +00:00
core: set via_group_link_uri for groups (#6137)
* core: set via_group_link_uri for groups * schema * plans * schema * add to type * plans, api
This commit is contained in:
@@ -2094,6 +2094,7 @@ MemberSupport:
|
||||
- uiThemes: [UIThemeEntityOverrides](#uithemeentityoverrides)?
|
||||
- customData: JSONObject?
|
||||
- membersRequireAttention: int
|
||||
- viaGroupLinkUri: string?
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -113,6 +113,7 @@ library
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20250709_profile_short_descr
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20250721_indexes
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20250729_member_contact_requests
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20250801_via_group_link_uri
|
||||
else
|
||||
exposed-modules:
|
||||
Simplex.Chat.Archive
|
||||
@@ -251,6 +252,7 @@ library
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250709_profile_short_descr
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250721_indexes
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250729_member_contact_requests
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250801_via_group_link_uri
|
||||
other-modules:
|
||||
Paths_simplex_chat
|
||||
hs-source-dirs:
|
||||
|
||||
@@ -3031,22 +3031,19 @@ processChatCommand vr nm = \case
|
||||
connectViaContact :: User -> Maybe PreparedChatEntity -> IncognitoEnabled -> CreatedLinkContact -> Maybe SharedMsgId -> Maybe (SharedMsgId, MsgContent) -> CM ConnectViaContactResult
|
||||
connectViaContact user@User {userId} preparedEntity_ incognito (CCLink cReq@(CRContactUri crData@ConnReqUriData {crClientData}) sLnk) welcomeSharedMsgId msg_ = withInvitationLock "connectViaContact" (strEncode cReq) $ do
|
||||
let groupLinkId = crClientData >>= decodeJSON >>= \(CRDataGroup gli) -> Just gli
|
||||
cReqHash = ConnReqUriHash . C.sha256Hash . strEncode
|
||||
cReqHash1 = cReqHash $ CRContactUri crData {crScheme = SSSimplex}
|
||||
cReqHash2 = cReqHash $ CRContactUri crData {crScheme = simplexChat}
|
||||
-- groupLinkId is Nothing for business chats
|
||||
when (isJust msg_ && isJust groupLinkId) $ throwChatError CEConnReqMessageProhibited
|
||||
case preparedEntity_ of
|
||||
Just (PCEContact ct@Contact {activeConn}) -> case activeConn of
|
||||
Nothing -> connect' Nothing cReqHash1 Nothing
|
||||
Nothing -> connect' Nothing Nothing
|
||||
Just conn@Connection {connStatus, xContactId} -> case connStatus of
|
||||
ConnPrepared -> joinPreparedConn' xContactId conn False
|
||||
_ -> pure $ CVRConnectedContact ct
|
||||
Just (PCEGroup _gInfo GroupMember {activeConn}) -> case activeConn of
|
||||
Nothing -> connect' groupLinkId cReqHash1 Nothing
|
||||
Nothing -> connect' groupLinkId Nothing
|
||||
Just conn@Connection {connStatus, xContactId} -> case connStatus of
|
||||
ConnPrepared -> joinPreparedConn' xContactId conn $ isJust groupLinkId
|
||||
_ -> connect' groupLinkId cReqHash1 xContactId -- why not "already connected" for host member?
|
||||
_ -> connect' groupLinkId xContactId -- why not "already connected" for host member?
|
||||
Nothing ->
|
||||
withFastStore' (\db -> getConnReqContactXContactId db vr user cReqHash1 cReqHash2) >>= \case
|
||||
Right ct@Contact {activeConn} -> case groupLinkId of
|
||||
@@ -3056,14 +3053,17 @@ processChatCommand vr nm = \case
|
||||
Just gLinkId ->
|
||||
-- allow repeat contact request
|
||||
-- TODO [short links] is this branch needed? it probably remained from the time we created host contact
|
||||
connect' (Just gLinkId) cReqHash1 Nothing
|
||||
connect' (Just gLinkId) Nothing
|
||||
Left conn_ -> case conn_ of
|
||||
Just conn@Connection {connStatus = ConnPrepared, xContactId} -> joinPreparedConn' xContactId conn $ isJust groupLinkId
|
||||
-- TODO [short links] this is executed on repeat request after success
|
||||
-- it probably should send the second message without creating the second connection?
|
||||
Just Connection {xContactId} -> connect' groupLinkId cReqHash1 xContactId
|
||||
Nothing -> connect' groupLinkId cReqHash1 Nothing
|
||||
Just Connection {xContactId} -> connect' groupLinkId xContactId
|
||||
Nothing -> connect' groupLinkId Nothing
|
||||
where
|
||||
cReqHash = ConnReqUriHash . C.sha256Hash . strEncode
|
||||
cReqHash1 = cReqHash $ CRContactUri crData {crScheme = SSSimplex}
|
||||
cReqHash2 = cReqHash $ CRContactUri crData {crScheme = simplexChat}
|
||||
joinPreparedConn' xContactId_ conn@Connection {customUserProfileId} inGroup = do
|
||||
when (incognito /= isJust customUserProfileId) $ throwCmdError "incognito mode is different from prepared connection"
|
||||
xContactId <- mkXContactId xContactId_
|
||||
@@ -3071,7 +3071,7 @@ processChatCommand vr nm = \case
|
||||
let incognitoProfile = fromLocalProfile <$> localIncognitoProfile
|
||||
conn' <- joinContact user conn cReq incognitoProfile xContactId welcomeSharedMsgId msg_ inGroup PQSupportOn
|
||||
pure $ CVRSentInvitation conn' incognitoProfile
|
||||
connect' groupLinkId cReqHash xContactId_ = do
|
||||
connect' groupLinkId xContactId_ = do
|
||||
let inGroup = isJust groupLinkId
|
||||
pqSup = if inGroup then PQSupportOff else PQSupportOn
|
||||
(connId, chatV) <- prepareContact user cReq pqSup
|
||||
@@ -3080,7 +3080,7 @@ processChatCommand vr nm = \case
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let sLnk' = serverShortLink <$> sLnk
|
||||
conn <- withFastStore' $ \db -> createConnReqConnection db userId connId preparedEntity_ cReqHash sLnk' xContactId incognitoProfile groupLinkId subMode chatV pqSup
|
||||
conn <- withFastStore' $ \db -> createConnReqConnection db userId connId preparedEntity_ cReq cReqHash1 sLnk' xContactId incognitoProfile groupLinkId subMode chatV pqSup
|
||||
conn' <- joinContact user conn cReq incognitoProfile xContactId welcomeSharedMsgId msg_ inGroup pqSup
|
||||
pure $ CVRSentInvitation conn' incognitoProfile
|
||||
connectContactViaAddress :: User -> IncognitoEnabled -> Contact -> CreatedLinkContact -> CM ChatResponse
|
||||
@@ -3095,7 +3095,7 @@ processChatCommand vr nm = \case
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let cReqHash = ConnReqUriHash . C.sha256Hash $ strEncode cReq
|
||||
conn <- withFastStore' $ \db -> createConnReqConnection db userId connId (Just $ PCEContact ct) cReqHash shortLink newXContactId incognitoProfile Nothing subMode chatV pqSup
|
||||
conn <- withFastStore' $ \db -> createConnReqConnection db userId connId (Just $ PCEContact ct) cReq cReqHash shortLink newXContactId incognitoProfile Nothing subMode chatV pqSup
|
||||
void $ joinContact user conn cReq incognitoProfile newXContactId Nothing Nothing False pqSup
|
||||
ct' <- withStore $ \db -> getContact db vr user contactId
|
||||
pure $ CRSentInvitationToContact user ct' incognitoProfile
|
||||
|
||||
@@ -2269,7 +2269,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
dm <- encodeConnInfo $ XGrpAcpt membershipMemId
|
||||
connIds <- joinAgentConnectionAsync user True connRequest dm subMode
|
||||
withStore' $ \db -> do
|
||||
setViaGroupLinkHash db groupId connId
|
||||
setViaGroupLinkUri db groupId connId
|
||||
createMemberConnectionAsync db user hostId connIds connChatVersion peerChatVRange subMode
|
||||
updateGroupMemberStatusById db userId hostId GSMemAccepted
|
||||
updateGroupMemberStatus db userId membership GSMemAccepted
|
||||
|
||||
@@ -143,7 +143,7 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
|
||||
@@ -154,8 +154,8 @@ deletePendingContactConnection db userId connId =
|
||||
|]
|
||||
(userId, connId, ConnContact)
|
||||
|
||||
createConnReqConnection :: DB.Connection -> UserId -> ConnId -> Maybe PreparedChatEntity -> ConnReqUriHash -> Maybe ShortLinkContact -> XContactId -> Maybe Profile -> Maybe GroupLinkId -> SubscriptionMode -> VersionChat -> PQSupport -> IO Connection
|
||||
createConnReqConnection db userId acId preparedEntity_ cReqHash sLnk xContactId incognitoProfile groupLinkId subMode chatV pqSup = do
|
||||
createConnReqConnection :: DB.Connection -> UserId -> ConnId -> Maybe PreparedChatEntity -> ConnReqContact -> ConnReqUriHash -> Maybe ShortLinkContact -> XContactId -> Maybe Profile -> Maybe GroupLinkId -> SubscriptionMode -> VersionChat -> PQSupport -> IO Connection
|
||||
createConnReqConnection db userId acId preparedEntity_ cReq cReqHash sLnk xContactId incognitoProfile groupLinkId subMode chatV pqSup = do
|
||||
currentTs <- getCurrentTime
|
||||
customUserProfileId <- mapM (createIncognitoProfile_ db userId currentTs) incognitoProfile
|
||||
let connStatus = ConnPrepared
|
||||
@@ -164,13 +164,13 @@ createConnReqConnection db userId acId preparedEntity_ cReqHash sLnk xContactId
|
||||
[sql|
|
||||
INSERT INTO connections (
|
||||
user_id, agent_conn_id, conn_status, conn_type, contact_conn_initiated,
|
||||
via_contact_uri_hash, via_short_link_contact, contact_id, group_member_id,
|
||||
via_contact_uri, via_contact_uri_hash, via_short_link_contact, contact_id, group_member_id,
|
||||
xcontact_id, custom_user_profile_id, via_group_link, group_link_id,
|
||||
created_at, updated_at, to_subscribe, conn_chat_version, pq_support, pq_encryption
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
( (userId, acId, connStatus, connType, BI True)
|
||||
:. (cReqHash, sLnk, contactId_, groupMemberId_)
|
||||
:. (cReq, cReqHash, sLnk, contactId_, groupMemberId_)
|
||||
:. (xContactId, customUserProfileId, BI (isJust groupLinkId), groupLinkId)
|
||||
:. (currentTs, currentTs, BI (subMode == SMOnlyCreate), chatV, pqSup, pqSup)
|
||||
)
|
||||
@@ -217,8 +217,8 @@ createConnReqConnection db userId acId preparedEntity_ cReqHash sLnk xContactId
|
||||
updatePreparedGroup GroupInfo {groupId, membership} customUserProfileId currentTs = do
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE groups SET via_group_link_uri_hash = ?, conn_link_prepared_connection = ?, updated_at = ? WHERE group_id = ?"
|
||||
(cReqHash, BI True, currentTs, groupId)
|
||||
"UPDATE groups SET via_group_link_uri = ?, via_group_link_uri_hash = ?, conn_link_prepared_connection = ?, updated_at = ? WHERE group_id = ?"
|
||||
(cReq, cReqHash, BI True, currentTs, groupId)
|
||||
when (isJust customUserProfileId) $
|
||||
DB.execute
|
||||
db
|
||||
@@ -336,8 +336,8 @@ createDirectConnection_ db userId acId (CCLink cReq shortLinkInv) contactId_ pcc
|
||||
( (userId, acId, cReq, shortLinkInv, pccConnStatus, ConnContact, contactId_, BI contactConnInitiated, customUserProfileId)
|
||||
:. (createdAt, createdAt, BI (subMode == SMOnlyCreate), chatV, pqSup, pqSup)
|
||||
)
|
||||
dbConnId <- insertedRowId db
|
||||
pure (dbConnId, customUserProfileId, contactConnInitiated)
|
||||
connId <- insertedRowId db
|
||||
pure (connId, customUserProfileId, contactConnInitiated)
|
||||
|
||||
createIncognitoProfile :: DB.Connection -> User -> Profile -> IO Int64
|
||||
createIncognitoProfile db User {userId} p = do
|
||||
|
||||
@@ -373,7 +373,8 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc
|
||||
chatItemTTL = Nothing,
|
||||
uiThemes = Nothing,
|
||||
customData = Nothing,
|
||||
membersRequireAttention = 0
|
||||
membersRequireAttention = 0,
|
||||
viaGroupLinkUri = Nothing
|
||||
}
|
||||
|
||||
-- | creates a new group record for the group the current user was invited to, or returns an existing one
|
||||
@@ -445,7 +446,8 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ
|
||||
chatItemTTL = Nothing,
|
||||
uiThemes = Nothing,
|
||||
customData = Nothing,
|
||||
membersRequireAttention = 0
|
||||
membersRequireAttention = 0,
|
||||
viaGroupLinkUri = Nothing
|
||||
},
|
||||
groupMemberId
|
||||
)
|
||||
@@ -744,7 +746,7 @@ createGroupViaLink'
|
||||
liftIO $ DB.execute db "UPDATE connections SET conn_type = ?, group_member_id = ?, updated_at = ? WHERE connection_id = ?" (ConnMember, hostMemberId, currentTs, connId)
|
||||
-- using IBUnknown since host is created without contact
|
||||
void $ createContactMemberInv_ db user groupId (Just hostMemberId) user invitedMember GCUserMember membershipStatus IBUnknown customUserProfileId currentTs vr
|
||||
liftIO $ setViaGroupLinkHash db groupId connId
|
||||
liftIO $ setViaGroupLinkUri db groupId connId
|
||||
(,) <$> getGroupInfo db vr user groupId <*> getGroupMemberById db vr user hostMemberId
|
||||
where
|
||||
insertHost_ currentTs groupId = do
|
||||
@@ -906,7 +908,7 @@ cleanupHostGroupLinkConn db user@User {userId} GroupInfo {groupId} = do
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE connections SET via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
UPDATE connections SET via_contact_uri = NULL, via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
WHERE user_id = ? AND via_group_link = 1 AND contact_id IN (
|
||||
SELECT contact_id
|
||||
FROM group_members
|
||||
@@ -954,7 +956,7 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = do
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
|
||||
mu.created_at, mu.updated_at,
|
||||
@@ -1911,7 +1913,7 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = do
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
|
||||
@@ -14,6 +14,7 @@ import Simplex.Chat.Store.Postgres.Migrations.M20250704_groups_conn_link_prepare
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20250709_profile_short_descr
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20250721_indexes
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20250729_member_contact_requests
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20250801_via_group_link_uri
|
||||
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Text, Maybe Text)]
|
||||
@@ -27,7 +28,8 @@ schemaMigrations =
|
||||
("20250704_groups_conn_link_prepared_connection", m20250704_groups_conn_link_prepared_connection, Just down_m20250704_groups_conn_link_prepared_connection),
|
||||
("20250709_profile_short_descr", m20250709_profile_short_descr, Just down_m20250709_profile_short_descr),
|
||||
("20250721_indexes", m20250721_indexes, Just down_m20250721_indexes),
|
||||
("20250729_member_contact_requests", m20250729_member_contact_requests, Just down_m20250729_member_contact_requests)
|
||||
("20250729_member_contact_requests", m20250729_member_contact_requests, Just down_m20250729_member_contact_requests),
|
||||
("20250801_via_group_link_uri", m20250801_via_group_link_uri, Just down_m20250801_via_group_link_uri)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.Postgres.Migrations.M20250801_via_group_link_uri where
|
||||
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Text.RawString.QQ (r)
|
||||
|
||||
m20250801_via_group_link_uri :: Text
|
||||
m20250801_via_group_link_uri =
|
||||
T.pack
|
||||
[r|
|
||||
ALTER TABLE groups ADD COLUMN via_group_link_uri BYTEA;
|
||||
ALTER TABLE connections ADD COLUMN via_contact_uri BYTEA;
|
||||
|]
|
||||
|
||||
down_m20250801_via_group_link_uri :: Text
|
||||
down_m20250801_via_group_link_uri =
|
||||
T.pack
|
||||
[r|
|
||||
ALTER TABLE groups DROP COLUMN via_group_link_uri;
|
||||
ALTER TABLE connections DROP COLUMN via_contact_uri;
|
||||
|]
|
||||
@@ -303,7 +303,8 @@ CREATE TABLE test_chat_schema.connections (
|
||||
pq_rcv_enabled smallint,
|
||||
quota_err_counter bigint DEFAULT 0 NOT NULL,
|
||||
short_link_inv bytea,
|
||||
via_short_link_contact bytea
|
||||
via_short_link_contact bytea,
|
||||
via_contact_uri bytea
|
||||
);
|
||||
|
||||
|
||||
@@ -653,7 +654,8 @@ CREATE TABLE test_chat_schema.groups (
|
||||
conn_link_started_connection smallint DEFAULT 0 NOT NULL,
|
||||
welcome_shared_msg_id bytea,
|
||||
request_shared_msg_id bytea,
|
||||
conn_link_prepared_connection smallint DEFAULT 0 NOT NULL
|
||||
conn_link_prepared_connection smallint DEFAULT 0 NOT NULL,
|
||||
via_group_link_uri bytea
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ import Simplex.Chat.Store.SQLite.Migrations.M20250704_groups_conn_link_prepared_
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250709_profile_short_descr
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250721_indexes
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250729_member_contact_requests
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250801_via_group_link_uri
|
||||
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Query, Maybe Query)]
|
||||
@@ -273,7 +274,8 @@ schemaMigrations =
|
||||
("20250704_groups_conn_link_prepared_connection", m20250704_groups_conn_link_prepared_connection, Just down_m20250704_groups_conn_link_prepared_connection),
|
||||
("20250709_profile_short_descr", m20250709_profile_short_descr, Just down_m20250709_profile_short_descr),
|
||||
("20250721_indexes", m20250721_indexes, Just down_m20250721_indexes),
|
||||
("20250729_member_contact_requests", m20250729_member_contact_requests, Just down_m20250729_member_contact_requests)
|
||||
("20250729_member_contact_requests", m20250729_member_contact_requests, Just down_m20250729_member_contact_requests),
|
||||
("20250801_via_group_link_uri", m20250801_via_group_link_uri, Just down_m20250801_via_group_link_uri)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.SQLite.Migrations.M20250801_via_group_link_uri where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20250801_via_group_link_uri :: Query
|
||||
m20250801_via_group_link_uri =
|
||||
[sql|
|
||||
ALTER TABLE groups ADD COLUMN via_group_link_uri BLOB;
|
||||
ALTER TABLE connections ADD COLUMN via_contact_uri BLOB;
|
||||
|]
|
||||
|
||||
down_m20250801_via_group_link_uri :: Query
|
||||
down_m20250801_via_group_link_uri =
|
||||
[sql|
|
||||
ALTER TABLE groups DROP COLUMN via_group_link_uri;
|
||||
ALTER TABLE connections DROP COLUMN via_contact_uri;
|
||||
|]
|
||||
@@ -65,7 +65,7 @@ Query:
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -973,7 +973,7 @@ Query:
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -1023,7 +1023,7 @@ Query:
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
|
||||
mu.created_at, mu.updated_at,
|
||||
@@ -1431,7 +1431,7 @@ SEARCH m USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
|
||||
Query:
|
||||
UPDATE connections SET via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
UPDATE connections SET via_contact_uri = NULL, via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
WHERE user_id = ? AND via_group_link = 1 AND contact_id IN (
|
||||
SELECT contact_id
|
||||
FROM group_members
|
||||
@@ -3660,6 +3660,14 @@ Query:
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE groups
|
||||
SET via_group_link_uri = ?, via_group_link_uri_hash = ?
|
||||
WHERE group_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM chat_items
|
||||
WHERE group_scope_group_member_id = ?
|
||||
@@ -4190,10 +4198,10 @@ Plan:
|
||||
Query:
|
||||
INSERT INTO connections (
|
||||
user_id, agent_conn_id, conn_status, conn_type, contact_conn_initiated,
|
||||
via_contact_uri_hash, via_short_link_contact, contact_id, group_member_id,
|
||||
via_contact_uri, via_contact_uri_hash, via_short_link_contact, contact_id, group_member_id,
|
||||
xcontact_id, custom_user_profile_id, via_group_link, group_link_id,
|
||||
created_at, updated_at, to_subscribe, conn_chat_version, pq_support, pq_encryption
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|
||||
Plan:
|
||||
|
||||
@@ -4620,16 +4628,6 @@ Query:
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE groups
|
||||
SET via_group_link_uri_hash = (SELECT via_contact_uri_hash FROM connections WHERE connection_id = ?)
|
||||
WHERE group_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SCALAR SUBQUERY 1
|
||||
SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE msg_deliveries
|
||||
SET delivery_status = ?, updated_at = ?
|
||||
@@ -4751,7 +4749,7 @@ Query:
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -4777,7 +4775,7 @@ Query:
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -5328,6 +5326,9 @@ Error: SQLite3 returned ErrorError while attempting to perform prepare "explain
|
||||
Query: CREATE TABLE temp_delete_members (contact_profile_id INTEGER, member_profile_id INTEGER, local_display_name TEXT)
|
||||
Error: SQLite3 returned ErrorError while attempting to perform prepare "explain query plan CREATE TABLE temp_delete_members (contact_profile_id INTEGER, member_profile_id INTEGER, local_display_name TEXT)": table temp_delete_members already exists
|
||||
|
||||
Query: DELETE FROM app_settings
|
||||
Plan:
|
||||
|
||||
Query: DELETE FROM calls WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH calls USING INDEX idx_calls_contact_id (contact_id=?)
|
||||
@@ -5717,6 +5718,9 @@ Plan:
|
||||
Query: DROP TABLE temp_delete_members
|
||||
Plan:
|
||||
|
||||
Query: INSERT INTO app_settings (app_settings) VALUES (?)
|
||||
Plan:
|
||||
|
||||
Query: INSERT INTO chat_item_mentions (chat_item_id, group_id, member_id, display_name) VALUES (?, ?, ?, ?)
|
||||
Plan:
|
||||
|
||||
@@ -6068,6 +6072,10 @@ Query: SELECT user_id FROM users WHERE local_display_name = ?
|
||||
Plan:
|
||||
SEARCH users USING COVERING INDEX sqlite_autoindex_users_2 (local_display_name=?)
|
||||
|
||||
Query: SELECT via_contact_uri, via_contact_uri_hash FROM connections WHERE connection_id = ?
|
||||
Plan:
|
||||
SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: SELECT xgrplinkmem_received FROM group_members WHERE group_member_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -6324,7 +6332,7 @@ Query: UPDATE groups SET user_member_profile_sent_at = ? WHERE user_id = ? AND g
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET via_group_link_uri_hash = ?, conn_link_prepared_connection = ?, updated_at = ? WHERE group_id = ?
|
||||
Query: UPDATE groups SET via_group_link_uri = ?, via_group_link_uri_hash = ?, conn_link_prepared_connection = ?, updated_at = ? WHERE group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
|
||||
@@ -154,7 +154,8 @@ CREATE TABLE groups(
|
||||
conn_link_started_connection INTEGER NOT NULL DEFAULT 0,
|
||||
welcome_shared_msg_id BLOB,
|
||||
request_shared_msg_id BLOB,
|
||||
conn_link_prepared_connection INTEGER NOT NULL DEFAULT 0, -- received
|
||||
conn_link_prepared_connection INTEGER NOT NULL DEFAULT 0,
|
||||
via_group_link_uri BLOB, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
@@ -327,6 +328,7 @@ CREATE TABLE connections(
|
||||
quota_err_counter INTEGER NOT NULL DEFAULT 0,
|
||||
short_link_inv BLOB,
|
||||
via_short_link_contact BLOB,
|
||||
via_contact_uri BLOB,
|
||||
FOREIGN KEY(snd_file_id, connection_id)
|
||||
REFERENCES snd_files(file_id, connection_id)
|
||||
ON DELETE CASCADE
|
||||
|
||||
@@ -638,21 +638,21 @@ type PreparedGroupRow = (Maybe ConnReqContact, Maybe ShortLinkContact, BoolInt,
|
||||
|
||||
type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe MemberId)
|
||||
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Text, Maybe Text, Maybe ImageData) :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. PreparedGroupRow :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64, Int) :. GroupMemberRow
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Text, Maybe Text, Maybe ImageData) :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. PreparedGroupRow :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64, Int, Maybe ConnReqContact) :. GroupMemberRow
|
||||
|
||||
type GroupMemberRow = (Int64, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId) :. ProfileRow :. (UTCTime, UTCTime) :. (Maybe UTCTime, Int64, Int64, Int64, Maybe UTCTime)
|
||||
|
||||
type ProfileRow = (ProfileId, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, LocalAlias, Maybe Preferences)
|
||||
|
||||
toGroupInfo :: VersionRangeChat -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, shortDescr, localAlias, description, image) :. (enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. preparedGroupRow :. businessRow :. (uiThemes, customData, chatItemTTL, membersRequireAttention) :. userMemberRow) =
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, shortDescr, localAlias, description, image) :. (enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. preparedGroupRow :. businessRow :. (uiThemes, customData, chatItemTTL, membersRequireAttention, viaGroupLinkUri) :. userMemberRow) =
|
||||
let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = vr}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
|
||||
fullGroupPreferences = mergeGroupPreferences groupPreferences
|
||||
groupProfile = GroupProfile {displayName, fullName, shortDescr, description, image, groupPreferences, memberAdmission}
|
||||
businessChat = toBusinessChatInfo businessRow
|
||||
preparedGroup = toPreparedGroup preparedGroupRow
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, preparedGroup, chatTags, chatItemTTL, uiThemes, customData, membersRequireAttention}
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, preparedGroup, chatTags, chatItemTTL, uiThemes, customData, membersRequireAttention, viaGroupLinkUri}
|
||||
|
||||
toPreparedGroup :: PreparedGroupRow -> Maybe PreparedGroup
|
||||
toPreparedGroup = \case
|
||||
@@ -698,7 +698,7 @@ groupInfoQuery =
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -784,16 +784,22 @@ addGroupChatTags db g@GroupInfo {groupId} = do
|
||||
chatTags <- getGroupChatTags db groupId
|
||||
pure (g :: GroupInfo) {chatTags}
|
||||
|
||||
setViaGroupLinkHash :: DB.Connection -> GroupId -> Int64 -> IO ()
|
||||
setViaGroupLinkHash db groupId connId =
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE groups
|
||||
SET via_group_link_uri_hash = (SELECT via_contact_uri_hash FROM connections WHERE connection_id = ?)
|
||||
WHERE group_id = ?
|
||||
|]
|
||||
(connId, groupId)
|
||||
setViaGroupLinkUri :: DB.Connection -> GroupId -> Int64 -> IO ()
|
||||
setViaGroupLinkUri db groupId connId = do
|
||||
r <-
|
||||
DB.query
|
||||
db
|
||||
"SELECT via_contact_uri, via_contact_uri_hash FROM connections WHERE connection_id = ?"
|
||||
(Only connId) :: IO [(Maybe ConnReqContact, Maybe ConnReqUriHash)]
|
||||
forM_ (listToMaybe r) $ \(viaContactUri, viaContactUriHash) ->
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE groups
|
||||
SET via_group_link_uri = ?, via_group_link_uri_hash = ?
|
||||
WHERE group_id = ?
|
||||
|]
|
||||
(viaContactUri, viaContactUriHash, groupId)
|
||||
|
||||
deleteConnectionRecord :: DB.Connection -> User -> Int64 -> IO ()
|
||||
deleteConnectionRecord db User {userId} cId = do
|
||||
|
||||
@@ -486,7 +486,8 @@ data GroupInfo = GroupInfo
|
||||
chatItemTTL :: Maybe Int64,
|
||||
uiThemes :: Maybe UIThemeEntityOverrides,
|
||||
customData :: Maybe CustomData,
|
||||
membersRequireAttention :: Int
|
||||
membersRequireAttention :: Int,
|
||||
viaGroupLinkUri :: Maybe ConnReqContact
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user