rpush 5.2.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +59 -0
  3. data/README.md +53 -8
  4. data/lib/generators/templates/add_adm.rb +1 -1
  5. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +2 -2
  6. data/lib/generators/templates/add_app_to_rapns.rb +2 -2
  7. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
  8. data/lib/generators/templates/add_gcm.rb +11 -25
  9. data/lib/generators/templates/add_rpush.rb +33 -83
  10. data/lib/generators/templates/add_wpns.rb +1 -1
  11. data/lib/generators/templates/create_rapns_apps.rb +1 -1
  12. data/lib/generators/templates/create_rapns_feedback.rb +3 -9
  13. data/lib/generators/templates/create_rapns_notifications.rb +3 -9
  14. data/lib/generators/templates/rename_rapns_to_rpush.rb +9 -33
  15. data/lib/generators/templates/rpush.rb +1 -4
  16. data/lib/generators/templates/rpush_2_0_0_updates.rb +5 -17
  17. data/lib/generators/templates/rpush_2_1_0_updates.rb +1 -1
  18. data/lib/generators/templates/rpush_2_6_0_updates.rb +1 -1
  19. data/lib/generators/templates/rpush_2_7_0_updates.rb +1 -1
  20. data/lib/generators/templates/rpush_3_0_0_updates.rb +1 -1
  21. data/lib/generators/templates/rpush_3_0_1_updates.rb +1 -1
  22. data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +1 -1
  23. data/lib/generators/templates/rpush_3_1_1_updates.rb +1 -1
  24. data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +1 -1
  25. data/lib/generators/templates/rpush_3_2_4_updates.rb +1 -1
  26. data/lib/generators/templates/rpush_3_3_0_updates.rb +1 -1
  27. data/lib/generators/templates/rpush_3_3_1_updates.rb +3 -3
  28. data/lib/generators/templates/rpush_4_1_0_updates.rb +1 -1
  29. data/lib/generators/templates/rpush_4_1_1_updates.rb +1 -1
  30. data/lib/generators/templates/rpush_4_2_0_updates.rb +1 -1
  31. data/lib/rpush/client/active_model/adm/data_validator.rb +1 -1
  32. data/lib/rpush/client/active_model/apns/app.rb +1 -17
  33. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +2 -2
  34. data/lib/rpush/client/active_model/apns/notification.rb +4 -0
  35. data/lib/rpush/client/active_model/apns/notification_payload_size_validator.rb +1 -1
  36. data/lib/rpush/client/active_model/apns2/app.rb +7 -1
  37. data/lib/rpush/client/active_model/certificate_private_key_validator.rb +19 -0
  38. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +1 -1
  39. data/lib/rpush/client/active_model/payload_data_size_validator.rb +1 -1
  40. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +1 -1
  41. data/lib/rpush/client/active_model/webpush/app.rb +41 -0
  42. data/lib/rpush/client/active_model/webpush/notification.rb +66 -0
  43. data/lib/rpush/client/active_model.rb +4 -0
  44. data/lib/rpush/client/active_record/apnsp8/notification.rb +1 -0
  45. data/lib/rpush/client/active_record/webpush/app.rb +11 -0
  46. data/lib/rpush/client/active_record/webpush/notification.rb +12 -0
  47. data/lib/rpush/client/active_record.rb +3 -0
  48. data/lib/rpush/client/redis/apnsp8/notification.rb +2 -0
  49. data/lib/rpush/client/redis/webpush/app.rb +15 -0
  50. data/lib/rpush/client/redis/webpush/notification.rb +15 -0
  51. data/lib/rpush/client/redis.rb +3 -0
  52. data/lib/rpush/configuration.rb +1 -1
  53. data/lib/rpush/daemon/apns2/delivery.rb +8 -1
  54. data/lib/rpush/daemon/apnsp8/delivery.rb +7 -1
  55. data/lib/rpush/daemon/string_helpers.rb +1 -1
  56. data/lib/rpush/daemon/webpush/delivery.rb +114 -0
  57. data/lib/rpush/daemon/webpush.rb +10 -0
  58. data/lib/rpush/daemon.rb +3 -0
  59. data/lib/rpush/version.rb +3 -3
  60. data/spec/functional/apns2_spec.rb +14 -2
  61. data/spec/functional/retry_spec.rb +1 -1
  62. data/spec/functional/webpush_spec.rb +31 -0
  63. data/spec/spec_helper.rb +3 -1
  64. data/spec/support/active_record_setup.rb +4 -3
  65. data/spec/support/config/database.yml +4 -4
  66. data/spec/support/simplecov_helper.rb +1 -1
  67. data/spec/unit/client/active_record/apns/notification_spec.rb +1 -1
  68. data/spec/unit/client/active_record/apns2/app_spec.rb +1 -0
  69. data/spec/unit/client/active_record/apns2/notification_spec.rb +1 -1
  70. data/spec/unit/client/active_record/apnsp8/notification_spec.rb +28 -0
  71. data/spec/unit/client/active_record/webpush/app_spec.rb +6 -0
  72. data/spec/unit/client/active_record/webpush/notification_spec.rb +6 -0
  73. data/spec/unit/client/redis/apns/notification_spec.rb +1 -1
  74. data/spec/unit/client/redis/apns2/notification_spec.rb +1 -1
  75. data/spec/unit/client/redis/apnsp8/notification_spec.rb +29 -0
  76. data/spec/unit/client/redis/webpush/app_spec.rb +5 -0
  77. data/spec/unit/client/redis/webpush/notification_spec.rb +5 -0
  78. data/spec/unit/client/shared/apns/notification.rb +15 -0
  79. data/spec/unit/client/shared/webpush/app.rb +33 -0
  80. data/spec/unit/client/shared/webpush/notification.rb +83 -0
  81. data/spec/unit/daemon/apnsp8/delivery_spec.rb +53 -0
  82. data/spec/unit/daemon/pushy/delivery_spec.rb +5 -3
  83. data/spec/unit/daemon/webpush/delivery_spec.rb +144 -0
  84. metadata +50 -5
