refactor: move Linear OAuth utils to connector, use httpx.AsyncClient

This commit is contained in:
CREDO23 2026-01-07 13:13:19 +02:00
parent 4b3d427e90
commit f1a715e04e
4 changed files with 50 additions and 67 deletions

View file

@ -399,11 +399,6 @@ async def fetch_airtable_user_email(access_token: str) -> str | None:
Returns: Returns:
User's email address or None if fetch fails User's email address or None if fetch fails
""" """
import httpx
import logging
logger = logging.getLogger(__name__)
try: try:
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
response = await client.get( response = await client.get(

View file

@ -9,6 +9,7 @@ import logging
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any
import httpx
import requests import requests
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select from sqlalchemy.future import select
@ -21,6 +22,53 @@ from app.utils.oauth_security import TokenEncryption
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
LINEAR_GRAPHQL_URL = "https://api.linear.app/graphql"
ORGANIZATION_QUERY = """
query {
organization {
name
}
}
"""
async def fetch_linear_organization_name(access_token: str) -> str | None:
"""
Fetch organization/workspace name from Linear GraphQL API.
Args:
access_token: The Linear OAuth access token
Returns:
Organization name or None if fetch fails
"""
try:
async with httpx.AsyncClient() as client:
response = await client.post(
LINEAR_GRAPHQL_URL,
headers={
"Authorization": access_token,
"Content-Type": "application/json",
},
json={"query": ORGANIZATION_QUERY},
timeout=10.0,
)
if response.status_code == 200:
data = response.json()
org_name = data.get("data", {}).get("organization", {}).get("name")
if org_name:
logger.debug(f"Fetched Linear organization name: {org_name}")
return org_name
logger.warning(f"Failed to fetch Linear org info: {response.status_code}")
return None
except Exception as e:
logger.warning(f"Error fetching Linear organization name: {e!s}")
return None
class LinearConnector: class LinearConnector:
"""Class for retrieving issues and comments from Linear.""" """Class for retrieving issues and comments from Linear."""

View file

@ -1,60 +0,0 @@
"""
Linear OAuth Utilities.
Provides functions for fetching user/organization info from Linear API.
Separated from linear_connector.py to avoid circular imports.
"""
import logging
import httpx
logger = logging.getLogger(__name__)
LINEAR_GRAPHQL_URL = "https://api.linear.app/graphql"
ORGANIZATION_QUERY = """
query {
organization {
name
}
}
"""
async def fetch_linear_organization_name(access_token: str) -> str | None:
"""
Fetch organization/workspace name from Linear GraphQL API.
Args:
access_token: The Linear OAuth access token
Returns:
Organization name or None if fetch fails
"""
try:
async with httpx.AsyncClient() as client:
response = await client.post(
LINEAR_GRAPHQL_URL,
headers={
"Authorization": access_token,
"Content-Type": "application/json",
},
json={"query": ORGANIZATION_QUERY},
timeout=10.0,
)
if response.status_code == 200:
data = response.json()
org_name = data.get("data", {}).get("organization", {}).get("name")
if org_name:
logger.debug(f"Fetched Linear organization name: {org_name}")
return org_name
logger.warning(f"Failed to fetch Linear org info: {response.status_code}")
return None
except Exception as e:
logger.warning(f"Error fetching Linear organization name: {e!s}")
return None

View file

@ -23,7 +23,7 @@ from app.db import (
User, User,
get_async_session, get_async_session,
) )
from app.connectors.linear_oauth import fetch_linear_organization_name from app.connectors.linear_connector import fetch_linear_organization_name
from app.schemas.linear_auth_credentials import LinearAuthCredentialsBase from app.schemas.linear_auth_credentials import LinearAuthCredentialsBase
from app.users import current_active_user from app.users import current_active_user
from app.utils.connector_naming import check_duplicate_connector, generate_unique_connector_name from app.utils.connector_naming import check_duplicate_connector, generate_unique_connector_name
@ -454,4 +454,4 @@ async def refresh_linear_token(
logger.error(f"Failed to refresh Linear token: {e!s}", exc_info=True) logger.error(f"Failed to refresh Linear token: {e!s}", exc_info=True)
raise HTTPException( raise HTTPException(
status_code=500, detail=f"Failed to refresh Linear token: {e!s}" status_code=500, detail=f"Failed to refresh Linear token: {e!s}"
) from e ) from e