diff --git a/app/mailers/administrator_notifications/channel_notifications_mailer.rb b/app/mailers/administrator_notifications/channel_notifications_mailer.rb new file mode 100644 index 000000000..6eee1ef42 --- /dev/null +++ b/app/mailers/administrator_notifications/channel_notifications_mailer.rb @@ -0,0 +1,10 @@ +class AdministratorNotifications::ChannelNotificationsMailer < ApplicationMailer + def slack_disconnect(account) + return unless smtp_config_set_or_development? + + emails = account.administrators.pluck(:email) + subject = 'Your Slack integration has expired' + @action_url = "#{ENV['FRONTEND_URL']}/app/accounts/#{account.id}/settings/integrations/slack" + send_mail_with_liquid(to: emails, subject: subject) and return + end +end diff --git a/app/models/concerns/reauthorizable.rb b/app/models/concerns/reauthorizable.rb index e20e24bd8..960e57322 100644 --- a/app/models/concerns/reauthorizable.rb +++ b/app/models/concerns/reauthorizable.rb @@ -36,7 +36,7 @@ module Reauthorizable # could used to manually prompt reauthorization if auth scope changes def prompt_reauthorization! ::Redis::Alfred.set(reauthorization_required_key, true) - # TODO: send_reauthorize_prompt_email + AdministratorNotifications::ChannelNotificationsMailer.slack_disconnect(account)&.deliver_later if (is_a? Integrations::Hook) && slack? end # call this after you successfully Reauthorized the object in UI diff --git a/app/models/integrations/hook.rb b/app/models/integrations/hook.rb index 82796a2f5..2df57ec2a 100644 --- a/app/models/integrations/hook.rb +++ b/app/models/integrations/hook.rb @@ -15,6 +15,8 @@ # reference_id :string # class Integrations::Hook < ApplicationRecord + include Reauthorizable + validates :account_id, presence: true validates :app_id, presence: true @@ -33,4 +35,8 @@ class Integrations::Hook < ApplicationRecord def slack? app_id == 'slack' end + + def disable + update(status: 'disabled') + end end diff --git a/app/views/mailers/administrator_notifications/channel_notifications_mailer/slack_disconnect.liquid b/app/views/mailers/administrator_notifications/channel_notifications_mailer/slack_disconnect.liquid new file mode 100644 index 000000000..2394a5958 --- /dev/null +++ b/app/views/mailers/administrator_notifications/channel_notifications_mailer/slack_disconnect.liquid @@ -0,0 +1,8 @@ +

Hello,

+ +

Your Slack integration has expired.

+

Please reconnect Slack to continue receiving messages on Slack

+ +

+Click here to re-connect. +

diff --git a/lib/integrations/slack/send_on_slack_service.rb b/lib/integrations/slack/send_on_slack_service.rb index 1ec42d009..051ac0fcb 100644 --- a/lib/integrations/slack/send_on_slack_service.rb +++ b/lib/integrations/slack/send_on_slack_service.rb @@ -41,17 +41,25 @@ class Integrations::Slack::SendOnSlackService < Base::SendOnChannelService end def send_message - sender = message.sender - sender_type = sender.class == Contact ? 'Contact' : 'Agent' - sender_name = sender.try(:name) ? "#{sender_type}: #{sender.try(:name)}" : sender_type - @slack_message = slack_client.chat_postMessage( channel: hook.reference_id, text: message_content, - username: sender_name, + username: sender_name(message.sender), thread_ts: conversation.identifier, - icon_url: avatar_url(sender) + icon_url: avatar_url(message.sender) ) + rescue Slack::Web::Api::Errors::AccountInactive => e + Rails.logger.info e + hook.authorization_error! + hook.disable if hook.enabled? + end + + def sender_name(sender) + sender.try(:name) ? "#{sender_type(sender)}: #{sender.try(:name)}" : sender_type(sender) + end + + def sender_type(sender) + sender.class == Contact ? 'Contact' : 'Agent' end def update_reference_id diff --git a/spec/lib/integrations/slack/send_on_slack_service_spec.rb b/spec/lib/integrations/slack/send_on_slack_service_spec.rb index 0fd8270fd..dc36de65f 100644 --- a/spec/lib/integrations/slack/send_on_slack_service_spec.rb +++ b/spec/lib/integrations/slack/send_on_slack_service_spec.rb @@ -27,5 +27,24 @@ describe Integrations::Slack::SendOnSlackService do builder.perform end + + it 'disables hook on Slack AccountInactive error' do + builder = described_class.new(message: message, hook: hook) + slack_client = double + expect(builder).to receive(:slack_client).and_return(slack_client) + expect(slack_client).to receive(:chat_postMessage).with( + channel: hook.reference_id, + text: message.content, + username: "Contact: #{message.sender.name}", + thread_ts: conversation.identifier, + icon_url: anything + ).and_raise(Slack::Web::Api::Errors::AccountInactive.new('Account disconnected')) + + allow(hook).to receive(:authorization_error!) + + builder.perform + expect(hook).to be_disabled + expect(hook).to have_received(:authorization_error!) + end end end