@@ -1,4 +1,4 @@
1
- class RenameRapnsToRpush < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class RenameRapnsToRpush < ActiveRecord::Migration[5.0]
2
2
  module Rpush
3
3
  class App < ActiveRecord::Base
4
4
  self.table_name = 'rpush_apps'
@@ -18,24 +18,12 @@ class RenameRapnsToRpush < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Mig
18
18
  rename_table :rapns_apps, :rpush_apps
19
19
  rename_table :rapns_feedback, :rpush_feedback
20
20
 
21
- if ActiveRecord.version >= Gem::Version.new('5.1')
22
- if index_name_exists?(:rpush_notifications, :index_rapns_notifications_multi)
23
- rename_index :rpush_notifications, :index_rapns_notifications_multi, :index_rpush_notifications_multi
24
- end
25
- else
26
- if index_name_exists?(:rpush_notifications, :index_rapns_notifications_multi, true)
27
- rename_index :rpush_notifications, :index_rapns_notifications_multi, :index_rpush_notifications_multi
28
- end
21
+ if index_name_exists?(:rpush_notifications, :index_rapns_notifications_multi)
22
+ rename_index :rpush_notifications, :index_rapns_notifications_multi, :index_rpush_notifications_multi
29
23
  end
30
24
 
31
- if ActiveRecord.version >= Gem::Version.new('5.1')
32
- if index_name_exists?(:rpush_feedback, :index_rapns_feedback_on_device_token)
33
- rename_index :rpush_feedback, :index_rapns_feedback_on_device_token, :index_rpush_feedback_on_device_token
34
- end
35
- else
36
- if index_name_exists?(:rpush_feedback, :index_rapns_feedback_on_device_token, true)
37
- rename_index :rpush_feedback, :index_rapns_feedback_on_device_token, :index_rpush_feedback_on_device_token
38
- end
25
+ if index_name_exists?(:rpush_feedback, :index_rapns_feedback_on_device_token)
26
+ rename_index :rpush_feedback, :index_rapns_feedback_on_device_token, :index_rpush_feedback_on_device_token
39
27
  end
