Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Support for Microsoft Oauth in Email Channel #6227

Merged
merged 51 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f3c4fcf
fix:
tejaswinichile Dec 30, 2022
cab4aa3
fix:
tejaswinichile Dec 30, 2022
579bebc
refresh tokens and fetch the mails from ms graph
tejaswinichile Jan 3, 2023
bb5a248
fix: refresh tokens with IMAP; commented conde for the HTTParty
tejaswinichile Jan 4, 2023
3247067
refresh tokens and fetch the mails from ms graph
tejaswinichile Jan 3, 2023
d91d1dc
code cleaning, hash indifferent access fix, updated schedule class an…
tejaswinichile Jan 4, 2023
44a55ac
send email via SMTP
tejaswinichile Jan 5, 2023
c71c602
code sanity changes, addded comments and references
tejaswinichile Jan 5, 2023
7a58a70
rubocop and spec fixes
tejaswinichile Jan 6, 2023
330a36e
Feat: microsoft email channel oauth provider and fetching emails
tejaswinichile Jan 10, 2023
96368e8
minor fixes
tejaswinichile Jan 10, 2023
5f99ffa
feat: code clean up and refactoring
tejaswinichile Jan 11, 2023
48bf5b5
feat: code clean up and refactoring
tejaswinichile Jan 11, 2023
b10ccb6
Remove all the frontend code
pranavrajs Jan 12, 2023
90471d7
Merge branch 'develop' into feat/microsoft-oauth-apis
pranavrajs Jan 12, 2023
7f43ab5
feat: MS reauthorization
tejaswinichile Jan 12, 2023
cb701d6
Merge branch 'feat/microsoft-oauth-apis' of https://github.com/chatwo…
tejaswinichile Jan 12, 2023
3fe0d06
update microsoft oauth concern
tejaswinichile Jan 12, 2023
cd9e93d
PR comments changes
tejaswinichile Jan 12, 2023
d8acd5f
PR comments changes
tejaswinichile Jan 12, 2023
3c23975
Fix: Specs
tejaswinichile Jan 12, 2023
b10d0f3
Merge branch 'feat/microsoft-oauth-apis' of https://github.com/chatwo…
tejaswinichile Jan 12, 2023
8deac0f
fix: rubocop
tejaswinichile Jan 12, 2023
de416ad
fix: rubocop
tejaswinichile Jan 12, 2023
85abe97
Merge branch 'feat/microsoft-oauth-apis' of https://github.com/chatwo…
tejaswinichile Jan 12, 2023
7cc3113
Merge branch 'develop' into feat/microsoft-oauth-apis
tejaswinichile Jan 13, 2023
7521813
fix: remove comman key for redis account id setup
tejaswinichile Jan 13, 2023
d55ff39
fix: remove comman key for redis account id setup
tejaswinichile Jan 13, 2023
179fb37
fix: remove comman key for redis account id setup
tejaswinichile Jan 13, 2023
8c668f6
Merge branch 'feat/microsoft-oauth-apis' of https://github.com/chatwo…
tejaswinichile Jan 13, 2023
d5a8e05
fix: PR comments resolved
tejaswinichile Jan 13, 2023
f0bcdda
fix: moved refersh_ms_oauth_token job to service
tejaswinichile Jan 13, 2023
4b28672
chore: refactor the token service
sojan-official Jan 13, 2023
d53b077
chore: rubocop fixes
sojan-official Jan 13, 2023
2708fc2
spces for callbacks controlelr
tejaswinichile Jan 13, 2023
5d712dd
spces for callbacks controlelr
tejaswinichile Jan 13, 2023
526b83a
Merge branch 'feat/microsoft-oauth-apis' of https://github.com/chatwo…
tejaswinichile Jan 13, 2023
9d941de
Merge branch 'develop' into feat/microsoft-oauth-apis
tejaswinichile Jan 13, 2023
799f46b
fix: failing specs
tejaswinichile Jan 16, 2023
5eab1de
Merge branch 'develop' into feat/microsoft-oauth-apis
tejaswinichile Jan 16, 2023
f18d7a5
chore: remove unneccesary mocks
sojan-official Jan 16, 2023
8e55349
Merge branch 'develop' into feat/microsoft-oauth-apis
sojan-official Jan 16, 2023
908c409
chore: callback controller specs
sojan-official Jan 16, 2023
6a9f78c
chore: remove unwanted code
sojan-official Jan 16, 2023
6adebd1
chore: spec for model
sojan-official Jan 16, 2023
80d977b
chore: rubocop
sojan-official Jan 16, 2023
7da09f6
chore: more specs
sojan-official Jan 16, 2023
cae923b
chore: refactor
sojan-official Jan 16, 2023
ba09939
chore: refactor
sojan-official Jan 16, 2023
10cf72c
chore: fix specs
sojan-official Jan 16, 2023
759fecf
Merge branch 'develop' into feat/microsoft-oauth-apis
sojan-official Jan 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: callback controller specs
  • Loading branch information
sojan-official committed Jan 16, 2023
commit 908c40912779a02fd19de66a4c3cfea62a9a8d39
45 changes: 22 additions & 23 deletions app/controllers/microsoft/callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ def show
redirect_uri: "#{base_url}/microsoft/callback"
)

ActiveRecord::Base.transaction do
inbox = find_or_create_inbox
::Redis::Alfred.delete(users_data['email'])
redirect_to app_microsoft_inbox_agents_url(account_id: account.id, inbox_id: inbox.id)
rescue StandardError => e
Rails.logger.error e
redirect_to microsoft_app_redirect_url
end
inbox = find_or_create_inbox
::Redis::Alfred.delete(users_data['email'])
redirect_to app_microsoft_inbox_agents_url(account_id: account.id, inbox_id: inbox.id)
rescue StandardError => e
ChatwootExceptionTracker.new(e).capture_exception
redirect_to '/'
end

