| index c6a98a2..85293d5 100644 |
| --- a/db.go |
| +++ b/db.go |
| @@ -268,13 +268,6 @@ CREATE TABLE IF NOT EXISTS apns_tokens ( |
| sandbox INTEGER NOT NULL DEFAULT 0, |
| created_at INTEGER NOT NULL |
| ); |
| -CREATE TABLE IF NOT EXISTS reactions ( |
| - message_id INTEGER NOT NULL, |
| - token TEXT NOT NULL, |
| - emoji TEXT NOT NULL, |
| - created_at INTEGER NOT NULL, |
| - PRIMARY KEY (message_id, token, emoji) |
| -); |
| -- Attachment/photo bytes. Two storage modes coexist so older DBs keep working: |
| -- * disk-backed (new): bytes live at blobDir/id; the data column is empty, size>0. |
| -- * legacy (pre-disk): bytes live in the data column; no file. getBlob falls back. |
| @@ -549,6 +542,12 @@ CREATE TABLE IF NOT EXISTS member_bots ( |
| // stored in clear and are no longer accepted; drop the table so a stolen DB |
| // retains no plaintext credentials. Members re-authenticate via device tokens. |
| "DROP TABLE IF EXISTS invites", |
| + // The reactions table is vestigial: reactions became encrypted message |
| + // events (the chat.react fold), so nothing writes or reads it anymore. |
| + // Legacy rows stored the reactor's RAW session token in the clear — drop |
| + // the table so a stolen DB retains no plaintext credentials (same |
| + // rationale as the invites drop above). |
| + "DROP TABLE IF EXISTS reactions", |
| // Which user a push subscription belongs to, so removing a user can drop their |
| // subscriptions (sign-out clears them by token; removal has only the user id). |
| "ALTER TABLE push_subscriptions ADD COLUMN user_id TEXT", |
| @@ -1391,7 +1390,7 @@ func (db *DB) userPresenceInfo(userID string) (pinned string, isAgent bool) { |
| |
| // removeUser deletes a user and all their traces (admin roster management): device |
| // tokens, thread membership + wrapped keys, DM-pair records, pending invites, their |
| -// instance-key copy, reactions, and their own messages — then cleans up any thread |
| +// instance-key copy, and their own messages — then cleans up any thread |
| // left with no members. Threads they merely shared (a DM/group with others) survive; |
| // the other members keep them. |
| func (db *DB) removeUser(id string) error { |
| @@ -1487,7 +1486,6 @@ func (db *DB) removeUser(id string) error { |
| {"DELETE FROM user_tiers WHERE user_id = ?", []any{id}}, |
| {"DELETE FROM tier_keys WHERE user_id = ?", []any{id}}, |
| {"DELETE FROM dm_pairs WHERE user_a = ? OR user_b = ?", []any{id, id}}, |
| - {"DELETE FROM reactions WHERE token = ?", []any{id}}, |
| {"DELETE FROM messages WHERE author_hash = ?", []any{id}}, |
| {"DELETE FROM push_subscriptions WHERE user_id = ?", []any{id}}, |
| {"DELETE FROM users WHERE id = ?", []any{id}}, |
| @@ -2986,16 +2984,13 @@ func (db *DB) editMessage(id int64, blob, authorHash string, window time.Duratio |
| return Message{ID: id, Blob: blob, EditedAt: now.Unix()}, true, nil |
| } |
| |
| -// deleteMessage hard-deletes a message (and its reactions) if authorHash is the |
| -// author — unsend-style, so the ciphertext is actually gone, not just hidden. |
| +// deleteMessage hard-deletes a message if authorHash is the author — |
| +// unsend-style, so the ciphertext is actually gone, not just hidden. |
| // Returns whether a row was removed (false = not the author / unknown id). |
| +// Reactions live inside encrypted message events, so there is nothing else |
| +// to clean up here. |
| func (db *DB) deleteMessage(id int64, authorHash string) (bool, error) { |
| - tx, err := db.sql.Begin() |
| - if err != nil { |
| - return false, err |
| - } |
| - defer tx.Rollback() |
| - res, err := tx.Exec("DELETE FROM messages WHERE id = ? AND author_hash = ?", id, authorHash) |
| + res, err := db.sql.Exec("DELETE FROM messages WHERE id = ? AND author_hash = ?", id, authorHash) |
| if err != nil { |
| return false, err |
| } |
| @@ -3003,13 +2998,7 @@ func (db *DB) deleteMessage(id int64, authorHash string) (bool, error) { |
| if err != nil { |
| return false, err |
| } |
| - if n == 0 { |
| - return false, tx.Commit() |
| - } |
| - if _, err := tx.Exec("DELETE FROM reactions WHERE message_id = ?", id); err != nil { |
| - return false, err |
| - } |
| - return true, tx.Commit() |
| + return n > 0, nil |
| } |
| |
| // messagesBefore returns the `limit` messages immediately older than `before` |
| @@ -3833,9 +3822,3 @@ func (db *DB) deleteMemberBot(id string) (bool, error) { |
| return n > 0, nil |
| } |
| |
| -// ---- reactions ---------------------------------------------------------- |
| -// |
| -// A reaction is (message_id, token, emoji). The emoji is stored in the clear so |
| -// the server can count and de-duplicate them; message content stays encrypted. |
| -// The token identifies the reactor for toggling, never their screen name. |
| - |