40
28
 
41
29
  update_type(RenameRapnsToRpush::Rpush::Notification, 'Rapns::Apns::Notification', 'Rpush::Apns::Notification')
@@ -60,24 +48,12 @@ class RenameRapnsToRpush < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Mig
60
48
  update_type(RenameRapnsToRpush::Rpush::App, 'Rpush::Adm::App', 'Rapns::Adm::App')
61
49
  update_type(RenameRapnsToRpush::Rpush::App, 'Rpush::Wpns::App', 'Rapns::Wpns::App')
62
50
 
63
- if ActiveRecord.version >= Gem::Version.new('5.1')
64
- if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
65
- rename_index :rpush_notifications, :index_rpush_notifications_multi, :index_rapns_notifications_multi
66
- end
67
- else
68
- if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
69
- rename_index :rpush_notifications, :index_rpush_notifications_multi, :index_rapns_notifications_multi
70
- end
51
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
52
+ rename_index :rpush_notifications, :index_rpush_notifications_multi, :index_rapns_notifications_multi
71
53
  end
72
54
 
73
- if ActiveRecord.version >= Gem::Version.new('5.1')
74
- if index_name_exists?(:rpush_feedback, :index_rpush_feedback_on_device_token)
75
- rename_index :rpush_feedback, :index_rpush_feedback_on_device_token, :index_rapns_feedback_on_device_token
76
- end
77
- else
78
- if index_name_exists?(:rpush_feedback, :index_rpush_feedback_on_device_token, true)
79
- rename_index :rpush_feedback, :index_rpush_feedback_on_device_token, :index_rapns_feedback_on_device_token
80
- end
55
+ if index_name_exists?(:rpush_feedback, :index_rpush_feedback_on_device_token)
56
+ rename_index :rpush_feedback, :index_rpush_feedback_on_device_token, :index_rapns_feedback_on_device_token
81
57
  end
82
58
 
83
59
  rename_table :rpush_notifications, :rapns_notifications
@@ -46,10 +46,7 @@ Rpush.reflect do |on|
46
46
  # Called when a notification is queued internally for delivery.
47
47
  # The internal queue for each app runner can be inspected:
48
48
  #
49
- # Rpush::Daemon::AppRunner.runners.each do |app_id, runner|
50
- # runner.app
51
- # runner.queue_size
52
- # end
49
+ # Rpush::Daemon::AppRunner.status
53
50
  #
54
51
  # on.notification_enqueued do |notification|
55
52
  # end
@@ -1,4 +1,4 @@
1
- class Rpush200Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush200Updates < ActiveRecord::Migration[5.0]
2
2
  module Rpush
3
3
  class App < ActiveRecord::Base
4
4
  self.table_name = 'rpush_apps'
@@ -17,14 +17,8 @@ class Rpush200Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migrat
17
17
  add_column :rpush_notifications, :processing, :boolean, null: false, default: false
18
18
  add_column :rpush_notifications, :priority, :integer, null: true
19
19
 
20
- if ActiveRecord.version >= Gem::Version.new('5.1')
21
- if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
22
- remove_index :rpush_notifications, name: :index_rpush_notifications_multi
23
- end
24
- else
25
- if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
26
- remove_index :rpush_notifications, name: :index_rpush_notifications_multi
27
- end
20
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
21
+ remove_index :rpush_notifications, name: :index_rpush_notifications_multi
28
22
  end
29
23
 
30
24
  add_index :rpush_notifications, [:delivered, :failed], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed'
@@ -52,14 +46,8 @@ class Rpush200Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migrat
52
46
  change_column :rpush_feedback, :app_id, :string
53
47
  rename_column :rpush_feedback, :app_id, :app
54
48
 
55
- if ActiveRecord.version >= Gem::Version.new('5.1')
56
- if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
57
- remove_index :rpush_notifications, name: :index_rpush_notifications_multi
58
- end
59
- else
60
- if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
61
- remove_index :rpush_notifications, name: :index_rpush_notifications_multi
62
- end
49
+ if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi)
50
+ remove_index :rpush_notifications, name: :index_rpush_notifications_multi
63
51
  end
