push_subscription.rb 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # frozen_string_literal: true
  2. # == Schema Information
  3. #
  4. # Table name: web_push_subscriptions
  5. #
  6. # id :bigint(8) not null, primary key
  7. # endpoint :string not null
  8. # key_p256dh :string not null
  9. # key_auth :string not null
  10. # data :json
  11. # created_at :datetime not null
  12. # updated_at :datetime not null
  13. # access_token_id :bigint(8)
  14. # user_id :bigint(8)
  15. #
  16. class Web::PushSubscription < ApplicationRecord
  17. belongs_to :user, optional: true
  18. belongs_to :access_token, class_name: 'Doorkeeper::AccessToken', optional: true
  19. has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription
  20. def push(notification)
  21. I18n.with_locale(associated_user&.locale || I18n.default_locale) do
  22. push_payload(payload_for_notification(notification), 48.hours.seconds)
  23. end
  24. end
  25. def pushable?(notification)
  26. data&.key?('alerts') && ActiveModel::Type::Boolean.new.cast(data['alerts'][notification.type.to_s])
  27. end
  28. def associated_user
  29. return @associated_user if defined?(@associated_user)
  30. @associated_user = if user_id.nil?
  31. session_activation.user
  32. else
  33. user
  34. end
  35. end
  36. def associated_access_token
  37. return @associated_access_token if defined?(@associated_access_token)
  38. @associated_access_token = if access_token_id.nil?
  39. find_or_create_access_token.token
  40. else
  41. access_token.token
  42. end
  43. end
  44. class << self
  45. def unsubscribe_for(application_id, resource_owner)
  46. access_token_ids = Doorkeeper::AccessToken.where(application_id: application_id, resource_owner_id: resource_owner.id, revoked_at: nil)
  47. .pluck(:id)
  48. where(access_token_id: access_token_ids).delete_all
  49. end
  50. end
  51. private
  52. def push_payload(message, ttl = 5.minutes.seconds)
  53. Webpush.payload_send(
  54. message: Oj.dump(message),
  55. endpoint: endpoint,
  56. p256dh: key_p256dh,
  57. auth: key_auth,
  58. ttl: ttl,
  59. ssl_timeout: 10,
  60. open_timeout: 10,
  61. read_timeout: 10,
  62. vapid: {
  63. subject: "mailto:#{::Setting.site_contact_email}",
  64. private_key: Rails.configuration.x.vapid_private_key,
  65. public_key: Rails.configuration.x.vapid_public_key,
  66. }
  67. )
  68. end
  69. def payload_for_notification(notification)
  70. ActiveModelSerializers::SerializableResource.new(
  71. notification,
  72. serializer: Web::NotificationSerializer,
  73. scope: self,
  74. scope_name: :current_push_subscription
  75. ).as_json
  76. end
  77. def find_or_create_access_token
  78. Doorkeeper::AccessToken.find_or_create_for(
  79. Doorkeeper::Application.find_by(superapp: true),
  80. session_activation.user_id,
  81. Doorkeeper::OAuth::Scopes.from_string('read write follow push'),
  82. Doorkeeper.configuration.access_token_expires_in,
  83. Doorkeeper.configuration.refresh_token_enabled?
  84. )
  85. end
  86. end