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.
Files changed (113) hide show
  1. checksums.yaml +15 -0
  2. data/CHANGELOG.md +83 -0
  3. data/LICENSE +7 -0
  4. data/README.md +168 -0
  5. data/bin/rapns +37 -0
  6. data/config/database.yml +44 -0
  7. data/lib/generators/rapns_generator.rb +25 -0
  8. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
  9. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  10. data/lib/generators/templates/add_gcm.rb +95 -0
  11. data/lib/generators/templates/create_rapns_apps.rb +16 -0
  12. data/lib/generators/templates/create_rapns_feedback.rb +15 -0
  13. data/lib/generators/templates/create_rapns_notifications.rb +26 -0
  14. data/lib/generators/templates/rapns.rb +87 -0
  15. data/lib/rapns/TODO +3 -0
  16. data/lib/rapns/apns/app.rb +25 -0
  17. data/lib/rapns/apns/binary_notification_validator.rb +12 -0
  18. data/lib/rapns/apns/device_token_format_validator.rb +12 -0
  19. data/lib/rapns/apns/feedback.rb +16 -0
  20. data/lib/rapns/apns/notification.rb +91 -0
  21. data/lib/rapns/apns_feedback.rb +13 -0
  22. data/lib/rapns/app.rb +16 -0
  23. data/lib/rapns/configuration.rb +89 -0
  24. data/lib/rapns/daemon/apns/app_runner.rb +26 -0
  25. data/lib/rapns/daemon/apns/certificate_expired_error.rb +20 -0
  26. data/lib/rapns/daemon/apns/connection.rb +142 -0
  27. data/lib/rapns/daemon/apns/delivery.rb +64 -0
  28. data/lib/rapns/daemon/apns/delivery_handler.rb +35 -0
  29. data/lib/rapns/daemon/apns/disconnection_error.rb +20 -0
  30. data/lib/rapns/daemon/apns/feedback_receiver.rb +89 -0
  31. data/lib/rapns/daemon/app_runner.rb +179 -0
  32. data/lib/rapns/daemon/batch.rb +112 -0
  33. data/lib/rapns/daemon/delivery.rb +23 -0
  34. data/lib/rapns/daemon/delivery_error.rb +19 -0
  35. data/lib/rapns/daemon/delivery_handler.rb +52 -0
  36. data/lib/rapns/daemon/delivery_handler_collection.rb +33 -0
  37. data/lib/rapns/daemon/feeder.rb +65 -0
  38. data/lib/rapns/daemon/gcm/app_runner.rb +13 -0
  39. data/lib/rapns/daemon/gcm/delivery.rb +228 -0
  40. data/lib/rapns/daemon/gcm/delivery_handler.rb +20 -0
  41. data/lib/rapns/daemon/interruptible_sleep.rb +65 -0
  42. data/lib/rapns/daemon/reflectable.rb +13 -0
  43. data/lib/rapns/daemon/store/active_record/reconnectable.rb +66 -0
  44. data/lib/rapns/daemon/store/active_record.rb +128 -0
  45. data/lib/rapns/daemon.rb +129 -0
  46. data/lib/rapns/deprecatable.rb +23 -0
  47. data/lib/rapns/deprecation.rb +23 -0
  48. data/lib/rapns/embed.rb +28 -0
  49. data/lib/rapns/gcm/app.rb +7 -0
  50. data/lib/rapns/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
  51. data/lib/rapns/gcm/notification.rb +37 -0
  52. data/lib/rapns/gcm/payload_data_size_validator.rb +13 -0
  53. data/lib/rapns/gcm/registration_ids_count_validator.rb +13 -0
  54. data/lib/rapns/logger.rb +76 -0
  55. data/lib/rapns/multi_json_helper.rb +16 -0
  56. data/lib/rapns/notification.rb +62 -0
  57. data/lib/rapns/notifier.rb +35 -0
  58. data/lib/rapns/push.rb +17 -0
  59. data/lib/rapns/rails-2-compatibility.rb +34 -0
  60. data/lib/rapns/reflection.rb +44 -0
  61. data/lib/rapns/upgraded.rb +31 -0
  62. data/lib/rapns/version.rb +3 -0
  63. data/lib/rapns_rails_2.rb +67 -0
  64. data/lib/tasks/cane.rake +18 -0
  65. data/lib/tasks/test.rake +38 -0
  66. data/spec/support/cert_with_password.pem +90 -0
  67. data/spec/support/cert_without_password.pem +59 -0
  68. data/spec/support/simplecov_helper.rb +13 -0
  69. data/spec/support/simplecov_quality_formatter.rb +8 -0
  70. data/spec/tmp/.gitkeep +0 -0
  71. data/spec/unit/apns/app_spec.rb +29 -0
  72. data/spec/unit/apns/feedback_spec.rb +9 -0
  73. data/spec/unit/apns/notification_spec.rb +215 -0
  74. data/spec/unit/apns_feedback_spec.rb +21 -0
  75. data/spec/unit/app_spec.rb +16 -0
  76. data/spec/unit/configuration_spec.rb +55 -0
  77. data/spec/unit/daemon/apns/app_runner_spec.rb +45 -0
  78. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
  79. data/spec/unit/daemon/apns/connection_spec.rb +287 -0
  80. data/spec/unit/daemon/apns/delivery_handler_spec.rb +59 -0
  81. data/spec/unit/daemon/apns/delivery_spec.rb +101 -0
  82. data/spec/unit/daemon/apns/disconnection_error_spec.rb +18 -0
  83. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +134 -0
  84. data/spec/unit/daemon/app_runner_shared.rb +83 -0
  85. data/spec/unit/daemon/app_runner_spec.rb +170 -0
  86. data/spec/unit/daemon/batch_spec.rb +219 -0
  87. data/spec/unit/daemon/delivery_error_spec.rb +13 -0
  88. data/spec/unit/daemon/delivery_handler_collection_spec.rb +37 -0
  89. data/spec/unit/daemon/delivery_handler_shared.rb +45 -0
  90. data/spec/unit/daemon/feeder_spec.rb +81 -0
  91. data/spec/unit/daemon/gcm/app_runner_spec.rb +19 -0
  92. data/spec/unit/daemon/gcm/delivery_handler_spec.rb +44 -0
  93. data/spec/unit/daemon/gcm/delivery_spec.rb +289 -0
  94. data/spec/unit/daemon/interruptible_sleep_spec.rb +68 -0
  95. data/spec/unit/daemon/reflectable_spec.rb +27 -0
  96. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +114 -0
  97. data/spec/unit/daemon/store/active_record_spec.rb +281 -0
  98. data/spec/unit/daemon_spec.rb +157 -0
  99. data/spec/unit/deprecatable_spec.rb +32 -0
  100. data/spec/unit/deprecation_spec.rb +15 -0
  101. data/spec/unit/embed_spec.rb +50 -0
  102. data/spec/unit/gcm/app_spec.rb +4 -0
  103. data/spec/unit/gcm/notification_spec.rb +52 -0
  104. data/spec/unit/logger_spec.rb +180 -0
  105. data/spec/unit/notification_shared.rb +45 -0
  106. data/spec/unit/notification_spec.rb +4 -0
  107. data/spec/unit/notifier_spec.rb +32 -0
  108. data/spec/unit/push_spec.rb +44 -0
  109. data/spec/unit/rapns_spec.rb +9 -0
  110. data/spec/unit/reflection_spec.rb +30 -0
  111. data/spec/unit/upgraded_spec.rb +40 -0
  112. data/spec/unit_spec_helper.rb +137 -0
  113. metadata +232 -0
@@ -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,7 @@
1
+ module Rapns
2
+ module Gcm
3
+ class App < Rapns::App
4
+ validates_presence_of :auth_key
5
+ end
6
+ end
7
+ 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
@@ -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,3 @@
1
+ module Rapns
2
+ VERSION = '3.4.3'
3
+ 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
@@ -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
@@ -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-----