64
52
 
65
53
  add_index :rpush_notifications, [:app_id, :delivered, :failed, :deliver_after], name: 'index_rpush_notifications_multi'
@@ -1,4 +1,4 @@
1
- class Rpush210Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush210Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :url_args, :text, null: true
4
4
  add_column :rpush_notifications, :category, :string, null: true
@@ -1,4 +1,4 @@
1
- class Rpush260Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush260Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :content_available, :boolean, default: false
4
4
  end
@@ -1,4 +1,4 @@
1
- class Rpush270Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush270Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  change_column :rpush_notifications, :alert, :text
4
4
  add_column :rpush_notifications, :notification, :text
@@ -1,4 +1,4 @@
1
- class Rpush300Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush300Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :mutable_content, :boolean, default: false
4
4
  change_column :rpush_notifications, :sound, :string, default: nil
@@ -1,4 +1,4 @@
1
- class Rpush301Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush301Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  change_column_null :rpush_notifications, :mutable_content, false
4
4
  change_column_null :rpush_notifications, :content_available, false
@@ -1,4 +1,4 @@
1
- class Rpush310AddPushy < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush310AddPushy < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :external_device_id, :string, null: true
4
4
  end
@@ -1,4 +1,4 @@
1
- class Rpush311Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush311Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  change_table :rpush_notifications do |t|
4
4
  t.remove_index name: 'index_rpush_notifications_multi'
@@ -1,4 +1,4 @@
1
- class Rpush320AddApnsP8 < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush320AddApnsP8 < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  add_column :rpush_apps, :apn_key, :string, null: true
4
4
  add_column :rpush_apps, :apn_key_id, :string, null: true
@@ -1,4 +1,4 @@
1
- class Rpush324Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush324Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  change_column :rpush_apps, :apn_key, :text, null: true
4
4
  end
@@ -1,4 +1,4 @@
1
- class Rpush330Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush330Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :thread_id, :string, null: true
4
4
  end
@@ -1,11 +1,11 @@
1
- class Rpush331Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
1
+ class Rpush331Updates < ActiveRecord::Migration[5.0]
2
2
  def self.up
3
3
  change_column :rpush_notifications, :device_token, :string, null: true
4
4
  change_column :rpush_feedback, :device_token, :string, null: true
5
5
  end
6
6
 
7
7
  def self.down
8
- change_column :rpush_notifications, :device_token, :string, { null: true, limit: 64 }
9
- change_column :rpush_feedback, :device_token, :string, { null: true, limit: 64 }
8
+ change_column :rpush_notifications, :device_token, :string, null: true, limit: 64
9
+ change_column :rpush_feedback, :device_token, :string, null: true, limit: 64
10
10
  end
11
11
  end
@@ -1,4 +1,4 @@
1
- class Rpush410Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"] : ActiveRecord::Migration
1
+ class Rpush410Updates < ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :dry_run, :boolean, null: false, default: false
4
4
  end
@@ -1,4 +1,4 @@
1
- class Rpush411Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"] : ActiveRecord::Migration
1
+ class Rpush411Updates < ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
2
2
  def self.up
3
3
  add_column :rpush_apps, :feedback_enabled, :boolean, default: true
4
4
  end
@@ -1,4 +1,4 @@
1
- class Rpush420Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"] : ActiveRecord::Migration
1
+ class Rpush420Updates < ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
2
2
  def self.up
3
3
  add_column :rpush_notifications, :sound_is_json, :boolean, null: true, default: false
4
4
  end
@@ -5,7 +5,7 @@ module Rpush
5
5
  class DataValidator < ::ActiveModel::Validator
6
6
  def validate(record)
7
7
  return unless record.collapse_key.nil? && record.data.nil?
8
- record.errors[:data] << 'must be set unless collapse_key is specified'
8
+ record.errors.add :data, 'must be set unless collapse_key is specified'
9
9
  end
10
10
  end
11
11
  end
@@ -7,29 +7,13 @@ module Rpush
7
7
  base.instance_eval do
8
8
  validates :environment, presence: true, inclusion: { in: %w(development production sandbox) }
