mirror of
https://github.com/lingble/chatwoot.git
synced 2025-12-18 03:37:15 +00:00
chore: add github installation steps
This commit is contained in:
@@ -2,18 +2,78 @@ class Github::CallbacksController < ApplicationController
|
|||||||
include Github::IntegrationHelper
|
include Github::IntegrationHelper
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
# Log all received parameters for debugging
|
||||||
|
Rails.logger.info("GitHub callback received parameters: #{params.to_unsafe_h}")
|
||||||
|
Rails.logger.info("installation_id present: #{params[:installation_id].present?}")
|
||||||
|
Rails.logger.info("code present: #{params[:code].present?}")
|
||||||
|
Rails.logger.info("setup_action: #{params[:setup_action]}")
|
||||||
|
Rails.logger.info("state present: #{params[:state].present?}")
|
||||||
|
|
||||||
|
if params[:installation_id].present? && params[:code].present?
|
||||||
|
Rails.logger.info('Handling installation with OAuth')
|
||||||
|
# Both installation and OAuth code present - handle both
|
||||||
|
handle_installation_with_oauth
|
||||||
|
elsif params[:installation_id].present?
|
||||||
|
Rails.logger.info('Handling installation only')
|
||||||
|
# Only installation_id present - redirect to OAuth
|
||||||
|
handle_installation
|
||||||
|
else
|
||||||
|
Rails.logger.info('Handling authorization only')
|
||||||
|
# Only OAuth code present - handle authorization
|
||||||
|
handle_authorization
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error("Github callback error: #{e.message}")
|
||||||
|
redirect_to fallback_redirect_uri
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def handle_installation_with_oauth
|
||||||
|
Rails.logger.info("Processing installation with OAuth - installation_id: #{params[:installation_id]}, code: #{params[:code]}")
|
||||||
|
# Handle both installation and OAuth in one go
|
||||||
|
installation_id = params[:installation_id]
|
||||||
|
|
||||||
|
@response = oauth_client.auth_code.get_token(
|
||||||
|
params[:code],
|
||||||
|
redirect_uri: "#{base_url}/github/callback"
|
||||||
|
)
|
||||||
|
|
||||||
|
handle_response(installation_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_installation
|
||||||
|
Rails.logger.info("Processing installation only - setup_action: #{params[:setup_action]}, installation_id: #{params[:installation_id]}")
|
||||||
|
if params[:setup_action] == 'install'
|
||||||
|
installation_id = params[:installation_id]
|
||||||
|
|
||||||
|
redirect_to build_oauth_url(installation_id)
|
||||||
|
else
|
||||||
|
Rails.logger.error("Unknown setup_action: #{params[:setup_action]}")
|
||||||
|
redirect_to github_integration_settings_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_authorization
|
||||||
|
Rails.logger.info("Processing authorization only - code: #{params[:code]}")
|
||||||
@response = oauth_client.auth_code.get_token(
|
@response = oauth_client.auth_code.get_token(
|
||||||
params[:code],
|
params[:code],
|
||||||
redirect_uri: "#{base_url}/github/callback"
|
redirect_uri: "#{base_url}/github/callback"
|
||||||
)
|
)
|
||||||
|
|
||||||
handle_response
|
handle_response
|
||||||
rescue StandardError => e
|
|
||||||
Rails.logger.error("Github callback error: #{e.message}")
|
|
||||||
redirect_to github_redirect_uri
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def build_oauth_url(installation_id)
|
||||||
|
GlobalConfigService.load('GITHUB_CLIENT_ID', nil)
|
||||||
|
|
||||||
|
# Store installation_id in session for later use
|
||||||
|
session[:github_installation_id] = installation_id
|
||||||
|
|
||||||
|
# For now, redirect to a page that will initiate OAuth with proper account context
|
||||||
|
# This is a temporary solution until we have a proper account-agnostic setup
|
||||||
|
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/1/settings/integrations/github?setup_action=install&installation_id=#{installation_id}"
|
||||||
|
end
|
||||||
|
|
||||||
def oauth_client
|
def oauth_client
|
||||||
app_id = GlobalConfigService.load('GITHUB_CLIENT_ID', nil)
|
app_id = GlobalConfigService.load('GITHUB_CLIENT_ID', nil)
|
||||||
@@ -30,21 +90,37 @@ class Github::CallbacksController < ApplicationController
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_response
|
def handle_response(installation_id = nil)
|
||||||
hook = account.hooks.new(
|
settings = {
|
||||||
access_token: parsed_body['access_token'],
|
|
||||||
status: 'enabled',
|
|
||||||
app_id: 'github',
|
|
||||||
settings: {
|
|
||||||
token_type: parsed_body['token_type'],
|
token_type: parsed_body['token_type'],
|
||||||
scope: parsed_body['scope']
|
scope: parsed_body['scope']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Add installation_id from parameter or session
|
||||||
|
if installation_id
|
||||||
|
settings[:installation_id] = installation_id
|
||||||
|
elsif session[:github_installation_id]
|
||||||
|
settings[:installation_id] = session[:github_installation_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Use account from state parameter - this should work for both flows now
|
||||||
|
target_account = account
|
||||||
|
|
||||||
|
hook = target_account.hooks.new(
|
||||||
|
access_token: parsed_body['access_token'],
|
||||||
|
status: 'enabled',
|
||||||
|
app_id: 'github',
|
||||||
|
settings: settings
|
||||||
)
|
)
|
||||||
hook.save!
|
hook.save!
|
||||||
|
|
||||||
|
# Clear session data
|
||||||
|
session.delete(:github_installation_id)
|
||||||
|
|
||||||
redirect_to github_redirect_uri
|
redirect_to github_redirect_uri
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Rails.logger.error("Github callback error: #{e.message}")
|
Rails.logger.error("Github callback error: #{e.message}")
|
||||||
redirect_to github_redirect_uri
|
redirect_to fallback_redirect_uri
|
||||||
end
|
end
|
||||||
|
|
||||||
def account
|
def account
|
||||||
@@ -52,15 +128,30 @@ class Github::CallbacksController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def account_id
|
def account_id
|
||||||
return unless params[:state]
|
# First try to get from state parameter (OAuth flow)
|
||||||
|
return verify_github_token(params[:state]) if params[:state].present?
|
||||||
|
|
||||||
verify_github_token(params[:state])
|
# Fallback to hardcoded account 1 for installation flow (temporary)
|
||||||
|
1
|
||||||
end
|
end
|
||||||
|
|
||||||
def github_redirect_uri
|
def github_redirect_uri
|
||||||
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{account.id}/settings/integrations/github"
|
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{account.id}/settings/integrations/github"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def github_integration_settings_url
|
||||||
|
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/1/settings/integrations/github"
|
||||||
|
end
|
||||||
|
|
||||||
|
def fallback_redirect_uri
|
||||||
|
if account_id
|
||||||
|
github_redirect_uri
|
||||||
|
else
|
||||||
|
# Fallback if no account context available
|
||||||
|
"#{ENV.fetch('FRONTEND_URL', nil)}/app/settings/integrations"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parsed_body
|
def parsed_body
|
||||||
@parsed_body ||= @response.response.parsed
|
@parsed_body ||= @response.response.parsed
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ class Integrations::App
|
|||||||
GlobalConfigService.load('SLACK_CLIENT_SECRET', nil).present?
|
GlobalConfigService.load('SLACK_CLIENT_SECRET', nil).present?
|
||||||
when 'linear'
|
when 'linear'
|
||||||
GlobalConfigService.load('LINEAR_CLIENT_ID', nil).present?
|
GlobalConfigService.load('LINEAR_CLIENT_ID', nil).present?
|
||||||
|
when 'github'
|
||||||
|
GlobalConfigService.load('GITHUB_CLIENT_ID', nil).present? && GlobalConfigService.load('GITHUB_CLIENT_SECRET', nil).present?
|
||||||
when 'shopify'
|
when 'shopify'
|
||||||
shopify_enabled?(account)
|
shopify_enabled?(account)
|
||||||
when 'leadsquared'
|
when 'leadsquared'
|
||||||
@@ -87,13 +89,11 @@ class Integrations::App
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build_github_action
|
def build_github_action
|
||||||
app_id = GlobalConfigService.load('GITHUB_CLIENT_ID', nil)
|
GlobalConfigService.load('GITHUB_CLIENT_ID', nil)
|
||||||
[
|
|
||||||
"#{params[:action]}?client_id=#{app_id}",
|
# For GitHub Apps, we need to redirect to the installation page first
|
||||||
"redirect_uri=#{self.class.github_integration_url}",
|
github_app_name = GlobalConfigService.load('GITHUB_APP_NAME', 'chatwoot-qa')
|
||||||
"state=#{encode_state}",
|
"https://github.com/apps/#{github_app_name}/installations/new"
|
||||||
'scope=repo,read:org'
|
|
||||||
].join('&')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def enabled?(account)
|
def enabled?(account)
|
||||||
|
|||||||
@@ -387,5 +387,10 @@
|
|||||||
locked: false
|
locked: false
|
||||||
description: 'Github client secret'
|
description: 'Github client secret'
|
||||||
type: secret
|
type: secret
|
||||||
|
- name: GITHUB_APP_NAME
|
||||||
|
display_title: 'Github App Name'
|
||||||
|
value:
|
||||||
|
locked: false
|
||||||
|
description: 'Github App name for installation URLs (e.g., "chatwoot-qa")'
|
||||||
## ------ End of Github Integration Config ------- #
|
## ------ End of Github Integration Config ------- #
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user