mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-29 19:35:20 +02:00
Merge pull request #335 from CREDO23/connector-airtable-refresh-token
[Feature] Airtable connector | Refresh access token when expired
This commit is contained in:
commit
3fec106c31
2 changed files with 80 additions and 1 deletions
|
|
@ -280,3 +280,78 @@ async def airtable_callback(
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=500, detail=f"Failed to complete Airtable OAuth: {e!s}"
|
status_code=500, detail=f"Failed to complete Airtable OAuth: {e!s}"
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
|
||||||
|
async def refresh_airtable_token(
|
||||||
|
session: AsyncSession, connector: SearchSourceConnector
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Refresh the Airtable access token for a connector.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
session: Database session
|
||||||
|
connector: Airtable connector to refresh
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Updated connector object
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info(f"Refreshing Airtable token for connector {connector.id}")
|
||||||
|
|
||||||
|
credentials = AirtableAuthCredentialsBase.from_dict(connector.config)
|
||||||
|
auth_header = make_basic_auth_header(
|
||||||
|
config.AIRTABLE_CLIENT_ID, config.AIRTABLE_CLIENT_SECRET
|
||||||
|
)
|
||||||
|
|
||||||
|
# Prepare token refresh data
|
||||||
|
refresh_data = {
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
"refresh_token": credentials.refresh_token,
|
||||||
|
"client_id": config.AIRTABLE_CLIENT_ID,
|
||||||
|
"client_secret": config.AIRTABLE_CLIENT_SECRET,
|
||||||
|
}
|
||||||
|
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
token_response = await client.post(
|
||||||
|
TOKEN_URL,
|
||||||
|
data=refresh_data,
|
||||||
|
headers={
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
"Authorization": auth_header,
|
||||||
|
},
|
||||||
|
timeout=30.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if token_response.status_code != 200:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=400, detail="Token refresh failed: {token_response.text}"
|
||||||
|
)
|
||||||
|
|
||||||
|
token_json = token_response.json()
|
||||||
|
|
||||||
|
# Calculate expiration time (UTC, tz-aware)
|
||||||
|
expires_at = None
|
||||||
|
if token_json.get("expires_in"):
|
||||||
|
now_utc = datetime.now(UTC)
|
||||||
|
expires_at = now_utc + timedelta(seconds=int(token_json["expires_in"]))
|
||||||
|
|
||||||
|
# Update credentials object
|
||||||
|
credentials.access_token = token_json["access_token"]
|
||||||
|
credentials.expires_in = token_json.get("expires_in")
|
||||||
|
credentials.expires_at = expires_at
|
||||||
|
credentials.scope = token_json.get("scope")
|
||||||
|
|
||||||
|
# Update connector config
|
||||||
|
connector.config = credentials.to_dict()
|
||||||
|
await session.commit()
|
||||||
|
await session.refresh(connector)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Successfully refreshed Airtable token for connector {connector.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return connector
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=500, detail=f"Failed to refresh Airtable token: {e!s}"
|
||||||
|
) from e
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from app.config import config
|
from app.config import config
|
||||||
from app.connectors.airtable_connector import AirtableConnector
|
from app.connectors.airtable_connector import AirtableConnector
|
||||||
from app.db import Document, DocumentType, SearchSourceConnectorType
|
from app.db import Document, DocumentType, SearchSourceConnectorType
|
||||||
|
from app.routes.airtable_add_connector_route import refresh_airtable_token
|
||||||
from app.schemas.airtable_auth_credentials import AirtableAuthCredentialsBase
|
from app.schemas.airtable_auth_credentials import AirtableAuthCredentialsBase
|
||||||
from app.services.llm_service import get_user_long_context_llm
|
from app.services.llm_service import get_user_long_context_llm
|
||||||
from app.services.task_logging_service import TaskLoggingService
|
from app.services.task_logging_service import TaskLoggingService
|
||||||
|
|
@ -102,7 +103,10 @@ async def index_airtable_records(
|
||||||
"Credentials expired",
|
"Credentials expired",
|
||||||
{"error_type": "ExpiredCredentials"},
|
{"error_type": "ExpiredCredentials"},
|
||||||
)
|
)
|
||||||
return 0, "Airtable credentials have expired. Please re-authenticate."
|
|
||||||
|
connector = await refresh_airtable_token(session, connector)
|
||||||
|
|
||||||
|
# return 0, "Airtable credentials have expired. Please re-authenticate."
|
||||||
|
|
||||||
# Calculate date range for indexing
|
# Calculate date range for indexing
|
||||||
start_date_str, end_date_str = calculate_date_range(
|
start_date_str, end_date_str = calculate_date_range(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue