diff --git a/surfsense_backend/app/connectors/confluence_history.py b/surfsense_backend/app/connectors/confluence_history.py index 8247bae70..9e10ffcf1 100644 --- a/surfsense_backend/app/connectors/confluence_history.py +++ b/surfsense_backend/app/connectors/confluence_history.py @@ -24,7 +24,7 @@ logger = logging.getLogger(__name__) class ConfluenceHistoryConnector: """ Confluence connector with OAuth support and automatic token refresh. - + This connector uses OAuth 2.0 access tokens to authenticate with the Confluence API. It automatically refreshes expired tokens when needed. Also supports legacy API token authentication for backward compatibility. @@ -81,8 +81,10 @@ class ConfluenceHistoryConnector: config_data = connector.config.copy() # Check if using OAuth or legacy API token - is_oauth = config_data.get("_token_encrypted", False) or config_data.get("access_token") - + is_oauth = config_data.get("_token_encrypted", False) or config_data.get( + "access_token" + ) + if is_oauth: # OAuth 2.0 authentication # Decrypt credentials if they are encrypted @@ -93,12 +95,16 @@ class ConfluenceHistoryConnector: # Decrypt sensitive fields if config_data.get("access_token"): - config_data["access_token"] = token_encryption.decrypt_token( - config_data["access_token"] + config_data["access_token"] = ( + token_encryption.decrypt_token( + config_data["access_token"] + ) ) if config_data.get("refresh_token"): - config_data["refresh_token"] = token_encryption.decrypt_token( - config_data["refresh_token"] + config_data["refresh_token"] = ( + token_encryption.decrypt_token( + config_data["refresh_token"] + ) ) logger.info( @@ -113,13 +119,19 @@ class ConfluenceHistoryConnector: ) from e try: - self._credentials = AtlassianAuthCredentialsBase.from_dict(config_data) + self._credentials = AtlassianAuthCredentialsBase.from_dict( + config_data + ) # Store cloud_id and base_url for API calls (with backward compatibility for site_url) self._cloud_id = config_data.get("cloud_id") - self._base_url = config_data.get("base_url") or config_data.get("site_url") + self._base_url = config_data.get("base_url") or config_data.get( + "site_url" + ) self._use_oauth = True except Exception as e: - raise ValueError(f"Invalid Confluence OAuth credentials: {e!s}") from e + raise ValueError( + f"Invalid Confluence OAuth credentials: {e!s}" + ) from e else: # Legacy API token authentication self._legacy_email = config_data.get("CONFLUENCE_EMAIL") @@ -127,11 +139,21 @@ class ConfluenceHistoryConnector: self._base_url = config_data.get("CONFLUENCE_BASE_URL") self._use_oauth = False - if not self._legacy_email or not self._legacy_api_token or not self._base_url: - raise ValueError("Confluence credentials not found in connector config") + if ( + not self._legacy_email + or not self._legacy_api_token + or not self._base_url + ): + raise ValueError( + "Confluence credentials not found in connector config" + ) # Check if token is expired and refreshable (only for OAuth) - if self._use_oauth and self._credentials.is_expired and self._credentials.is_refreshable: + if ( + self._use_oauth + and self._credentials.is_expired + and self._credentials.is_refreshable + ): try: logger.info( f"Confluence token expired for connector {self._connector_id}, refreshing..." @@ -170,7 +192,9 @@ class ConfluenceHistoryConnector: self._credentials = AtlassianAuthCredentialsBase.from_dict(config_data) self._cloud_id = config_data.get("cloud_id") # Handle backward compatibility: check both base_url and site_url - self._base_url = config_data.get("base_url") or config_data.get("site_url") + self._base_url = config_data.get("base_url") or config_data.get( + "site_url" + ) # Invalidate cached client so it's recreated with new token if self._http_client: @@ -230,10 +254,10 @@ class ConfluenceHistoryConnector: if not self._use_oauth: # For legacy auth, use the base_url directly return self._base_url or "" - + if not self._cloud_id: raise ValueError("Cloud ID not available. Cannot construct API URL.") - + # Use the Atlassian API format: https://api.atlassian.com/ex/confluence/{cloudid} return f"https://api.atlassian.com/ex/confluence/{self._cloud_id}" @@ -261,11 +285,12 @@ class ConfluenceHistoryConnector: # For now, we'll use the legacy client's make_api_request method # But since it's sync, we'll need to wrap it import asyncio + loop = asyncio.get_event_loop() return await loop.run_in_executor( None, client.make_api_request, endpoint, params ) - + # OAuth flow token = await self._get_valid_token() base_url = await self._get_base_url() @@ -446,7 +471,9 @@ class ConfluenceHistoryConnector: if cursor: params["cursor"] = cursor - result = await self._make_api_request(f"pages/{page_id}/{comment_type}", params) + result = await self._make_api_request( + f"pages/{page_id}/{comment_type}", params + ) if not isinstance(result, dict) or "results" not in result: break # No comments or invalid response @@ -495,6 +522,7 @@ class ConfluenceHistoryConnector: await self._get_valid_token() # ConfluenceConnector.get_pages_by_date_range is synchronous import asyncio + loop = asyncio.get_event_loop() return await loop.run_in_executor( None, @@ -504,7 +532,7 @@ class ConfluenceHistoryConnector: space_ids, include_comments, ) - + # OAuth flow all_pages = [] @@ -562,4 +590,3 @@ class ConfluenceHistoryConnector: async def __aexit__(self, exc_type, exc_val, exc_tb): """Async context manager exit.""" await self.close() - diff --git a/surfsense_backend/app/connectors/jira_connector.py b/surfsense_backend/app/connectors/jira_connector.py index 7bc8f2f03..370460e04 100644 --- a/surfsense_backend/app/connectors/jira_connector.py +++ b/surfsense_backend/app/connectors/jira_connector.py @@ -283,11 +283,11 @@ class JiraConnector: # Query issues that were either created OR updated within the date range # Use end_date + 1 day with < operator to include the full end date from datetime import datetime, timedelta - + # Parse end_date and add 1 day for inclusive end date end_date_obj = datetime.strptime(end_date, "%Y-%m-%d") end_date_next = (end_date_obj + timedelta(days=1)).strftime("%Y-%m-%d") - + # Check both created and updated dates to catch all relevant issues # Use 'created' and 'updated' (standard JQL field names) date_filter = ( @@ -297,9 +297,7 @@ class JiraConnector: jql = f"{date_filter} ORDER BY created DESC" if project_key: - jql = ( - f'project = "{project_key}" AND ({date_filter}) ORDER BY created DESC' - ) + jql = f'project = "{project_key}" AND ({date_filter}) ORDER BY created DESC' # Define fields to retrieve fields = [ diff --git a/surfsense_backend/app/connectors/jira_history.py b/surfsense_backend/app/connectors/jira_history.py index 3e8c69104..6e04ec2a4 100644 --- a/surfsense_backend/app/connectors/jira_history.py +++ b/surfsense_backend/app/connectors/jira_history.py @@ -24,7 +24,7 @@ logger = logging.getLogger(__name__) class JiraHistoryConnector: """ Jira connector with OAuth support and automatic token refresh. - + This connector uses OAuth 2.0 access tokens to authenticate with the Jira API. It automatically refreshes expired tokens when needed. Also supports legacy API token authentication for backward compatibility. @@ -80,8 +80,10 @@ class JiraHistoryConnector: config_data = connector.config.copy() # Check if using OAuth or legacy API token - is_oauth = config_data.get("_token_encrypted", False) or config_data.get("access_token") - + is_oauth = config_data.get("_token_encrypted", False) or config_data.get( + "access_token" + ) + if is_oauth: # OAuth 2.0 authentication if not config.SECRET_KEY: @@ -118,7 +120,9 @@ class JiraHistoryConnector: ) from e try: - self._credentials = AtlassianAuthCredentialsBase.from_dict(config_data) + self._credentials = AtlassianAuthCredentialsBase.from_dict( + config_data + ) self._cloud_id = config_data.get("cloud_id") self._base_url = config_data.get("base_url") self._use_oauth = True @@ -131,11 +135,19 @@ class JiraHistoryConnector: self._base_url = config_data.get("JIRA_BASE_URL") self._use_oauth = False - if not self._legacy_email or not self._legacy_api_token or not self._base_url: + if ( + not self._legacy_email + or not self._legacy_api_token + or not self._base_url + ): raise ValueError("Jira credentials not found in connector config") # Check if token is expired and refreshable (only for OAuth) - if self._use_oauth and self._credentials.is_expired and self._credentials.is_refreshable: + if ( + self._use_oauth + and self._credentials.is_expired + and self._credentials.is_refreshable + ): try: logger.info( f"Jira token expired for connector {self._connector_id}, refreshing..." @@ -206,7 +218,7 @@ class JiraHistoryConnector: if self._use_oauth: # Ensure we have valid token (will refresh if needed) await self._get_valid_token() - + self._jira_client = JiraConnector( base_url=self._base_url, access_token=self._credentials.access_token, @@ -230,7 +242,7 @@ class JiraHistoryConnector: access_token=self._credentials.access_token, cloud_id=self._cloud_id, ) - + return self._jira_client async def get_issues_by_date_range( @@ -256,10 +268,10 @@ class JiraHistoryConnector: # Ensure token is valid (will refresh if needed) if self._use_oauth: await self._get_valid_token() - + # Get client with valid credentials client = await self._get_jira_client() - + # JiraConnector methods are synchronous, so we call them directly # Token refresh has already been handled above return client.get_issues_by_date_range( @@ -317,4 +329,3 @@ class JiraHistoryConnector: async def __aexit__(self, exc_type, exc_val, exc_tb): """Async context manager exit.""" await self.close() - diff --git a/surfsense_backend/app/routes/__init__.py b/surfsense_backend/app/routes/__init__.py index 5b4e24d8f..5015b80c2 100644 --- a/surfsense_backend/app/routes/__init__.py +++ b/surfsense_backend/app/routes/__init__.py @@ -4,6 +4,7 @@ from .airtable_add_connector_route import ( router as airtable_add_connector_router, ) from .circleback_webhook_route import router as circleback_webhook_router +from .confluence_add_connector_route import router as confluence_add_connector_router from .discord_add_connector_route import router as discord_add_connector_router from .documents_routes import router as documents_router from .editor_routes import router as editor_router @@ -17,7 +18,6 @@ from .google_gmail_add_connector_route import ( router as google_gmail_add_connector_router, ) from .jira_add_connector_route import router as jira_add_connector_router -from .confluence_add_connector_route import router as confluence_add_connector_router from .linear_add_connector_route import router as linear_add_connector_router from .logs_routes import router as logs_router from .luma_add_connector_route import router as luma_add_connector_router diff --git a/surfsense_backend/app/routes/confluence_add_connector_route.py b/surfsense_backend/app/routes/confluence_add_connector_route.py index f651219e1..e86d411b6 100644 --- a/surfsense_backend/app/routes/confluence_add_connector_route.py +++ b/surfsense_backend/app/routes/confluence_add_connector_route.py @@ -87,7 +87,9 @@ async def connect_confluence(space_id: int, user: User = Depends(current_active_ raise HTTPException(status_code=400, detail="space_id is required") if not config.ATLASSIAN_CLIENT_ID: - raise HTTPException(status_code=500, detail="Atlassian OAuth not configured.") + raise HTTPException( + status_code=500, detail="Atlassian OAuth not configured." + ) if not config.SECRET_KEY: raise HTTPException( @@ -113,7 +115,9 @@ async def connect_confluence(space_id: int, user: User = Depends(current_active_ auth_url = f"{AUTHORIZATION_URL}?{urlencode(auth_params)}" - logger.info(f"Generated Confluence OAuth URL for user {user.id}, space {space_id}") + logger.info( + f"Generated Confluence OAuth URL for user {user.id}, space {space_id}" + ) return {"auth_url": auth_url} except Exception as e: @@ -216,7 +220,9 @@ async def confluence_callback( error_detail = token_response.text try: error_json = token_response.json() - error_detail = error_json.get("error_description", error_json.get("error", error_detail)) + error_detail = error_json.get( + "error_description", error_json.get("error", error_detail) + ) except Exception: pass raise HTTPException( @@ -252,7 +258,9 @@ async def confluence_callback( break if not cloud_id: - logger.warning("Could not determine Confluence cloud ID from accessible resources") + logger.warning( + "Could not determine Confluence cloud ID from accessible resources" + ) # Calculate expiration time (UTC, tz-aware) expires_at = None @@ -409,7 +417,9 @@ async def refresh_confluence_token( error_detail = token_response.text try: error_json = token_response.json() - error_detail = error_json.get("error_description", error_json.get("error", error_detail)) + error_detail = error_json.get( + "error_description", error_json.get("error", error_detail) + ) except Exception: pass raise HTTPException( @@ -431,7 +441,8 @@ async def refresh_confluence_token( if not access_token: raise HTTPException( - status_code=400, detail="No access token received from Confluence refresh" + status_code=400, + detail="No access token received from Confluence refresh", ) # Update credentials object with encrypted tokens @@ -449,7 +460,9 @@ async def refresh_confluence_token( credentials.cloud_id = connector.config.get("cloud_id") if not credentials.base_url: # Check both base_url and site_url for backward compatibility - credentials.base_url = connector.config.get("base_url") or connector.config.get("site_url") + credentials.base_url = connector.config.get( + "base_url" + ) or connector.config.get("site_url") # Update connector config with encrypted tokens credentials_dict = credentials.to_dict() @@ -458,7 +471,9 @@ async def refresh_confluence_token( await session.commit() await session.refresh(connector) - logger.info(f"Successfully refreshed Confluence token for connector {connector.id}") + logger.info( + f"Successfully refreshed Confluence token for connector {connector.id}" + ) return connector except HTTPException: @@ -468,4 +483,3 @@ async def refresh_confluence_token( raise HTTPException( status_code=500, detail=f"Failed to refresh Confluence token: {e!s}" ) from e - diff --git a/surfsense_backend/app/routes/discord_add_connector_route.py b/surfsense_backend/app/routes/discord_add_connector_route.py index 70a0046a3..6bebac718 100644 --- a/surfsense_backend/app/routes/discord_add_connector_route.py +++ b/surfsense_backend/app/routes/discord_add_connector_route.py @@ -217,7 +217,9 @@ async def discord_callback( error_detail = token_response.text try: error_json = token_response.json() - error_detail = error_json.get("error_description", error_json.get("error", error_detail)) + error_detail = error_json.get( + "error_description", error_json.get("error", error_detail) + ) except Exception: pass raise HTTPException( @@ -263,7 +265,9 @@ async def discord_callback( # Store the bot token from config and OAuth metadata connector_config = { - "bot_token": token_encryption.encrypt_token(bot_token), # Use bot token from config + "bot_token": token_encryption.encrypt_token( + bot_token + ), # Use bot token from config "oauth_access_token": token_encryption.encrypt_token(oauth_access_token) if oauth_access_token else None, # Store OAuth token for reference @@ -356,7 +360,7 @@ async def refresh_discord_token( ) -> SearchSourceConnector: """ Refresh the Discord OAuth tokens for a connector. - + Note: Bot tokens from config don't expire, but OAuth access tokens might. This function refreshes OAuth tokens if needed, but always uses bot token from config. @@ -400,7 +404,9 @@ async def refresh_discord_token( f"No refresh token available for connector {connector.id}. Using bot token from config." ) # Update bot token from config (in case it was changed) - credentials.bot_token = token_encryption.encrypt_token(config.DISCORD_BOT_TOKEN) + credentials.bot_token = token_encryption.encrypt_token( + config.DISCORD_BOT_TOKEN + ) credentials_dict = credentials.to_dict() credentials_dict["_token_encrypted"] = True connector.config = credentials_dict @@ -428,7 +434,9 @@ async def refresh_discord_token( error_detail = token_response.text try: error_json = token_response.json() - error_detail = error_json.get("error_description", error_json.get("error", error_detail)) + error_detail = error_json.get( + "error_description", error_json.get("error", error_detail) + ) except Exception: pass # If refresh fails, bot token from config is still valid @@ -437,7 +445,9 @@ async def refresh_discord_token( "Using bot token from config." ) # Update bot token from config - credentials.bot_token = token_encryption.encrypt_token(config.DISCORD_BOT_TOKEN) + credentials.bot_token = token_encryption.encrypt_token( + config.DISCORD_BOT_TOKEN + ) credentials.refresh_token = None # Clear invalid refresh token credentials_dict = credentials.to_dict() credentials_dict["_token_encrypted"] = True @@ -463,7 +473,7 @@ async def refresh_discord_token( # Always use bot token from config (bot tokens don't expire) credentials.bot_token = token_encryption.encrypt_token(config.DISCORD_BOT_TOKEN) - + # Update OAuth tokens if available if oauth_access_token: # Store OAuth access token for reference @@ -493,7 +503,9 @@ async def refresh_discord_token( await session.commit() await session.refresh(connector) - logger.info(f"Successfully refreshed Discord OAuth tokens for connector {connector.id}") + logger.info( + f"Successfully refreshed Discord OAuth tokens for connector {connector.id}" + ) return connector except HTTPException: @@ -506,4 +518,3 @@ async def refresh_discord_token( raise HTTPException( status_code=500, detail=f"Failed to refresh Discord tokens: {e!s}" ) from e - diff --git a/surfsense_backend/app/routes/jira_add_connector_route.py b/surfsense_backend/app/routes/jira_add_connector_route.py index a22260d68..740c30300 100644 --- a/surfsense_backend/app/routes/jira_add_connector_route.py +++ b/surfsense_backend/app/routes/jira_add_connector_route.py @@ -86,7 +86,9 @@ async def connect_jira(space_id: int, user: User = Depends(current_active_user)) raise HTTPException(status_code=400, detail="space_id is required") if not config.ATLASSIAN_CLIENT_ID: - raise HTTPException(status_code=500, detail="Atlassian OAuth not configured.") + raise HTTPException( + status_code=500, detail="Atlassian OAuth not configured." + ) if not config.SECRET_KEY: raise HTTPException( @@ -215,7 +217,9 @@ async def jira_callback( error_detail = token_response.text try: error_json = token_response.json() - error_detail = error_json.get("error_description", error_json.get("error", error_detail)) + error_detail = error_json.get( + "error_description", error_json.get("error", error_detail) + ) except Exception: pass raise HTTPException( @@ -254,9 +258,7 @@ async def jira_callback( # Filter for Jira instances (resources with type "jira" or id field) jira_instances = [ - r - for r in resources - if r.get("id") and (r.get("name") or r.get("url")) + r for r in resources if r.get("id") and (r.get("name") or r.get("url")) ] if not jira_instances: @@ -270,7 +272,7 @@ async def jira_callback( jira_instance = jira_instances[0] cloud_id = jira_instance["id"] base_url = jira_instance.get("url") - + # If URL is not provided, construct it from cloud_id if not base_url: # Try to extract from name or construct default format @@ -433,7 +435,9 @@ async def refresh_jira_token( error_detail = token_response.text try: error_json = token_response.json() - error_detail = error_json.get("error_description", error_json.get("error", error_detail)) + error_detail = error_json.get( + "error_description", error_json.get("error", error_detail) + ) except Exception: pass raise HTTPException( diff --git a/surfsense_backend/app/schemas/atlassian_auth_credentials.py b/surfsense_backend/app/schemas/atlassian_auth_credentials.py index 3290e5d67..cbb4772e6 100644 --- a/surfsense_backend/app/schemas/atlassian_auth_credentials.py +++ b/surfsense_backend/app/schemas/atlassian_auth_credentials.py @@ -13,7 +13,7 @@ from pydantic import BaseModel, field_validator class AtlassianAuthCredentialsBase(BaseModel): """ Base model for Atlassian OAuth 2.0 credentials. - + Used for both Jira and Confluence connectors since they share the same Atlassian OAuth infrastructure and token structure. """ @@ -84,4 +84,3 @@ class AtlassianAuthCredentialsBase(BaseModel): if isinstance(v, datetime): return v if v.tzinfo else v.replace(tzinfo=UTC) return v - diff --git a/surfsense_backend/app/schemas/discord_auth_credentials.py b/surfsense_backend/app/schemas/discord_auth_credentials.py index 0c18a7554..7ea4ee55c 100644 --- a/surfsense_backend/app/schemas/discord_auth_credentials.py +++ b/surfsense_backend/app/schemas/discord_auth_credentials.py @@ -73,4 +73,3 @@ class DiscordAuthCredentialsBase(BaseModel): if isinstance(v, datetime): return v if v.tzinfo else v.replace(tzinfo=UTC) return v - diff --git a/surfsense_backend/app/tasks/connector_indexers/confluence_indexer.py b/surfsense_backend/app/tasks/connector_indexers/confluence_indexer.py index 85aa10e1a..09022a30b 100644 --- a/surfsense_backend/app/tasks/connector_indexers/confluence_indexer.py +++ b/surfsense_backend/app/tasks/connector_indexers/confluence_indexer.py @@ -90,9 +90,11 @@ async def index_confluence_pages( {"stage": "client_initialization"}, ) - confluence_client: ConfluenceHistoryConnector | None = ConfluenceHistoryConnector( - session=session, - connector_id=connector_id, + confluence_client: ConfluenceHistoryConnector | None = ( + ConfluenceHistoryConnector( + session=session, + connector_id=connector_id, + ) ) # Calculate date range @@ -421,11 +423,11 @@ async def index_confluence_pages( logger.info( f"Confluence indexing completed: {documents_indexed} new pages, {documents_skipped} skipped" ) - + # Close the client connection if confluence_client: await confluence_client.close() - + return ( total_processed, None, diff --git a/surfsense_backend/app/tasks/connector_indexers/discord_indexer.py b/surfsense_backend/app/tasks/connector_indexers/discord_indexer.py index 5c92d2601..110732831 100644 --- a/surfsense_backend/app/tasks/connector_indexers/discord_indexer.py +++ b/surfsense_backend/app/tasks/connector_indexers/discord_indexer.py @@ -69,7 +69,9 @@ async def index_discord_messages( try: # Normalize date parameters - handle 'undefined' strings from frontend - if start_date and (start_date.lower() == "undefined" or start_date.strip() == ""): + if start_date and ( + start_date.lower() == "undefined" or start_date.strip() == "" + ): start_date = None if end_date and (end_date.lower() == "undefined" or end_date.strip() == ""): end_date = None @@ -118,12 +120,13 @@ async def index_discord_messages( elif has_legacy: # Backward compatibility: use legacy token format discord_token = connector.config.get("DISCORD_BOT_TOKEN") - + # Decrypt token if it's encrypted (legacy tokens might be encrypted) token_encrypted = connector.config.get("_token_encrypted", False) if token_encrypted and config.SECRET_KEY and discord_token: try: from app.utils.oauth_security import TokenEncryption + token_encryption = TokenEncryption(config.SECRET_KEY) discord_token = token_encryption.decrypt_token(discord_token) logger.info( @@ -135,7 +138,7 @@ async def index_discord_messages( "Trying to use token as-is (might be unencrypted)." ) # Continue with token as-is - might be unencrypted legacy token - + discord_client = DiscordConnector(token=discord_token) else: await task_logger.log_task_failure( @@ -210,11 +213,16 @@ async def index_discord_messages( f"Date parsing error: {e!s}", {"error_type": "InvalidDateFormat", "start_date": start_date}, ) - return 0, f"Invalid start_date format: {start_date}. Expected YYYY-MM-DD format." + return ( + 0, + f"Invalid start_date format: {start_date}. Expected YYYY-MM-DD format.", + ) try: end_date_iso = ( - datetime.strptime(end_date, "%Y-%m-%d").replace(tzinfo=UTC).isoformat() + datetime.strptime(end_date, "%Y-%m-%d") + .replace(tzinfo=UTC) + .isoformat() ) except ValueError as e: await task_logger.log_task_failure( @@ -223,7 +231,10 @@ async def index_discord_messages( f"Date parsing error: {e!s}", {"error_type": "InvalidDateFormat", "end_date": end_date}, ) - return 0, f"Invalid end_date format: {end_date}. Expected YYYY-MM-DD format." + return ( + 0, + f"Invalid end_date format: {end_date}. Expected YYYY-MM-DD format.", + ) logger.info( f"Indexing Discord messages from {start_date_iso} to {end_date_iso}" @@ -384,8 +395,10 @@ async def index_discord_messages( ) # Check if document with this unique identifier already exists - existing_document = await check_document_by_unique_identifier( - session, unique_identifier_hash + existing_document = ( + await check_document_by_unique_identifier( + session, unique_identifier_hash + ) ) if existing_document: @@ -406,8 +419,10 @@ async def index_discord_messages( chunks = await create_document_chunks( combined_document_string ) - doc_embedding = config.embedding_model_instance.embed( - combined_document_string + doc_embedding = ( + config.embedding_model_instance.embed( + combined_document_string + ) ) # Update existing document @@ -429,7 +444,9 @@ async def index_discord_messages( # Delete old chunks and add new ones existing_document.chunks = chunks - existing_document.updated_at = get_current_timestamp() + existing_document.updated_at = ( + get_current_timestamp() + ) documents_indexed += 1 logger.info( @@ -439,7 +456,9 @@ async def index_discord_messages( # Document doesn't exist - create new one # Process chunks - chunks = await create_document_chunks(combined_document_string) + chunks = await create_document_chunks( + combined_document_string + ) doc_embedding = config.embedding_model_instance.embed( combined_document_string ) diff --git a/surfsense_backend/app/tasks/connector_indexers/jira_indexer.py b/surfsense_backend/app/tasks/connector_indexers/jira_indexer.py index 47ad0986f..7209deb49 100644 --- a/surfsense_backend/app/tasks/connector_indexers/jira_indexer.py +++ b/surfsense_backend/app/tasks/connector_indexers/jira_indexer.py @@ -95,9 +95,7 @@ async def index_jira_issues( # Create connector with session and connector_id for internal refresh # Token refresh will happen automatically when needed - jira_client = JiraHistoryConnector( - session=session, connector_id=connector_id - ) + jira_client = JiraHistoryConnector(session=session, connector_id=connector_id) # Calculate date range # Handle "undefined" strings from frontend @@ -395,10 +393,10 @@ async def index_jira_issues( logger.info( f"JIRA indexing completed: {documents_indexed} new issues, {documents_skipped} skipped" ) - + # Clean up the connector await jira_client.close() - + return ( total_processed, None, @@ -435,4 +433,4 @@ async def index_jira_issues( await jira_client.close() except Exception: pass - return 0, f"Failed to index JIRA issues: {e!s}" \ No newline at end of file + return 0, f"Failed to index JIRA issues: {e!s}" diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/confluence-config.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/confluence-config.tsx index 879a71128..59fa89554 100644 --- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/confluence-config.tsx +++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/confluence-config.tsx @@ -80,7 +80,8 @@ export const ConfluenceConfig: FC = ({ // For OAuth connectors, show simple info message if (isOAuth) { - const siteUrl = (connector.config?.base_url as string) || (connector.config?.site_url as string) || "Unknown"; + const siteUrl = + (connector.config?.base_url as string) || (connector.config?.site_url as string) || "Unknown"; return (
{/* OAuth Info */} diff --git a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/discord-config.tsx b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/discord-config.tsx index 464bc438f..dd4c89c8e 100644 --- a/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/discord-config.tsx +++ b/surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/discord-config.tsx @@ -18,9 +18,9 @@ export const DiscordConfig: FC = () => {

Add Bot to Servers

- Before indexing, make sure the Discord bot has been added to the servers (guilds) you want to - index. The bot can only access messages from servers it's been added to. Use the OAuth - authorization flow to add the bot to your servers. + Before indexing, make sure the Discord bot has been added to the servers (guilds) you + want to index. The bot can only access messages from servers it's been added to. Use the + OAuth authorization flow to add the bot to your servers.

diff --git a/surfsense_web/hooks/use-connector-edit-page.ts b/surfsense_web/hooks/use-connector-edit-page.ts index 5eb55bf1c..a1a3c88f4 100644 --- a/surfsense_web/hooks/use-connector-edit-page.ts +++ b/surfsense_web/hooks/use-connector-edit-page.ts @@ -449,13 +449,13 @@ export function useConnectorEditPage(connectorId: number, searchSpaceId: string) case "JIRA_CONNECTOR": { // Check if this is an OAuth connector (has access_token or _token_encrypted flag) const isJiraOAuth = !!(originalConfig.access_token || originalConfig._token_encrypted); - + if (isJiraOAuth) { // OAuth connectors don't allow editing credentials through the form // Only allow name changes, which are handled separately break; } - + // Legacy API token connector - allow editing credentials if ( formData.JIRA_BASE_URL !== originalConfig.JIRA_BASE_URL ||