9
9
  validates :certificate, presence: true
10
- validate :certificate_has_matching_private_key
10
+ validates_with Rpush::Client::ActiveModel::CertificatePrivateKeyValidator
11
11
  end
12
12
  end
13
13
 
14
14
  def service_name
15
15
  'apns'
16
16
  end
17
-
18
- private
19
-
20
- def certificate_has_matching_private_key
21
- result = false
22
- if certificate.present?
23
- begin
24
- x509 = OpenSSL::X509::Certificate.new(certificate)
25
- pkey = OpenSSL::PKey::RSA.new(certificate, password)
26
- result = x509 && pkey
27
- rescue OpenSSL::OpenSSLError
28
- errors.add :certificate, 'value must contain a certificate and a private key.'
29
- end
30
- end
31
- result
32
- end
33
17
  end
34
18
  end
35
19
  end
@@ -4,8 +4,8 @@ module Rpush
4
4
  module Apns
5
5
  class DeviceTokenFormatValidator < ::ActiveModel::Validator
6
6
  def validate(record)
7
- return if record.device_token =~ /^[a-z0-9]\w+$/i
8
- record.errors[:device_token] << "is invalid"
7
+ return if record.device_token =~ /\A[a-z0-9]\w+\z/i
8
+ record.errors.add :device_token, "is invalid"
9
9
  end
10
10
  end
11
11
  end
@@ -52,6 +52,10 @@ module Rpush
52
52
  self.data = (data || {}).merge(CONTENT_AVAILABLE_KEY => true)
53
53
  end
54
54
 
55
+ def content_available?
56
+ (self.data || {})[CONTENT_AVAILABLE_KEY]
57
+ end
58
+
55
59
  def as_json(options = nil) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
56
60
  json = ActiveSupport::OrderedHash.new
57
61
 
@@ -6,7 +6,7 @@ module Rpush
6
6
  def validate(record)
7
7
  limit = record.class.max_payload_bytesize
8
8
  return unless record.payload.bytesize > limit
9
- record.errors[:base] << "APN notification cannot be larger than #{limit} bytes. Try condensing your alert and device attributes."
9
+ record.errors.add :base, "APN notification cannot be larger than #{limit} bytes. Try condensing your alert and device attributes."
10
10
  end
11
11
  end
12
12
  end
@@ -3,7 +3,13 @@ module Rpush
3
3
  module ActiveModel
4
4
  module Apns2
5
5
  module App
6
- extend Rpush::Client::ActiveModel::Apns::App
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ validates :environment, presence: true, inclusion: { in: %w(development production sandbox) }
9
+ validates :certificate, presence: true
10
+ validates_with Rpush::Client::ActiveModel::CertificatePrivateKeyValidator
11
+ end
12
+ end
7
13
 
8
14
  def service_name
9
15
  'apns2'
@@ -0,0 +1,19 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ class CertificatePrivateKeyValidator < ::ActiveModel::Validator
5
+ def validate(record)
6
+ if record.certificate.present?
7
+ begin
8
+ x509 = OpenSSL::X509::Certificate.new(record.certificate)
9
+ pkey = OpenSSL::PKey::RSA.new(record.certificate, record.password)
10
+ x509 && pkey
11
+ rescue OpenSSL::OpenSSLError
12
+ record.errors.add :certificate, 'value must contain a certificate and a private key.'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,7 +5,7 @@ module Rpush
5
5
  class ExpiryCollapseKeyMutualInclusionValidator < ::ActiveModel::Validator
6
6
  def validate(record)
7
7
  return unless record.collapse_key && !record.expiry
8
- record.errors[:expiry] << 'must be set when using a collapse_key'
8
+ record.errors.add :expiry, 'must be set when using a collapse_key'
9
9
  end
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ module Rpush
5
5
  def validate(record)
6
6
  limit = options[:limit] || 1024
7
7
  return unless record.data && record.payload_data_size > limit
8
- record.errors[:base] << "Notification payload data cannot be larger than #{limit} bytes."
8
+ record.errors.add :base, "Notification payload data cannot be larger than #{limit} bytes."
9
9
  end
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ module Rpush
5
5
  def validate(record)
