diff --git a/app/controllers/settings/push_notifications_controller.rb b/app/controllers/settings/push_notifications_controller.rb index 551ae46e..f207cb32 100644 --- a/app/controllers/settings/push_notifications_controller.rb +++ b/app/controllers/settings/push_notifications_controller.rb @@ -4,6 +4,6 @@ class Settings::PushNotificationsController < ApplicationController before_action :authenticate_user! def index - @subscriptions = current_user.web_push_subscriptions + @subscriptions = current_user.web_push_subscriptions.active end end diff --git a/app/models/user/push_notification_methods.rb b/app/models/user/push_notification_methods.rb index f2446805..01138633 100644 --- a/app/models/user/push_notification_methods.rb +++ b/app/models/user/push_notification_methods.rb @@ -4,7 +4,7 @@ module User::PushNotificationMethods def push_notification(app, resource) raise ArgumentError("Resource must respond to `as_push_notification`") unless resource.respond_to? :as_push_notification - web_push_subscriptions.each do |s| + web_push_subscriptions.active.find_each do |s| n = Rpush::Webpush::Notification.new n.app = app n.registration_ids = [s.subscription.symbolize_keys] diff --git a/app/models/web_push_subscription.rb b/app/models/web_push_subscription.rb index dddf28db..6821d10b 100644 --- a/app/models/web_push_subscription.rb +++ b/app/models/web_push_subscription.rb @@ -2,4 +2,7 @@ class WebPushSubscription < ApplicationRecord belongs_to :user + + scope :active, -> { where(failures: ...3) } + scope :failed, -> { where(failures: 3..) } end diff --git a/config/initializers/rpush.rb b/config/initializers/rpush.rb index 0aaf129c..3cb8eb77 100644 --- a/config/initializers/rpush.rb +++ b/config/initializers/rpush.rb @@ -57,8 +57,14 @@ Rpush.reflect do |on| # Called when notification delivery failed. # Call 'error_code' and 'error_description' on the notification for the cause. - # on.notification_failed do |notification| - # end + on.notification_failed do |notification| + # See: https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_safari_and_other_browsers#3994594 + if %i[403 410].include? notification.error_code + subscription = WebPushSubscription::where("subscription ->> 'endpoint' = ?", notification.registration_ids.first[:endpoint]) + subscription.increment :failures + subscription.save + end + end # Called when the notification delivery failed and only the notification ID # is present in memory. diff --git a/db/migrate/20221226101907_add_failures_to_web_push_subscriptions.rb b/db/migrate/20221226101907_add_failures_to_web_push_subscriptions.rb new file mode 100644 index 00000000..e52b50e7 --- /dev/null +++ b/db/migrate/20221226101907_add_failures_to_web_push_subscriptions.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddFailuresToWebPushSubscriptions < ActiveRecord::Migration[6.1] + def change + add_column :web_push_subscriptions, :failures, :integer, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index 6c2491d6..05514255 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -387,6 +387,7 @@ ActiveRecord::Schema.define(version: 2022_12_27_065923) do t.json "subscription" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.integer "failures", default: 0 t.index ["user_id"], name: "index_web_push_subscriptions_on_user_id" end