diff --git a/README.md b/README.md index d8791c9..4ae9477 100644 --- a/README.md +++ b/README.md @@ -26,34 +26,28 @@ A version of supported Ruby, currently: To use this gem, you need to instantiate a client with your firebase credentials: ```ruby -fcm = FCM.new( - GOOGLE_APPLICATION_CREDENTIALS_PATH, - FIREBASE_PROJECT_ID -) +fcm = FCM.new(GOOGLE_APPLICATION_CREDENTIALS_PATH) ``` +**Note:** The Firebase project ID is automatically extracted from your Firebase service credentials file. + ## About the `GOOGLE_APPLICATION_CREDENTIALS_PATH` The `GOOGLE_APPLICATION_CREDENTIALS_PATH` is meant to contain your firebase credentials. The easiest way to provide them is to pass here an absolute path to a file with your credentials: ```ruby -fcm = FCM.new( - '/path/to/credentials.json', - FIREBASE_PROJECT_ID -) +fcm = FCM.new('/path/to/credentials.json') ``` As per their secret nature, you might not want to have them in your repository. In that case, another supported solution is to pass a `StringIO` that contains your credentials: ```ruby -fcm = FCM.new( - StringIO.new(ENV.fetch('FIREBASE_CREDENTIALS')), - FIREBASE_PROJECT_ID -) - +fcm = FCM.new(StringIO.new(ENV.fetch('FIREBASE_CREDENTIALS'))) ``` +The gem will automatically extract the `project_id` from your Firebase service credentials file. + ## Usage ## HTTP v1 API @@ -61,10 +55,7 @@ fcm = FCM.new( To migrate to HTTP v1 see: https://firebase.google.com/docs/cloud-messaging/migrate-v1 ```ruby -fcm = FCM.new( - GOOGLE_APPLICATION_CREDENTIALS_PATH, - FIREBASE_PROJECT_ID -) +fcm = FCM.new(GOOGLE_APPLICATION_CREDENTIALS_PATH) message = { 'token': "000iddqd", # send to a specific device # 'topic': "yourTopic", @@ -108,8 +99,7 @@ https://firebase.google.com/docs/cloud-messaging/android/device-group#managing_d Then you will need a notification key which you can create for a particular `key_name` which needs to be uniquely named per app in case you have multiple apps for the same `project_id`. This ensures that notifications only go to the intended target app. The `create` method will do this and return the token `notification_key`, that represents the device group, in the response: -`project_id` is the SENDER_ID in your cloud settings. -https://firebase.google.com/docs/cloud-messaging/concept-options#senderid +**Note:** The `project_id` parameter used in device group management is your Firebase project's sender ID, which can be found in your Firebase project settings under Cloud Messaging. ```ruby params = { key_name: "appUser-Chris", diff --git a/lib/fcm.rb b/lib/fcm.rb index 3622c77..a0bdbda 100644 --- a/lib/fcm.rb +++ b/lib/fcm.rb @@ -12,13 +12,12 @@ class FCM INSTANCE_ID_API = "https://iid.googleapis.com" TOPIC_REGEX = /[a-zA-Z0-9\-_.~%]+/ - def initialize(json_key_path = "", project_name = "", http_options = {}) + def initialize(json_key_path = '', http_options = {}) @json_key_path = json_key_path - @project_name = project_name @http_options = http_options end - # See https://firebase.google.com/docs/cloud-messaging/send-message + # See https://firebase.google.com/docs/cloud-messaging/send/v1-api # { # "token": "4sdsx", # "notification": { @@ -42,17 +41,17 @@ def initialize(json_key_path = "", project_name = "", http_options = {}) # } # } # } - # fcm = FCM.new(json_key_path, project_name) + # fcm = FCM.new(json_key_path) # fcm.send_v1( # { "token": "4sdsx",, "to" : "notification": {}.. } # ) def send_notification_v1(message) - return if @project_name.empty? + return if firebase_project_id.empty? post_body = { 'message': message } for_uri(BASE_URI_V1) do |connection| response = connection.post( - "#{@project_name}/messages:send", post_body.to_json + "#{firebase_project_id}/messages:send", post_body.to_json ) build_response(response) end @@ -168,7 +167,7 @@ def send_to_topic(topic, options = {}) for_uri(BASE_URI_V1) do |connection| response = connection.post( - "#{@project_name}/messages:send", body.to_json + "#{firebase_project_id}/messages:send", body.to_json ) build_response(response) end @@ -181,7 +180,7 @@ def send_to_topic_condition(condition, options = {}) for_uri(BASE_URI_V1) do |connection| response = connection.post( - "#{@project_name}/messages:send", body.to_json + "#{firebase_project_id}/messages:send", body.to_json ) build_response(response) end @@ -298,4 +297,23 @@ def json_key File.open(@json_key_path) end end + + def firebase_project_id + @firebase_project_id ||= extract_project_id + end + + def extract_project_id + return '' if @json_key_path.nil? || @json_key_path == '' + + json_content = if @json_key_path.respond_to?(:read) + @json_key_path.read.tap { @json_key_path.rewind } + else + File.read(@json_key_path) + end + + credentials = JSON.parse(json_content) + credentials['project_id'] || '' + rescue JSON::ParserError, Errno::ENOENT + '' + end end diff --git a/spec/fcm_spec.rb b/spec/fcm_spec.rb index a3f24e1..9bddc9e 100644 --- a/spec/fcm_spec.rb +++ b/spec/fcm_spec.rb @@ -1,7 +1,7 @@ require "spec_helper" describe FCM do - let(:project_name) { 'test-project' } + let(:firebase_project_id) { 'test-project' } let(:json_key_path) { 'path/to/json/key.json' } let(:client) { FCM.new(json_key_path) } @@ -15,6 +15,8 @@ before do allow(client).to receive(:json_key) + allow(client).to receive(:extract_project_id) + .and_return(firebase_project_id) # Mock the Google::Auth::ServiceAccountCredentials allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds). @@ -38,9 +40,9 @@ end describe "#send_v1 or #send_notification_v1" do - let(:client) { FCM.new(json_key_path, project_name) } + let(:client) { FCM.new(json_key_path) } - let(:uri) { "#{FCM::BASE_URI_V1}#{project_name}/messages:send" } + let(:uri) { "#{FCM::BASE_URI_V1}#{firebase_project_id}/messages:send" } let(:status_code) { 200 } let(:stub_fcm_send_v1_request) do @@ -177,8 +179,8 @@ include_examples 'succesfuly send notification' end - context 'when project_name is empty' do - let(:project_name) { '' } + context 'when firebase_project_id is empty' do + let(:firebase_project_id) { '' } let(:send_v1_params) do { 'token' => '4sdsx', @@ -249,9 +251,9 @@ end describe '#send_to_topic' do - let(:client) { FCM.new(json_key_path, project_name) } + let(:client) { FCM.new(json_key_path) } - let(:uri) { "#{FCM::BASE_URI_V1}#{project_name}/messages:send" } + let(:uri) { "#{FCM::BASE_URI_V1}#{firebase_project_id}/messages:send" } let(:topic) { 'news' } let(:params) do @@ -300,9 +302,9 @@ end describe "#send_to_topic_condition" do - let(:client) { FCM.new(json_key_path, project_name) } + let(:client) { FCM.new(json_key_path) } - let(:uri) { "#{FCM::BASE_URI_V1}#{project_name}/messages:send" } + let(:uri) { "#{FCM::BASE_URI_V1}#{firebase_project_id}/messages:send" } let(:topic_condition) { "'foo' in topics" } let(:params) do