From 3a831e390f892d6841fed0514457218f8bd14b25 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 6 Nov 2025 22:01:43 +0100 Subject: [PATCH] Clean watchers when losing access to board https://app.fizzy.do/5986089/cards/2814 --- app/models/board/accessible.rb | 5 +++++ ...4151_add_user_and_card_index_to_watches.rb | 5 +++++ db/schema.rb | 3 ++- db/schema_cache.yml | 19 ++++++++++++++++++- test/models/access_test.rb | 16 ++++++++++++++++ test/models/board/accessible_test.rb | 2 ++ 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20251106154151_add_user_and_card_index_to_watches.rb diff --git a/app/models/board/accessible.rb b/app/models/board/accessible.rb index 6d62c0b21..75b2e982e 100644 --- a/app/models/board/accessible.rb +++ b/app/models/board/accessible.rb @@ -45,6 +45,7 @@ module Board::Accessible mentions_for_user(user).destroy_all notifications_for_user(user).destroy_all + watches_for(user).destroy_all end def watchers @@ -89,4 +90,8 @@ module Board::Accessible (notifications.source_type = 'Event' AND events.eventable_type = 'Comment' AND event_comment_cards.board_id = ?)", id, id) end + + def watches_for(user) + Watch.where(card: cards, user: user) + end end diff --git a/db/migrate/20251106154151_add_user_and_card_index_to_watches.rb b/db/migrate/20251106154151_add_user_and_card_index_to_watches.rb new file mode 100644 index 000000000..1ad20894a --- /dev/null +++ b/db/migrate/20251106154151_add_user_and_card_index_to_watches.rb @@ -0,0 +1,5 @@ +class AddUserAndCardIndexToWatches < ActiveRecord::Migration[8.2] + def change + add_index :watches, %i[ user_id card_id ] + end +end diff --git a/db/schema.rb b/db/schema.rb index fbf5f98df..9516f3206 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.2].define(version: 2025_11_05_122933) do +ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do create_table "accesses", force: :cascade do |t| t.datetime "accessed_at" t.integer "board_id", null: false @@ -404,6 +404,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_05_122933) do t.integer "user_id", null: false t.boolean "watching", default: true, null: false t.index ["card_id"], name: "index_watches_on_card_id" + t.index ["user_id", "card_id"], name: "index_watches_on_user_id_and_card_id" t.index ["user_id"], name: "index_watches_on_user_id" end diff --git a/db/schema_cache.yml b/db/schema_cache.yml index 60b8b29da..f818b58bf 100644 --- a/db/schema_cache.yml +++ b/db/schema_cache.yml @@ -2760,6 +2760,23 @@ indexes: nulls_not_distinct: comment: valid: true + - !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition + table: watches + name: index_watches_on_user_id_and_card_id + unique: false + columns: + - user_id + - card_id + lengths: {} + orders: {} + opclasses: {} + where: + type: + using: + include: + nulls_not_distinct: + comment: + valid: true webhook_delinquency_trackers: - !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition table: webhook_delinquency_trackers @@ -2843,4 +2860,4 @@ indexes: nulls_not_distinct: comment: valid: true -version: 20251105122933 +version: 20251106154151 diff --git a/test/models/access_test.rb b/test/models/access_test.rb index 0ea14a250..1b9ea2d12 100644 --- a/test/models/access_test.rb +++ b/test/models/access_test.rb @@ -64,4 +64,20 @@ class AccessTest < ActiveSupport::TestCase assert_empty remaining_mentions end + + test "watches are destroyed when access is lost" do + kevin = users(:kevin) + board = boards(:writebook) + card = board.cards.first + + assert card.watched_by?(kevin) + + kevin_access = accesses(:writebook_kevin) + + perform_enqueued_jobs only: Board::CleanInaccessibleDataJob do + kevin_access.destroy + end + + assert_not card.watched_by?(kevin) + end end diff --git a/test/models/board/accessible_test.rb b/test/models/board/accessible_test.rb index a384efad3..8c3beef5e 100644 --- a/test/models/board/accessible_test.rb +++ b/test/models/board/accessible_test.rb @@ -38,4 +38,6 @@ class Board::AccessibleTest < ActiveSupport::TestCase boards(:writebook).access_for(users(:kevin)).access_only! assert_not_includes boards(:writebook).reload.watchers, users(:kevin) end + + # NOTE: The tests for clearing inaccessible data are in +AccessTest+ end