From 61b7a04528e875e61361bb22ed3b45fbee38f3fd Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 3 May 2024 16:26:24 +0200 Subject: [PATCH] Fix race condition in `POST /api/v1/push/subscription` Fixes #30103 --- .../api/v1/push/subscriptions_controller.rb | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb index 3634acf956..7a9a4763ad 100644 --- a/app/controllers/api/v1/push/subscriptions_controller.rb +++ b/app/controllers/api/v1/push/subscriptions_controller.rb @@ -1,9 +1,12 @@ # frozen_string_literal: true class Api::V1::Push::SubscriptionsController < Api::BaseController + include Redisable + include Lockable + before_action -> { doorkeeper_authorize! :push } before_action :require_user! - before_action :set_push_subscription + before_action :set_push_subscription, only: [:show, :update] before_action :check_push_subscription, only: [:show, :update] def show @@ -11,16 +14,18 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController end def create - @push_subscription&.destroy! + with_redis_lock("push_subscription:#{current_user.id}") do + Web::PushSubscription.where(access_token_id: doorkeeper_token.id).destroy_all - @push_subscription = Web::PushSubscription.create!( - endpoint: subscription_params[:endpoint], - key_p256dh: subscription_params[:keys][:p256dh], - key_auth: subscription_params[:keys][:auth], - data: data_params, - user_id: current_user.id, - access_token_id: doorkeeper_token.id - ) + @push_subscription = Web::PushSubscription.create!( + endpoint: subscription_params[:endpoint], + key_p256dh: subscription_params[:keys][:p256dh], + key_auth: subscription_params[:keys][:auth], + data: data_params, + user_id: current_user.id, + access_token_id: doorkeeper_token.id + ) + end render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer end @@ -31,7 +36,7 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController end def destroy - @push_subscription&.destroy! + Web::PushSubscription.where(access_token_id: doorkeeper_token.id).destroy_all render_empty end