rpush 7.0.1 → 9.0.0
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 +34 -4
- data/README.md +24 -44
- data/lib/generators/rpush_migration_generator.rb +1 -0
- data/lib/generators/templates/rpush.rb +23 -13
- data/lib/generators/templates/rpush_7_1_0_updates.rb +12 -0
- data/lib/rpush/client/active_model/apns/notification.rb +0 -4
- data/lib/rpush/client/active_model/{gcm → fcm}/app.rb +4 -3
- data/lib/rpush/client/active_model/{gcm → fcm}/expiry_collapse_key_mutual_inclusion_validator.rb +1 -1
- data/lib/rpush/client/active_model/fcm/notification.rb +129 -0
- data/lib/rpush/client/active_model/fcm/notification_keys_in_allowed_list_validator.rb +20 -0
- data/lib/rpush/client/active_model.rb +4 -3
- data/lib/rpush/client/active_record/{gcm → fcm}/app.rb +2 -2
- data/lib/rpush/client/active_record/{gcm → fcm}/notification.rb +2 -2
- data/lib/rpush/client/active_record.rb +2 -2
- data/lib/rpush/client/redis/app.rb +2 -0
- data/lib/rpush/client/redis/{gcm → fcm}/app.rb +2 -2
- data/lib/rpush/client/redis/{gcm → fcm}/notification.rb +2 -2
- data/lib/rpush/client/redis.rb +2 -2
- data/lib/rpush/configuration.rb +2 -19
- data/lib/rpush/daemon/apns2/delivery.rb +0 -1
- data/lib/rpush/daemon/apnsp8/delivery.rb +0 -1
- data/lib/rpush/daemon/fcm/delivery.rb +162 -0
- data/lib/rpush/daemon/{gcm.rb → fcm.rb} +1 -1
- data/lib/rpush/daemon/google_credential_cache.rb +41 -0
- data/lib/rpush/daemon/service_config_methods.rb +0 -2
- data/lib/rpush/daemon/store/active_record.rb +15 -12
- data/lib/rpush/daemon/store/interface.rb +3 -3
- data/lib/rpush/daemon/store/redis.rb +13 -9
- data/lib/rpush/daemon/webpush/delivery.rb +2 -2
- data/lib/rpush/daemon.rb +3 -9
- data/lib/rpush/reflection_collection.rb +3 -3
- data/lib/rpush/version.rb +2 -2
- data/lib/rpush.rb +1 -1
- data/spec/functional/apns2_spec.rb +2 -6
- data/spec/functional/cli_spec.rb +41 -15
- data/spec/functional/embed_spec.rb +57 -26
- data/spec/functional/{gcm_priority_spec.rb → fcm_priority_spec.rb} +13 -7
- data/spec/functional/fcm_spec.rb +77 -0
- data/spec/functional/retry_spec.rb +21 -4
- data/spec/functional/synchronization_spec.rb +1 -1
- data/spec/functional_spec_helper.rb +1 -7
- data/spec/spec_helper.rb +4 -1
- data/spec/support/active_record_setup.rb +3 -1
- data/spec/unit/client/active_record/{gcm → fcm}/app_spec.rb +2 -2
- data/spec/unit/client/active_record/fcm/notification_spec.rb +10 -0
- data/spec/unit/client/active_record/shared/app.rb +1 -1
- data/spec/unit/client/redis/fcm/app_spec.rb +5 -0
- data/spec/unit/client/redis/fcm/notification_spec.rb +5 -0
- data/spec/unit/client/shared/apns/notification.rb +0 -15
- data/spec/unit/client/shared/fcm/app.rb +4 -0
- data/spec/unit/client/shared/fcm/notification.rb +92 -0
- data/spec/unit/configuration_spec.rb +1 -1
- data/spec/unit/daemon/apnsp8/delivery_spec.rb +1 -1
- data/spec/unit/daemon/fcm/delivery_spec.rb +127 -0
- data/spec/unit/daemon/service_config_methods_spec.rb +1 -1
- data/spec/unit/daemon/shared/store.rb +0 -42
- data/spec/unit/daemon/wns/delivery_spec.rb +1 -1
- data/spec/unit/logger_spec.rb +1 -1
- data/spec/unit_spec_helper.rb +1 -1
- metadata +127 -69
- data/lib/rpush/apns_feedback.rb +0 -18
- data/lib/rpush/client/active_model/gcm/notification.rb +0 -62
- data/lib/rpush/daemon/apns/delivery.rb +0 -43
- data/lib/rpush/daemon/apns/feedback_receiver.rb +0 -91
- data/lib/rpush/daemon/apns.rb +0 -17
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +0 -152
- data/lib/rpush/daemon/dispatcher/tcp.rb +0 -22
- data/lib/rpush/daemon/gcm/delivery.rb +0 -241
- data/lib/rpush/daemon/tcp_connection.rb +0 -190
- data/spec/functional/apns_spec.rb +0 -162
- data/spec/functional/gcm_spec.rb +0 -46
- data/spec/functional/new_app_spec.rb +0 -44
- data/spec/unit/apns_feedback_spec.rb +0 -39
- data/spec/unit/client/active_record/gcm/notification_spec.rb +0 -14
- data/spec/unit/client/redis/gcm/app_spec.rb +0 -5
- data/spec/unit/client/redis/gcm/notification_spec.rb +0 -5
- data/spec/unit/client/shared/gcm/app.rb +0 -4
- data/spec/unit/client/shared/gcm/notification.rb +0 -77
- data/spec/unit/daemon/apns/delivery_spec.rb +0 -108
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +0 -137
- data/spec/unit/daemon/dispatcher/tcp_spec.rb +0 -32
- data/spec/unit/daemon/gcm/delivery_spec.rb +0 -387
- data/spec/unit/daemon/tcp_connection_spec.rb +0 -292
@@ -0,0 +1,162 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Daemon
|
3
|
+
module Fcm
|
4
|
+
# https://firebase.google.com/docs/cloud-messaging/server
|
5
|
+
class Delivery < Rpush::Daemon::Delivery
|
6
|
+
include MultiJsonHelper
|
7
|
+
|
8
|
+
HOST = 'https://fcm.googleapis.com'.freeze
|
9
|
+
SCOPE = 'https://www.googleapis.com/auth/firebase.messaging'.freeze
|
10
|
+
|
11
|
+
def initialize(app, http, notification, batch)
|
12
|
+
if necessary_data_exists?(app)
|
13
|
+
@app = app
|
14
|
+
@http = http
|
15
|
+
@notification = notification
|
16
|
+
@batch = batch
|
17
|
+
|
18
|
+
@uri = URI.parse("#{HOST}/v1/projects/#{@app.firebase_project_id || ENV['FIREBASE_PROJECT_ID']}/messages:send")
|
19
|
+
else
|
20
|
+
Rpush.logger.error("Cannot find necessary configuration! Please make sure you have set all necessary ENV variables or firebase_project_id and json_key attributes.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def perform
|
25
|
+
handle_response(do_post)
|
26
|
+
rescue SocketError => error
|
27
|
+
mark_retryable(@notification, Time.now + 10.seconds, error)
|
28
|
+
raise
|
29
|
+
rescue StandardError => error
|
30
|
+
mark_failed(error)
|
31
|
+
raise
|
32
|
+
ensure
|
33
|
+
@batch.notification_processed
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def handle_response(response)
|
39
|
+
case response.code.to_i
|
40
|
+
when 200
|
41
|
+
ok
|
42
|
+
when 400
|
43
|
+
bad_request(response)
|
44
|
+
when 401
|
45
|
+
unauthorized
|
46
|
+
when 403
|
47
|
+
sender_id_mismatch
|
48
|
+
when 404
|
49
|
+
unregistered(response)
|
50
|
+
when 429
|
51
|
+
too_many_requests
|
52
|
+
when 500
|
53
|
+
internal_server_error(response)
|
54
|
+
when 502
|
55
|
+
bad_gateway(response)
|
56
|
+
when 503
|
57
|
+
service_unavailable(response)
|
58
|
+
when 500..599
|
59
|
+
other_5xx_error(response)
|
60
|
+
else
|
61
|
+
fail Rpush::DeliveryError.new(response.code.to_i, @notification.id, Rpush::Daemon::HTTP_STATUS_CODES[response.code.to_i])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def ok
|
66
|
+
reflect(:fcm_delivered_to_recipient, @notification)
|
67
|
+
mark_delivered
|
68
|
+
log_info("#{@notification.id} sent to #{@notification.device_token}")
|
69
|
+
end
|
70
|
+
|
71
|
+
def bad_request(response)
|
72
|
+
fail Rpush::DeliveryError.new(400, @notification.id, "FCM failed to handle the JSON request. (#{parse_error(response)})")
|
73
|
+
end
|
74
|
+
|
75
|
+
def unauthorized
|
76
|
+
fail Rpush::DeliveryError.new(401, @notification.id, 'Unauthorized, Bearer token could not be validated.')
|
77
|
+
end
|
78
|
+
|
79
|
+
def sender_id_mismatch
|
80
|
+
fail Rpush::DeliveryError.new(403, @notification.id, 'The sender ID was mismatched. It seems the device token is wrong.')
|
81
|
+
end
|
82
|
+
|
83
|
+
def unregistered(response)
|
84
|
+
error = parse_error(response)
|
85
|
+
reflect(:fcm_invalid_device_token, @app, error, @notification.device_token)
|
86
|
+
fail Rpush::DeliveryError.new(404, @notification.id, "Client was not registered for your app. (#{error})")
|
87
|
+
end
|
88
|
+
|
89
|
+
def too_many_requests
|
90
|
+
fail Rpush::DeliveryError.new(429, @notification.id, 'Slow down. Too many requests were sent!')
|
91
|
+
end
|
92
|
+
|
93
|
+
def internal_server_error(response)
|
94
|
+
retry_delivery(@notification, response)
|
95
|
+
log_warn("FCM responded with an Internal Error. " + retry_message)
|
96
|
+
end
|
97
|
+
|
98
|
+
def bad_gateway(response)
|
99
|
+
retry_delivery(@notification, response)
|
100
|
+
log_warn("FCM responded with a Bad Gateway Error. " + retry_message)
|
101
|
+
end
|
102
|
+
|
103
|
+
def service_unavailable(response)
|
104
|
+
retry_delivery(@notification, response)
|
105
|
+
log_warn("FCM responded with an Service Unavailable Error. " + retry_message)
|
106
|
+
end
|
107
|
+
|
108
|
+
def other_5xx_error(response)
|
109
|
+
retry_delivery(@notification, response)
|
110
|
+
log_warn("FCM responded with a 5xx Error. " + retry_message)
|
111
|
+
end
|
112
|
+
|
113
|
+
def parse_error(response)
|
114
|
+
error = multi_json_load(response.body)['error']
|
115
|
+
"#{error['status']}: #{error['message']}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def deliver_after_header(response)
|
119
|
+
Rpush::Daemon::RetryHeaderParser.parse(response.header['retry-after'])
|
120
|
+
end
|
121
|
+
|
122
|
+
def retry_delivery(notification, response)
|
123
|
+
time = deliver_after_header(response)
|
124
|
+
if time
|
125
|
+
mark_retryable(notification, time)
|
126
|
+
else
|
127
|
+
mark_retryable_exponential(notification)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def retry_message
|
132
|
+
"Notification #{@notification.id} will be retried after #{@notification.deliver_after.strftime('%Y-%m-%d %H:%M:%S')} (retry #{@notification.retries})."
|
133
|
+
end
|
134
|
+
|
135
|
+
def obtain_access_token
|
136
|
+
GoogleCredentialCache.instance.access_token(SCOPE, @app.json_key)
|
137
|
+
end
|
138
|
+
|
139
|
+
def do_post
|
140
|
+
token = obtain_access_token['access_token']
|
141
|
+
post = Net::HTTP::Post.new(@uri.path, 'Content-Type' => 'application/json',
|
142
|
+
'Authorization' => "Bearer #{token}")
|
143
|
+
post.body = @notification.as_json.to_json
|
144
|
+
@http.request(@uri, post)
|
145
|
+
end
|
146
|
+
|
147
|
+
def necessary_data_exists?(app)
|
148
|
+
# Needed for Google Auth
|
149
|
+
# See https://github.com/googleapis/google-auth-library-ruby#example-environment-variables
|
150
|
+
# for further information
|
151
|
+
(app.firebase_project_id || ENV.key?('FIREBASE_PROJECT_ID')) &&
|
152
|
+
(app.json_key || (
|
153
|
+
ENV.key?('GOOGLE_ACCOUNT_TYPE') &&
|
154
|
+
ENV.key?('GOOGLE_CLIENT_ID') &&
|
155
|
+
ENV.key?('GOOGLE_CLIENT_EMAIL') &&
|
156
|
+
ENV.key?('GOOGLE_PRIVATE_KEY')
|
157
|
+
))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
module Rpush
|
3
|
+
module Daemon
|
4
|
+
class GoogleCredentialCache
|
5
|
+
include Singleton
|
6
|
+
include Loggable
|
7
|
+
|
8
|
+
# Assuming tokens are valid for 1 hour
|
9
|
+
TOKEN_VALID_FOR_SEC = 60 * 59
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@credentials_cache = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def access_token(scope, json_key)
|
16
|
+
key = hash_key(scope, json_key)
|
17
|
+
|
18
|
+
if @credentials_cache[key].nil? || Time.now > @credentials_cache[key][:expires_at]
|
19
|
+
token = fetch_fresh_token(scope, json_key)
|
20
|
+
expires_at = Time.now + TOKEN_VALID_FOR_SEC
|
21
|
+
@credentials_cache[key] = { token: token, expires_at: expires_at }
|
22
|
+
end
|
23
|
+
|
24
|
+
@credentials_cache[key][:token]
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def fetch_fresh_token(scope, json_key)
|
30
|
+
json_key_io = json_key ? StringIO.new(json_key) : nil
|
31
|
+
log_debug("FCM - Obtaining access token.")
|
32
|
+
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(scope: scope, json_key_io: json_key_io)
|
33
|
+
authorizer.fetch_access_token
|
34
|
+
end
|
35
|
+
|
36
|
+
def hash_key(scope, json_key)
|
37
|
+
scope.hash ^ json_key.hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -3,8 +3,6 @@ module Rpush
|
|
3
3
|
module ServiceConfigMethods
|
4
4
|
DISPATCHERS = {
|
5
5
|
http: Rpush::Daemon::Dispatcher::Http,
|
6
|
-
tcp: Rpush::Daemon::Dispatcher::Tcp,
|
7
|
-
apns_tcp: Rpush::Daemon::Dispatcher::ApnsTcp,
|
8
6
|
apns_http2: Rpush::Daemon::Dispatcher::ApnsHttp2,
|
9
7
|
apnsp8_http2: Rpush::Daemon::Dispatcher::Apnsp8Http2
|
10
8
|
}
|
@@ -138,21 +138,14 @@ module Rpush
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
def
|
142
|
-
|
143
|
-
|
144
|
-
device_token: device_token, app_id: app.id)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def create_gcm_notification(attrs, data, registration_ids, deliver_after, app)
|
149
|
-
notification = Rpush::Client::ActiveRecord::Gcm::Notification.new
|
150
|
-
create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
141
|
+
def create_fcm_notification(attrs, data, app)
|
142
|
+
notification = Rpush::Client::ActiveRecord::Fcm::Notification.new
|
143
|
+
create_fcm_like_notification(notification, attrs, data, app)
|
151
144
|
end
|
152
145
|
|
153
146
|
def create_adm_notification(attrs, data, registration_ids, deliver_after, app)
|
154
147
|
notification = Rpush::Client::ActiveRecord::Adm::Notification.new
|
155
|
-
|
148
|
+
create_adm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
156
149
|
end
|
157
150
|
|
158
151
|
def update_app(app)
|
@@ -194,7 +187,17 @@ module Rpush
|
|
194
187
|
|
195
188
|
private
|
196
189
|
|
197
|
-
def
|
190
|
+
def create_fcm_like_notification(notification, attrs, data, app) # rubocop:disable Metrics/ParameterLists
|
191
|
+
with_database_reconnect_and_retry do
|
192
|
+
notification.assign_attributes(attrs)
|
193
|
+
notification.data = data
|
194
|
+
notification.app = app
|
195
|
+
notification.save!
|
196
|
+
notification
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def create_adm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable Metrics/ParameterLists
|
198
201
|
with_database_reconnect_and_retry do
|
199
202
|
notification.assign_attributes(attrs)
|
200
203
|
notification.data = data
|
@@ -4,9 +4,9 @@ module Rpush
|
|
4
4
|
class Interface
|
5
5
|
PUBLIC_METHODS = [:deliverable_notifications, :mark_retryable,
|
6
6
|
:mark_batch_retryable, :mark_delivered, :mark_batch_delivered,
|
7
|
-
:mark_failed, :mark_batch_failed,
|
8
|
-
:
|
9
|
-
:update_notification, :release_connection,
|
7
|
+
:mark_failed, :mark_batch_failed,
|
8
|
+
:create_fcm_notification, :create_adm_notification,
|
9
|
+
:update_app, :update_notification, :release_connection,
|
10
10
|
:all_apps, :app, :mark_ids_failed, :mark_ids_retryable,
|
11
11
|
:reopen_log, :pending_delivery_count, :translate_integer_notification_id]
|
12
12
|
|
@@ -88,18 +88,14 @@ module Rpush
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
def
|
92
|
-
Rpush::Client::Redis::
|
93
|
-
|
94
|
-
|
95
|
-
def create_gcm_notification(attrs, data, registration_ids, deliver_after, app)
|
96
|
-
notification = Rpush::Client::Redis::Gcm::Notification.new
|
97
|
-
create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
91
|
+
def create_fcm_notification(attrs, data, app)
|
92
|
+
notification = Rpush::Client::Redis::Fcm::Notification.new
|
93
|
+
create_fcm_like_notification(notification, attrs, data, app)
|
98
94
|
end
|
99
95
|
|
100
96
|
def create_adm_notification(attrs, data, registration_ids, deliver_after, app)
|
101
97
|
notification = Rpush::Client::Redis::Adm::Notification.new
|
102
|
-
|
98
|
+
create_adm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
|
103
99
|
end
|
104
100
|
|
105
101
|
def update_app(app)
|
@@ -138,7 +134,15 @@ module Rpush
|
|
138
134
|
nil
|
139
135
|
end
|
140
136
|
|
141
|
-
def
|
137
|
+
def create_fcm_like_notification(notification, attrs, data, app) # rubocop:disable Metrics/ParameterLists
|
138
|
+
notification.assign_attributes(attrs)
|
139
|
+
notification.data = data
|
140
|
+
notification.app = app
|
141
|
+
notification.save!
|
142
|
+
notification
|
143
|
+
end
|
144
|
+
|
145
|
+
def create_adm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable Metrics/ParameterLists
|
142
146
|
notification.assign_attributes(attrs)
|
143
147
|
notification.data = data
|
144
148
|
notification.registration_ids = registration_ids
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "web-push"
|
4
4
|
|
5
5
|
module Rpush
|
6
6
|
module Daemon
|
@@ -10,7 +10,7 @@ module Rpush
|
|
10
10
|
# We just override #perform to inject the http instance that is managed
|
11
11
|
# by Rpush.
|
12
12
|
#
|
13
|
-
class Request < ::
|
13
|
+
class Request < ::WebPush::Request
|
14
14
|
def perform(http)
|
15
15
|
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
16
16
|
req.body = body
|
data/lib/rpush/daemon.rb
CHANGED
@@ -19,11 +19,8 @@ require 'rpush/daemon/batch'
|
|
19
19
|
require 'rpush/daemon/queue_payload'
|
20
20
|
require 'rpush/daemon/synchronizer'
|
21
21
|
require 'rpush/daemon/app_runner'
|
22
|
-
require 'rpush/daemon/tcp_connection'
|
23
22
|
require 'rpush/daemon/dispatcher_loop'
|
24
23
|
require 'rpush/daemon/dispatcher/http'
|
25
|
-
require 'rpush/daemon/dispatcher/tcp'
|
26
|
-
require 'rpush/daemon/dispatcher/apns_tcp'
|
27
24
|
require 'rpush/daemon/dispatcher/apns_http2'
|
28
25
|
require 'rpush/daemon/dispatcher/apnsp8_http2'
|
29
26
|
require 'rpush/daemon/service_config_methods'
|
@@ -38,10 +35,6 @@ require 'rpush/daemon/rpc/client'
|
|
38
35
|
|
39
36
|
require 'rpush/daemon/store/interface'
|
40
37
|
|
41
|
-
require 'rpush/daemon/apns/delivery'
|
42
|
-
require 'rpush/daemon/apns/feedback_receiver'
|
43
|
-
require 'rpush/daemon/apns'
|
44
|
-
|
45
38
|
require 'rpush/daemon/apns2/delivery'
|
46
39
|
require 'rpush/daemon/apns2'
|
47
40
|
|
@@ -49,8 +42,9 @@ require 'rpush/daemon/apnsp8/delivery'
|
|
49
42
|
require 'rpush/daemon/apnsp8/token'
|
50
43
|
require 'rpush/daemon/apnsp8'
|
51
44
|
|
52
|
-
require 'rpush/daemon/
|
53
|
-
require 'rpush/daemon/
|
45
|
+
require 'rpush/daemon/fcm/delivery'
|
46
|
+
require 'rpush/daemon/fcm'
|
47
|
+
require 'rpush/daemon/google_credential_cache'
|
54
48
|
|
55
49
|
require 'rpush/daemon/wpns/delivery'
|
56
50
|
require 'rpush/daemon/wpns'
|
@@ -4,10 +4,10 @@ module Rpush
|
|
4
4
|
|
5
5
|
REFLECTIONS = [
|
6
6
|
:apns_feedback, :notification_enqueued, :notification_delivered,
|
7
|
-
:notification_failed, :notification_will_retry,
|
8
|
-
:
|
7
|
+
:notification_failed, :notification_will_retry,
|
8
|
+
:fcm_delivered_to_recipient, :fcm_failed_to_recipient, :fcm_canonical_id, :fcm_invalid_device_token,
|
9
9
|
:error, :adm_canonical_id, :adm_failed_to_recipient, :wns_invalid_channel,
|
10
|
-
:
|
10
|
+
:ssl_certificate_will_expire, :ssl_certificate_revoked,
|
11
11
|
:notification_id_will_retry, :notification_id_failed
|
12
12
|
]
|
13
13
|
|
data/lib/rpush/version.rb
CHANGED
data/lib/rpush.rb
CHANGED
@@ -3,6 +3,7 @@ require 'multi_json'
|
|
3
3
|
require 'active_support/all'
|
4
4
|
require 'net-http2'
|
5
5
|
require 'jwt'
|
6
|
+
require 'googleauth'
|
6
7
|
|
7
8
|
require 'rails'
|
8
9
|
|
@@ -19,7 +20,6 @@ require 'rpush/reflectable'
|
|
19
20
|
require 'rpush/plugin'
|
20
21
|
require 'rpush/embed'
|
21
22
|
require 'rpush/push'
|
22
|
-
require 'rpush/apns_feedback'
|
23
23
|
|
24
24
|
module Rpush
|
25
25
|
def self.jruby?
|
@@ -79,8 +79,7 @@ describe 'APNs http2 adapter' do
|
|
79
79
|
headers: {
|
80
80
|
'apns-expiration' => '0',
|
81
81
|
'apns-priority' => '10',
|
82
|
-
'apns-topic' => 'com.example.app'
|
83
|
-
'apns-push-type' => 'background'
|
82
|
+
'apns-topic' => 'com.example.app'
|
84
83
|
}
|
85
84
|
}
|
86
85
|
)
|
@@ -114,8 +113,7 @@ describe 'APNs http2 adapter' do
|
|
114
113
|
headers: {
|
115
114
|
'apns-topic' => bundle_id,
|
116
115
|
'apns-expiration' => '0',
|
117
|
-
'apns-priority' => '10'
|
118
|
-
'apns-push-type' => 'background'
|
116
|
+
'apns-priority' => '10'
|
119
117
|
}
|
120
118
|
}
|
121
119
|
).and_return(fake_http2_request)
|
@@ -257,7 +255,6 @@ describe 'APNs http2 adapter' do
|
|
257
255
|
Rpush.reflect do |on|
|
258
256
|
on.error do |error|
|
259
257
|
expect(error).to be_kind_of(StandardError)
|
260
|
-
reflector.accept
|
261
258
|
end
|
262
259
|
end
|
263
260
|
|
@@ -292,7 +289,6 @@ describe 'APNs http2 adapter' do
|
|
292
289
|
on.error do |error|
|
293
290
|
reflected_error = true
|
294
291
|
expect(error).to be_kind_of(StandardError)
|
295
|
-
reflector.accept
|
296
292
|
end
|
297
293
|
end
|
298
294
|
|
data/spec/functional/cli_spec.rb
CHANGED
@@ -2,31 +2,57 @@ require 'functional_spec_helper'
|
|
2
2
|
|
3
3
|
describe Rpush::CLI do
|
4
4
|
def create_app
|
5
|
-
app = Rpush::
|
5
|
+
app = Rpush::Apns2::App.new
|
6
6
|
app.certificate = TEST_CERT
|
7
7
|
app.name = 'test'
|
8
|
-
app.environment = '
|
8
|
+
app.environment = 'development'
|
9
|
+
app.bundle_id = 'com.example.app'
|
9
10
|
app.save!
|
10
11
|
app
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
let(:fake_client) {
|
15
|
+
double(
|
16
|
+
prepare_request: fake_http2_request,
|
17
|
+
close: 'ok',
|
18
|
+
call_async: 'ok',
|
19
|
+
join: 'ok',
|
20
|
+
on: 'ok'
|
21
|
+
)
|
22
|
+
}
|
23
|
+
let(:fake_http2_request) { double }
|
24
|
+
let(:fake_http_resp_headers) {
|
25
|
+
{
|
26
|
+
":status" => "200",
|
27
|
+
"apns-id"=>"C6D65840-5E3F-785A-4D91-B97D305C12F6"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
let(:fake_http_resp_body) { '' }
|
17
31
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
Rpush.embed
|
32
|
+
before do
|
33
|
+
create_app
|
34
|
+
Rpush.config.push_poll = 0.5
|
22
35
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
36
|
+
allow(NetHttp2::Client).
|
37
|
+
to receive(:new).and_return(fake_client)
|
38
|
+
allow(fake_http2_request).
|
39
|
+
to receive(:on).with(:headers).
|
40
|
+
and_yield(fake_http_resp_headers)
|
41
|
+
allow(fake_http2_request).
|
42
|
+
to receive(:on).with(:body_chunk).
|
43
|
+
and_yield(fake_http_resp_body)
|
44
|
+
allow(fake_http2_request).
|
45
|
+
to receive(:on).with(:close).
|
46
|
+
and_yield
|
47
|
+
|
48
|
+
Rpush.embed
|
49
|
+
end
|
27
50
|
|
28
|
-
|
51
|
+
after do
|
52
|
+
timeout { Rpush.shutdown }
|
53
|
+
end
|
29
54
|
|
55
|
+
describe 'status' do
|
30
56
|
it 'prints the status' do
|
31
57
|
expect(subject).to receive(:configure_rpush) { true }
|
32
58
|
expect(subject).to receive(:puts).with(/app_runners:/)
|
@@ -1,49 +1,80 @@
|
|
1
1
|
require 'functional_spec_helper'
|
2
2
|
|
3
3
|
describe 'embedding' do
|
4
|
-
|
5
|
-
|
6
|
-
let(:notification) { Rpush::Apns::Notification.new }
|
7
|
-
let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
|
8
|
-
let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
|
9
|
-
let(:io_double) { double(select: nil) }
|
10
|
-
|
11
|
-
before do
|
4
|
+
def create_app
|
5
|
+
app = Rpush::Apns2::App.new
|
12
6
|
app.certificate = TEST_CERT
|
13
7
|
app.name = 'test'
|
14
|
-
app.environment = '
|
8
|
+
app.environment = 'development'
|
9
|
+
app.bundle_id = 'com.example.app'
|
15
10
|
app.save!
|
11
|
+
app
|
12
|
+
end
|
16
13
|
|
14
|
+
let(:fake_device_token) { 'a' * 108 }
|
15
|
+
let(:notification_data) { nil }
|
16
|
+
|
17
|
+
def create_notification(app)
|
18
|
+
notification = Rpush::Apns2::Notification.new
|
17
19
|
notification.app = app
|
20
|
+
notification.sound = 'default'
|
18
21
|
notification.alert = 'test'
|
19
|
-
notification.device_token =
|
22
|
+
notification.device_token = fake_device_token
|
23
|
+
notification.data = notification_data
|
24
|
+
notification.content_available = 1
|
20
25
|
notification.save!
|
21
|
-
|
22
|
-
stub_tcp_connection
|
26
|
+
notification
|
23
27
|
end
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
let(:app) { create_app }
|
30
|
+
let(:notification) { create_notification(app) }
|
31
|
+
|
32
|
+
let(:fake_client) {
|
33
|
+
double(
|
34
|
+
prepare_request: fake_http2_request,
|
35
|
+
close: 'ok',
|
36
|
+
call_async: 'ok',
|
37
|
+
join: 'ok',
|
38
|
+
on: 'ok'
|
39
|
+
)
|
40
|
+
}
|
41
|
+
let(:fake_http2_request) { double }
|
42
|
+
let(:fake_http_resp_headers) {
|
43
|
+
{
|
44
|
+
":status" => "200",
|
45
|
+
"apns-id"=>"C6D65840-5E3F-785A-4D91-B97D305C12F6"
|
46
|
+
}
|
47
|
+
}
|
48
|
+
let(:fake_http_resp_body) { '' }
|
31
49
|
|
32
50
|
before do
|
33
|
-
Rpush.config.push_poll = 5
|
51
|
+
Rpush.config.push_poll = 0.5
|
52
|
+
|
53
|
+
allow(NetHttp2::Client).
|
54
|
+
to receive(:new).and_return(fake_client)
|
55
|
+
allow(fake_http2_request).
|
56
|
+
to receive(:on).with(:headers).
|
57
|
+
and_yield(fake_http_resp_headers)
|
58
|
+
allow(fake_http2_request).
|
59
|
+
to receive(:on).with(:body_chunk).
|
60
|
+
and_yield(fake_http_resp_body)
|
61
|
+
allow(fake_http2_request).
|
62
|
+
to receive(:on).with(:close).
|
63
|
+
and_yield
|
64
|
+
|
34
65
|
Rpush.embed
|
35
66
|
end
|
36
67
|
|
68
|
+
after do
|
69
|
+
timeout { Rpush.shutdown }
|
70
|
+
end
|
71
|
+
|
37
72
|
it 'delivers a notification successfully' do
|
38
73
|
expect do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
sleep 0.1
|
43
|
-
end
|
74
|
+
until notification.delivered
|
75
|
+
notification.reload
|
76
|
+
sleep 0.1
|
44
77
|
end
|
45
78
|
end.to change(notification, :delivered).to(true)
|
46
79
|
end
|
47
|
-
|
48
|
-
after { Timeout.timeout(timeout) { Rpush.shutdown } }
|
49
80
|
end
|