rapns_rails_2 3.4.3
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 +15 -0
- data/CHANGELOG.md +83 -0
- data/LICENSE +7 -0
- data/README.md +168 -0
- data/bin/rapns +37 -0
- data/config/database.yml +44 -0
- data/lib/generators/rapns_generator.rb +25 -0
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
- data/lib/generators/templates/add_app_to_rapns.rb +11 -0
- data/lib/generators/templates/add_gcm.rb +95 -0
- data/lib/generators/templates/create_rapns_apps.rb +16 -0
- data/lib/generators/templates/create_rapns_feedback.rb +15 -0
- data/lib/generators/templates/create_rapns_notifications.rb +26 -0
- data/lib/generators/templates/rapns.rb +87 -0
- data/lib/rapns/TODO +3 -0
- data/lib/rapns/apns/app.rb +25 -0
- data/lib/rapns/apns/binary_notification_validator.rb +12 -0
- data/lib/rapns/apns/device_token_format_validator.rb +12 -0
- data/lib/rapns/apns/feedback.rb +16 -0
- data/lib/rapns/apns/notification.rb +91 -0
- data/lib/rapns/apns_feedback.rb +13 -0
- data/lib/rapns/app.rb +16 -0
- data/lib/rapns/configuration.rb +89 -0
- data/lib/rapns/daemon/apns/app_runner.rb +26 -0
- data/lib/rapns/daemon/apns/certificate_expired_error.rb +20 -0
- data/lib/rapns/daemon/apns/connection.rb +142 -0
- data/lib/rapns/daemon/apns/delivery.rb +64 -0
- data/lib/rapns/daemon/apns/delivery_handler.rb +35 -0
- data/lib/rapns/daemon/apns/disconnection_error.rb +20 -0
- data/lib/rapns/daemon/apns/feedback_receiver.rb +89 -0
- data/lib/rapns/daemon/app_runner.rb +179 -0
- data/lib/rapns/daemon/batch.rb +112 -0
- data/lib/rapns/daemon/delivery.rb +23 -0
- data/lib/rapns/daemon/delivery_error.rb +19 -0
- data/lib/rapns/daemon/delivery_handler.rb +52 -0
- data/lib/rapns/daemon/delivery_handler_collection.rb +33 -0
- data/lib/rapns/daemon/feeder.rb +65 -0
- data/lib/rapns/daemon/gcm/app_runner.rb +13 -0
- data/lib/rapns/daemon/gcm/delivery.rb +228 -0
- data/lib/rapns/daemon/gcm/delivery_handler.rb +20 -0
- data/lib/rapns/daemon/interruptible_sleep.rb +65 -0
- data/lib/rapns/daemon/reflectable.rb +13 -0
- data/lib/rapns/daemon/store/active_record/reconnectable.rb +66 -0
- data/lib/rapns/daemon/store/active_record.rb +128 -0
- data/lib/rapns/daemon.rb +129 -0
- data/lib/rapns/deprecatable.rb +23 -0
- data/lib/rapns/deprecation.rb +23 -0
- data/lib/rapns/embed.rb +28 -0
- data/lib/rapns/gcm/app.rb +7 -0
- data/lib/rapns/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
- data/lib/rapns/gcm/notification.rb +37 -0
- data/lib/rapns/gcm/payload_data_size_validator.rb +13 -0
- data/lib/rapns/gcm/registration_ids_count_validator.rb +13 -0
- data/lib/rapns/logger.rb +76 -0
- data/lib/rapns/multi_json_helper.rb +16 -0
- data/lib/rapns/notification.rb +62 -0
- data/lib/rapns/notifier.rb +35 -0
- data/lib/rapns/push.rb +17 -0
- data/lib/rapns/rails-2-compatibility.rb +34 -0
- data/lib/rapns/reflection.rb +44 -0
- data/lib/rapns/upgraded.rb +31 -0
- data/lib/rapns/version.rb +3 -0
- data/lib/rapns_rails_2.rb +67 -0
- data/lib/tasks/cane.rake +18 -0
- data/lib/tasks/test.rake +38 -0
- data/spec/support/cert_with_password.pem +90 -0
- data/spec/support/cert_without_password.pem +59 -0
- data/spec/support/simplecov_helper.rb +13 -0
- data/spec/support/simplecov_quality_formatter.rb +8 -0
- data/spec/tmp/.gitkeep +0 -0
- data/spec/unit/apns/app_spec.rb +29 -0
- data/spec/unit/apns/feedback_spec.rb +9 -0
- data/spec/unit/apns/notification_spec.rb +215 -0
- data/spec/unit/apns_feedback_spec.rb +21 -0
- data/spec/unit/app_spec.rb +16 -0
- data/spec/unit/configuration_spec.rb +55 -0
- data/spec/unit/daemon/apns/app_runner_spec.rb +45 -0
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
- data/spec/unit/daemon/apns/connection_spec.rb +287 -0
- data/spec/unit/daemon/apns/delivery_handler_spec.rb +59 -0
- data/spec/unit/daemon/apns/delivery_spec.rb +101 -0
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +18 -0
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +134 -0
- data/spec/unit/daemon/app_runner_shared.rb +83 -0
- data/spec/unit/daemon/app_runner_spec.rb +170 -0
- data/spec/unit/daemon/batch_spec.rb +219 -0
- data/spec/unit/daemon/delivery_error_spec.rb +13 -0
- data/spec/unit/daemon/delivery_handler_collection_spec.rb +37 -0
- data/spec/unit/daemon/delivery_handler_shared.rb +45 -0
- data/spec/unit/daemon/feeder_spec.rb +81 -0
- data/spec/unit/daemon/gcm/app_runner_spec.rb +19 -0
- data/spec/unit/daemon/gcm/delivery_handler_spec.rb +44 -0
- data/spec/unit/daemon/gcm/delivery_spec.rb +289 -0
- data/spec/unit/daemon/interruptible_sleep_spec.rb +68 -0
- data/spec/unit/daemon/reflectable_spec.rb +27 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +114 -0
- data/spec/unit/daemon/store/active_record_spec.rb +281 -0
- data/spec/unit/daemon_spec.rb +157 -0
- data/spec/unit/deprecatable_spec.rb +32 -0
- data/spec/unit/deprecation_spec.rb +15 -0
- data/spec/unit/embed_spec.rb +50 -0
- data/spec/unit/gcm/app_spec.rb +4 -0
- data/spec/unit/gcm/notification_spec.rb +52 -0
- data/spec/unit/logger_spec.rb +180 -0
- data/spec/unit/notification_shared.rb +45 -0
- data/spec/unit/notification_spec.rb +4 -0
- data/spec/unit/notifier_spec.rb +32 -0
- data/spec/unit/push_spec.rb +44 -0
- data/spec/unit/rapns_spec.rb +9 -0
- data/spec/unit/reflection_spec.rb +30 -0
- data/spec/unit/upgraded_spec.rb +40 -0
- data/spec/unit_spec_helper.rb +137 -0
- metadata +232 -0
data/lib/rapns/embed.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
def self.embed(options = {})
|
|
3
|
+
Rapns.require_for_daemon
|
|
4
|
+
|
|
5
|
+
config = Rapns::ConfigurationWithoutDefaults.new
|
|
6
|
+
options.each { |k, v| config.send("#{k}=", v) }
|
|
7
|
+
config.embedded = true
|
|
8
|
+
Rapns.config.update(config)
|
|
9
|
+
Rapns::Daemon.start
|
|
10
|
+
|
|
11
|
+
Kernel.at_exit { shutdown }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.shutdown
|
|
15
|
+
return unless Rapns.config.embedded
|
|
16
|
+
Rapns::Daemon.shutdown
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.sync
|
|
20
|
+
return unless Rapns.config.embedded
|
|
21
|
+
Rapns::Daemon::AppRunner.sync
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.debug
|
|
25
|
+
return unless Rapns.config.embedded
|
|
26
|
+
Rapns::Daemon::AppRunner.debug
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Gcm
|
|
3
|
+
class ExpiryCollapseKeyMutualInclusionValidator < ActiveModel::Validator
|
|
4
|
+
def validate(record)
|
|
5
|
+
if record.collapse_key && !record.expiry
|
|
6
|
+
record.errors.add(:expiry, "must be set when using a collapse_key")
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Gcm
|
|
3
|
+
class Notification < Rapns::Notification
|
|
4
|
+
validates_presence_of :registration_ids
|
|
5
|
+
validates_with Rapns::Gcm::ExpiryCollapseKeyMutualInclusionValidator
|
|
6
|
+
validates_with Rapns::Gcm::PayloadDataSizeValidator
|
|
7
|
+
validates_with Rapns::Gcm::RegistrationIdsCountValidator
|
|
8
|
+
|
|
9
|
+
def registration_ids=(ids)
|
|
10
|
+
ids = [ids] if ids && !ids.is_a?(Array)
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def as_json
|
|
15
|
+
json = {
|
|
16
|
+
'registration_ids' => registration_ids,
|
|
17
|
+
'delay_while_idle' => delay_while_idle,
|
|
18
|
+
'data' => data
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if collapse_key
|
|
22
|
+
json['collapse_key'] = collapse_key
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if expiry
|
|
26
|
+
json['time_to_live'] = expiry
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
json
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def payload_data_size
|
|
33
|
+
multi_json_dump(as_json['data']).bytesize
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Gcm
|
|
3
|
+
class PayloadDataSizeValidator < ActiveModel::Validator
|
|
4
|
+
LIMIT = 4096
|
|
5
|
+
|
|
6
|
+
def validate(record)
|
|
7
|
+
if record.payload_data_size > LIMIT
|
|
8
|
+
record.errors.add(:base, "GCM 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 Rapns
|
|
2
|
+
module Gcm
|
|
3
|
+
class RegistrationIdsCountValidator < ActiveModel::Validator
|
|
4
|
+
LIMIT = 1000
|
|
5
|
+
|
|
6
|
+
def validate(record)
|
|
7
|
+
if record.registration_ids && record.registration_ids.size > LIMIT
|
|
8
|
+
record.errors.add(:base, "GCM notification number of registration_ids cannot be larger than #{LIMIT}")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/rapns/logger.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
class Logger
|
|
3
|
+
def initialize(options)
|
|
4
|
+
@options = options
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
log = File.open(File.join(Rails.root, 'log', 'rapns.log'), 'a')
|
|
8
|
+
log.sync = true
|
|
9
|
+
setup_logger(log)
|
|
10
|
+
rescue Errno::ENOENT, Errno::EPERM => e
|
|
11
|
+
@logger = nil
|
|
12
|
+
error(e)
|
|
13
|
+
error('Logging disabled.')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def info(msg)
|
|
18
|
+
log(:info, msg)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def error(msg, options = {})
|
|
22
|
+
airbrake_notify(msg) if notify_via_airbrake?(msg, options)
|
|
23
|
+
log(:error, msg, 'ERROR', STDERR)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def warn(msg)
|
|
27
|
+
log(:warn, msg, 'WARNING', STDERR)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def setup_logger(log)
|
|
33
|
+
if Rapns.config.logger
|
|
34
|
+
@logger = Rapns.config.logger
|
|
35
|
+
elsif ActiveSupport.const_defined?('BufferedLogger')
|
|
36
|
+
@logger = ActiveSupport::BufferedLogger.new(log, Rails.logger.level)
|
|
37
|
+
@logger.auto_flushing = Rails.logger.respond_to?(:auto_flushing) ? Rails.logger.auto_flushing : true
|
|
38
|
+
else
|
|
39
|
+
@logger = ActiveSupport::Logger.new(log, Rails.logger.level)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def log(where, msg, prefix = nil, io = STDOUT)
|
|
44
|
+
if msg.is_a?(Exception)
|
|
45
|
+
formatted_backtrace = msg.backtrace.join("\n")
|
|
46
|
+
msg = "#{msg.class.name}, #{msg.message}\n#{formatted_backtrace}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
formatted_msg = "[#{Time.now.to_s(:db)}] "
|
|
50
|
+
formatted_msg << "[#{prefix}] " if prefix
|
|
51
|
+
formatted_msg << msg
|
|
52
|
+
|
|
53
|
+
if io == STDERR
|
|
54
|
+
io.puts formatted_msg
|
|
55
|
+
elsif @options[:foreground]
|
|
56
|
+
io.puts formatted_msg
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@logger.send(where, formatted_msg) if @logger
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def airbrake_notify(e)
|
|
63
|
+
return unless @options[:airbrake_notify] == true
|
|
64
|
+
|
|
65
|
+
if defined?(Airbrake)
|
|
66
|
+
Airbrake.notify_or_ignore(e)
|
|
67
|
+
elsif defined?(HoptoadNotifier)
|
|
68
|
+
HoptoadNotifier.notify_or_ignore(e)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def notify_via_airbrake?(msg, options)
|
|
73
|
+
msg.is_a?(Exception) && options[:airbrake_notify] != false
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module MultiJsonHelper
|
|
3
|
+
def multi_json_load(string, options = {})
|
|
4
|
+
# Calling load on multi_json less than v1.3.0 attempts to load a file from disk.
|
|
5
|
+
if Gem.loaded_specs['multi_json'].version >= Gem::Version.create('1.3.0')
|
|
6
|
+
MultiJson.load(string, options)
|
|
7
|
+
else
|
|
8
|
+
MultiJson.decode(string, options)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def multi_json_dump(string, options = {})
|
|
13
|
+
MultiJson.respond_to?(:dump) ? MultiJson.dump(string, options) : MultiJson.encode(string, options)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
class Notification < ActiveRecord::Base
|
|
3
|
+
include Rapns::MultiJsonHelper
|
|
4
|
+
|
|
5
|
+
self.table_name = 'rapns_notifications'
|
|
6
|
+
self.store_full_sti_class = true
|
|
7
|
+
|
|
8
|
+
# TODO: Dump using multi json.
|
|
9
|
+
serialize :registration_ids
|
|
10
|
+
|
|
11
|
+
belongs_to :app, :class_name => 'Rapns::App'
|
|
12
|
+
|
|
13
|
+
if Rapns.attr_accessible_available?
|
|
14
|
+
attr_accessible :badge, :device_token, :sound, :alert, :data, :expiry,:delivered,
|
|
15
|
+
:delivered_at, :failed, :failed_at, :error_code, :error_description, :retries, :deliver_after,
|
|
16
|
+
:alert_is_json, :app, :app_id, :collapse_key, :delay_while_idle, :registration_ids
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
validates_numericality_of :expiry, :allow_nil => true
|
|
20
|
+
validates_presence_of :app
|
|
21
|
+
|
|
22
|
+
named_scope :ready_for_delivery, lambda {
|
|
23
|
+
{
|
|
24
|
+
:conditions => ['delivered = ? AND failed = ? AND (deliver_after IS NULL OR deliver_after < ?)',
|
|
25
|
+
false, false, Time.now]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
named_scope :for_apps, lambda { |apps|
|
|
30
|
+
{
|
|
31
|
+
:conditions => ['app_id IN (?)', apps.map(&:id)]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def initialize(*args)
|
|
36
|
+
attributes = args.first
|
|
37
|
+
if attributes.is_a?(Hash) && attributes.keys.include?(:attributes_for_device)
|
|
38
|
+
msg = ":attributes_for_device via mass-assignment is deprecated. Use :data or the attributes_for_device= instance method."
|
|
39
|
+
Rapns::Deprecation.warn(msg)
|
|
40
|
+
end
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def data=(attrs)
|
|
45
|
+
return unless attrs
|
|
46
|
+
raise ArgumentError, "must be a Hash" if !attrs.is_a?(Hash)
|
|
47
|
+
write_attribute(:data, multi_json_dump(attrs))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def data
|
|
51
|
+
multi_json_load(read_attribute(:data)) if read_attribute(:data)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def payload
|
|
55
|
+
multi_json_dump(as_json)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def payload_size
|
|
59
|
+
payload.bytesize
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
|
|
3
|
+
module Rapns
|
|
4
|
+
# This class notifies the sleeping Rapns Daemon that there are new Notifications to send,
|
|
5
|
+
# and to interrupt its sleep to send them immediately. The purpose of this is to allow
|
|
6
|
+
# much higher sleep times to reduce database polling activity.
|
|
7
|
+
class Notifier
|
|
8
|
+
def initialize(host, port)
|
|
9
|
+
@host, @port = host, port
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# notify the daemon that there is a Notification to send.
|
|
13
|
+
def notify
|
|
14
|
+
socket.write('x')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @return [UDPSocket]
|
|
18
|
+
def socket
|
|
19
|
+
if @socket.nil?
|
|
20
|
+
@socket = UDPSocket.new
|
|
21
|
+
@socket.connect(@host, @port)
|
|
22
|
+
end
|
|
23
|
+
@socket
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# close the udp socket
|
|
27
|
+
def close
|
|
28
|
+
if @socket
|
|
29
|
+
@socket.close
|
|
30
|
+
@socket = nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/rapns/push.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
def self.push(options = {})
|
|
3
|
+
Rapns.require_for_daemon
|
|
4
|
+
|
|
5
|
+
config = Rapns::ConfigurationWithoutDefaults.new
|
|
6
|
+
options.each { |k, v| config.send("#{k}=", v) }
|
|
7
|
+
config.push = true
|
|
8
|
+
Rapns.config.update(config)
|
|
9
|
+
|
|
10
|
+
Upgraded.check(:exit => false)
|
|
11
|
+
Rapns::Daemon.initialize_store
|
|
12
|
+
Rapns::Daemon::AppRunner.sync
|
|
13
|
+
Rapns::Daemon::Feeder.start
|
|
14
|
+
Rapns::Daemon::AppRunner.wait
|
|
15
|
+
Rapns::Daemon::AppRunner.stop
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'active_record/base'
|
|
2
|
+
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class Validator
|
|
5
|
+
|
|
6
|
+
def initialize(options)
|
|
7
|
+
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ActiveRecord::Validations::ClassMethods
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def validates_with(*args, &block)
|
|
17
|
+
options = args.extract_options!
|
|
18
|
+
args.each do |klass|
|
|
19
|
+
validator = klass.new(options, &block)
|
|
20
|
+
validator.setup(self) if validator.respond_to?(:setup)
|
|
21
|
+
|
|
22
|
+
#if validator.respond_to?(:attributes) && !validator.attributes.empty?
|
|
23
|
+
# validator.attributes.each do |attribute|
|
|
24
|
+
# _validators[attribute.to_sym] << validator
|
|
25
|
+
# end
|
|
26
|
+
#else
|
|
27
|
+
# _validators[nil] << validator
|
|
28
|
+
#end
|
|
29
|
+
|
|
30
|
+
validate(validator, options)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
def self.reflect
|
|
3
|
+
yield reflections if block_given?
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def self.reflections
|
|
7
|
+
@reflections ||= Reflections.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Reflections
|
|
11
|
+
class NoSuchReflectionError < StandardError; end
|
|
12
|
+
|
|
13
|
+
REFLECTIONS = [
|
|
14
|
+
:apns_feedback, :notification_enqueued, :notification_delivered,
|
|
15
|
+
:notification_failed, :notification_will_retry, :apns_connection_lost,
|
|
16
|
+
:gcm_canonical_id, :gcm_invalid_registration_id, :error, :apns_certificate_will_expire
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
REFLECTIONS.each do |reflection|
|
|
20
|
+
class_eval(<<-RUBY, __FILE__, __LINE__)
|
|
21
|
+
def #{reflection}(*args, &blk)
|
|
22
|
+
raise "block required" unless block_given?
|
|
23
|
+
reflections[:#{reflection}] = blk
|
|
24
|
+
end
|
|
25
|
+
RUBY
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def __dispatch(reflection, *args)
|
|
29
|
+
unless REFLECTIONS.include?(reflection.to_sym)
|
|
30
|
+
raise NoSuchReflectionError, reflection
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if reflections[reflection]
|
|
34
|
+
reflections[reflection].call(*args)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def reflections
|
|
41
|
+
@reflections ||= {}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Rapns
|
|
2
|
+
module Upgraded
|
|
3
|
+
def self.check(options = {})
|
|
4
|
+
count = 0
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
count = Rapns::App.count
|
|
8
|
+
rescue ActiveRecord::StatementInvalid
|
|
9
|
+
puts "!!!! RAPNS NOT STARTED !!!!"
|
|
10
|
+
puts
|
|
11
|
+
puts "As of version v2.0.0 apps are configured in the database instead of rapns.yml."
|
|
12
|
+
puts "Please run 'rails g rapns' to generate the new migrations and create your app."
|
|
13
|
+
puts "See https://github.com/ileitch/rapns for further instructions."
|
|
14
|
+
puts
|
|
15
|
+
exit 1 if options[:exit]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if count == 0
|
|
19
|
+
Rapns.logger.warn("You have not created an app yet. See https://github.com/ileitch/rapns for instructions.")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if File.exists?(File.join(Rails.root, 'config', 'rapns', 'rapns.yml'))
|
|
23
|
+
Rapns.logger.warn(<<-EOS)
|
|
24
|
+
Since 2.0.0 rapns uses command-line options and a Ruby based configuration file.
|
|
25
|
+
Please run 'rails g rapns' to generate a new configuration file into config/initializers.
|
|
26
|
+
Remove config/rapns/rapns.yml to avoid this warning.
|
|
27
|
+
EOS
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
require 'multi_json'
|
|
3
|
+
|
|
4
|
+
module Rapns
|
|
5
|
+
|
|
6
|
+
def self.is_rails2?
|
|
7
|
+
require 'rails'
|
|
8
|
+
false
|
|
9
|
+
rescue MissingSourceFile
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.is_rails2_or_3?
|
|
14
|
+
is_rails2? || ::Rails::VERSION::STRING < '4'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.attr_accessible_available?
|
|
18
|
+
is_rails2_or_3?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
require 'rapns/version'
|
|
24
|
+
require 'rapns/rails-2-compatibility' if Rapns.is_rails2?
|
|
25
|
+
require 'rapns/deprecation'
|
|
26
|
+
require 'rapns/deprecatable'
|
|
27
|
+
require 'rapns/logger'
|
|
28
|
+
require 'rapns/multi_json_helper'
|
|
29
|
+
require 'rapns/notification'
|
|
30
|
+
require 'rapns/app'
|
|
31
|
+
require 'rapns/configuration'
|
|
32
|
+
require 'rapns/reflection'
|
|
33
|
+
require 'rapns/embed'
|
|
34
|
+
require 'rapns/push'
|
|
35
|
+
require 'rapns/apns_feedback'
|
|
36
|
+
require 'rapns/upgraded'
|
|
37
|
+
|
|
38
|
+
require 'rapns/apns/binary_notification_validator'
|
|
39
|
+
require 'rapns/apns/device_token_format_validator'
|
|
40
|
+
require 'rapns/apns/notification'
|
|
41
|
+
require 'rapns/apns/feedback'
|
|
42
|
+
require 'rapns/apns/app'
|
|
43
|
+
|
|
44
|
+
require 'rapns/gcm/expiry_collapse_key_mutual_inclusion_validator'
|
|
45
|
+
require 'rapns/gcm/payload_data_size_validator'
|
|
46
|
+
require 'rapns/gcm/registration_ids_count_validator'
|
|
47
|
+
require 'rapns/gcm/notification'
|
|
48
|
+
require 'rapns/gcm/app'
|
|
49
|
+
|
|
50
|
+
module Rapns
|
|
51
|
+
def self.jruby?
|
|
52
|
+
defined? JRUBY_VERSION
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.require_for_daemon
|
|
56
|
+
require 'rapns/daemon'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.logger
|
|
60
|
+
@logger ||= Logger.new(:foreground => Rapns.config.foreground,
|
|
61
|
+
:airbrake_notify => Rapns.config.airbrake_notify)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.logger=(logger)
|
|
65
|
+
@logger = logger
|
|
66
|
+
end
|
|
67
|
+
end
|
data/lib/tasks/cane.rake
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'cane/rake_task'
|
|
3
|
+
|
|
4
|
+
desc "Run cane to check quality metrics"
|
|
5
|
+
Cane::RakeTask.new(:quality) do |cane|
|
|
6
|
+
cane.add_threshold 'coverage/covered_percent', :>=, 98
|
|
7
|
+
cane.no_style = false
|
|
8
|
+
cane.style_measure = 1000
|
|
9
|
+
cane.no_doc = true
|
|
10
|
+
cane.abc_max = 20
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
namespace :spec do
|
|
14
|
+
task :cane => ['spec', 'quality']
|
|
15
|
+
end
|
|
16
|
+
rescue LoadError
|
|
17
|
+
warn "cane not available, quality task not provided."
|
|
18
|
+
end
|
data/lib/tasks/test.rake
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
namespace :test do
|
|
2
|
+
task :build_rails do
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
def cmd(str, clean_env = true)
|
|
6
|
+
puts "* #{str}"
|
|
7
|
+
retval = if clean_env
|
|
8
|
+
Bundler.with_clean_env { `#{str}` }
|
|
9
|
+
else
|
|
10
|
+
`#{str}`
|
|
11
|
+
end
|
|
12
|
+
puts retval.strip
|
|
13
|
+
retval
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
rapns_root = Dir.pwd
|
|
17
|
+
path = '/tmp/rails_test'
|
|
18
|
+
cmd("rm -rf #{path}")
|
|
19
|
+
FileUtils.mkdir_p(path)
|
|
20
|
+
pwd = Dir.pwd
|
|
21
|
+
|
|
22
|
+
cmd("bundle exec rails --version", false)
|
|
23
|
+
cmd("bundle exec rails new #{path} --skip-bundle", false)
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
Dir.chdir(path)
|
|
27
|
+
cmd('echo "gem \'rake\'" >> Gemfile')
|
|
28
|
+
cmd("echo \"gem 'rapns_rails_2', :path => '#{rapns_root}'\" >> Gemfile")
|
|
29
|
+
cmd('bundle install')
|
|
30
|
+
cmd('bundle exec script/generate rapns')
|
|
31
|
+
cmd('bundle exec rake db:migrate')
|
|
32
|
+
ensure
|
|
33
|
+
Dir.chdir(pwd)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
puts "Built into #{path}"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Bag Attributes
|
|
2
|
+
localKeyID: A4 1A DB 3E 3E 45 D9 C7 51 1E E6 DC 4E BC 29 19 E4 22 95 35
|
|
3
|
+
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
|
|
4
|
+
issuer=/C=UK/ST=Some-State/O=Internet Widgits Pty Ltd
|
|
5
|
+
-----BEGIN CERTIFICATE-----
|
|
6
|
+
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
|
|
33
|
+
-----END CERTIFICATE-----
|
|
34
|
+
Bag Attributes
|
|
35
|
+
localKeyID: A4 1A DB 3E 3E 45 D9 C7 51 1E E6 DC 4E BC 29 19 E4 22 95 35
|
|
36
|
+
Key Attributes: <No Attributes>
|
|
37
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
38
|
+
Proc-Type: 4,ENCRYPTED
|
|
39
|
+
DEK-Info: DES-EDE3-CBC,874F2C982467BF08
|
|
40
|
+
|
|
41
|
+
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
|
|
90
|
+
-----END RSA PRIVATE KEY-----
|