feat: use of imap login as default if present (#10249)

When moving form using Gmail Legacy auth to using OAuth, we need the
email address that will be used to connect. This is because we need to
store this email address in the cache and reuse when we get the callback
to find the associated inbox.

However there are cases where the imap login might be
`support@company.com` and the email used to communicate will be
`contact@company.com` (Probably an alias) In that case, we need to send
the correct email address to Chatwoot when re-authenticating

At the moment, we used the inbox email. This PR adds a check that
defaults to to `imap_login` if that is available and imap is enabled

This PR also fixes an unrelated problem where the email inbox creation
flow was not working

---

Tested it, it is working correctly

![CleanShot 2024-10-09 at 14 23
47@2x](https://github.com/user-attachments/assets/0e2cb6c8-1224-4b45-b34a-7b19611249bc)
This commit is contained in:
Shivam Mishra
2024-10-09 15:01:11 +05:30
committed by GitHub
parent aa5fa0c758
commit f18ed01eb7
5 changed files with 28 additions and 7 deletions

View File

@@ -1,6 +1,15 @@
class Google::CallbacksController < OauthCallbackController
include GoogleConcern
def find_channel_by_email
# find by imap_login first, and then by email
# this ensures the legacy users can migrate correctly even if inbox email address doesn't match
imap_channel = Channel::Email.find_by(imap_login: users_data['email'], account: account)
return imap_channel if imap_channel
Channel::Email.find_by(email: users_data['email'], account: account)
end
private
def provider_name

View File

@@ -25,7 +25,7 @@ class OauthCallbackController < ApplicationController
end
def find_or_create_inbox
channel_email = Channel::Email.find_by(email: users_data['email'], account: account)
channel_email = find_channel_by_email
# we need this value to know where to redirect on sucessful processing of the callback
channel_exists = channel_email.present?
@@ -39,6 +39,10 @@ class OauthCallbackController < ApplicationController
[channel_email.inbox, channel_exists]
end
def find_channel_by_email
Channel::Email.find_by(email: users_data['email'], account: account)
end
def update_channel(channel_email)
channel_email.update!({
imap_login: users_data['email'], imap_address: imap_address,

View File

@@ -47,7 +47,7 @@ const emailProviderList = computed(() => {
function onClick(emailProvider) {
if (emailProvider.isEnabled) {
this.provider = emailProvider.key;
provider.value = emailProvider.key;
}
}
</script>

View File

@@ -1,5 +1,5 @@
<script setup>
import { ref } from 'vue';
import { ref, computed } from 'vue';
import InboxReconnectionRequired from '../../components/InboxReconnectionRequired.vue';
import googleClient from 'dashboard/api/channel/googleClient';
@@ -17,11 +17,18 @@ const { t } = useI18n();
const isRequestingAuthorization = ref(false);
const inboxEmail = computed(() => {
if (props.inbox.imap_login && props.inbox.imap_enabled) {
return props.inbox.imap_login;
}
return props.inbox.email;
});
async function requestAuthorization() {
try {
isRequestingAuthorization.value = true;
const response = await googleClient.generateAuthorization({
email: props.inbox.email,
email: inboxEmail.value,
});
const {

View File

@@ -39,8 +39,9 @@ RSpec.describe 'Google::CallbacksController', type: :request do
expect(Redis::Alfred.get(cache_key)).to be_nil
end
it 'creates updates inbox channel config if inbox exists and authentication is successful' do
inbox = create(:channel_email, account: account, email: email)&.inbox
it 'updates inbox channel config if inbox exists with imap_login and authentication is successful' do
channel_email = create(:channel_email, account: account, imap_login: email)
inbox = channel_email.inbox
expect(inbox.channel.provider_config).to eq({})
stub_request(:post, 'https://accounts.google.com/o/oauth2/token')
@@ -50,7 +51,7 @@ RSpec.describe 'Google::CallbacksController', type: :request do
get google_callback_url, params: { code: code }
expect(response).to redirect_to app_email_inbox_settings_url(account_id: account.id, inbox_id: account.inboxes.last.id)
expect(response).to redirect_to app_email_inbox_settings_url(account_id: account.id, inbox_id: inbox.id)
expect(account.inboxes.count).to be 1
expect(inbox.channel.reload.provider_config.keys).to include('access_token', 'refresh_token', 'expires_on')
expect(inbox.channel.reload.provider_config['access_token']).to eq response_body_success[:access_token]