feat: Support Azure single-tenant application using the Graph API (#6728) (#6878)

This commit is contained in:
Tejaswini Chile
2023-06-28 08:13:08 +05:30
committed by GitHub
parent 4a770fdea7
commit d05c953eef
14 changed files with 451 additions and 13 deletions

View File

@@ -43,6 +43,29 @@ RSpec.describe 'Microsoft Authorization API', type: :request do
expect(response.parsed_body['url']).to eq response_url
expect(Redis::Alfred.get(administrator.email)).to eq(account.id.to_s)
end
it 'creates a new authorization and returns the redirect url for single tenant' do
with_modified_env AZURE_TENANT_ID: 'azure_tenant_id' do
post "/api/v1/accounts/#{account.id}/microsoft/authorization",
headers: administrator.create_new_auth_token,
params: { email: administrator.email },
as: :json
microsoft_service = Class.new { extend MicrosoftConcern }
response_url = microsoft_service.microsoft_client.auth_code.authorize_url(
{
redirect_uri: "#{ENV.fetch('FRONTEND_URL', 'http://localhost:3000')}/microsoft/callback",
scope: 'offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send openid profile',
prompt: 'consent'
}
)
expect(response.parsed_body['url']).to eq response_url
end
expect(response).to have_http_status(:success)
expect(Redis::Alfred.get(administrator.email)).to eq(account.id.to_s)
end
end
end
end

View File

@@ -7,6 +7,12 @@ RSpec.describe Inboxes::FetchImapEmailInboxesJob do
imap_password: 'password', account: account)
end
let(:email_inbox) { create(:inbox, channel: imap_email_channel, account: account) }
let(:microsoft_imap_email_channel) do
create(:channel_email, provider: 'microsoft', imap_enabled: true, imap_address: 'outlook.office365.com',
imap_port: 993, imap_login: 'imap@outlook.com', imap_password: 'password', account: account,
provider_config: { access_token: 'access_token' })
end
let(:ms_email_inbox) { create(:inbox, channel: microsoft_imap_email_channel, account: account) }
it 'enqueues the job' do
expect { described_class.perform_later }.to have_enqueued_job(described_class)
@@ -20,4 +26,24 @@ RSpec.describe Inboxes::FetchImapEmailInboxesJob do
described_class.perform_now
end
end
context 'when microsoft inbox' do
it 'calls fetch ms graph email job for single tenant app' do
stub_request(:get, 'https://graph.microsoft.com/v1.0/me/messages?$filter=receivedDateTime%20ge%202023-05-23T00:00:00Z%20and%20receivedDateTime%20le%202023-05-25T00:00:00Z&$select=id&$top=1000')
with_modified_env AZURE_TENANT_ID: 'azure_tenant_id' do
expect(Inboxes::FetchMsGraphEmailForTenantJob).to receive(:perform_later).with(microsoft_imap_email_channel).once
described_class.perform_now
end
end
it 'calls fetch imap email job for multi tenant app' do
with_modified_env AZURE_TENANT_ID: nil do
expect(Inboxes::FetchImapEmailsJob).to receive(:perform_later).with(microsoft_imap_email_channel).once
described_class.perform_now
end
end
end
end

View File

