diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d04e8bf..50bd3bdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ### Unreleased * Support html safe translations for Rails 7+ +* iOS notifications now default to retrieving the APNS .p8 key from Rails credentials. ### 1.6.3 diff --git a/docs/delivery_methods/ios.md b/docs/delivery_methods/ios.md index 48b32885..a6a80737 100644 --- a/docs/delivery_methods/ios.md +++ b/docs/delivery_methods/ios.md @@ -6,9 +6,9 @@ Send Apple Push Notifications with HTTP2 using the `apnotic` gem. The benefit of bundle add "apnotic" ``` -## Apple Push Notification Service (APNS) Authentication +## Apple Push Notification Service (APNs) Authentication -Token-based authentication is used for APNS. +Token-based authentication is used for APNs. * A single key can be used for every app in your developer account. * Token authentication never expires, unlike certificate authentication which must be renewed annually. @@ -28,7 +28,7 @@ With custom configuration: ```ruby class CommentNotification - deliver_by :ios, format: :ios_format, cert_path: :ios_cert_path, key_id: :ios_key_id, team_id: :ios_team_id, pool_size: 5 + deliver_by :ios, format: :ios_format, development: Rails.env.local?, pool_size: 5 # Customize notification # See https://github.com/ostinelli/apnotic#apnoticnotification @@ -36,18 +36,6 @@ class CommentNotification apn.alert = "Hello world" apn.custom_payload = { url: root_url } end - - def ios_cert_path - Rails.root.join("config/certs/ios/apns.p8") - end - - def ios_key_id - Rails.application.credentials.dig(:ios, :key_id) - end - - def ios_team_id - Rails.application.credentials.dig(:ios, :team_id) - end end ``` @@ -63,15 +51,23 @@ end The APN bundle identifier -* `cert_path: Rails.root.join("config/certs/ios/apns.p8")` - *Optional* +* `apns_key: Rails.application.credentials.dig(:ios, :apns_key)` - *Optional* + + Your APNs p8 certificate + + Copy paste the contents of your private key (.p8 file) in your credentials, like so. - The location of your APNs p8 certificate. - This can also accept a StringIO object `StringIO.new("p8 file content as string")`. - As well as a File object `File.open("path/to/p8.file")`. + ```text + ios: + apns_key: |- + -----BEGIN PRIVATE KEY----- + YOUR_PRIVATE_KEY_CONTENTS_GO_HERE + -----END PRIVATE KEY----- + ``` * `key_id: Rails.application.credentials.dig(:ios, :key_id)` - *Optional* - Your APN Key ID + Your APNs Key ID If nothing passed, we'll default to `Rails.application.credentials.dig(:ios, :key_id)` If a String is passed, we'll use that as the key ID. @@ -79,7 +75,7 @@ end * `team_id: Rails.application.credentials.dig(:ios, :team_id)` - *Optional* - Your APN Team ID + Your APNs Team ID If nothing passed, we'll default to `Rails.application.credentials.dig(:ios, :team_id)` If a String is passed, we'll use that as the team ID. @@ -91,7 +87,7 @@ end * `development: false` - *Optional* - Set this to true to use the APNS sandbox environment for sending notifications. This is required when running the app to your device via Xcode. Running the app via TestFlight or the App Store should not use development. + Set this to true to use the APNs sandbox environment for sending notifications. This is required when running the app to your device via Xcode. Running the app via TestFlight or the App Store should not use development. ## Gathering Notification Tokens diff --git a/lib/noticed/delivery_methods/ios.rb b/lib/noticed/delivery_methods/ios.rb index 42150fe1..1cf43bb2 100644 --- a/lib/noticed/delivery_methods/ios.rb +++ b/lib/noticed/delivery_methods/ios.rb @@ -9,7 +9,7 @@ def deliver raise ArgumentError, "bundle_identifier is missing" if bundle_identifier.blank? raise ArgumentError, "key_id is missing" if key_id.blank? raise ArgumentError, "team_id is missing" if team_id.blank? - raise ArgumentError, "Could not find APN cert at '#{cert_path}'" unless valid_cert_path? + raise ArgumentError, "apns_key is missing" if apns_key.blank? device_tokens.each do |device_token| connection_pool.with do |connection| @@ -88,7 +88,7 @@ def new_connection_pool def connection_pool_options { auth_method: :token, - cert_path: cert_path, + cert_path: StringIO.new(apns_key), key_id: key_id, team_id: team_id } @@ -106,15 +106,15 @@ def bundle_identifier end end - def cert_path - option = options[:cert_path] + def apns_key + option = options[:apns_key] case option when String option when Symbol notification.send(option) else - Rails.root.join("config/certs/ios/apns.p8") + Rails.application.credentials.dig(:ios, :apns_key) end end @@ -152,15 +152,6 @@ def development? end end - def valid_cert_path? - case cert_path - when File, StringIO - cert_path.size > 0 - else - File.exist?(cert_path) - end - end - def pool_options { size: options.fetch(:pool_size, 5) diff --git a/test/delivery_methods/ios_test.rb b/test/delivery_methods/ios_test.rb index 8b90f924..f2f5ab88 100644 --- a/test/delivery_methods/ios_test.rb +++ b/test/delivery_methods/ios_test.rb @@ -48,7 +48,7 @@ class IosTest < ActiveSupport::TestCase assert_equal "team_id is missing", exception.message end - test "raises error when cert missing" do + test "raises error when apns_key is missing" do exception = assert_raises ArgumentError do Noticed::DeliveryMethods::Ios.new.perform( notification_class: "IosExample", @@ -60,7 +60,7 @@ class IosTest < ActiveSupport::TestCase ) end - assert_match "Could not find APN cert at", exception.message + assert_match "apns_key is missing", exception.message end test "raises error when ios_device_tokens method is missing" do