From f2c52f10e55a28af5b40370682c8e3a25719c820 Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Wed, 6 Jan 2021 10:45:01 +0100 Subject: [PATCH] Fixes #3346 - Initial configure step after adding XOAUTH account not functional. --- app/controllers/channels_google_controller.rb | 2 + .../channels_microsoft365_controller.rb | 2 + app/models/channel.rb | 4 +- ...13_issue_3346_xoauth2_token_not_fetched.rb | 25 ++++++++++ ...sue_3346_xoauth2_token_not_fetched_spec.rb | 50 +++++++++++++++++++ 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20210106100013_issue_3346_xoauth2_token_not_fetched.rb create mode 100644 spec/db/migrate/issue_3346_xoauth2_token_not_fetched_spec.rb diff --git a/app/controllers/channels_google_controller.rb b/app/controllers/channels_google_controller.rb index c85db0965..4d2c1e23e 100644 --- a/app/controllers/channels_google_controller.rb +++ b/app/controllers/channels_google_controller.rb @@ -73,6 +73,8 @@ class ChannelsGoogleController < ApplicationController channel.options[:inbound][:options][key] = params[:options][key] end + channel.refresh_xoauth2!(force: true) + result = EmailHelper::Probe.inbound(channel.options[:inbound]) raise Exceptions::UnprocessableEntity, ( result[:message_human] || result[:message] ) if result[:result] == 'invalid' diff --git a/app/controllers/channels_microsoft365_controller.rb b/app/controllers/channels_microsoft365_controller.rb index 8fd589d61..4740eb535 100644 --- a/app/controllers/channels_microsoft365_controller.rb +++ b/app/controllers/channels_microsoft365_controller.rb @@ -73,6 +73,8 @@ class ChannelsMicrosoft365Controller < ApplicationController channel.options[:inbound][:options][key] = params[:options][key] end + channel.refresh_xoauth2!(force: true) + result = EmailHelper::Probe.inbound(channel.options[:inbound]) raise Exceptions::UnprocessableEntity, ( result[:message_human] || result[:message] ) if result[:result] == 'invalid' diff --git a/app/models/channel.rb b/app/models/channel.rb index fa00f54ac..60318abf3 100644 --- a/app/models/channel.rb +++ b/app/models/channel.rb @@ -336,9 +336,9 @@ get instance of channel driver self.class.driver_class(options[:adapter]) end - def refresh_xoauth2! + def refresh_xoauth2!(force: false) return if options.dig(:auth, :type) != 'XOAUTH2' - return if ApplicationHandleInfo.current == 'application_server' + return if !force && ApplicationHandleInfo.current == 'application_server' result = ExternalCredential.refresh_token(options[:auth][:provider], options[:auth]) diff --git a/db/migrate/20210106100013_issue_3346_xoauth2_token_not_fetched.rb b/db/migrate/20210106100013_issue_3346_xoauth2_token_not_fetched.rb new file mode 100644 index 000000000..1d59cbd0a --- /dev/null +++ b/db/migrate/20210106100013_issue_3346_xoauth2_token_not_fetched.rb @@ -0,0 +1,25 @@ +class Issue3346Xoauth2TokenNotFetched < ActiveRecord::Migration[5.2] + def change + # return if it's a new setup + return if !Setting.exists?(name: 'system_init_done') + + Channel.where(area: ['Google::Account', 'Microsoft365::Account']).find_each do |channel| + next if skip?(channel) + + begin + channel.refresh_xoauth2! + rescue => e + Rails.logger.error e + end + end + end + + private + + def skip?(channel) + return true if channel.options.blank? + return true if channel.options.dig(:inbound, :options, :auth_type) != 'XOAUTH2' + + channel.options[:inbound][:options][:password].present? + end +end diff --git a/spec/db/migrate/issue_3346_xoauth2_token_not_fetched_spec.rb b/spec/db/migrate/issue_3346_xoauth2_token_not_fetched_spec.rb new file mode 100644 index 000000000..f75d893fc --- /dev/null +++ b/spec/db/migrate/issue_3346_xoauth2_token_not_fetched_spec.rb @@ -0,0 +1,50 @@ +require 'rails_helper' + +RSpec.describe Issue3346Xoauth2TokenNotFetched, type: :db_migration do + + shared_examples 'XOAUTH2 channel migration' do |channel_type| + + context 'when valid Channel is present' do + + before do + channel = create(channel_type) + channel.options[:inbound][:options][:password] = 'some_password' + channel.save! + end + + it "doesn't refresh the token" do + allow(ExternalCredential).to receive(:refresh_token) + migrate + expect(ExternalCredential).not_to have_received(:refresh_token) + end + end + + context 'when broken Channel is present' do + + before do + channel = create(channel_type) + channel.options[:inbound][:options].delete(:password) + channel.save! + end + + it 'refreshes the token' do + allow(ExternalCredential).to receive(:refresh_token) + migrate + expect(ExternalCredential).to have_received(:refresh_token) + end + + it "doesn't break if refresh fails" do + allow(ExternalCredential).to receive(:refresh_token).and_raise(RuntimeError) + expect { migrate }.not_to raise_error + end + end + end + + context 'when Microsoft365 Channel is present' do + it_behaves_like 'XOAUTH2 channel migration', :microsoft365_channel + end + + context 'when Google Channel is present' do + it_behaves_like 'XOAUTH2 channel migration', :google_channel + end +end