rapns_rails_2 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
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-----