rapns_rails_2 3.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
MIIE/jCCAuYCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCVUsxEzARBgNV
|
7
|
+
BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
|
8
|
+
ZDAeFw0xMjEyMjgxMzU4NTdaFw0xNDEyMjgxMzU4NTdaMEUxCzAJBgNVBAYTAkFV
|
9
|
+
MRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz
|
10
|
+
IFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDYCSfYP0P7
|
11
|
+
F+JbxUHYsl/9Plr2bFZGMBygqs5RWpw1X977p4FqcNtnRmGENQ/I5vE3KkAKCAlS
|
12
|
+
gmus7CjB9/FVzoJq65cT3wBkcqAAzPgIQuI0UjP+rLktV84eUup7Pt6f/Bmt/fBj
|
13
|
+
h3fvf80nBQcdK2ztu1xtTs7EsRgyudUDDEIUZw9ddK21RbCMYE0PFY0QapNVvevs
|
14
|
+
8lDVUJX60bZqVqzhvlTzmEaBF+E66J/DhHuhcWZV588hVKjHMNED9Aq4PxRy78vI
|
15
|
+
54v1buX2Y9C6dHfIzfu7zz0Zv5NAY1BZKpaglVGKArOrX+K6O7Bq+DwckTm1AbUf
|
16
|
+
pQqi10ghveOtVrm4GXJ4OYW8ohdYKMFjzwhgTTr/NQ+EVlcZ+8AOPVPPJk0HgPu/
|
17
|
+
eMNiLytvcSnB09OzIUAzcxOof2a1zfxn7aPzBTEC6kkoDJC/BDG8wxySUz0zRyyM
|
18
|
+
jUN2+J1mBJZX1h1sM/4ycAzsX1EYm2II5GGJaFngiV45Qv7wTC7W31kvih7FsdUX
|
19
|
+
rEYMkevB5AFPUtIvzevLUObLbPW4yWvU2CMcKLZdIaPTvtPMba91t1YOdufpPRDd
|
20
|
+
HTmT42h0aUWDSrcWDAuZPPPqEIQNjRVCudtHtobZDeaUfvbx05CvypyuNFaPonuQ
|
21
|
+
l5h0LpZWPetvfsrOlMxPm2kfVcxm8mWjzQIDAQABMA0GCSqGSIb3DQEBBQUAA4IC
|
22
|
+
AQBiwdPfLU0kjbU1hM6grUHduLqOPDqLT5gefGRrL5fDqb86G08+Wz+Tnn1YmH+7
|
23
|
+
rfiQhCrdi4zxRv6ZEaKZeEm/q1UMttuUdXuzd25BEEtav4R0POdR+H1q3trlS0ol
|
24
|
+
EcWlAbRgVaT2tTyKGAW54fH8vZPqS6IP+mXIzfaOFECPEgAO8BL8t7hBDpkL4ASO
|
25
|
+
HbU7ktYamsr6PAei3kXAnJ1thXyQqrhelwLrQJyM8RVOJYUgVbl6Fpdtgu7YQF5G
|
26
|
+
kxTAfshSmDCQkf+tbUEs44rZ6BZ2TWnbXjQGkRntHcMCP/1rjsPPdX3oeZ7P3jMQ
|
27
|
+
XER3drdm1mOiSdDUKbem9GzQ9Dx7WkwKNLYAZ+IWzVRACzGxnkxXyxOEFIgesDgg
|
28
|
+
RIhczN+eLIR8iwcUxEVKFmmsbEIve3Uh1/NE6xGudbfZDNfhyOhiNYIBnQqVkk8l
|
29
|
+
c3gw2UDR3lXTayiiXhK2l1etsyxtYncT3pgDsCe72RODrGKbASt3FzfBbalzN0GG
|
30
|
+
9tiPSNtGqCch9q4eHfViUh9s3+8n4bknAYcwzQ96+gMEn8PUVtDBv9F8Kxffn/Jt
|
31
|
+
XMWKX76nTVuAuCLkXxrKwc01lq8SeuvCH650xsv0LBvxj9h6vR34vHGrj0C3sH2E
|
32
|
+
VQpelKNv8IEwkSiQcwDtU8H0jaPJNqmYlkrxasSrSeg6PA==
|
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-----
|