mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-27 07:56: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.
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
|