Add endpoint to remove web push subscription (#32626)
This commit is contained in:
parent
d1b20ea8f7
commit
05f23df3b7
@ -1,7 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
||||||
before_action :require_user!
|
before_action :require_user!, except: :destroy
|
||||||
before_action :set_push_subscription, only: :update
|
before_action :set_push_subscription, only: :update
|
||||||
before_action :destroy_previous_subscriptions, only: :create, if: :prior_subscriptions?
|
before_action :destroy_previous_subscriptions, only: :create, if: :prior_subscriptions?
|
||||||
after_action :update_session_with_subscription, only: :create
|
after_action :update_session_with_subscription, only: :create
|
||||||
@ -17,6 +17,13 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
|||||||
render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer
|
render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
push_subscription = ::Web::PushSubscription.find_by_token_for(:unsubscribe, params[:id])
|
||||||
|
push_subscription&.destroy
|
||||||
|
|
||||||
|
head 200
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def active_session
|
def active_session
|
||||||
|
@ -29,6 +29,8 @@ class Web::PushSubscription < ApplicationRecord
|
|||||||
|
|
||||||
delegate :locale, to: :associated_user
|
delegate :locale, to: :associated_user
|
||||||
|
|
||||||
|
generates_token_for :unsubscribe, expires_in: Web::PushNotificationWorker::TTL
|
||||||
|
|
||||||
def pushable?(notification)
|
def pushable?(notification)
|
||||||
policy_allows_notification?(notification) && alert_enabled_for_notification_type?(notification)
|
policy_allows_notification?(notification) && alert_enabled_for_notification_type?(notification)
|
||||||
end
|
end
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
class Web::PushNotificationWorker
|
class Web::PushNotificationWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
sidekiq_options queue: 'push', retry: 5
|
sidekiq_options queue: 'push', retry: 5
|
||||||
|
|
||||||
TTL = 48.hours.to_s
|
TTL = 48.hours
|
||||||
URGENCY = 'normal'
|
URGENCY = 'normal'
|
||||||
|
|
||||||
def perform(subscription_id, notification_id)
|
def perform(subscription_id, notification_id)
|
||||||
@ -23,12 +24,13 @@ class Web::PushNotificationWorker
|
|||||||
|
|
||||||
request.add_headers(
|
request.add_headers(
|
||||||
'Content-Type' => 'application/octet-stream',
|
'Content-Type' => 'application/octet-stream',
|
||||||
'Ttl' => TTL,
|
'Ttl' => TTL.to_s,
|
||||||
'Urgency' => URGENCY,
|
'Urgency' => URGENCY,
|
||||||
'Content-Encoding' => 'aesgcm',
|
'Content-Encoding' => 'aesgcm',
|
||||||
'Encryption' => "salt=#{Webpush.encode64(payload.fetch(:salt)).delete('=')}",
|
'Encryption' => "salt=#{Webpush.encode64(payload.fetch(:salt)).delete('=')}",
|
||||||
'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{web_push_request.crypto_key_header}",
|
'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{web_push_request.crypto_key_header}",
|
||||||
'Authorization' => web_push_request.authorization_header
|
'Authorization' => web_push_request.authorization_header,
|
||||||
|
'Unsubscribe-URL' => subscription_url
|
||||||
)
|
)
|
||||||
|
|
||||||
request.perform do |response|
|
request.perform do |response|
|
||||||
@ -72,4 +74,8 @@ class Web::PushNotificationWorker
|
|||||||
def request_pool
|
def request_pool
|
||||||
RequestPool.current
|
RequestPool.current
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def subscription_url
|
||||||
|
api_web_push_subscription_url(id: @subscription.generate_token_for(:unsubscribe))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -346,7 +346,7 @@ namespace :api, format: false do
|
|||||||
namespace :web do
|
namespace :web do
|
||||||
resource :settings, only: [:update]
|
resource :settings, only: [:update]
|
||||||
resources :embeds, only: [:show]
|
resources :embeds, only: [:show]
|
||||||
resources :push_subscriptions, only: [:create] do
|
resources :push_subscriptions, only: [:create, :destroy] do
|
||||||
member do
|
member do
|
||||||
put :update
|
put :update
|
||||||
end
|
end
|
||||||
|
55
spec/requests/api/web/push_subscriptions_spec.rb
Normal file
55
spec/requests/api/web/push_subscriptions_spec.rb
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'API Web Push Subscriptions' do
|
||||||
|
describe 'DELETE /api/web/push_subscriptions/:id' do
|
||||||
|
subject { delete api_web_push_subscription_path(token) }
|
||||||
|
|
||||||
|
context 'when the subscription exists' do
|
||||||
|
let!(:web_push_subscription) do
|
||||||
|
Fabricate(:web_push_subscription)
|
||||||
|
end
|
||||||
|
let(:token) do
|
||||||
|
web_push_subscription.generate_token_for(:unsubscribe)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes the subscription' do
|
||||||
|
expect { subject }
|
||||||
|
.to change(Web::PushSubscription, :count).by(-1)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the subscription does not exist' do
|
||||||
|
let(:web_push_subscription) do
|
||||||
|
Fabricate(:web_push_subscription)
|
||||||
|
end
|
||||||
|
let(:token) do
|
||||||
|
web_push_subscription.generate_token_for(:unsubscribe)
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
token # memoize before destroying the record
|
||||||
|
web_push_subscription.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does nothing' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the token is invalid' do
|
||||||
|
let(:token) { 'invalid--invalid' }
|
||||||
|
|
||||||
|
it 'does nothing' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -61,6 +61,7 @@ RSpec.describe Web::PushNotificationWorker do
|
|||||||
'Ttl' => '172800',
|
'Ttl' => '172800',
|
||||||
'Urgency' => 'normal',
|
'Urgency' => 'normal',
|
||||||
'Authorization' => 'WebPush jwt.encoded.payload',
|
'Authorization' => 'WebPush jwt.encoded.payload',
|
||||||
|
'Unsubscribe-URL' => %r{/api/web/push_subscriptions/},
|
||||||
},
|
},
|
||||||
body: "+\xB8\xDBT}\u0013\xB6\xDD.\xF9\xB0\xA7\xC8Ҁ\xFD\x99#\xF7\xAC\x83\xA4\xDB,\u001F\xB5\xB9w\x85>\xF7\xADr"
|
body: "+\xB8\xDBT}\u0013\xB6\xDD.\xF9\xB0\xA7\xC8Ҁ\xFD\x99#\xF7\xAC\x83\xA4\xDB,\u001F\xB5\xB9w\x85>\xF7\xADr"
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user