From 5a8310d5a7d0e9132c2651b9600a3d5ff67a5060 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 12 Dec 2024 13:18:40 -0500 Subject: [PATCH] fix(pins)_: delete pins when the og message is deleted (#6173) Found when fixing https://github.com/status-im/status-desktop/issues/16639 When a message is deleted, we need to delete the pins too as they are no longer available. This was done using an ON DELETE clause (thanks @osmaczko) I also made sure the SELECT query for the pins doesn't return deleted messages --- protocol/message_persistence.go | 1 + ...inned_messages_add_on_delete_clause.up.sql | 19 ++++++++ protocol/persistence_test.go | 44 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 protocol/migrations/sqlite/1733428521_pinned_messages_add_on_delete_clause.up.sql diff --git a/protocol/message_persistence.go b/protocol/message_persistence.go index fe0958f62..3b9144877 100644 --- a/protocol/message_persistence.go +++ b/protocol/message_persistence.go @@ -1250,6 +1250,7 @@ func (db sqlitePersistence) PinnedMessageByChatIDs(chatIDs []string, currCursor WHERE pm.pinned = 1 AND NOT(m1.hide) AND m1.local_chat_id IN %s %s + AND m1.deleted = 0 ORDER BY cursor DESC %s `, allFields, cursorField, "(?"+strings.Repeat(",?", len(chatIDs)-1)+")", cursorWhere, limitStr), diff --git a/protocol/migrations/sqlite/1733428521_pinned_messages_add_on_delete_clause.up.sql b/protocol/migrations/sqlite/1733428521_pinned_messages_add_on_delete_clause.up.sql new file mode 100644 index 000000000..83c7de93a --- /dev/null +++ b/protocol/migrations/sqlite/1733428521_pinned_messages_add_on_delete_clause.up.sql @@ -0,0 +1,19 @@ +CREATE TABLE pin_messages_new ( + id VARCHAR PRIMARY KEY NOT NULL, + message_id VARCHAR NOT NULL, + whisper_timestamp INTEGER NOT NULL, + chat_id VARCHAR NOT NULL, + local_chat_id VARCHAR NOT NULL, + clock_value INT NOT NULL, + pinned BOOLEAN NOT NULL, + pinned_by TEXT, + FOREIGN KEY (message_id) REFERENCES user_messages(id) ON DELETE CASCADE +); + +INSERT INTO pin_messages_new (id, message_id, whisper_timestamp, chat_id, local_chat_id, clock_value, pinned, pinned_by) +SELECT id, message_id, whisper_timestamp, chat_id, local_chat_id, clock_value, pinned, pinned_by +FROM pin_messages; + +DROP TABLE pin_messages; + +ALTER TABLE pin_messages_new RENAME TO pin_messages; diff --git a/protocol/persistence_test.go b/protocol/persistence_test.go index 329418d00..adfa26ce6 100644 --- a/protocol/persistence_test.go +++ b/protocol/persistence_test.go @@ -666,6 +666,50 @@ func TestDeleteMessagesByChatID(t *testing.T) { } +func TestDeletePinnedMessageByID(t *testing.T) { + db, err := openTestDB() + require.NoError(t, err) + p := newSQLitePersistence(db) + id := "1" + + err = insertMinimalMessage(p, id) + require.NoError(t, err) + + m, err := p.MessageByID(id) + require.NoError(t, err) + require.Equal(t, id, m.ID) + + pinMessageProto := protobuf.PinMessage{ + ChatId: testPublicChatID, + MessageId: m.ID, + Pinned: true, + Clock: 2, + MessageType: protobuf.MessageType_PUBLIC_GROUP, + } + + pinMessage := &common.PinMessage{ + PinMessage: &pinMessageProto, + } + + inserted, err := p.SavePinMessage(pinMessage) + require.NoError(t, err) + require.True(t, inserted) + + pinnedMsgs, _, err := p.PinnedMessageByChatID(testPublicChatID, "", 10) + require.NoError(t, err) + require.Len(t, pinnedMsgs, 1) + + err = p.DeleteMessage(m.ID) + require.NoError(t, err) + + _, err = p.MessageByID(id) + require.EqualError(t, err, "record not found") + + pinnedMsgs, _, err = p.PinnedMessageByChatID(testPublicChatID, "", 10) + require.NoError(t, err) + require.Len(t, pinnedMsgs, 0) +} + func TestMarkMessageSeen(t *testing.T) { chatID := "test-chat" db, err := openTestDB()