Post the browser's push subscription from every page, and register it once

Only room pages posted the subscription again, so a browser that
changed its password and closed the profile page went without
notifications until it next opened a room. A small controller in the
layout does it now, still once per session, and the bell is back to how
it was.

Two tabs posting at once after a password change could both miss the
row and insert two, so the endpoint is looked up again under the same
write lock as the session check.

From #371.

(cherry picked from commit 3786ee5244)
This commit is contained in:
Jeremy Daer committed 2026-10-19 13:15:14 -07:00
1 parent 931f6b2c38
commit fadf6f1859
7 files changed
+73 -35

No files matched your search

@@ -10,7 +10,7 @@ class Users::PushSubscriptionsController < ApplicationController
# Existing endpoints must pass current validations too
if subscription.valid?
head save_while_signed_in(subscription) ? :ok : :unauthorized
head register_while_signed_in(subscription) ? :ok : :unauthorized
else
head :unprocessable_entity
end
@@ -27,12 +27,18 @@ class Users::PushSubscriptionsController < ApplicationController
end
# A password change ends every session and subscription. A request that authenticated just before it mustn't
# put one back, so the session is checked under the same write lock as the save. Validation, which looks up
# the endpoint's address, runs before taking the lock.
def save_while_signed_in(subscription)
# put one back, so the session is checked under the same write lock as the save, and the endpoint is looked up
# again there so two tabs posting at once register it once. Validation, which resolves the endpoint's address,
# runs before taking the lock.
def register_while_signed_in(subscription)
Push::Subscription.transaction do
Session.exists?(Current.session.id) &&
(subscription.new_record? ? subscription.save!(validate: false) : subscription.touch)
if Session.exists?(Current.session.id)
if existing = @push_subscriptions.find_by(push_subscription_params)
existing.touch
else
subscription.save!(validate: false)
end
end
end
end