6
6
  limit = options[:limit] || 100
7
7
  return unless record.registration_ids && record.registration_ids.size > limit
8
- record.errors[:base] << "Number of registration_ids cannot be larger than #{limit}."
8
+ record.errors.add :base, "Number of registration_ids cannot be larger than #{limit}."
9
9
  end
10
10
  end
11
11
  end
@@ -0,0 +1,41 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Webpush
5
+ module App
6
+
7
+ class VapidKeypairValidator < ::ActiveModel::Validator
8
+ def validate(record)
9
+ return if record.vapid_keypair.blank?
10
+ keypair = record.vapid
11
+ %i[ subject public_key private_key ].each do |key|
12
+ unless keypair.key?(key)
13
+ record.errors.add(:vapid_keypair, "must have a #{key} entry")
14
+ end
15
+ end
16
+ rescue
17
+ record.errors.add(:vapid_keypair, 'must be valid JSON')
18
+ end
19
+ end
20
+
21
+ def self.included(base)
22
+ base.class_eval do
23
+ alias_attribute :vapid_keypair, :certificate
24
+ validates :vapid_keypair, presence: true
25
+ validates_with VapidKeypairValidator
26
+ end
27
+ end
28
+
29
+ def service_name
30
+ 'webpush'
31
+ end
32
+
33
+ def vapid
34
+ @vapid ||= JSON.parse(vapid_keypair).symbolize_keys
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,66 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Webpush
5
+ module Notification
6
+
7
+ class RegistrationValidator < ::ActiveModel::Validator
8
+ KEYS = %i[ endpoint keys ].freeze
9
+ def validate(record)
10
+ return if record.registration_ids.blank?
11
+ return if record.registration_ids.size > 1
12
+ reg = record.registration_ids.first
13
+ unless reg.is_a?(Hash) &&
14
+ (KEYS-reg.keys).empty? &&
15
+ reg[:endpoint].is_a?(String) &&
16
+ reg[:keys].is_a?(Hash)
17
+ record.errors.add(:base, 'Registration must have :endpoint (String) and :keys (Hash) keys')
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.included(base)
23
+ base.instance_eval do
24
+ alias_attribute :time_to_live, :expiry
25
+
26
+ validates :registration_ids, presence: true
27
+ validates :data, presence: true
28
+ validates :time_to_live, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
29
+
30
+ validates_with Rpush::Client::ActiveModel::PayloadDataSizeValidator, limit: 4096
31
+ validates_with Rpush::Client::ActiveModel::RegistrationIdsCountValidator, limit: 1
32
+ validates_with RegistrationValidator
33
+ end
34
+ end
35
+
36
+ def data=(value)
37
+ value = value.stringify_keys if value.respond_to?(:stringify_keys)
38
+ super value
39
+ end
40
+
41
+ def subscription
42
+ @subscription ||= registration_ids.first.deep_symbolize_keys
43
+ end
44
+
45
+ def message
46
+ data['message'].presence if data
47
+ end
48
+
49
+ # https://webpush-wg.github.io/webpush-protocol/#urgency
50
+ def urgency
51
+ data['urgency'].presence if data
52
+ end
53
+
54
+ def as_json(_options = nil)
55
+ {
56
+ 'data' => data,
57
+ 'time_to_live' => time_to_live,
58
+ 'registration_ids' => registration_ids
59
+ }
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -3,6 +3,7 @@ require 'active_model'
3
3
  require 'rpush/client/active_model/notification'
4
4
  require 'rpush/client/active_model/payload_data_size_validator'
5
5
  require 'rpush/client/active_model/registration_ids_count_validator'
6
+ require 'rpush/client/active_model/certificate_private_key_validator'
6
7
 
7
8
  require 'rpush/client/active_model/apns/device_token_format_validator'
8
9
  require 'rpush/client/active_model/apns/app'
@@ -32,3 +33,6 @@ require 'rpush/client/active_model/wns/notification'
32
33
  require 'rpush/client/active_model/pushy/app'
33
34
  require 'rpush/client/active_model/pushy/notification'
