rpush 1.0.0-java → 2.0.0-java
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +37 -22
- data/bin/rpush +13 -4
- data/lib/generators/rpush_generator.rb +2 -0
- data/lib/generators/templates/add_adm.rb +5 -5
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +1 -1
- data/lib/generators/templates/add_app_to_rapns.rb +2 -2
- data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
- data/lib/generators/templates/add_gcm.rb +32 -32
- data/lib/generators/templates/add_rpush.rb +67 -67
- data/lib/generators/templates/add_wpns.rb +2 -2
- data/lib/generators/templates/create_rapns_apps.rb +5 -5
- data/lib/generators/templates/create_rapns_feedback.rb +2 -2
- data/lib/generators/templates/create_rapns_notifications.rb +15 -15
- data/lib/generators/templates/rpush.rb +28 -7
- data/lib/generators/templates/rpush_2_0_0_updates.rb +42 -0
- data/lib/rpush/client/active_model/adm/app.rb +23 -0
- data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
- data/lib/rpush/client/active_model/adm/notification.rb +28 -0
- data/lib/rpush/client/active_model/apns/app.rb +37 -0
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
- data/lib/rpush/client/active_model/apns/notification.rb +90 -0
- data/lib/rpush/client/active_model/gcm/app.rb +19 -0
- data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
- data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
- data/lib/rpush/client/active_model/notification.rb +26 -0
- data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
- data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
- data/lib/rpush/client/active_model/wpns/app.rb +13 -0
- data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
- data/lib/rpush/client/active_model.rb +21 -0
- data/lib/rpush/client/active_record/adm/app.rb +11 -0
- data/lib/rpush/client/active_record/adm/notification.rb +11 -0
- data/lib/rpush/client/active_record/apns/app.rb +11 -0
- data/lib/rpush/client/active_record/apns/feedback.rb +22 -0
- data/lib/rpush/client/active_record/apns/notification.rb +46 -0
- data/lib/rpush/client/active_record/app.rb +17 -0
- data/lib/rpush/client/active_record/gcm/app.rb +11 -0
- data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
- data/lib/rpush/client/active_record/notification.rb +38 -0
- data/lib/rpush/client/active_record/wpns/app.rb +11 -0
- data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
- data/lib/rpush/client/active_record.rb +19 -0
- data/lib/rpush/client/redis/adm/app.rb +14 -0
- data/lib/rpush/client/redis/adm/notification.rb +11 -0
- data/lib/rpush/client/redis/apns/app.rb +11 -0
- data/lib/rpush/client/redis/apns/feedback.rb +20 -0
- data/lib/rpush/client/redis/apns/notification.rb +11 -0
- data/lib/rpush/client/redis/app.rb +24 -0
- data/lib/rpush/client/redis/gcm/app.rb +11 -0
- data/lib/rpush/client/redis/gcm/notification.rb +11 -0
- data/lib/rpush/client/redis/notification.rb +68 -0
- data/lib/rpush/client/redis/wpns/app.rb +11 -0
- data/lib/rpush/client/redis/wpns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +35 -0
- data/lib/rpush/configuration.rb +27 -6
- data/lib/rpush/daemon/adm/delivery.rb +56 -55
- data/lib/rpush/daemon/apns/delivery.rb +20 -44
- data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
- data/lib/rpush/daemon/apns.rb +6 -5
- data/lib/rpush/daemon/app_runner.rb +103 -99
- data/lib/rpush/daemon/batch.rb +54 -40
- data/lib/rpush/daemon/delivery.rb +13 -3
- data/lib/rpush/daemon/delivery_error.rb +10 -2
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +114 -0
- data/lib/rpush/daemon/dispatcher/http.rb +3 -3
- data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
- data/lib/rpush/daemon/dispatcher_loop.rb +37 -23
- data/lib/rpush/daemon/errors.rb +18 -0
- data/lib/rpush/daemon/feeder.rb +28 -39
- data/lib/rpush/daemon/gcm/delivery.rb +19 -20
- data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
- data/lib/rpush/daemon/loggable.rb +2 -4
- data/lib/rpush/daemon/proc_title.rb +16 -0
- data/lib/rpush/daemon/queue_payload.rb +12 -0
- data/lib/rpush/daemon/reflectable.rb +3 -5
- data/lib/rpush/daemon/retry_header_parser.rb +6 -6
- data/lib/rpush/daemon/retryable_error.rb +2 -0
- data/lib/rpush/daemon/ring_buffer.rb +16 -0
- data/lib/rpush/daemon/service_config_methods.rb +23 -7
- data/lib/rpush/daemon/signal_handler.rb +56 -0
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +21 -17
- data/lib/rpush/daemon/store/active_record.rb +71 -38
- data/lib/rpush/daemon/store/interface.rb +19 -0
- data/lib/rpush/daemon/store/redis.rb +149 -0
- data/lib/rpush/daemon/string_helpers.rb +15 -0
- data/lib/rpush/daemon/synchronizer.rb +60 -0
- data/lib/rpush/daemon/tcp_connection.rb +6 -11
- data/lib/rpush/daemon/wpns/delivery.rb +21 -30
- data/lib/rpush/daemon.rb +40 -60
- data/lib/rpush/deprecatable.rb +4 -3
- data/lib/rpush/deprecation.rb +7 -10
- data/lib/rpush/embed.rb +8 -3
- data/lib/rpush/logger.rb +11 -15
- data/lib/rpush/push.rb +1 -2
- data/lib/rpush/reflection.rb +8 -12
- data/lib/rpush/version.rb +1 -1
- data/lib/rpush.rb +5 -29
- data/lib/tasks/quality.rake +35 -0
- data/lib/tasks/test.rake +1 -5
- data/spec/.rubocop.yml +4 -0
- data/spec/functional/adm_spec.rb +3 -6
- data/spec/functional/apns_spec.rb +117 -24
- data/spec/functional/embed_spec.rb +20 -20
- data/spec/functional/gcm_spec.rb +4 -7
- data/spec/functional/new_app_spec.rb +59 -0
- data/spec/functional/retry_spec.rb +46 -0
- data/spec/functional/synchronization_spec.rb +68 -0
- data/spec/functional/wpns_spec.rb +3 -6
- data/spec/functional_spec_helper.rb +26 -0
- data/spec/integration/rpush_spec.rb +13 -0
- data/spec/integration/support/gcm_success_response.json +1 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/active_record_setup.rb +48 -0
- data/{config → spec/support/config}/database.yml +0 -0
- data/spec/support/install.sh +43 -7
- data/spec/support/simplecov_helper.rb +9 -5
- data/spec/support/simplecov_quality_formatter.rb +10 -6
- data/spec/unit/apns_feedback_spec.rb +3 -3
- data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
- data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
- data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
- data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
- data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
- data/spec/unit/client/active_record/app_spec.rb +30 -0
- data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
- data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
- data/spec/unit/client/active_record/notification_spec.rb +21 -0
- data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
- data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
- data/spec/unit/configuration_spec.rb +12 -5
- data/spec/unit/daemon/adm/delivery_spec.rb +66 -55
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
- data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +22 -17
- data/spec/unit/daemon/app_runner_spec.rb +78 -186
- data/spec/unit/daemon/batch_spec.rb +52 -115
- data/spec/unit/daemon/delivery_spec.rb +15 -1
- data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
- data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
- data/spec/unit/daemon/dispatcher_loop_spec.rb +6 -24
- data/spec/unit/daemon/feeder_spec.rb +38 -39
- data/spec/unit/daemon/gcm/delivery_spec.rb +122 -101
- data/spec/unit/daemon/reflectable_spec.rb +2 -2
- data/spec/unit/daemon/retryable_error_spec.rb +1 -1
- data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
- data/spec/unit/daemon/signal_handler_spec.rb +95 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +48 -27
- data/spec/unit/daemon/store/active_record_spec.rb +38 -47
- data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
- data/spec/unit/daemon/wpns/delivery_spec.rb +58 -50
- data/spec/unit/daemon_spec.rb +48 -82
- data/spec/unit/embed_spec.rb +6 -4
- data/spec/unit/logger_spec.rb +35 -43
- data/spec/unit/notification_shared.rb +9 -79
- data/spec/unit/push_spec.rb +6 -10
- data/spec/unit/reflection_spec.rb +25 -25
- data/spec/unit/rpush_spec.rb +1 -2
- data/spec/unit_spec_helper.rb +33 -88
- metadata +126 -76
- data/lib/rpush/TODO +0 -3
- data/lib/rpush/adm/app.rb +0 -15
- data/lib/rpush/adm/data_validator.rb +0 -11
- data/lib/rpush/adm/notification.rb +0 -29
- data/lib/rpush/apns/app.rb +0 -29
- data/lib/rpush/apns/binary_notification_validator.rb +0 -12
- data/lib/rpush/apns/device_token_format_validator.rb +0 -12
- data/lib/rpush/apns/feedback.rb +0 -16
- data/lib/rpush/apns/notification.rb +0 -84
- data/lib/rpush/app.rb +0 -18
- data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
- data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
- data/lib/rpush/daemon/dispatcher_loop_collection.rb +0 -33
- data/lib/rpush/daemon/too_many_requests_error.rb +0 -20
- data/lib/rpush/gcm/app.rb +0 -11
- data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
- data/lib/rpush/gcm/notification.rb +0 -30
- data/lib/rpush/notification.rb +0 -69
- data/lib/rpush/notifier.rb +0 -52
- data/lib/rpush/payload_data_size_validator.rb +0 -10
- data/lib/rpush/railtie.rb +0 -11
- data/lib/rpush/registration_ids_count_validator.rb +0 -10
- data/lib/rpush/wpns/app.rb +0 -9
- data/lib/rpush/wpns/notification.rb +0 -26
- data/lib/tasks/cane.rake +0 -18
- data/lib/tasks/rpush.rake +0 -16
- data/spec/unit/apns/app_spec.rb +0 -29
- data/spec/unit/apns/feedback_spec.rb +0 -9
- data/spec/unit/apns/notification_spec.rb +0 -208
- data/spec/unit/app_spec.rb +0 -30
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
- data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +0 -37
- data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
- data/spec/unit/daemon/too_many_requests_error_spec.rb +0 -14
- data/spec/unit/gcm/app_spec.rb +0 -4
- data/spec/unit/notification_spec.rb +0 -15
- data/spec/unit/notifier_spec.rb +0 -49
- data/spec/unit/wpns/app_spec.rb +0 -4
- data/spec/unit/wpns/notification_spec.rb +0 -30
@@ -6,11 +6,11 @@ class AddWpns < ActiveRecord::Migration
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.up
|
9
|
-
add_column :rapns_notifications, :uri, :string, :
|
9
|
+
add_column :rapns_notifications, :uri, :string, null: true
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.down
|
13
|
-
AddWpns::Rapns::Notification.where(:
|
13
|
+
AddWpns::Rapns::Notification.where(type: 'Rapns::Wpns::Notification').delete_all
|
14
14
|
remove_column :rapns_notifications, :uri
|
15
15
|
end
|
16
16
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
class CreateRapnsApps < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
3
|
create_table :rapns_apps do |t|
|
4
|
-
t.string :key, :
|
5
|
-
t.string :environment, :
|
6
|
-
t.text :certificate, :
|
7
|
-
t.string :password, :
|
8
|
-
t.integer :connections, :
|
4
|
+
t.string :key, null: false
|
5
|
+
t.string :environment, null: false
|
6
|
+
t.text :certificate, null: false
|
7
|
+
t.string :password, null: true
|
8
|
+
t.integer :connections, null: false, default: 1
|
9
9
|
t.timestamps
|
10
10
|
end
|
11
11
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class CreateRapnsFeedback < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
3
|
create_table :rapns_feedback do |t|
|
4
|
-
t.string :device_token, :
|
5
|
-
t.timestamp :failed_at, :
|
4
|
+
t.string :device_token, null: false, limit: 64
|
5
|
+
t.timestamp :failed_at, null: false
|
6
6
|
t.timestamps
|
7
7
|
end
|
8
8
|
|
@@ -1,28 +1,28 @@
|
|
1
1
|
class CreateRapnsNotifications < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
3
|
create_table :rapns_notifications do |t|
|
4
|
-
t.integer :badge, :
|
5
|
-
t.string :device_token, :
|
6
|
-
t.string :sound, :
|
7
|
-
t.string :alert, :
|
8
|
-
t.text :attributes_for_device, :
|
9
|
-
t.integer :expiry, :
|
10
|
-
t.boolean :delivered, :
|
11
|
-
t.timestamp :delivered_at, :
|
12
|
-
t.boolean :failed, :
|
13
|
-
t.timestamp :failed_at, :
|
14
|
-
t.integer :error_code, :
|
15
|
-
t.string :error_description, :
|
16
|
-
t.timestamp :deliver_after, :
|
4
|
+
t.integer :badge, null: true
|
5
|
+
t.string :device_token, null: false, limit: 64
|
6
|
+
t.string :sound, null: true, default: "1.aiff"
|
7
|
+
t.string :alert, null: true
|
8
|
+
t.text :attributes_for_device, null: true
|
9
|
+
t.integer :expiry, null: false, default: 1.day.to_i
|
10
|
+
t.boolean :delivered, null: false, default: false
|
11
|
+
t.timestamp :delivered_at, null: true
|
12
|
+
t.boolean :failed, null: false, default: false
|
13
|
+
t.timestamp :failed_at, null: true
|
14
|
+
t.integer :error_code, null: true
|
15
|
+
t.string :error_description, null: true
|
16
|
+
t.timestamp :deliver_after, null: true
|
17
17
|
t.timestamps
|
18
18
|
end
|
19
19
|
|
20
|
-
add_index :rapns_notifications, [:delivered, :failed, :deliver_after], :
|
20
|
+
add_index :rapns_notifications, [:delivered, :failed, :deliver_after], name: 'index_rapns_notifications_multi'
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.down
|
24
24
|
if index_name_exists?(:rapns_notifications, 'index_rapns_notifications_multi', true)
|
25
|
-
remove_index :rapns_notifications, :
|
25
|
+
remove_index :rapns_notifications, name: 'index_rapns_notifications_multi'
|
26
26
|
end
|
27
27
|
drop_table :rapns_notifications
|
28
28
|
end
|
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
Rpush.configure do |config|
|
4
4
|
|
5
|
+
# Supported clients are :active_record and :redis.
|
6
|
+
# config.client = :active_record
|
7
|
+
|
8
|
+
# Options passed to Redis.new
|
9
|
+
# config.redis_options = {}
|
10
|
+
|
5
11
|
# Run in the foreground?
|
6
12
|
# config.foreground = false
|
7
13
|
|
@@ -11,15 +17,12 @@
|
|
11
17
|
# Frequency in seconds to check for feedback
|
12
18
|
# config.feedback_poll = 60
|
13
19
|
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
#
|
20
|
+
# The maximum number of notifications to load from the store every `push_poll` seconds.
|
21
|
+
# If some notifications are still enqueued internally, Rpush will load the batch_size less
|
22
|
+
# the number enqueued. An exception to this is if the service is able to receive multiple
|
23
|
+
# notification payloads over the connection with a single write, such as APNs.
|
18
24
|
# config.batch_size = 100
|
19
25
|
|
20
|
-
# Perform updates to the storage backend in batches to reduce IO.
|
21
|
-
# config.batch_storage_updates = true
|
22
|
-
|
23
26
|
# Path to write PID file. Relative to Rails root unless absolute.
|
24
27
|
# config.pid_file = '/path/to/rpush.pid'
|
25
28
|
|
@@ -56,12 +59,22 @@ Rpush.reflect do |on|
|
|
56
59
|
# on.notification_failed do |notification|
|
57
60
|
# end
|
58
61
|
|
62
|
+
# Called when the notification delivery failed and only the notification ID
|
63
|
+
# is present in memory.
|
64
|
+
# on.notification_id_failed do |app, notification_id, error_code, error_description|
|
65
|
+
# end
|
66
|
+
|
59
67
|
# Called when a notification will be retried at a later date.
|
60
68
|
# Call 'deliver_after' on the notification for the next delivery date
|
61
69
|
# and 'retries' for the number of times this notification has been retried.
|
62
70
|
# on.notification_will_retry do |notification|
|
63
71
|
# end
|
64
72
|
|
73
|
+
# Called when a notification will be retried and only the notification ID
|
74
|
+
# is present in memory.
|
75
|
+
# on.notification_id_will_retry do |app, notification_id, retry_after|
|
76
|
+
# end
|
77
|
+
|
65
78
|
# Called when a TCP connection is lost and will be reconnected.
|
66
79
|
# on.tcp_connection_lost do |app, error|
|
67
80
|
# end
|
@@ -98,6 +111,14 @@ Rpush.reflect do |on|
|
|
98
111
|
# on.adm_canonical_id do |old_id, canonical_id|
|
99
112
|
# end
|
100
113
|
|
114
|
+
# Called when Failed to deliver to ADM. Check the 'reason' string for further
|
115
|
+
# explanations.
|
116
|
+
#
|
117
|
+
# If the reason is the string 'Unregistered', you should remove
|
118
|
+
# this registration id from your records.
|
119
|
+
# on.adm_failed_to_recipient do |notification, registration_id, reason|
|
120
|
+
# end
|
121
|
+
|
101
122
|
# Called when an exception is raised.
|
102
123
|
# on.error do |error|
|
103
124
|
# end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Rpush200Updates < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :rpush_notifications, :processing, :boolean, null: false, default: false
|
4
|
+
add_column :rpush_notifications, :priority, :integer, null: true
|
5
|
+
|
6
|
+
if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
|
7
|
+
remove_index :rpush_notifications, name: :index_rpush_notifications_multi
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :rpush_notifications, [:delivered, :failed], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed'
|
11
|
+
|
12
|
+
rename_column :rpush_feedback, :app, :app_id
|
13
|
+
|
14
|
+
if postgresql?
|
15
|
+
execute('ALTER TABLE rpush_feedback ALTER COLUMN app_id TYPE integer USING (trim(app_id)::integer)')
|
16
|
+
else
|
17
|
+
change_column :rpush_feedback, :app_id, :integer
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.down
|
22
|
+
change_column :rpush_feedback, :app_id, :string
|
23
|
+
rename_column :rpush_feedback, :app_id, :app
|
24
|
+
|
25
|
+
if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true)
|
26
|
+
remove_index :rpush_notifications, name: :index_rpush_notifications_multi
|
27
|
+
end
|
28
|
+
|
29
|
+
add_index :rpush_notifications, [:app_id, :delivered, :failed, :deliver_after], name: 'index_rpush_notifications_multi'
|
30
|
+
|
31
|
+
remove_column :rpush_notifications, :priority
|
32
|
+
remove_column :rpush_notifications, :processing
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.adapter_name
|
36
|
+
ActiveRecord::Base.configurations[Rails.env]['adapter']
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.postgresql?
|
40
|
+
adapter_name =~ /postgresql/
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Adm
|
5
|
+
module App
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
validates :client_id, :client_secret, presence: true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def access_token_expired?
|
13
|
+
access_token_expiration.nil? || access_token_expiration < Time.now
|
14
|
+
end
|
15
|
+
|
16
|
+
def service_name
|
17
|
+
'adm'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Adm
|
5
|
+
class DataValidator < ::ActiveModel::Validator
|
6
|
+
def validate(record)
|
7
|
+
return unless record.collapse_key.nil? && record.data.nil?
|
8
|
+
record.errors[:data] << 'must be set unless collapse_key is specified'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Adm
|
5
|
+
module Notification
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
validates :registration_ids, presence: true
|
9
|
+
|
10
|
+
validates_with Rpush::Client::ActiveModel::PayloadDataSizeValidator, limit: 6144
|
11
|
+
validates_with Rpush::Client::ActiveModel::RegistrationIdsCountValidator, limit: 100
|
12
|
+
|
13
|
+
validates_with Rpush::Client::ActiveModel::Adm::DataValidator
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_json
|
18
|
+
json = { 'data' => data }
|
19
|
+
json['consolidationKey'] = collapse_key if collapse_key
|
20
|
+
# number of seconds before message is expired
|
21
|
+
json['expiresAfter'] = expiry if expiry
|
22
|
+
json
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Apns
|
5
|
+
module 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
|
+
validate :certificate_has_matching_private_key
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def service_name
|
15
|
+
'apns'
|
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, 'Certificate value must contain a certificate and a private key.'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Apns
|
5
|
+
class BinaryNotificationValidator < ::ActiveModel::Validator
|
6
|
+
MAX_BYTES = 256
|
7
|
+
|
8
|
+
def validate(record)
|
9
|
+
return unless record.payload_size > MAX_BYTES
|
10
|
+
record.errors[:base] << "APN notification cannot be larger than #{MAX_BYTES} bytes. Try condensing your alert and device attributes."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Apns
|
5
|
+
class DeviceTokenFormatValidator < ::ActiveModel::Validator
|
6
|
+
def validate(record)
|
7
|
+
return if record.device_token =~ /^[a-z0-9]{64}$/i
|
8
|
+
record.errors[:device_token] << "is invalid"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Apns
|
5
|
+
module Notification
|
6
|
+
APNS_DEFAULT_EXPIRY = 1.day.to_i
|
7
|
+
APNS_PRIORITY_IMMEDIATE = 10
|
8
|
+
APNS_PRIORITY_CONSERVE_POWER = 5
|
9
|
+
APNS_PRIORITIES = [APNS_PRIORITY_IMMEDIATE, APNS_PRIORITY_CONSERVE_POWER]
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.instance_eval do
|
13
|
+
validates :device_token, presence: true
|
14
|
+
validates :badge, numericality: true, allow_nil: true
|
15
|
+
validates :priority, inclusion: { in: APNS_PRIORITIES }, allow_nil: true
|
16
|
+
|
17
|
+
validates_with Rpush::Client::ActiveModel::Apns::DeviceTokenFormatValidator
|
18
|
+
validates_with Rpush::Client::ActiveModel::Apns::BinaryNotificationValidator
|
19
|
+
|
20
|
+
base.const_set('APNS_DEFAULT_EXPIRY', APNS_DEFAULT_EXPIRY) unless base.const_defined?('APNS_DEFAULT_EXPIRY')
|
21
|
+
base.const_set('APNS_PRIORITY_IMMEDIATE', APNS_PRIORITY_IMMEDIATE) unless base.const_defined?('APNS_PRIORITY_IMMEDIATE')
|
22
|
+
base.const_set('APNS_PRIORITY_CONSERVE_POWER', APNS_PRIORITY_CONSERVE_POWER) unless base.const_defined?('APNS_PRIORITY_CONSERVE_POWER')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def device_token=(token)
|
27
|
+
write_attribute(:device_token, token.delete(" <>")) unless token.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
MDM_KEY = '__rpush_mdm__'
|
31
|
+
def mdm=(magic)
|
32
|
+
self.data = (data || {}).merge(MDM_KEY => magic)
|
33
|
+
end
|
34
|
+
|
35
|
+
CONTENT_AVAILABLE_KEY = '__rpush_content_available__'
|
36
|
+
def content_available=(bool)
|
37
|
+
return unless bool
|
38
|
+
self.data = (data || {}).merge(CONTENT_AVAILABLE_KEY => true)
|
39
|
+
end
|
40
|
+
|
41
|
+
def as_json # rubocop:disable Metrics/PerceivedComplexity
|
42
|
+
json = ActiveSupport::OrderedHash.new
|
43
|
+
|
44
|
+
if data && data.key?(MDM_KEY)
|
45
|
+
json['mdm'] = data[MDM_KEY]
|
46
|
+
else
|
47
|
+
json['aps'] = ActiveSupport::OrderedHash.new
|
48
|
+
json['aps']['alert'] = alert if alert
|
49
|
+
json['aps']['badge'] = badge if badge
|
50
|
+
json['aps']['sound'] = sound if sound
|
51
|
+
|
52
|
+
if data && data[CONTENT_AVAILABLE_KEY]
|
53
|
+
json['aps']['content-available'] = 1
|
54
|
+
end
|
55
|
+
|
56
|
+
if data
|
57
|
+
non_aps_attributes = data.reject { |k, _| k == CONTENT_AVAILABLE_KEY }
|
58
|
+
non_aps_attributes.each { |k, v| json[k.to_s] = v }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
json
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_binary(options = {})
|
66
|
+
frame_id = options[:for_validation] ? 0 : id
|
67
|
+
frame = ""
|
68
|
+
frame << [1, 32, device_token].pack("cnH*")
|
69
|
+
frame << [2, payload.bytesize, payload].pack("cna*")
|
70
|
+
frame << [3, 4, frame_id].pack("cnN")
|
71
|
+
frame << [4, 4, expiry || APNS_DEFAULT_EXPIRY].pack("cnN")
|
72
|
+
frame << [5, 1, priority_for_frame].pack("cnc")
|
73
|
+
[2, frame.bytesize].pack("cN") + frame
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def priority_for_frame
|
79
|
+
# It is an error to use APNS_PRIORITY_IMMEDIATE for a notification that only contains content-available.
|
80
|
+
if as_json['aps'].keys == ['content-available']
|
81
|
+
APNS_PRIORITY_CONSERVE_POWER
|
82
|
+
else
|
83
|
+
priority || APNS_PRIORITY_IMMEDIATE
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Gcm
|
5
|
+
module App
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
validates :auth_key, presence: true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def service_name
|
13
|
+
'gcm'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Gcm
|
5
|
+
class ExpiryCollapseKeyMutualInclusionValidator < ::ActiveModel::Validator
|
6
|
+
def validate(record)
|
7
|
+
return unless record.collapse_key && !record.expiry
|
8
|
+
record.errors[:expiry] << 'must be set when using a collapse_key'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Gcm
|
5
|
+
module Notification
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
validates :registration_ids, presence: true
|
9
|
+
|
10
|
+
validates_with Rpush::Client::ActiveModel::PayloadDataSizeValidator, limit: 4096
|
11
|
+
validates_with Rpush::Client::ActiveModel::RegistrationIdsCountValidator, limit: 1000
|
12
|
+
|
13
|
+
validates_with Rpush::Client::ActiveModel::Gcm::ExpiryCollapseKeyMutualInclusionValidator
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_json
|
18
|
+
json = {
|
19
|
+
'registration_ids' => registration_ids,
|
20
|
+
'delay_while_idle' => delay_while_idle,
|
21
|
+
'data' => data
|
22
|
+
}
|
23
|
+
json['collapse_key'] = collapse_key if collapse_key
|
24
|
+
json['time_to_live'] = expiry if expiry
|
25
|
+
json
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Notification
|
5
|
+
def self.included(base)
|
6
|
+
base.instance_eval do
|
7
|
+
validates :expiry, numericality: true, allow_nil: true
|
8
|
+
validates :app, presence: true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def payload
|
13
|
+
multi_json_dump(as_json)
|
14
|
+
end
|
15
|
+
|
16
|
+
def payload_size
|
17
|
+
payload.bytesize
|
18
|
+
end
|
19
|
+
|
20
|
+
def payload_data_size
|
21
|
+
multi_json_dump(as_json['data']).bytesize
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
class PayloadDataSizeValidator < ::ActiveModel::Validator
|
5
|
+
def validate(record)
|
6
|
+
limit = options[:limit] || 1024
|
7
|
+
return unless record.data && record.payload_data_size > limit
|
8
|
+
record.errors[:base] << "Notification payload data cannot be larger than #{limit} bytes."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
class RegistrationIdsCountValidator < ::ActiveModel::Validator
|
5
|
+
def validate(record)
|
6
|
+
limit = options[:limit] || 100
|
7
|
+
return unless record.registration_ids && record.registration_ids.size > limit
|
8
|
+
record.errors[:base] << "Number of registration_ids cannot be larger than #{limit}."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Client
|
3
|
+
module ActiveModel
|
4
|
+
module Wpns
|
5
|
+
module Notification
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
validates :uri, presence: true
|
9
|
+
validates :uri, format: { with: %r{https?://[\S]+} }
|
10
|
+
validates :alert, presence: true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
require 'rpush/client/active_model/notification'
|
4
|
+
require 'rpush/client/active_model/payload_data_size_validator'
|
5
|
+
require 'rpush/client/active_model/registration_ids_count_validator'
|
6
|
+
|
7
|
+
require 'rpush/client/active_model/apns/binary_notification_validator'
|
8
|
+
require 'rpush/client/active_model/apns/device_token_format_validator'
|
9
|
+
require 'rpush/client/active_model/apns/app'
|
10
|
+
require 'rpush/client/active_model/apns/notification'
|
11
|
+
|
12
|
+
require 'rpush/client/active_model/adm/data_validator'
|
13
|
+
require 'rpush/client/active_model/adm/app'
|
14
|
+
require 'rpush/client/active_model/adm/notification'
|
15
|
+
|
16
|
+
require 'rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator'
|
17
|
+
require 'rpush/client/active_model/gcm/app'
|
18
|
+
require 'rpush/client/active_model/gcm/notification'
|
19
|
+
|
20
|
+
require 'rpush/client/active_model/wpns/app'
|
21
|
+
require 'rpush/client/active_model/wpns/notification'
|