mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-28 00:16:48 +09:00
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)
49 lines
1.6 KiB
Ruby
49 lines
1.6 KiB
Ruby
class Users::PushSubscriptionsController < ApplicationController
|
|
before_action :set_push_subscriptions
|
|
|
|
def index
|
|
end
|
|
|
|
def create
|
|
subscription = @push_subscriptions.find_or_initialize_by(push_subscription_params)
|
|
subscription.user_agent = request.user_agent if subscription.new_record?
|
|
|
|
# Existing endpoints must pass current validations too
|
|
if subscription.valid?
|
|
head register_while_signed_in(subscription) ? :ok : :unauthorized
|
|
else
|
|
head :unprocessable_entity
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
@push_subscriptions.destroy_by(id: params[:id])
|
|
redirect_to user_push_subscriptions_url
|
|
end
|
|
|
|
private
|
|
def set_push_subscriptions
|
|
@push_subscriptions = Current.user.push_subscriptions
|
|
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, 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
|
|
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
|
|
|
|
def push_subscription_params
|
|
params.require(:push_subscription).permit(:endpoint, :p256dh_key, :auth_key)
|
|
end
|
|
end
|