mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-09 16:20:09 +09:00
6e312c6028
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>
69 lines
2.0 KiB
Ruby
69 lines
2.0 KiB
Ruby
class Room::MessagePusher
|
|
attr_reader :room, :message
|
|
|
|
def initialize(room:, message:)
|
|
@room, @message = room, message
|
|
end
|
|
|
|
def push
|
|
build_payload.tap do |payload|
|
|
push_to_users_involved_in_everything(payload)
|
|
push_to_users_involved_in_mentions(payload)
|
|
end
|
|
end
|
|
|
|
private
|
|
def build_payload
|
|
if room.direct?
|
|
build_direct_payload
|
|
else
|
|
build_shared_payload
|
|
end
|
|
end
|
|
|
|
def build_direct_payload
|
|
{
|
|
title: message.creator.name,
|
|
body: message.plain_text_body,
|
|
path: Rails.application.routes.url_helpers.room_path(room)
|
|
}
|
|
end
|
|
|
|
def build_shared_payload
|
|
{
|
|
title: room.name,
|
|
body: "#{message.creator.name}: #{message.plain_text_body}",
|
|
path: Rails.application.routes.url_helpers.room_path(room)
|
|
}
|
|
end
|
|
|
|
def push_to_users_involved_in_everything(payload)
|
|
enqueue_payload_for_delivery payload, push_subscriptions_for_users_involved_in_everything
|
|
end
|
|
|
|
def push_to_users_involved_in_mentions(payload)
|
|
enqueue_payload_for_delivery payload, push_subscriptions_for_mentionable_users(message.mentionees)
|
|
end
|
|
|
|
def push_subscriptions_for_users_involved_in_everything
|
|
relevant_subscriptions.merge(Membership.involved_in_everything)
|
|
end
|
|
|
|
def push_subscriptions_for_mentionable_users(mentionees)
|
|
relevant_subscriptions.merge(Membership.involved_in_mentions).where(user_id: mentionees.ids)
|
|
end
|
|
|
|
# Banning keeps the user's subscriptions, so that unbanning brings their notifications back,
|
|
# but nobody who can't sign in should be sent what's said in their rooms meanwhile.
|
|
def relevant_subscriptions
|
|
Push::Subscription
|
|
.joins(user: :memberships)
|
|
.merge(User.active)
|
|
.merge(Membership.visible.disconnected.where(room: room).where.not(user: message.creator))
|
|
end
|
|
|
|
def enqueue_payload_for_delivery(payload, subscriptions)
|
|
Rails.configuration.x.web_push_pool.queue(payload, subscriptions)
|
|
end
|
|
end
|