Files
leadchat/lib/integrations/linear/processor_service.rb
Muhsin Keloth a8d53a6df4 feat(linear): Support refresh tokens and migrate legacy OAuth tokens (#13721)
Linear is deprecating long-lived OAuth2 access tokens (valid for 10
years) in favor of short-lived access tokens with refresh tokens.
Starting October 1, 2025, all new OAuth2 apps will default to refresh
tokens. Linear will no longer issue long-lived access tokens. Please
read more details
[here](https://linear.app/developers/oauth-2-0-authentication#migrate-to-using-refresh-tokens)
We currently use long-lived tokens in our Linear integration (valid for
up to 10 years). To remain compatible, this PR ensures compatibility by
supporting refresh-token-based auth and migrating existing legacy
tokens.

Fixes
https://linear.app/chatwoot/issue/CW-5541/migrate-linear-oauth2-integration-to-support-refresh-tokens
2026-03-17 13:09:03 +04:00

87 lines
2.2 KiB
Ruby

class Integrations::Linear::ProcessorService
pattr_initialize [:account!]
def teams
response = linear_client.teams
return { error: response[:error] } if response[:error]
{ data: response['teams']['nodes'].map(&:as_json) }
end
def team_entities(team_id)
response = linear_client.team_entities(team_id)
return response if response[:error]
{
data: {
users: response['users']['nodes'].map(&:as_json),
projects: response['projects']['nodes'].map(&:as_json),
states: response['workflowStates']['nodes'].map(&:as_json),
labels: response['issueLabels']['nodes'].map(&:as_json)
}
}
end
def create_issue(params, user = nil)
response = linear_client.create_issue(params, user)
return response if response[:error]
{
data: { id: response['issueCreate']['issue']['id'],
title: response['issueCreate']['issue']['title'],
identifier: response['issueCreate']['issue']['identifier'] }
}
end
def link_issue(link, issue_id, title, user = nil)
response = linear_client.link_issue(link, issue_id, title, user)
return response if response[:error]
{
data: {
id: issue_id,
link: link,
link_id: response.with_indifferent_access[:attachmentLinkURL][:attachment][:id]
}
}
end
def unlink_issue(link_id)
response = linear_client.unlink_issue(link_id)
return response if response[:error]
{
data: { link_id: link_id }
}
end
def search_issue(term)
response = linear_client.search_issue(term)
return response if response[:error]
{ data: response['searchIssues']['nodes'].map(&:as_json) }
end
def linked_issues(url)
response = linear_client.linked_issues(url)
return response if response[:error]
{ data: response['attachmentsForURL']['nodes'].map(&:as_json) }
end
private
def linear_hook
@linear_hook ||= account.hooks.find_by!(app_id: 'linear')
end
def linear_client
@linear_client ||= Linear.new(linear_access_token)
end
def linear_access_token
@linear_access_token ||= Integrations::Linear::AccessTokenService.new(hook: linear_hook).access_token
end
end