Files
once-campfire/test/models/room/push_test.rb
T
Jeremy Daer 6e312c6028 Stop sending push notifications to banned users (#338)
Banning a user deletes their sessions and closes their connections but
keeps their push subscriptions, and Room::MessagePusher chose recipients
by membership alone. A banned user's browser or phone therefore went on
receiving the room name, sender and text of new direct messages,
mentions, and messages in rooms they had set to everything.

Choose subscriptions from active users only. The subscriptions are kept,
so unbanning brings notifications back without the user having to
subscribe again (the client doesn't resubscribe while the browser still
holds a subscription).

Co-authored-by: Marcello Costagliola <176920116+namespaceMarcello@users.noreply.github.com>
2026-10-07 11:25:16 -07:00

121 lines
4.3 KiB
Ruby

require "test_helper"
class Room::PushTest < ActiveSupport::TestCase
include ActiveJob::TestHelper
setup do
stub_web_push_dns_resolution
end
test "deliver new message to other room users with push subscriptions" do
task_count = Push::Subscription.count - users(:david).push_subscriptions.count
perform_enqueued_jobs only: Room::PushMessageJob do
WebPush.expects(:payload_send).times(task_count)
rooms(:hq).messages.create! body: "This is from earth", client_message_id: "earth", creator: users(:david)
end
wait_for_web_push_delivery_pool_tasks(task_count)
end
test "notifies subscribed users" do
perform_enqueued_jobs only: Room::PushMessageJob do
WebPush.expects(:payload_send).times(2)
rooms(:designers).messages.create! body: "This is from earth", client_message_id: "earth", creator: users(:david)
end
wait_for_web_push_delivery_pool_tasks(2)
perform_enqueued_jobs only: Room::PushMessageJob do
WebPush.expects(:payload_send).times(3)
rooms(:designers).messages.create! body: "Hey #{mention_attachment_for(:kevin)}", client_message_id: "earth", creator: users(:david)
end
wait_for_web_push_delivery_pool_tasks(5)
end
test "does not notify for connected rooms" do
memberships(:kevin_designers).connected
perform_enqueued_jobs only: Room::PushMessageJob do
WebPush.expects(:payload_send).times(2)
rooms(:designers).messages.create! body: "Hey @kevin", client_message_id: "earth", creator: users(:david)
end
wait_for_web_push_delivery_pool_tasks(2)
end
test "does not notify for invisible rooms" do
memberships(:kevin_designers).update! involvement: "invisible"
perform_enqueued_jobs only: Room::PushMessageJob do
WebPush.expects(:payload_send).times(2)
rooms(:designers).messages.create! body: "Hey @kevin", client_message_id: "earth", creator: users(:david)
end
wait_for_web_push_delivery_pool_tasks(2)
end
test "destroys invalid subscriptions" do
memberships(:kevin_designers).update! involvement: "invisible"
assert_difference -> { Push::Subscription.count }, -2 do
perform_enqueued_jobs only: Room::PushMessageJob do
WebPush.expects(:payload_send).times(2).raises(WebPush::ExpiredSubscription.new(Struct.new(:body).new, "example.com"))
rooms(:designers).messages.create! body: "Hey @kevin", client_message_id: "earth", creator: users(:david)
end
wait_for_web_push_delivery_pool_tasks(2)
wait_for_invalidation_pool_tasks(2)
end
end
test "does not notify banned users" do
users(:kevin).ban
assert_not_includes pushed_users { post_to_designers_mentioning_kevin }, users(:kevin)
end
test "notifies users again once they're unbanned" do
users(:kevin).ban
users(:kevin).unban
assert_includes pushed_users { post_to_designers_mentioning_kevin }, users(:kevin)
end
test "does not notify banned users of direct messages" do
users(:kevin).ban
pushed = pushed_users do
rooms(:david_and_kevin).messages.create! body: "Just between us", client_message_id: "earth", creator: users(:david)
end
assert_not_includes pushed, users(:kevin)
end
test "notifies active users mentioned" do
assert_includes pushed_users { post_to_designers_mentioning_kevin }, users(:kevin)
end
private
def post_to_designers_mentioning_kevin
rooms(:designers).messages.create! body: "Hey #{mention_attachment_for(:kevin)}", client_message_id: "earth", creator: users(:david)
end
def pushed_users(&block)
queued = []
Rails.configuration.x.web_push_pool.stubs(:queue).with { |_payload, subscriptions| queued.concat subscriptions.to_a }
perform_enqueued_jobs(only: Room::PushMessageJob, &block)
queued.map(&:user).uniq
end
def wait_for_web_push_delivery_pool_tasks(count)
wait_for_pool_tasks(Rails.configuration.x.web_push_pool.delivery_pool, count)
end
def wait_for_invalidation_pool_tasks(count)
wait_for_pool_tasks(Rails.configuration.x.web_push_pool.invalidation_pool, count)
end
def wait_for_pool_tasks(pool, count)
start = Time.now
timeout = 0.2
while pool.completed_task_count < count
raise "Timeout waiting for pool tasks to complete" if Time.now - start > timeout
sleep timeout / 10.0
end
end
end