private
Expand All @@ -40,24 +38,26 @@ def account
@account ||= Account.find(account_id)
end

def microsoft_app_redirect_url
app_new_microsoft_inbox_url(account_id: account.id)
end

def find_or_create_inbox
channel_email = create_imap_email_channel

return channel_email.inbox if channel_email.inbox.presence
channel_email = Channel::Email.find_by(email: users_data['email'], account: account)
channel_email ||= create_microsoft_channel_with_inbox
update_microsoft_channel(channel_email)
channel_email.inbox
end

account.inboxes.create_or_find_by!(
account: account,
channel: channel_email,
name: users_data['name']
)
def create_microsoft_channel_with_inbox
ActiveRecord::Base.transaction do
channel_email = Channel::Email.create!(email: users_data['email'], account: account)
account.inboxes.create!(
account: account,
channel: channel_email,
name: users_data['name']
)
channel_email
end
end

def create_imap_email_channel
channel_email = Channel::Email.find_or_create_by!(email: users_data['email'], account: account)
def update_microsoft_channel(channel_email)
channel_email.update!({
imap_login: users_data['email'], imap_address: 'outlook.office365.com',
imap_port: '993', imap_enabled: true,
Expand All @@ -68,6 +68,5 @@ def create_imap_email_channel
expires_on: (Time.current.utc + 1.hour).to_s
}
})
channel_email.reload
end
end
80 changes: 52 additions & 28 deletions spec/controllers/microsoft/callbacks_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,66 @@

RSpec.describe 'Microsoft::CallbacksController', type: :request do
let(:account) { create(:account) }
let(:administrator) { create(:user, account: account, role: :administrator) }
let(:microsoft_client) do
OAuth2::Client.new('client_id', 'client_secret', {
site: 'https://login.microsoftonline.com',
redirect_uri: 'http://0.0.0.0/microsoft/callback',
authorize_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'
})
end
let(:auth_code) { microsoft_client.auth_code }
let(:code) { SecureRandom.hex(10) }
let(:email) { Faker::Internet.email }

before do
Redis::Alfred.set('test@test.com', account.id)
OAuth2::Response.register_parser(:id_token, ['application/json']) do |_body|
{ id_token: JWT.encode({ email: 'test@test.com', name: 'test' }, false) }
end
Redis::Alfred.set(email, account.id)
end

describe 'GET /microsoft/callback' do
let(:response_body_success) do
{ id_token: JWT.encode({ email: email, name: 'test' }, false), access_token: SecureRandom.hex(10), token_type: 'Bearer',
refresh_token: SecureRandom.hex(10) }
end

it 'creates inboxes if authentication is successful' do
headers = { 'Content-Type' => 'application/json' }
body = { id_token: JWT.encode({ email: 'test@test.com', name: 'test' }, false) }
# rubocop:disable RSpec/VerifiedDoubles
microsoft_response = double('response', headers: headers, body: body)
subject = OAuth2::Response.new(microsoft_response)
response = double(OAuth2::Response, response: subject)
# rubocop:enable RSpec/VerifiedDoubles
allow(OAuth2::Client).to receive(:new).and_return(microsoft_client)
allow(microsoft_client).to receive(:auth_code).and_return(auth_code)
allow(auth_code).to receive(:get_token).and_return(response)

get microsoft_callback_url

account.reload
stub_request(:post, 'https://login.microsoftonline.com/common/oauth2/v2.0/token')
.with(body: { 'code' => code, 'grant_type' => 'authorization_code',
'redirect_uri' => "#{ENV.fetch('FRONTEND_URL', nil)}/microsoft/callback" })
.to_return(status: 200, body: response_body_success.to_json, headers: { 'Content-Type' => 'application/json' })

get microsoft_callback_url, params: { code: code }

expect(response).to redirect_to app_microsoft_inbox_agents_url(account_id: account.id, inbox_id: account.inboxes.last.id)
expect(account.inboxes.count).to be 1
expect(account.inboxes.last.name).to eq 'test'
inbox = account.inboxes.last
expect(inbox.name).to eq 'test'
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]
expect(inbox.channel.imap_address).to eq 'outlook.office365.com'
expect(Redis::Alfred.get(email)).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
expect(inbox.channel.provider_config).to eq({})

stub_request(:post, 'https://login.microsoftonline.com/common/oauth2/v2.0/token')
.with(body: { 'code' => code, 'grant_type' => 'authorization_code',
'redirect_uri' => "#{ENV.fetch('FRONTEND_URL', nil)}/microsoft/callback" })
.to_return(status: 200, body: response_body_success.to_json, headers: { 'Content-Type' => 'application/json' })

get microsoft_callback_url, params: { code: code }

expect(response).to redirect_to app_microsoft_inbox_agents_url(account_id: account.id, inbox_id: account.inboxes.last.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]
expect(inbox.channel.imap_address).to eq 'outlook.office365.com'
expect(Redis::Alfred.get(email)).to be_nil
end

it 'redirects to microsoft app in case of error' do
stub_request(:post, 'https://login.microsoftonline.com/common/oauth2/v2.0/token')
.with(body: { 'code' => code, 'grant_type' => 'authorization_code',
'redirect_uri' => "#{ENV.fetch('FRONTEND_URL', nil)}/microsoft/callback" })
.to_return(status: 401)

get microsoft_callback_url, params: { code: code }

expect(response).to redirect_to '/'
expect(Redis::Alfred.get(email).to_i).to eq account.id
end
end
end