mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 11:37:58 +00:00
- Add `actor=app` parameter to Linear OAuth authorization URL for consistent app-level authorization https://linear.app/developers/oauth-actor-authorization - Implement user attribution for Linear issue creation and linking using `createAsUser` and `displayIconUrl` parameters - Enhance Linear integration to properly attribute actions to specific Chatwoot agents **Note** - The displayIconUrl parameter is being sent correctly to Linear's GraphQL API (verified through testing), but there is an issues with icon is not attaching properly. - We might need to disconnect the integration connect again.
130 lines
2.9 KiB
Ruby
130 lines
2.9 KiB
Ruby
class Integrations::App
|
|
include Linear::IntegrationHelper
|
|
attr_accessor :params
|
|
|
|
def initialize(params)
|
|
@params = params
|
|
end
|
|
|
|
def id
|
|
params[:id]
|
|
end
|
|
|
|
def name
|
|
I18n.t("integration_apps.#{params[:i18n_key]}.name")
|
|
end
|
|
|
|
def description
|
|
I18n.t("integration_apps.#{params[:i18n_key]}.description")
|
|
end
|
|
|
|
def short_description
|
|
I18n.t("integration_apps.#{params[:i18n_key]}.short_description")
|
|
end
|
|
|
|
def logo
|
|
params[:logo]
|
|
end
|
|
|
|
def fields
|
|
params[:fields]
|
|
end
|
|
|
|
# There is no way to get the account_id from the linear callback
|
|
# so we are using the generate_linear_token method to generate a token and encode it in the state parameter
|
|
def encode_state
|
|
generate_linear_token(Current.account.id)
|
|
end
|
|
|
|
def action
|
|
case params[:id]
|
|
when 'slack'
|
|
client_id = GlobalConfigService.load('SLACK_CLIENT_ID', nil)
|
|
"#{params[:action]}&client_id=#{client_id}&redirect_uri=#{self.class.slack_integration_url}"
|
|
when 'linear'
|
|
build_linear_action
|
|
else
|
|
params[:action]
|
|
end
|
|
end
|
|
|
|
def active?(account)
|
|
case params[:id]
|
|
when 'slack'
|
|
GlobalConfigService.load('SLACK_CLIENT_SECRET', nil).present?
|
|
when 'linear'
|
|
GlobalConfigService.load('LINEAR_CLIENT_ID', nil).present?
|
|
when 'shopify'
|
|
shopify_enabled?(account)
|
|
when 'leadsquared'
|
|
account.feature_enabled?('crm_integration')
|
|
when 'notion'
|
|
notion_enabled?(account)
|
|
else
|
|
true
|
|
end
|
|
end
|
|
|
|
def build_linear_action
|
|
app_id = GlobalConfigService.load('LINEAR_CLIENT_ID', nil)
|
|
[
|
|
"#{params[:action]}?response_type=code",
|
|
"client_id=#{app_id}",
|
|
"redirect_uri=#{self.class.linear_integration_url}",
|
|
"state=#{encode_state}",
|
|
'scope=read,write',
|
|
'prompt=consent',
|
|
'actor=app'
|
|
].join('&')
|
|
end
|
|
|
|
def enabled?(account)
|
|
case params[:id]
|
|
when 'webhook'
|
|
account.webhooks.exists?
|
|
when 'dashboard_apps'
|
|
account.dashboard_apps.exists?
|
|
else
|
|
account.hooks.exists?(app_id: id)
|
|
end
|
|
end
|
|
|
|
def hooks
|
|
Current.account.hooks.where(app_id: id)
|
|
end
|
|
|
|
def self.slack_integration_url
|
|
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{Current.account.id}/settings/integrations/slack"
|
|
end
|
|
|
|
def self.linear_integration_url
|
|
"#{ENV.fetch('FRONTEND_URL', nil)}/linear/callback"
|
|
end
|
|
|
|
class << self
|
|
def apps
|
|
Hashie::Mash.new(APPS_CONFIG)
|
|
end
|
|
|
|
def all
|
|
apps.values.each_with_object([]) do |app, result|
|
|
result << new(app)
|
|
end
|
|
end
|
|
|
|
def find(params)
|
|
all.detect { |app| app.id == params[:id] }
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def shopify_enabled?(account)
|
|
account.feature_enabled?('shopify_integration') && GlobalConfigService.load('SHOPIFY_CLIENT_ID', nil).present?
|
|
end
|
|
|
|
def notion_enabled?(account)
|
|
account.feature_enabled?('notion_integration') && GlobalConfigService.load('NOTION_CLIENT_ID', nil).present?
|
|
end
|
|
end
|