34
35
  require 'rpush/client/active_model/pushy/time_to_live_validator'
36
+
37
+ require 'rpush/client/active_model/webpush/app'
38
+ require 'rpush/client/active_model/webpush/notification'
@@ -3,6 +3,7 @@ module Rpush
3
3
  module ActiveRecord
4
4
  module Apnsp8
5
5
  class Notification < Rpush::Client::ActiveRecord::Apns::Notification
6
+ include Rpush::Client::ActiveModel::Apns2::Notification
6
7
  end
7
8
  end
8
9
  end
@@ -0,0 +1,11 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Webpush
5
+ class App < Rpush::Client::ActiveRecord::App
6
+ include Rpush::Client::ActiveModel::Webpush::App
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Webpush
5
+ class Notification < Rpush::Client::ActiveRecord::Notification
6
+ include Rpush::Client::ActiveModel::Webpush::Notification
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -32,3 +32,6 @@ require 'rpush/client/active_record/adm/app'
32
32
 
33
33
  require 'rpush/client/active_record/pushy/notification'
34
34
  require 'rpush/client/active_record/pushy/app'
35
+
36
+ require 'rpush/client/active_record/webpush/notification'
37
+ require 'rpush/client/active_record/webpush/app'
@@ -3,6 +3,8 @@ module Rpush
3
3
  module Redis
4
4
  module Apnsp8
5
5
  class Notification < Rpush::Client::Redis::Notification
6
+ include Rpush::Client::ActiveModel::Apns::Notification
7
+ include Rpush::Client::ActiveModel::Apns2::Notification
6
8
  include Rpush::Client::ActiveModel::Apnsp8::Notification
7
9
  end
8
10
  end
@@ -0,0 +1,15 @@
1
+ module Rpush
2
+ module Client
3
+ module Redis
4
+ module Webpush
5
+ class App < Rpush::Client::Redis::App
6
+ include Rpush::Client::ActiveModel::Webpush::App
7
+
8
+ def vapid_keypair=(value)
9
+ self.certificate = value
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Rpush
2
+ module Client
3
+ module Redis
4
+ module Webpush
5
+ class Notification < Rpush::Client::Redis::Notification
6
+ include Rpush::Client::ActiveModel::Webpush::Notification
7
+
8
+ def time_to_live=(value)
9
+ self.expiry = value
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -44,6 +44,9 @@ require 'rpush/client/redis/wns/badge_notification'
44
44
  require 'rpush/client/redis/pushy/app'
45
45
  require 'rpush/client/redis/pushy/notification'
46
46
 
47
+ require 'rpush/client/redis/webpush/app'
48
+ require 'rpush/client/redis/webpush/notification'
49
+
47
50
  Modis.configure do |config|
48
51
  config.namespace = :rpush
49
52
  end
@@ -106,7 +106,7 @@ module Rpush
106
106
  client_module = Rpush::Client.const_get(client.to_s.camelize)
107
107
  Rpush.send(:include, client_module) unless Rpush.ancestors.include?(client_module)
108
108
 
109
- [:Apns, :Gcm, :Wpns, :Wns, :Adm, :Pushy].each do |service|
109
+ [:Apns, :Gcm, :Wpns, :Wns, :Adm, :Pushy, :Webpush].each do |service|
110
110
  Rpush.const_set(service, client_module.const_get(service)) unless Rpush.const_defined?(service)
111
111
  end
112
112
 
@@ -107,7 +107,14 @@ module Rpush
107
107
  end
108
108
 
109
109
  def prepare_headers(notification)
110
- notification_data(notification)[HTTP2_HEADERS_KEY] || {}
110
+ headers = {}
111
+
112
+ headers['apns-expiration'] = '0'
113
+ headers['apns-priority'] = '10'
114
+ headers['apns-topic'] = @app.bundle_id
115
+ headers['apns-push-type'] = 'background' if notification.content_available?
116
+
117
+ headers.merge notification_data(notification)[HTTP2_HEADERS_KEY] || {}
111
118
  end
112
119
 
113
120
  def notification_data(notification)