@@ -0,0 +1,68 @@
require 'rails_helper'
RSpec.describe Inboxes::FetchMsGraphEmailForTenantJob do
include ActionMailbox::TestHelper
let(:account) { create(:account) }
let(:microsoft_imap_email_channel) do
create(:channel_email, provider: 'microsoft', imap_enabled: true, imap_address: 'outlook.office365.com',
imap_port: 993, imap_login: 'imap@outlook.com', imap_password: 'password', account: account,
provider_config: { access_token: 'access_token' })
end
let(:ms_email_inbox) { create(:inbox, channel: microsoft_imap_email_channel, account: account) }
let(:inbound_mail) { create_inbound_email_from_mail(from: 'testemail@gmail.com', to: 'imap@outlook.com', subject: 'Hello!') }
let(:yesterday) { (Time.zone.today - 1).strftime('%FT%TZ') }
let(:tomorrow) { (Time.zone.today + 1).strftime('%FT%TZ') }
it 'enqueues the job' do
expect { described_class.perform_later }.to have_enqueued_job(described_class)
.on_queue('scheduled_jobs')
end
context 'when imap fetch new emails for microsoft mailer' do
before do
stub_request(:get, "https://graph.microsoft.com/v1.0/me/messages?$filter=receivedDateTime%20ge%20#{yesterday}%20and%20receivedDateTime%20le%20#{tomorrow}&$select=id&$top=1000")
.with(
headers: {
'Accept' => '*/*',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization' => 'Bearer access_token',
'User-Agent' => 'Ruby'
}
)
.to_return(status: 200, body: '{"value":[{"id":"1"}]}', headers: {})
stub_request(:get, 'https://graph.microsoft.com/v1.0/me/messages/1/$value')
.with(
headers: {
'Accept' => '*/*',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization' => 'Bearer access_token',
'User-Agent' => 'Ruby'
}
)
.to_return(status: 200, body: '', headers: {})
end
it 'fetch and process all emails' do
ms_imap_email_inbox = double
with_modified_env AZURE_TENANT_ID: 'azure_tenant_id' do
email = Mail.new do
to 'test@outlook.com'
from 'test@gmail.com'
subject :test.to_s
body 'hello'
end
imap_fetch_mail = Net::IMAP::FetchData.new
imap_fetch_mail.attr = { RFC822: email }.with_indifferent_access
allow(Mail).to receive(:read_from_string).and_return(inbound_mail)
allow(Imap::ImapMailbox).to receive(:new).and_return(ms_imap_email_inbox)
expect(ms_imap_email_inbox).to receive(:process).with(inbound_mail, microsoft_imap_email_channel).once
described_class.perform_now(microsoft_imap_email_channel)
end
end
end
end

View File

@@ -0,0 +1,61 @@
require 'rails_helper'
# explicitly requiring since we are loading apms conditionally in application.rb
require 'sentry-ruby'
describe MicrosoftGraphApi do
let(:yesterday) { (Time.zone.today - 1).strftime('%FT%TZ') }
let(:tomorrow) { (Time.zone.today + 1).strftime('%FT%TZ') }
describe '#get_from_api' do
before do
stub_request(:get, "https://graph.microsoft.com/v1.0/me/messages?$filter=receivedDateTime%20ge%20#{yesterday}%20and%20receivedDateTime%20le%20#{tomorrow}&$select=id&$top=1000")
.with(
headers: {
'Accept' => '*/*',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization' => 'Bearer access_token',
'User-Agent' => 'Ruby'
}
)
.to_return(status: 200, body: '{"value":[{"id":"1"}]}', headers: {})
stub_request(:get, 'https://graph.microsoft.com/v1.0/me/messages/1/$value')
.with(
headers: {
'Accept' => '*/*',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization' => 'Bearer access_token',
'User-Agent' => 'Ruby'
}
)
.to_return(status: 200, body: '', headers: {})
stub_request(:post, 'https://graph.microsoft.com/v1.0/me/sendMail')
.with(
body: 'email body',
headers: {
'Accept' => '*/*',
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization' => 'Bearer access_token',
'User-Agent' => 'Ruby'
}
)
.to_return(status: 200, body: 'email body', headers: { 'Content-Type' => 'text/plain' })
end
it 'fetch emails' do
graph_query = { :$filter => "receivedDateTime ge #{yesterday} and receivedDateTime le #{tomorrow}", :$top => '1000', :$select => 'id' }
response = described_class.new('access_token').get_from_api('me/messages', {}, graph_query)
json_response = JSON.parse(response.body)
expect(json_response['value'][0]['id']).to eq '1'
end
it 'post emails' do
response = described_class.new('access_token').post_to_api('me/sendMail', {}, 'email body')
expect(response.is_a?(Net::HTTPSuccess)).to be true
expect(response.body).to eq('email body')
end
end
end