mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-25 19:15:18 +02:00
feat(backend): Add legacy token handling in NotionHistoryConnector and log warnings for legacy usage in indexing
This commit is contained in:
parent
b3f553802c
commit
c6d25ed7d8
2 changed files with 72 additions and 9 deletions
|
|
@ -77,6 +77,8 @@ class NotionHistoryConnector:
|
||||||
self._pages_with_skipped_content: list[str] = []
|
self._pages_with_skipped_content: list[str] = []
|
||||||
# Optional callback to notify about retry progress (for user notifications)
|
# Optional callback to notify about retry progress (for user notifications)
|
||||||
self._on_retry_callback: RetryCallbackType | None = None
|
self._on_retry_callback: RetryCallbackType | None = None
|
||||||
|
# Track if using legacy integration token (for upgrade notification)
|
||||||
|
self._using_legacy_token: bool = False
|
||||||
|
|
||||||
def set_retry_callback(self, callback: RetryCallbackType | None) -> None:
|
def set_retry_callback(self, callback: RetryCallbackType | None) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -119,6 +121,18 @@ class NotionHistoryConnector:
|
||||||
|
|
||||||
config_data = connector.config.copy()
|
config_data = connector.config.copy()
|
||||||
|
|
||||||
|
# Check for legacy integration token format first
|
||||||
|
# (for connectors created before OAuth was implemented)
|
||||||
|
legacy_token = config_data.get("NOTION_INTEGRATION_TOKEN")
|
||||||
|
raw_access_token = config_data.get("access_token")
|
||||||
|
|
||||||
|
# Validate that we have some form of token
|
||||||
|
if not raw_access_token and not legacy_token:
|
||||||
|
raise ValueError(
|
||||||
|
"Notion integration not properly connected. "
|
||||||
|
"Please remove and re-add the Notion connector."
|
||||||
|
)
|
||||||
|
|
||||||
# Decrypt credentials if they are encrypted
|
# Decrypt credentials if they are encrypted
|
||||||
token_encrypted = config_data.get("_token_encrypted", False)
|
token_encrypted = config_data.get("_token_encrypted", False)
|
||||||
if token_encrypted and config.SECRET_KEY:
|
if token_encrypted and config.SECRET_KEY:
|
||||||
|
|
@ -143,13 +157,38 @@ class NotionHistoryConnector:
|
||||||
f"Failed to decrypt Notion credentials for connector {self._connector_id}: {e!s}"
|
f"Failed to decrypt Notion credentials for connector {self._connector_id}: {e!s}"
|
||||||
)
|
)
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Failed to decrypt Notion credentials: {e!s}"
|
"Notion credentials could not be decrypted. "
|
||||||
|
"Please remove and re-add the Notion connector."
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
# Handle legacy format: convert NOTION_INTEGRATION_TOKEN to access_token
|
||||||
|
if not config_data.get("access_token") and legacy_token:
|
||||||
|
config_data["access_token"] = legacy_token
|
||||||
|
self._using_legacy_token = True
|
||||||
|
logger.info(
|
||||||
|
f"Using legacy NOTION_INTEGRATION_TOKEN for connector {self._connector_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Final validation: ensure we have a valid access_token after all processing
|
||||||
|
final_token = config_data.get("access_token")
|
||||||
|
if not final_token or (isinstance(final_token, str) and not final_token.strip()):
|
||||||
|
raise ValueError(
|
||||||
|
"Notion access token is invalid or empty. "
|
||||||
|
"Please remove and re-add the Notion connector."
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._credentials = NotionAuthCredentialsBase.from_dict(config_data)
|
self._credentials = NotionAuthCredentialsBase.from_dict(config_data)
|
||||||
|
except KeyError as e:
|
||||||
|
raise ValueError(
|
||||||
|
f"Notion credentials are incomplete (missing {e}). "
|
||||||
|
"Please reconnect your Notion account."
|
||||||
|
) from e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f"Invalid Notion credentials: {e!s}") from e
|
raise ValueError(
|
||||||
|
f"Notion credentials format error: {e!s}. "
|
||||||
|
"Please reconnect your Notion account."
|
||||||
|
) from e
|
||||||
|
|
||||||
# Check if token is expired and refreshable
|
# Check if token is expired and refreshable
|
||||||
if self._credentials.is_expired and self._credentials.is_refreshable:
|
if self._credentials.is_expired and self._credentials.is_refreshable:
|
||||||
|
|
@ -356,6 +395,15 @@ class NotionHistoryConnector:
|
||||||
"""
|
"""
|
||||||
return len(self._pages_with_skipped_content)
|
return len(self._pages_with_skipped_content)
|
||||||
|
|
||||||
|
def is_using_legacy_token(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check if connector is using legacy integration token format.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if using legacy NOTION_INTEGRATION_TOKEN, False if using OAuth
|
||||||
|
"""
|
||||||
|
return self._using_legacy_token
|
||||||
|
|
||||||
def _record_skipped_content(self, page_title: str):
|
def _record_skipped_content(self, page_title: str):
|
||||||
"""
|
"""
|
||||||
Record that a page had unsupported content skipped.
|
Record that a page had unsupported content skipped.
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,13 @@ async def index_notion_pages(
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{pages_with_skipped_content} pages had Notion AI content skipped (not available via API)"
|
f"{pages_with_skipped_content} pages had Notion AI content skipped (not available via API)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check if using legacy integration token and log warning
|
||||||
|
if notion_client.is_using_legacy_token():
|
||||||
|
logger.warning(
|
||||||
|
f"Connector {connector_id} is using legacy integration token. "
|
||||||
|
"Recommend reconnecting with OAuth."
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await task_logger.log_task_failure(
|
await task_logger.log_task_failure(
|
||||||
log_entry,
|
log_entry,
|
||||||
|
|
@ -471,8 +478,8 @@ async def index_notion_pages(
|
||||||
# Add user-friendly message about skipped Notion AI content
|
# Add user-friendly message about skipped Notion AI content
|
||||||
if pages_with_skipped_ai_content > 0:
|
if pages_with_skipped_ai_content > 0:
|
||||||
result_message += (
|
result_message += (
|
||||||
f" Audio transcriptions and AI summaries from Notion aren't accessible "
|
" Audio transcriptions and AI summaries from Notion aren't accessible "
|
||||||
f"via their API — all other content was saved."
|
"via their API - all other content was saved."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Log success
|
# Log success
|
||||||
|
|
@ -496,18 +503,26 @@ async def index_notion_pages(
|
||||||
# Clean up the async client
|
# Clean up the async client
|
||||||
await notion_client.close()
|
await notion_client.close()
|
||||||
|
|
||||||
# Return user-friendly message about skipped AI content (if any)
|
# Build user-friendly notification messages
|
||||||
# This will be shown in the notification to inform users
|
# This will be shown in the notification to inform users
|
||||||
user_notification_message = None
|
notification_parts = []
|
||||||
|
|
||||||
if pages_with_skipped_ai_content > 0:
|
if pages_with_skipped_ai_content > 0:
|
||||||
user_notification_message = (
|
notification_parts.append(
|
||||||
"Some Notion AI content couldn't be synced (Notion API limitation)"
|
"Some Notion AI content couldn't be synced (API limitation)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if notion_client.is_using_legacy_token():
|
||||||
|
notification_parts.append(
|
||||||
|
"Using legacy token. Reconnect with OAuth for better reliability."
|
||||||
|
)
|
||||||
|
|
||||||
|
user_notification_message = " ".join(notification_parts) if notification_parts else None
|
||||||
|
|
||||||
return (
|
return (
|
||||||
total_processed,
|
total_processed,
|
||||||
user_notification_message,
|
user_notification_message,
|
||||||
) # Return message about skipped AI content if any
|
)
|
||||||
|
|
||||||
except SQLAlchemyError as db_error:
|
except SQLAlchemyError as db_error:
|
||||||
await session.rollback()
|
await session.rollback()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue