diff --git a/app/jobs/collection/clean_inaccessible_notifications_job.rb b/app/jobs/collection/clean_inaccessible_notifications_job.rb new file mode 100644 index 000000000..e332e46ab --- /dev/null +++ b/app/jobs/collection/clean_inaccessible_notifications_job.rb @@ -0,0 +1,5 @@ +class Collection::CleanInaccessibleNotificationsJob < ApplicationJob + def perform(user, collection) + collection.clean_inaccessible_notifications_for(user) + end +end diff --git a/app/models/access.rb b/app/models/access.rb index 32595ff9f..214e021f2 100644 --- a/app/models/access.rb +++ b/app/models/access.rb @@ -6,6 +6,8 @@ class Access < ApplicationRecord scope :ordered_by_recently_accessed, -> { order(accessed_at: :desc) } + after_destroy_commit :clean_inaccessible_notifications_later + def accessed touch :accessed_at unless recently_accessed? end @@ -14,4 +16,8 @@ class Access < ApplicationRecord def recently_accessed? accessed_at&.> 5.minutes.ago end + + def clean_inaccessible_notifications_later + Collection::CleanInaccessibleNotificationsJob.perform_later(user, collection) + end end diff --git a/app/models/collection/accessible.rb b/app/models/collection/accessible.rb index b4daae86f..8554c2d6d 100644 --- a/app/models/collection/accessible.rb +++ b/app/models/collection/accessible.rb @@ -36,6 +36,14 @@ module Collection::Accessible accesses.find_by(user: user) end + def clean_inaccessible_notifications_for(user) + user.notifications.find_each do |notification| + if notification.card&.collection == self + notification.destroy + end + end + end + private def grant_access_to_everyone accesses.grant_to(User.all) if all_access_previously_changed?(to: true) diff --git a/test/models/access_test.rb b/test/models/access_test.rb index 3db37fd18..6cbdc1ed5 100644 --- a/test/models/access_test.rb +++ b/test/models/access_test.rb @@ -14,4 +14,28 @@ class AccessTest < ActiveSupport::TestCase accesses(:writebook_kevin).accessed end end + + test "notifications are destroyed when access is lost" do + kevin = users(:kevin) + collection = collections(:writebook) + + assert kevin.notifications.count > 0 + + notifications_to_be_destroyed = kevin.notifications.select do |notification| + notification.card&.collection == collection + end + assert notifications_to_be_destroyed.any? + + kevin_access = accesses(:writebook_kevin) + + perform_enqueued_jobs only: Collection::CleanInaccessibleNotificationsJob do + kevin_access.destroy + end + + remaining_notifications = kevin.notifications.reload.select do |notification| + notification.card&.collection == collection + end + + assert_empty remaining_notifications + end end