core: fix deleting user with chat tags (#6374)

* core: fix deleting user with chat tags

* schema, tests

* schema

* update simplexmq

* update ios

* plans
This commit is contained in:
spaced4ndy
2025-10-23 07:30:36 +00:00
committed by GitHub
parent 505fde30f8
commit 2badeea19c
9 changed files with 117 additions and 4 deletions

View File

@@ -120,6 +120,7 @@ library
Simplex.Chat.Store.Postgres.Migrations.M20250919_group_summary
Simplex.Chat.Store.Postgres.Migrations.M20250922_remove_unused_connections
Simplex.Chat.Store.Postgres.Migrations.M20251007_connections_sync
Simplex.Chat.Store.Postgres.Migrations.M20251017_chat_tags_cascade
else
exposed-modules:
Simplex.Chat.Archive
@@ -264,6 +265,7 @@ library
Simplex.Chat.Store.SQLite.Migrations.M20250919_group_summary
Simplex.Chat.Store.SQLite.Migrations.M20250922_remove_unused_connections
Simplex.Chat.Store.SQLite.Migrations.M20251007_connections_sync
Simplex.Chat.Store.SQLite.Migrations.M20251017_chat_tags_cascade
other-modules:
Paths_simplex_chat
hs-source-dirs:

View File

@@ -20,6 +20,7 @@ import Simplex.Chat.Store.Postgres.Migrations.M20250813_delivery_tasks
import Simplex.Chat.Store.Postgres.Migrations.M20250919_group_summary
import Simplex.Chat.Store.Postgres.Migrations.M20250922_remove_unused_connections
import Simplex.Chat.Store.Postgres.Migrations.M20251007_connections_sync
import Simplex.Chat.Store.Postgres.Migrations.M20251017_chat_tags_cascade
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
schemaMigrations :: [(String, Text, Maybe Text)]
@@ -39,7 +40,8 @@ schemaMigrations =
("20250813_delivery_tasks", m20250813_delivery_tasks, Just down_m20250813_delivery_tasks),
("20250919_group_summary", m20250919_group_summary, Just down_m20250919_group_summary),
("20250922_remove_unused_connections", m20250922_remove_unused_connections, Just down_m20250922_remove_unused_connections),
("20251007_connections_sync", m20251007_connections_sync, Just down_m20251007_connections_sync)
("20251007_connections_sync", m20251007_connections_sync, Just down_m20251007_connections_sync),
("20251017_chat_tags_cascade", m20251017_chat_tags_cascade, Just down_m20251017_chat_tags_cascade)
]
-- | The list of migrations in ascending order by date

View File

@@ -0,0 +1,32 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.Postgres.Migrations.M20251017_chat_tags_cascade where
import Data.Text (Text)
import qualified Data.Text as T
import Text.RawString.QQ (r)
m20251017_chat_tags_cascade :: Text
m20251017_chat_tags_cascade =
T.pack
[r|
ALTER TABLE chat_tags DROP CONSTRAINT chat_tags_user_id_fkey;
ALTER TABLE chat_tags
ADD CONSTRAINT chat_tags_user_id_fkey
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON DELETE CASCADE;
|]
down_m20251017_chat_tags_cascade :: Text
down_m20251017_chat_tags_cascade =
T.pack
[r|
ALTER TABLE chat_tags DROP CONSTRAINT chat_tags_user_id_fkey;
ALTER TABLE chat_tags
ADD CONSTRAINT chat_tags_user_id_fkey
FOREIGN KEY (user_id)
REFERENCES users(user_id);
|]

View File

@@ -2479,7 +2479,7 @@ ALTER TABLE ONLY test_chat_schema.chat_tags_chats
ALTER TABLE ONLY test_chat_schema.chat_tags
ADD CONSTRAINT chat_tags_user_id_fkey FOREIGN KEY (user_id) REFERENCES test_chat_schema.users(user_id);
ADD CONSTRAINT chat_tags_user_id_fkey FOREIGN KEY (user_id) REFERENCES test_chat_schema.users(user_id) ON DELETE CASCADE;

View File

@@ -143,6 +143,7 @@ import Simplex.Chat.Store.SQLite.Migrations.M20250813_delivery_tasks
import Simplex.Chat.Store.SQLite.Migrations.M20250919_group_summary
import Simplex.Chat.Store.SQLite.Migrations.M20250922_remove_unused_connections
import Simplex.Chat.Store.SQLite.Migrations.M20251007_connections_sync
import Simplex.Chat.Store.SQLite.Migrations.M20251017_chat_tags_cascade
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
schemaMigrations :: [(String, Query, Maybe Query)]
@@ -285,7 +286,8 @@ schemaMigrations =
("20250813_delivery_tasks", m20250813_delivery_tasks, Just down_m20250813_delivery_tasks),
("20250919_group_summary", m20250919_group_summary, Just down_m20250919_group_summary),
("20250922_remove_unused_connections", m20250922_remove_unused_connections, Just down_m20250922_remove_unused_connections),
("20251007_connections_sync", m20251007_connections_sync, Just down_m20251007_connections_sync)
("20251007_connections_sync", m20251007_connections_sync, Just down_m20251007_connections_sync),
("20251017_chat_tags_cascade", m20251017_chat_tags_cascade, Just down_m20251017_chat_tags_cascade)
]
-- | The list of migrations in ascending order by date

