diff --git a/Gemfile b/Gemfile index 0748607..832259b 100644 --- a/Gemfile +++ b/Gemfile @@ -103,3 +103,5 @@ gem 'bootstrap-sass', '~> 3.3.5' gem 'react-rails', '~> 1.10.0' gem 'rolify' gem 'rails-controller-testing' + +gem "rpush", "~> 4.1" diff --git a/Gemfile.lock b/Gemfile.lock index a5b953d..66e265b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,6 +50,7 @@ GEM annotate (2.7.4) activerecord (>= 3.2, < 6.0) rake (>= 10.4, < 13.0) + ansi (1.5.0) arel (9.0.0) autoprefixer-rails (8.6.2) execjs @@ -141,6 +142,7 @@ GEM haml (>= 4.0, < 6) nokogiri (>= 1.6.0) ruby_parser (~> 3.5) + http-2 (0.10.1) i18n (1.0.1) concurrent-ruby (~> 1.0) jbuilder (2.7.0) @@ -177,6 +179,10 @@ GEM multi_xml (0.6.0) multipart-post (2.0.0) mysql2 (0.5.2) + net-http-persistent (3.0.1) + connection_pool (~> 2.2) + net-http2 (0.18.2) + http-2 (~> 0.10.1) net-scp (1.2.1) net-ssh (>= 2.6.5) net-ssh (5.0.1) @@ -245,6 +251,15 @@ GEM actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) rolify (5.2.0) + rpush (4.1.0) + activesupport + ansi + jwt (>= 1.5.6) + multi_json (~> 1.0) + net-http-persistent + net-http2 (~> 0.14) + railties + thor (>= 0.18.1, < 2.0) rspec-core (3.7.1) rspec-support (~> 3.7.0) rspec-expectations (3.7.0) @@ -360,6 +375,7 @@ DEPENDENCIES rails-controller-testing react-rails (~> 1.10.0) rolify + rpush (~> 4.1) rspec-rails sass-rails (~> 5.0) sdoc (~> 0.4.0) diff --git a/config/initializers/rpush.rb b/config/initializers/rpush.rb new file mode 100644 index 0000000..90332bc --- /dev/null +++ b/config/initializers/rpush.rb @@ -0,0 +1,143 @@ +Rpush.configure do |config| + + # Supported clients are :active_record and :redis + config.client = :active_record + + # Options passed to Redis.new + # config.redis_options = {} + + # Frequency in seconds to check for new notifications. + config.push_poll = 2 + + # The maximum number of notifications to load from the store every `push_poll` seconds. + # If some notifications are still enqueued internally, Rpush will load the batch_size less + # the number enqueued. An exception to this is if the service is able to receive multiple + # notification payloads over the connection with a single write, such as APNs. + config.batch_size = 100 + + # Path to write PID file. Relative to current directory unless absolute. + config.pid_file = 'tmp/rpush.pid' + + # Path to log file. Relative to current directory unless absolute. + config.log_file = 'log/rpush.log' + + config.log_level = (defined?(Rails) && Rails.logger) ? Rails.logger.level : ::Logger::Severity::INFO + + # Define a custom logger. + # config.logger = MyLogger.new + + # config.apns.feedback_receiver.enabled = true + # config.apns.feedback_receiver.frequency = 60 + +end + +Rpush.reflect do |on| + + # Called with a Rpush::Apns::Feedback instance when feedback is received + # from the APNs that a notification has failed to be delivered. + # Further notifications should not be sent to the device. + # on.apns_feedback do |feedback| + # end + + # Called when a notification is queued internally for delivery. + # The internal queue for each app runner can be inspected: + # + # Rpush::Daemon::AppRunner.runners.each do |app_id, runner| + # runner.app + # runner.queue_size + # end + # + # on.notification_enqueued do |notification| + # end + + # Called when a notification is successfully delivered. + # on.notification_delivered do |notification| + # end + + # Called when notification delivery failed. + # Call 'error_code' and 'error_description' on the notification for the cause. + # on.notification_failed do |notification| + # end + + # Called when the notification delivery failed and only the notification ID + # is present in memory. + # on.notification_id_failed do |app, notification_id, error_code, error_description| + # end + + # Called when a notification will be retried at a later date. + # Call 'deliver_after' on the notification for the next delivery date + # and 'retries' for the number of times this notification has been retried. + # on.notification_will_retry do |notification| + # end + + # Called when a notification will be retried and only the notification ID + # is present in memory. + # on.notification_id_will_retry do |app, notification_id, retry_after| + # end + + # Called when a TCP connection is lost and will be reconnected. + # on.tcp_connection_lost do |app, error| + # end + + # Called for each recipient which successfully receives a notification. This + # can occur more than once for the same notification when there are multiple + # recipients. + # on.gcm_delivered_to_recipient do |notification, registration_id| + # end + + # Called for each recipient which fails to receive a notification. This + # can occur more than once for the same notification when there are multiple + # recipients. (do not handle invalid registration IDs here) + # on.gcm_failed_to_recipient do |notification, error, registration_id| + # end + + # Called when the GCM returns a canonical registration ID. + # You will need to replace old_id with canonical_id in your records. + # on.gcm_canonical_id do |old_id, canonical_id| + # end + + # Called when the GCM returns a failure that indicates an invalid registration id. + # You will need to delete the registration_id from your records. + # on.gcm_invalid_registration_id do |app, error, registration_id| + # end + + # Called when an SSL certificate will expire within 1 month. + # Implement on.error to catch errors raised when the certificate expires. + # on.ssl_certificate_will_expire do |app, expiration_time| + # end + + # Called when an SSL certificate has been revoked. + # on.ssl_certificate_revoked do |app, error| + # end + + # Called when the ADM returns a canonical registration ID. + # You will need to replace old_id with canonical_id in your records. + # on.adm_canonical_id do |old_id, canonical_id| + # end + + # Called when Failed to deliver to ADM. Check the 'reason' string for further + # explanations. + # + # If the reason is the string 'Unregistered', you should remove + # this registration id from your records. + # on.adm_failed_to_recipient do |notification, registration_id, reason| + # end + + # Called when Failed to deliver to WNS. Check the 'reason' string for further + # explanations. + # You should remove this uri from your records + # on.wns_invalid_channel do |notification, uri, reason| + # end + + # Called when an exception is raised. + # on.error do |error| + # end +end + +if defined?(Rails) + ActiveSupport.on_load(:after_initialize) do + Rpush.embed + end +else + Rpush.embed +end diff --git a/db/migrate/20190508204803_add_rpush.rb b/db/migrate/20190508204803_add_rpush.rb new file mode 100644 index 0000000..5e938ed --- /dev/null +++ b/db/migrate/20190508204803_add_rpush.rb @@ -0,0 +1,402 @@ +# NOTE TO THE CURIOUS. +# +# Congratulations on being a diligent developer and vetting the migrations +# added to your project! +# +# You're probably thinking "This migration is huge!". It is, but that doesn't +# mean it'll take a long time to run, or that the reason for it being +# this size is because of lousy developers. +# +# Rpush used to be known as Rapns. In an effort to reduce clutter in db/migrate +# for new users of Rpush, what you see below is a concatenation of the +# migrations added to Rapns over its lifetime. +# +# The reason for concatenating old migrations - instead of producing a new +# one that attempts to recreate their accumulative state - is that I don't +# want to introduce any bugs by writing a new migration. +# +# So while this looks like a scary amount of code, it is in fact the safest +# approach. The constituent parts of this migration have been executed +# many times, by many people! + +class AddRpush < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.migrations + [CreateRapnsNotifications, CreateRapnsFeedback, + AddAlertIsJsonToRapnsNotifications, AddAppToRapns, + CreateRapnsApps, AddGcm, AddWpns, AddAdm, RenameRapnsToRpush, + AddFailAfterToRpushNotifications] + end + + def self.up + migrations.map(&:up) + end + + def self.down + migrations.reverse.each do |m| + begin + m.down + rescue ActiveRecord::StatementInvalid => e + p e + end + end + end + + class CreateRapnsNotifications < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + create_table :rapns_notifications do |t| + t.integer :badge, null: true + t.string :device_token, null: false, limit: 64 + t.string :sound, null: true, default: "1.aiff" + t.string :alert, null: true + t.text :attributes_for_device, null: true + t.integer :expiry, null: false, default: 1.day.to_i + t.boolean :delivered, null: false, default: false + t.timestamp :delivered_at, null: true + t.boolean :failed, null: false, default: false + t.timestamp :failed_at, null: true + t.integer :error_code, null: true + t.string :error_description, null: true + t.timestamp :deliver_after, null: true + t.timestamps + end + + add_index :rapns_notifications, [:delivered, :failed, :deliver_after], name: 'index_rapns_notifications_multi' + end + + def self.down + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rapns_notifications, 'index_rapns_notifications_multi') + remove_index :rapns_notifications, name: 'index_rapns_notifications_multi' + end + else + if index_name_exists?(:rapns_notifications, 'index_rapns_notifications_multi', true) + remove_index :rapns_notifications, name: 'index_rapns_notifications_multi' + end + end + + drop_table :rapns_notifications + end + end + + class CreateRapnsFeedback < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + create_table :rapns_feedback do |t| + t.string :device_token, null: false, limit: 64 + t.timestamp :failed_at, null: false + t.timestamps + end + + add_index :rapns_feedback, :device_token + end + + def self.down + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rapns_feedback, :index_rapns_feedback_on_device_token) + remove_index :rapns_feedback, name: :index_rapns_feedback_on_device_token + end + else + if index_name_exists?(:rapns_feedback, :index_rapns_feedback_on_device_token, true) + remove_index :rapns_feedback, name: :index_rapns_feedback_on_device_token + end + end + + drop_table :rapns_feedback + end + end + + class AddAlertIsJsonToRapnsNotifications < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rapns_notifications, :alert_is_json, :boolean, null: true, default: false + end + + def self.down + remove_column :rapns_notifications, :alert_is_json + end + end + + class AddAppToRapns < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rapns_notifications, :app, :string, null: true + add_column :rapns_feedback, :app, :string, null: true + end + + def self.down + remove_column :rapns_notifications, :app + remove_column :rapns_feedback, :app + end + end + + class CreateRapnsApps < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + create_table :rapns_apps do |t| + t.string :key, null: false + t.string :environment, null: false + t.text :certificate, null: false + t.string :password, null: true + t.integer :connections, null: false, default: 1 + t.timestamps + end + end + + def self.down + drop_table :rapns_apps + end + end + + class AddGcm < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + module Rapns + class App < ActiveRecord::Base + self.table_name = 'rapns_apps' + end + + class Notification < ActiveRecord::Base + belongs_to :app + self.table_name = 'rapns_notifications' + end + end + + def self.up + add_column :rapns_notifications, :type, :string, null: true + add_column :rapns_apps, :type, :string, null: true + + AddGcm::Rapns::Notification.update_all type: 'Rapns::Apns::Notification' + AddGcm::Rapns::App.update_all type: 'Rapns::Apns::App' + + change_column :rapns_notifications, :type, :string, null: false + change_column :rapns_apps, :type, :string, null: false + change_column :rapns_notifications, :device_token, :string, { null: true, limit: 64 } + change_column :rapns_notifications, :expiry, :integer, { null: true, default: 1.day.to_i } + change_column :rapns_apps, :environment, :string, null: true + change_column :rapns_apps, :certificate, :text, null: true, default: nil + + change_column :rapns_notifications, :error_description, :text, null: true, default: nil + change_column :rapns_notifications, :sound, :string, default: 'default' + + rename_column :rapns_notifications, :attributes_for_device, :data + rename_column :rapns_apps, :key, :name + + add_column :rapns_apps, :auth_key, :string, null: true + + add_column :rapns_notifications, :collapse_key, :string, null: true + add_column :rapns_notifications, :delay_while_idle, :boolean, null: false, default: false + + reg_ids_type = ActiveRecord::Base.connection.adapter_name.include?('Mysql') ? :mediumtext : :text + add_column :rapns_notifications, :registration_ids, reg_ids_type, null: true + add_column :rapns_notifications, :app_id, :integer, null: true + add_column :rapns_notifications, :retries, :integer, null: true, default: 0 + + AddGcm::Rapns::Notification.reset_column_information + AddGcm::Rapns::App.reset_column_information + + AddGcm::Rapns::App.all.each do |app| + AddGcm::Rapns::Notification.where(app: app.name).update_all(app_id: app.id) + end + + change_column :rapns_notifications, :app_id, :integer, null: false + remove_column :rapns_notifications, :app + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rapns_notifications, "index_rapns_notifications_multi") + remove_index :rapns_notifications, name: "index_rapns_notifications_multi" + elsif index_name_exists?(:rapns_notifications, "index_rapns_notifications_on_delivered_failed_deliver_after") + remove_index :rapns_notifications, name: "index_rapns_notifications_on_delivered_failed_deliver_after" + end + else + if index_name_exists?(:rapns_notifications, "index_rapns_notifications_multi", true) + remove_index :rapns_notifications, name: "index_rapns_notifications_multi" + elsif index_name_exists?(:rapns_notifications, "index_rapns_notifications_on_delivered_failed_deliver_after", false) + remove_index :rapns_notifications, name: "index_rapns_notifications_on_delivered_failed_deliver_after" + end + end + + add_index :rapns_notifications, [:app_id, :delivered, :failed, :deliver_after], name: "index_rapns_notifications_multi" + end + + def self.down + AddGcm::Rapns::Notification.where(type: 'Rapns::Gcm::Notification').delete_all + + remove_column :rapns_notifications, :type + remove_column :rapns_apps, :type + + change_column :rapns_notifications, :device_token, :string, { null: false, limit: 64 } + change_column :rapns_notifications, :expiry, :integer, { null: false, default: 1.day.to_i } + change_column :rapns_apps, :environment, :string, null: false + change_column :rapns_apps, :certificate, :text, null: false + + change_column :rapns_notifications, :error_description, :string, null: true, default: nil + change_column :rapns_notifications, :sound, :string, default: '1.aiff' + + rename_column :rapns_notifications, :data, :attributes_for_device + rename_column :rapns_apps, :name, :key + + remove_column :rapns_apps, :auth_key + + remove_column :rapns_notifications, :collapse_key + remove_column :rapns_notifications, :delay_while_idle + remove_column :rapns_notifications, :registration_ids + remove_column :rapns_notifications, :retries + + add_column :rapns_notifications, :app, :string, null: true + + AddGcm::Rapns::Notification.reset_column_information + AddGcm::Rapns::App.reset_column_information + + AddGcm::Rapns::App.all.each do |app| + AddGcm::Rapns::Notification.where(app_id: app.id).update_all(app: app.key) + end + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rapns_notifications, :index_rapns_notifications_multi) + remove_index :rapns_notifications, name: :index_rapns_notifications_multi + end + else + if index_name_exists?(:rapns_notifications, :index_rapns_notifications_multi, true) + remove_index :rapns_notifications, name: :index_rapns_notifications_multi + end + end + + remove_column :rapns_notifications, :app_id + + add_index :rapns_notifications, [:delivered, :failed, :deliver_after], name: :index_rapns_notifications_multi + end + end + + class AddWpns < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + module Rapns + class Notification < ActiveRecord::Base + self.table_name = 'rapns_notifications' + end + end + + def self.up + add_column :rapns_notifications, :uri, :string, null: true + end + + def self.down + AddWpns::Rapns::Notification.where(type: 'Rapns::Wpns::Notification').delete_all + remove_column :rapns_notifications, :uri + end + end + + class AddAdm < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + module Rapns + class Notification < ActiveRecord::Base + self.table_name = 'rapns_notifications' + end + end + + def self.up + add_column :rapns_apps, :client_id, :string, null: true + add_column :rapns_apps, :client_secret, :string, null: true + add_column :rapns_apps, :access_token, :string, null: true + add_column :rapns_apps, :access_token_expiration, :datetime, null: true + end + + def self.down + AddAdm::Rapns::Notification.where(type: 'Rapns::Adm::Notification').delete_all + + remove_column :rapns_apps, :client_id + remove_column :rapns_apps, :client_secret + remove_column :rapns_apps, :access_token + remove_column :rapns_apps, :access_token_expiration + end + end + + class RenameRapnsToRpush < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + module Rpush + class App < ActiveRecord::Base + self.table_name = 'rpush_apps' + end + + class Notification < ActiveRecord::Base + self.table_name = 'rpush_notifications' + end + end + + def self.update_type(model, from, to) + model.where(type: from).update_all(type: to) + end + + def self.up + rename_table :rapns_notifications, :rpush_notifications + rename_table :rapns_apps, :rpush_apps + rename_table :rapns_feedback, :rpush_feedback + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rpush_notifications, :index_rapns_notifications_multi) + rename_index :rpush_notifications, :index_rapns_notifications_multi, :index_rpush_notifications_multi + end + else + if index_name_exists?(:rpush_notifications, :index_rapns_notifications_multi, true) + rename_index :rpush_notifications, :index_rapns_notifications_multi, :index_rpush_notifications_multi + end + end + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rpush_feedback, :index_rapns_feedback_on_device_token) + rename_index :rpush_feedback, :index_rapns_feedback_on_device_token, :index_rpush_feedback_on_device_token + end + else + if index_name_exists?(:rpush_feedback, :index_rapns_feedback_on_device_token, true) + rename_index :rpush_feedback, :index_rapns_feedback_on_device_token, :index_rpush_feedback_on_device_token + end + end + + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rapns::Apns::Notification', 'Rpush::Apns::Notification') + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rapns::Gcm::Notification', 'Rpush::Gcm::Notification') + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rapns::Adm::Notification', 'Rpush::Adm::Notification') + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rapns::Wpns::Notification', 'Rpush::Wpns::Notification') + + update_type(RenameRapnsToRpush::Rpush::App, 'Rapns::Apns::App', 'Rpush::Apns::App') + update_type(RenameRapnsToRpush::Rpush::App, 'Rapns::Gcm::App', 'Rpush::Gcm::App') + update_type(RenameRapnsToRpush::Rpush::App, 'Rapns::Adm::App', 'Rpush::Adm::App') + update_type(RenameRapnsToRpush::Rpush::App, 'Rapns::Wpns::App', 'Rpush::Wpns::App') + end + + def self.down + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rpush::Apns::Notification', 'Rapns::Apns::Notification') + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rpush::Gcm::Notification', 'Rapns::Gcm::Notification') + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rpush::Adm::Notification', 'Rapns::Adm::Notification') + update_type(RenameRapnsToRpush::Rpush::Notification, 'Rpush::Wpns::Notification', 'Rapns::Wpns::Notification') + + update_type(RenameRapnsToRpush::Rpush::App, 'Rpush::Apns::App', 'Rapns::Apns::App') + update_type(RenameRapnsToRpush::Rpush::App, 'Rpush::Gcm::App', 'Rapns::Gcm::App') + update_type(RenameRapnsToRpush::Rpush::App, 'Rpush::Adm::App', 'Rapns::Adm::App') + update_type(RenameRapnsToRpush::Rpush::App, 'Rpush::Wpns::App', 'Rapns::Wpns::App') + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi) + rename_index :rpush_notifications, :index_rpush_notifications_multi, :index_rapns_notifications_multi + end + else + if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true) + rename_index :rpush_notifications, :index_rpush_notifications_multi, :index_rapns_notifications_multi + end + end + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rpush_feedback, :index_rpush_feedback_on_device_token) + rename_index :rpush_feedback, :index_rpush_feedback_on_device_token, :index_rapns_feedback_on_device_token + end + else + if index_name_exists?(:rpush_feedback, :index_rpush_feedback_on_device_token, true) + rename_index :rpush_feedback, :index_rpush_feedback_on_device_token, :index_rapns_feedback_on_device_token + end + end + + rename_table :rpush_notifications, :rapns_notifications + rename_table :rpush_apps, :rapns_apps + rename_table :rpush_feedback, :rapns_feedback + end + end + + class AddFailAfterToRpushNotifications < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :fail_after, :timestamp, null: true + end + + def self.down + remove_column :rpush_notifications, :fail_after + end + end +end diff --git a/db/migrate/20190508204804_rpush_2_0_0_updates.rb b/db/migrate/20190508204804_rpush_2_0_0_updates.rb new file mode 100644 index 0000000..f26eb6b --- /dev/null +++ b/db/migrate/20190508204804_rpush_2_0_0_updates.rb @@ -0,0 +1,79 @@ +class Rpush200Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + module Rpush + class App < ActiveRecord::Base + self.table_name = 'rpush_apps' + end + + class Notification < ActiveRecord::Base + self.table_name = 'rpush_notifications' + end + end + + def self.update_type(model, from, to) + model.where(type: from).update_all(type: to) + end + + def self.up + add_column :rpush_notifications, :processing, :boolean, null: false, default: false + add_column :rpush_notifications, :priority, :integer, null: true + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi) + remove_index :rpush_notifications, name: :index_rpush_notifications_multi + end + else + if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true) + remove_index :rpush_notifications, name: :index_rpush_notifications_multi + end + end + + add_index :rpush_notifications, [:delivered, :failed], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed' + + rename_column :rpush_feedback, :app, :app_id + + if postgresql? + execute('ALTER TABLE rpush_feedback ALTER COLUMN app_id TYPE integer USING (trim(app_id)::integer)') + else + change_column :rpush_feedback, :app_id, :integer + end + + [:Apns, :Gcm, :Wpns, :Adm].each do |service| + update_type(Rpush200Updates::Rpush::App, "Rpush::#{service}::App", "Rpush::Client::ActiveRecord::#{service}::App") + update_type(Rpush200Updates::Rpush::Notification, "Rpush::#{service}::Notification", "Rpush::Client::ActiveRecord::#{service}::Notification") + end + end + + def self.down + [:Apns, :Gcm, :Wpns, :Adm].each do |service| + update_type(Rpush200Updates::Rpush::App, "Rpush::Client::ActiveRecord::#{service}::App", "Rpush::#{service}::App") + update_type(Rpush200Updates::Rpush::Notification, "Rpush::Client::ActiveRecord::#{service}::Notification", "Rpush::#{service}::Notification") + end + + change_column :rpush_feedback, :app_id, :string + rename_column :rpush_feedback, :app_id, :app + + if ActiveRecord.version >= Gem::Version.new('5.1') + if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi) + remove_index :rpush_notifications, name: :index_rpush_notifications_multi + end + else + if index_name_exists?(:rpush_notifications, :index_rpush_notifications_multi, true) + remove_index :rpush_notifications, name: :index_rpush_notifications_multi + end + end + + add_index :rpush_notifications, [:app_id, :delivered, :failed, :deliver_after], name: 'index_rpush_notifications_multi' + + remove_column :rpush_notifications, :priority + remove_column :rpush_notifications, :processing + end + + def self.adapter_name + env = (defined?(Rails) && Rails.env) ? Rails.env : 'development' + Hash[ActiveRecord::Base.configurations[env].map { |k,v| [k.to_sym,v] }][:adapter] + end + + def self.postgresql? + adapter_name =~ /postgresql|postgis/ + end +end diff --git a/db/migrate/20190508204805_rpush_2_1_0_updates.rb b/db/migrate/20190508204805_rpush_2_1_0_updates.rb new file mode 100644 index 0000000..34ac5cf --- /dev/null +++ b/db/migrate/20190508204805_rpush_2_1_0_updates.rb @@ -0,0 +1,11 @@ +class Rpush210Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :url_args, :text, null: true + add_column :rpush_notifications, :category, :string, null: true + end + + def self.down + remove_column :rpush_notifications, :url_args + remove_column :rpush_notifications, :category + end +end diff --git a/db/migrate/20190508204806_rpush_2_6_0_updates.rb b/db/migrate/20190508204806_rpush_2_6_0_updates.rb new file mode 100644 index 0000000..e21ee06 --- /dev/null +++ b/db/migrate/20190508204806_rpush_2_6_0_updates.rb @@ -0,0 +1,10 @@ +class Rpush260Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :content_available, :boolean, default: false + end + + def self.down + remove_column :rpush_notifications, :content_available + end +end + diff --git a/db/migrate/20190508204807_rpush_2_7_0_updates.rb b/db/migrate/20190508204807_rpush_2_7_0_updates.rb new file mode 100644 index 0000000..93ec65d --- /dev/null +++ b/db/migrate/20190508204807_rpush_2_7_0_updates.rb @@ -0,0 +1,12 @@ +class Rpush270Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + change_column :rpush_notifications, :alert, :text + add_column :rpush_notifications, :notification, :text + end + + def self.down + change_column :rpush_notifications, :alert, :string + remove_column :rpush_notifications, :notification + end +end + diff --git a/db/migrate/20190508204808_rpush_3_0_0_updates.rb b/db/migrate/20190508204808_rpush_3_0_0_updates.rb new file mode 100644 index 0000000..f790f05 --- /dev/null +++ b/db/migrate/20190508204808_rpush_3_0_0_updates.rb @@ -0,0 +1,11 @@ +class Rpush300Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :mutable_content, :boolean, default: false + change_column :rpush_notifications, :sound, :string, default: nil + end + + def self.down + remove_column :rpush_notifications, :mutable_content + change_column :rpush_notifications, :sound, :string, default: 'default' + end +end diff --git a/db/migrate/20190508204809_rpush_3_0_1_updates.rb b/db/migrate/20190508204809_rpush_3_0_1_updates.rb new file mode 100644 index 0000000..beb57cb --- /dev/null +++ b/db/migrate/20190508204809_rpush_3_0_1_updates.rb @@ -0,0 +1,13 @@ +class Rpush301Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + change_column_null :rpush_notifications, :mutable_content, false + change_column_null :rpush_notifications, :content_available, false + change_column_null :rpush_notifications, :alert_is_json, false + end + + def self.down + change_column_null :rpush_notifications, :mutable_content, true + change_column_null :rpush_notifications, :content_available, true + change_column_null :rpush_notifications, :alert_is_json, true + end +end diff --git a/db/migrate/20190508204810_rpush_3_1_0_add_pushy.rb b/db/migrate/20190508204810_rpush_3_1_0_add_pushy.rb new file mode 100644 index 0000000..cc59623 --- /dev/null +++ b/db/migrate/20190508204810_rpush_3_1_0_add_pushy.rb @@ -0,0 +1,9 @@ +class Rpush310AddPushy < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :external_device_id, :string, null: true + end + + def self.down + remove_column :rpush_notifications, :external_device_id + end +end diff --git a/db/migrate/20190508204811_rpush_3_1_1_updates.rb b/db/migrate/20190508204811_rpush_3_1_1_updates.rb new file mode 100644 index 0000000..c357764 --- /dev/null +++ b/db/migrate/20190508204811_rpush_3_1_1_updates.rb @@ -0,0 +1,15 @@ +class Rpush311Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + change_table :rpush_notifications do |t| + t.remove_index name: 'index_rpush_notifications_multi' + t.index [:delivered, :failed, :processing, :deliver_after, :created_at], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed' + end + end + + def self.down + change_table :rpush_notifications do |t| + t.remove_index name: 'index_rpush_notifications_multi' + t.index [:delivered, :failed], name: 'index_rpush_notifications_multi', where: 'NOT delivered AND NOT failed' + end + end +end diff --git a/db/migrate/20190508204812_rpush_3_2_0_add_apns_p8.rb b/db/migrate/20190508204812_rpush_3_2_0_add_apns_p8.rb new file mode 100644 index 0000000..7295409 --- /dev/null +++ b/db/migrate/20190508204812_rpush_3_2_0_add_apns_p8.rb @@ -0,0 +1,15 @@ +class Rpush320AddApnsP8 < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_apps, :apn_key, :string, null: true + add_column :rpush_apps, :apn_key_id, :string, null: true + add_column :rpush_apps, :team_id, :string, null: true + add_column :rpush_apps, :bundle_id, :string, null: true + end + + def self.down + remove_column :rpush_apps, :apn_key + remove_column :rpush_apps, :apn_key_id + remove_column :rpush_apps, :team_id + remove_column :rpush_apps, :bundle_id + end +end diff --git a/db/migrate/20190508204813_rpush_3_2_4_updates.rb b/db/migrate/20190508204813_rpush_3_2_4_updates.rb new file mode 100644 index 0000000..7f22620 --- /dev/null +++ b/db/migrate/20190508204813_rpush_3_2_4_updates.rb @@ -0,0 +1,9 @@ +class Rpush324Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + change_column :rpush_apps, :apn_key, :text, null: true + end + + def self.down + change_column :rpush_apps, :apn_key, :string, null: true + end +end diff --git a/db/migrate/20190508204814_rpush_3_3_0_updates.rb b/db/migrate/20190508204814_rpush_3_3_0_updates.rb new file mode 100644 index 0000000..fa1f904 --- /dev/null +++ b/db/migrate/20190508204814_rpush_3_3_0_updates.rb @@ -0,0 +1,9 @@ +class Rpush330Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :thread_id, :string, null: true + end + + def self.down + remove_column :rpush_notifications, :thread_id + end +end diff --git a/db/migrate/20190508204815_rpush_3_3_1_updates.rb b/db/migrate/20190508204815_rpush_3_3_1_updates.rb new file mode 100644 index 0000000..62fec8b --- /dev/null +++ b/db/migrate/20190508204815_rpush_3_3_1_updates.rb @@ -0,0 +1,11 @@ +class Rpush331Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration + def self.up + change_column :rpush_notifications, :device_token, :string, null: true + change_column :rpush_feedback, :device_token, :string, null: true + end + + def self.down + change_column :rpush_notifications, :device_token, :string, { null: true, limit: 64 } + change_column :rpush_feedback, :device_token, :string, { null: true, limit: 64 } + end +end diff --git a/db/migrate/20190508204816_rpush_4_1_0_updates.rb b/db/migrate/20190508204816_rpush_4_1_0_updates.rb new file mode 100644 index 0000000..53f67bb --- /dev/null +++ b/db/migrate/20190508204816_rpush_4_1_0_updates.rb @@ -0,0 +1,9 @@ +class Rpush410Updates < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"] : ActiveRecord::Migration + def self.up + add_column :rpush_notifications, :dry_run, :boolean, null: false, default: false + end + + def self.down + remove_column :rpush_notifications, :dry_run + end +end diff --git a/db/schema.rb b/db/schema.rb index 9381d88..6d25c8a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_05_08_192738) do +ActiveRecord::Schema.define(version: 2019_05_08_204816) do create_table "android_device_registration_tokens", force: :cascade do |t| t.string "token" @@ -72,6 +72,74 @@ ActiveRecord::Schema.define(version: 2019_05_08_192738) do t.index ["resource_type", "resource_id"], name: "index_roles_on_resource_type_and_resource_id" end + create_table "rpush_apps", force: :cascade do |t| + t.string "name", null: false + t.string "environment" + t.text "certificate" + t.string "password" + t.integer "connections", default: 1, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "type", null: false + t.string "auth_key" + t.string "client_id" + t.string "client_secret" + t.string "access_token" + t.datetime "access_token_expiration" + t.text "apn_key" + t.string "apn_key_id" + t.string "team_id" + t.string "bundle_id" + end + + create_table "rpush_feedback", force: :cascade do |t| + t.string "device_token", limit: 64 + t.datetime "failed_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "app_id" + t.index ["device_token"], name: "index_rpush_feedback_on_device_token" + end + + create_table "rpush_notifications", force: :cascade do |t| + t.integer "badge" + t.string "device_token", limit: 64 + t.string "sound" + t.text "alert" + t.text "data" + t.integer "expiry", default: 86400 + t.boolean "delivered", default: false, null: false + t.datetime "delivered_at" + t.boolean "failed", default: false, null: false + t.datetime "failed_at" + t.integer "error_code" + t.text "error_description" + t.datetime "deliver_after" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "alert_is_json", default: false, null: false + t.string "type", null: false + t.string "collapse_key" + t.boolean "delay_while_idle", default: false, null: false + t.text "registration_ids" + t.integer "app_id", null: false + t.integer "retries", default: 0 + t.string "uri" + t.datetime "fail_after" + t.boolean "processing", default: false, null: false + t.integer "priority" + t.text "url_args" + t.string "category" + t.boolean "content_available", default: false, null: false + t.text "notification" + t.boolean "mutable_content", default: false, null: false + t.string "external_device_id" + t.string "thread_id" + t.boolean "dry_run", default: false, null: false + t.index ["app_id", "delivered", "failed", "deliver_after"], name: "index_rapns_notifications_multi" + t.index ["delivered", "failed", "processing", "deliver_after", "created_at"], name: "index_rpush_notifications_multi", where: "NOT delivered AND NOT failed" + end + create_table "transactions", force: :cascade do |t| t.integer "debtor_id", null: false t.integer "creditor_id", null: false