docbrown/app/models/device.rb
Fernando Valverde cf3bde4259
Add mobile push notifications to Forem (#12419)
* First commit with iOS PN working

* RPush cleanup worker + unique jobs config

* Remove rpush tables from schema.rb

* PR feedback

* Feature flag and test for route

* Tests and feature flag PushNotification ::Send

* Update app/controllers/devices_controller.rb

Co-authored-by: Michael Kohl <citizen428@dev.to>

* Update spec/routing/devices_routes_spec.rb

Co-authored-by: Michael Kohl <citizen428@dev.to>

* Update spec/services/push_notifications/send_spec.rb

Co-authored-by: Michael Kohl <citizen428@dev.to>

* PR feedback

* Set Rpush driver and url

* More PR feedback

* Apply suggestions from code review

Co-authored-by: Jamie Gaskins <jgaskins@gmail.com>

* PR feedback from Rhymes

* Don’t double render

* Sure

Co-authored-by: Josh Puetz <hi@joshpuetz.com>
Co-authored-by: Josh Puetz <josh@dev.to>
Co-authored-by: Michael Kohl <citizen428@dev.to>
Co-authored-by: Jamie Gaskins <jgaskins@gmail.com>
2021-03-12 14:08:18 -06:00

80 lines
2.2 KiB
Ruby

class Device < ApplicationRecord
belongs_to :user
IOS = "iOS".freeze
ANDROID = "Android".freeze
validates :token, uniqueness: { scope: %i[user_id platform app_bundle] }
validates :platform, inclusion: { in: [IOS, ANDROID] }
def create_notification(title, body, payload)
case platform
when IOS
ios_notification(title, body, payload)
when ANDROID
android_notification(title, body, payload)
end
end
private
def ios_notification(title, body, payload)
n = Rpush::Apns2::Notification.new
# [@forem/backend] `.where().first` is necessary because we use Redis data storage
# https://github.com/rpush/rpush/wiki/Using-Redis#find_by_name-cannot-be-used-in-rpush-redis
# rubocop:disable Rails/FindBy
n.app = Rpush::Apns2::App.where(name: app_bundle).first || recreate_ios_app!
# rubocop:enable Rails/FindBy
n.device_token = token
n.data = {
aps: {
alert: {
title: ApplicationConfig["COMMUNITY_NAME"],
subtitle: title,
body: body
},
'thread-id': ApplicationConfig["COMMUNITY_NAME"]
},
data: payload
}
n.save!
end
def android_notification(title, body, payload)
n = Rpush::Gcm::Notification.new
# [@forem/backend] `.where().first` is necessary because we use Redis data storage
# https://github.com/rpush/rpush/wiki/Using-Redis#find_by_name-cannot-be-used-in-rpush-redis
# rubocop:disable Rails/FindBy
n.app = Rpush::Gcm::App.where(name: app_bundle).first || recreate_android_app!
# rubocop:enable Rails/FindBy
n.registration_ids = [token]
n.priority = "high"
n.content_available = true
n.notification = { title: title, body: body }
n.data = { data: payload }
n.save!
end
def recreate_ios_app!
app = Rpush::Apns2::App.new
app.name = app_bundle
app.certificate = Base64.decode64(ApplicationConfig["RPUSH_IOS_PEM"])
app.environment = Rails.env.production? ? "production" : "development"
app.password = ""
app.bundle_id = app_bundle
app.connections = 1
app.save!
app
end
def recreate_android_app!
app = Rpush::Gcm::App.new
app.name = app_bundle
app.auth_key = "..."
app.connections = 1
app.save!
app
end
end