mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-11-03 20:48:07 +00:00 
			
		
		
		
	Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
		
			
				
	
	
		
			114 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
class OauthCallbackController < ApplicationController
 | 
						|
  def show
 | 
						|
    @response = oauth_client.auth_code.get_token(
 | 
						|
      oauth_code,
 | 
						|
      redirect_uri: "#{base_url}/#{provider_name}/callback"
 | 
						|
    )
 | 
						|
 | 
						|
    handle_response
 | 
						|
  rescue StandardError => e
 | 
						|
    ChatwootExceptionTracker.new(e).capture_exception
 | 
						|
    redirect_to '/'
 | 
						|
  end
 | 
						|
 | 
						|
  private
 | 
						|
 | 
						|
  def handle_response
 | 
						|
    inbox, already_exists = find_or_create_inbox
 | 
						|
 | 
						|
    if already_exists
 | 
						|
      redirect_to app_email_inbox_settings_url(account_id: account.id, inbox_id: inbox.id)
 | 
						|
    else
 | 
						|
      redirect_to app_email_inbox_agents_url(account_id: account.id, inbox_id: inbox.id)
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def find_or_create_inbox
 | 
						|
    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?
 | 
						|
 | 
						|
    channel_email ||= create_channel_with_inbox
 | 
						|
    update_channel(channel_email)
 | 
						|
 | 
						|
    # reauthorize channel, this code path only triggers when microsoft auth is successful
 | 
						|
    # reauthorized will also update cache keys for the associated inbox
 | 
						|
    channel_email.reauthorized!
 | 
						|
 | 
						|
    [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,
 | 
						|
                            imap_port: '993', imap_enabled: true,
 | 
						|
                            provider: provider_name,
 | 
						|
                            provider_config: {
 | 
						|
                              access_token: parsed_body['access_token'],
 | 
						|
                              refresh_token: parsed_body['refresh_token'],
 | 
						|
                              expires_on: (Time.current.utc + 1.hour).to_s
 | 
						|
                            }
 | 
						|
                          })
 | 
						|
  end
 | 
						|
 | 
						|
  def provider_name
 | 
						|
    raise NotImplementedError
 | 
						|
  end
 | 
						|
 | 
						|
  def oauth_client
 | 
						|
    raise NotImplementedError
 | 
						|
  end
 | 
						|
 | 
						|
  def create_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'] || fallback_name
 | 
						|
      )
 | 
						|
      channel_email
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def users_data
 | 
						|
    decoded_token = JWT.decode parsed_body[:id_token], nil, false
 | 
						|
    decoded_token[0]
 | 
						|
  end
 | 
						|
 | 
						|
  def account_from_signed_id
 | 
						|
    raise ActionController::BadRequest, 'Missing state variable' if params[:state].blank?
 | 
						|
 | 
						|
    account = GlobalID::Locator.locate_signed(params[:state])
 | 
						|
    raise 'Invalid or expired state' if account.nil?
 | 
						|
 | 
						|
    account
 | 
						|
  end
 | 
						|
 | 
						|
  def account
 | 
						|
    @account ||= account_from_signed_id
 | 
						|
  end
 | 
						|
 | 
						|
  # Fallback name, for when name field is missing from users_data
 | 
						|
  def fallback_name
 | 
						|
    users_data['email'].split('@').first.parameterize.titleize
 | 
						|
  end
 | 
						|
 | 
						|
  def oauth_code
 | 
						|
    params[:code]
 | 
						|
  end
 | 
						|
 | 
						|
  def base_url
 | 
						|
    ENV.fetch('FRONTEND_URL', 'http://localhost:3000')
 | 
						|
  end
 | 
						|
 | 
						|
  def parsed_body
 | 
						|
    @parsed_body ||= @response.response.parsed
 | 
						|
  end
 | 
						|
end
 |