View File

@@ -0,0 +1,30 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20251017_chat_tags_cascade where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20251017_chat_tags_cascade :: Query
m20251017_chat_tags_cascade =
[sql|
PRAGMA writable_schema=1;
UPDATE sqlite_master
SET sql = replace(sql, 'user_id INTEGER REFERENCES users', 'user_id INTEGER REFERENCES users ON DELETE CASCADE')
WHERE name = 'chat_tags' AND type = 'table';
PRAGMA writable_schema=0;
|]
down_m20251017_chat_tags_cascade :: Query
down_m20251017_chat_tags_cascade =
[sql|
PRAGMA writable_schema=1;
UPDATE sqlite_master
SET sql = replace(sql, 'user_id INTEGER REFERENCES users ON DELETE CASCADE', 'user_id INTEGER REFERENCES users')
WHERE name = 'chat_tags' AND type = 'table';
PRAGMA writable_schema=0;
|]

View File

@@ -3329,6 +3329,16 @@ Query:
Plan:
SEARCH chat_item_versions USING INDEX idx_chat_item_versions_chat_item_id (chat_item_id=?)
Query:
SELECT chat_tag_id, chat_tag_emoji, chat_tag_text
FROM chat_tags
WHERE user_id = ?
ORDER BY tag_order
Plan:
SEARCH chat_tags USING INDEX idx_chat_tags_user_id (user_id=?)
USE TEMP B-TREE FOR ORDER BY
Query:
SELECT command_id, connection_id, command_function, command_status
FROM commands
@@ -4333,6 +4343,20 @@ Query:
Plan:
Query:
INSERT INTO chat_tags (user_id, chat_tag_emoji, chat_tag_text, tag_order)
VALUES (?,?,?, COALESCE((SELECT MAX(tag_order) + 1 FROM chat_tags WHERE user_id = ?), 1))
Plan:
SCALAR SUBQUERY 1
SEARCH chat_tags USING INDEX idx_chat_tags_user_id (user_id=?)
Query:
INSERT INTO chat_tags_chats (contact_id, chat_tag_id)
VALUES (?,?)
Plan:
Query:
INSERT INTO commands (connection_id, command_function, command_status, user_id, created_at, updated_at)
VALUES (?,?,?,?,?,?)

View File

@@ -663,7 +663,7 @@ CREATE TABLE operator_usage_conditions(
);
CREATE TABLE chat_tags(
chat_tag_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER REFERENCES users,
user_id INTEGER REFERENCES users ON DELETE CASCADE,
chat_tag_text TEXT NOT NULL,
chat_tag_emoji TEXT,
tag_order INTEGER NOT NULL

View File

@@ -134,6 +134,7 @@ chatDirectTests = do
it "both users have contact link" testMultipleUserAddresses
it "create user with same servers" testCreateUserSameServers
it "delete user" testDeleteUser
it "delete user with chat tags" testDeleteUserChatTags
it "users have different chat item TTL configuration, chat items expire" testUsersDifferentCIExpirationTTL
it "chat items expire after restart for all users according to per user configuration" testUsersRestartCIExpiration
it "chat items only expire for users who configured expiration" testEnableCIExpirationOnlyForOneUser
@@ -2110,6 +2111,26 @@ testDeleteUser =
alice ##> "/users"
alice <## "no users"
testDeleteUserChatTags :: HasCallStack => TestParams -> IO ()
testDeleteUserChatTags =
testChat2 aliceProfile bobProfile $
\alice bob -> do
connectUsers alice bob
alice ##> "/_create tag {\"text\":\"my tag\"}"
alice <## "[{\"chatTagId\":1,\"chatTagText\":\"my tag\"}]"
alice ##> "/_tags @2 1"
alice <## "chat tags updated"
alice ##> "/create user alisa"
showActiveUser alice "alisa"
alice ##> "/_delete user 1 del_smp=off"
alice <## "ok"
alice ##> "/users"
alice <## "alisa (active)"
testUsersDifferentCIExpirationTTL :: HasCallStack => TestParams -> IO ()
testUsersDifferentCIExpirationTTL ps = do
withNewTestChat ps "bob" bobProfile $ \bob -> do