feat: FCM HTTP v1 API changes (#9629)

Fixes https://linear.app/chatwoot/issue/CW-3210/legacy-firebase-changes
This commit is contained in:
Muhsin Keloth
2024-06-18 10:38:06 +05:30
committed by GitHub
parent 7968e98529
commit 9046730206
7 changed files with 196 additions and 24 deletions

View File

@@ -0,0 +1,40 @@
class Notification::FcmService
SCOPES = ['https://www.googleapis.com/auth/firebase.messaging'].freeze
def initialize(project_id, credentials)
@project_id = project_id
@credentials = credentials
@token_info = nil
end
def fcm_client
FCM.new(current_token, credentials_path, @project_id)
end
private
def current_token
@token_info = generate_token if @token_info.nil? || token_expired?
@token_info[:token]
end
def token_expired?
Time.zone.now >= @token_info[:expires_at]
end
def generate_token
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: credentials_path,
scope: SCOPES
)
token = authorizer.fetch_access_token!
{
token: token['access_token'],
expires_at: Time.zone.now + token['expires_in'].to_i
}
end
def credentials_path
StringIO.new(@credentials)
end
end

View File

@@ -70,36 +70,81 @@ class Notification::PushNotificationService
end
def send_fcm_push(subscription)
return unless ENV['FCM_SERVER_KEY']
return unless firebase_credentials_present?
return unless subscription.fcm?
fcm = FCM.new(ENV.fetch('FCM_SERVER_KEY', nil))
response = fcm.send([subscription.subscription_attributes['push_token']], fcm_options)
fcm_service = Notification::FcmService.new(
GlobalConfigService.load('FIREBASE_PROJECT_ID', nil), GlobalConfigService.load('FIREBASE_CREDENTIALS', nil)
)
fcm = fcm_service.fcm_client
response = fcm.send_v1(fcm_options(subscription))
remove_subscription_if_error(subscription, response)
end
def send_push_via_chatwoot_hub(subscription)
return if ENV['FCM_SERVER_KEY']
return unless ActiveModel::Type::Boolean.new.cast(ENV.fetch('ENABLE_PUSH_RELAY_SERVER', true))
return if firebase_credentials_present?
return unless chatwoot_hub_enabled?
return unless subscription.fcm?
ChatwootHub.send_browser_push([subscription.subscription_attributes['push_token']], fcm_options)
ChatwootHub.send_push(fcm_options(subscription))
end
def firebase_credentials_present?
GlobalConfigService.load('FIREBASE_PROJECT_ID', nil) && GlobalConfigService.load('FIREBASE_CREDENTIALS', nil)
end
def chatwoot_hub_enabled?
ActiveModel::Type::Boolean.new.cast(ENV.fetch('ENABLE_PUSH_RELAY_SERVER', true))
end
def remove_subscription_if_error(subscription, response)
subscription.destroy! if JSON.parse(response[:body])['results']&.first&.keys&.include?('error')
end
def fcm_options
def fcm_options(subscription)
{
notification: {
title: notification.push_message_title,
body: notification.push_message_body,
sound: 'default'
},
android: { priority: 'high' },
data: { notification: notification.fcm_push_data.to_json },
collapse_key: "chatwoot_#{notification.primary_actor_type.downcase}_#{notification.primary_actor_id}"
'token': subscription.subscription_attributes['push_token'],
'data': fcm_data,
'notification': fcm_notification,
'android': fcm_android_options,
'apns': fcm_apns_options,
'fcm_options': {
analytics_label: 'Label'
}
}
end
def fcm_data
{
payload: {
data: {
notification: notification.fcm_push_data
}
}.to_json
}
end
def fcm_notification
{
title: notification.push_message_title,
body: notification.push_message_body
}
end
def fcm_android_options
{
priority: 'high'
}
end
def fcm_apns_options
{
payload: {
aps: {
sound: 'default',
category: Time.zone.now.to_i.to_s
}
}
}
end
end