mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-21 18:55:16 +02:00
feat: add extract_identifier_from_credentials to connector naming
This commit is contained in:
parent
d979c156f8
commit
4c6a782cec
1 changed files with 125 additions and 34 deletions
|
|
@ -1,4 +1,18 @@
|
|||
from app.db import SearchSourceConnectorType
|
||||
"""
|
||||
Connector Naming Utilities.
|
||||
|
||||
Provides functions for generating unique, user-friendly connector names.
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
from uuid import UUID
|
||||
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.future import select
|
||||
|
||||
from app.db import SearchSourceConnector, SearchSourceConnectorType
|
||||
|
||||
# Friendly display names for connector types
|
||||
BASE_NAME_FOR_TYPE = {
|
||||
|
|
@ -7,54 +21,131 @@ BASE_NAME_FOR_TYPE = {
|
|||
SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR: "Google Calendar",
|
||||
SearchSourceConnectorType.SLACK_CONNECTOR: "Slack",
|
||||
SearchSourceConnectorType.NOTION_CONNECTOR: "Notion",
|
||||
SearchSourceConnectorType.GITHUB_CONNECTOR: "GitHub",
|
||||
SearchSourceConnectorType.LINEAR_CONNECTOR: "Linear",
|
||||
SearchSourceConnectorType.JIRA_CONNECTOR: "Jira",
|
||||
SearchSourceConnectorType.DISCORD_CONNECTOR: "Discord",
|
||||
SearchSourceConnectorType.CONFLUENCE_CONNECTOR: "Confluence",
|
||||
SearchSourceConnectorType.AIRTABLE_CONNECTOR: "Airtable",
|
||||
SearchSourceConnectorType.LUMA_CONNECTOR: "Luma",
|
||||
# Add other connectors as needed, fallback below
|
||||
}
|
||||
|
||||
|
||||
def get_base_name_for_type(connector_type: SearchSourceConnectorType) -> str:
|
||||
"""Get a friendly display name for a connector type."""
|
||||
return BASE_NAME_FOR_TYPE.get(connector_type, connector_type.replace("_", " ").title())
|
||||
|
||||
|
||||
def generate_unique_connector_name(connector_type: SearchSourceConnectorType, identifier: str | None) -> str:
|
||||
def extract_identifier_from_credentials(
|
||||
connector_type: SearchSourceConnectorType,
|
||||
credentials: dict[str, Any],
|
||||
) -> str | None:
|
||||
"""
|
||||
Extract a unique identifier from connector credentials.
|
||||
|
||||
Args:
|
||||
connector_type: The type of connector
|
||||
credentials: The connector credentials dict
|
||||
|
||||
Returns:
|
||||
Identifier string (workspace name, email, etc.) or None
|
||||
"""
|
||||
if connector_type == SearchSourceConnectorType.SLACK_CONNECTOR:
|
||||
return credentials.get("team_name")
|
||||
|
||||
if connector_type == SearchSourceConnectorType.NOTION_CONNECTOR:
|
||||
return credentials.get("workspace_name")
|
||||
|
||||
if connector_type == SearchSourceConnectorType.DISCORD_CONNECTOR:
|
||||
return credentials.get("guild_name")
|
||||
|
||||
if connector_type in (
|
||||
SearchSourceConnectorType.JIRA_CONNECTOR,
|
||||
SearchSourceConnectorType.CONFLUENCE_CONNECTOR,
|
||||
):
|
||||
base_url = credentials.get("base_url", "")
|
||||
if base_url:
|
||||
try:
|
||||
parsed = urlparse(base_url)
|
||||
hostname = parsed.netloc or parsed.path
|
||||
if ".atlassian.net" in hostname:
|
||||
return hostname.replace(".atlassian.net", "")
|
||||
return hostname
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
# Google, Linear, Airtable require API calls - return None
|
||||
return None
|
||||
|
||||
|
||||
def generate_connector_name_with_identifier(
|
||||
connector_type: SearchSourceConnectorType,
|
||||
identifier: str | None,
|
||||
) -> str:
|
||||
"""
|
||||
Generate a connector name with an identifier.
|
||||
|
||||
Args:
|
||||
connector_type: The type of connector
|
||||
identifier: User identifier (email, workspace name, etc.)
|
||||
|
||||
Returns:
|
||||
Name like "Gmail - john@example.com" or just "Gmail" if no identifier
|
||||
"""
|
||||
base = get_base_name_for_type(connector_type)
|
||||
if identifier:
|
||||
return f"{base} - {identifier}"
|
||||
return base
|
||||
|
||||
|
||||
def extract_identifier_from_credentials(connector_type: SearchSourceConnectorType, credentials: dict) -> str | None:
|
||||
if connector_type == SearchSourceConnectorType.GOOGLE_GMAIL_CONNECTOR:
|
||||
return credentials.get("email") or credentials.get("user_email")
|
||||
if connector_type == SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR:
|
||||
return credentials.get("email")
|
||||
if connector_type == SearchSourceConnectorType.GOOGLE_CALENDAR_CONNECTOR:
|
||||
return credentials.get("email")
|
||||
if connector_type == SearchSourceConnectorType.SLACK_CONNECTOR:
|
||||
return credentials.get("team_name") or credentials.get("team_id")
|
||||
if connector_type == SearchSourceConnectorType.NOTION_CONNECTOR:
|
||||
return credentials.get("workspace_name")
|
||||
if connector_type == SearchSourceConnectorType.GITHUB_CONNECTOR:
|
||||
return credentials.get("username")
|
||||
if connector_type == SearchSourceConnectorType.LINEAR_CONNECTOR:
|
||||
return credentials.get("workspace_name")
|
||||
if connector_type == SearchSourceConnectorType.JIRA_CONNECTOR:
|
||||
return credentials.get("base_url") or credentials.get("cloud_id")
|
||||
if connector_type == SearchSourceConnectorType.CONFLUENCE_CONNECTOR:
|
||||
return credentials.get("base_url") or credentials.get("cloud_id")
|
||||
if connector_type == SearchSourceConnectorType.DISCORD_CONNECTOR:
|
||||
return credentials.get("guild_name")
|
||||
if connector_type == SearchSourceConnectorType.AIRTABLE_CONNECTOR:
|
||||
return credentials.get("base_name")
|
||||
if connector_type == SearchSourceConnectorType.LUMA_CONNECTOR:
|
||||
return credentials.get("account_name")
|
||||
for key in ["email", "username", "workspace_name", "team_name", "base_url", "guild_name", "site_name", "account_name"]:
|
||||
if credentials.get(key):
|
||||
return credentials.get(key)
|
||||
return None
|
||||
async def count_connectors_of_type(
|
||||
session: AsyncSession,
|
||||
connector_type: SearchSourceConnectorType,
|
||||
search_space_id: int,
|
||||
user_id: UUID,
|
||||
) -> int:
|
||||
"""Count existing connectors of a type for a user in a search space."""
|
||||
result = await session.execute(
|
||||
select(func.count(SearchSourceConnector.id)).where(
|
||||
SearchSourceConnector.connector_type == connector_type,
|
||||
SearchSourceConnector.search_space_id == search_space_id,
|
||||
SearchSourceConnector.user_id == user_id,
|
||||
)
|
||||
)
|
||||
return result.scalar() or 0
|
||||
|
||||
|
||||
async def generate_unique_connector_name(
|
||||
session: AsyncSession,
|
||||
connector_type: SearchSourceConnectorType,
|
||||
search_space_id: int,
|
||||
user_id: UUID,
|
||||
identifier: str | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Generate a unique connector name.
|
||||
|
||||
If an identifier is provided (email, workspace name, etc.), uses it with base name.
|
||||
Otherwise, falls back to counting existing connectors for uniqueness.
|
||||
|
||||
Args:
|
||||
session: Database session
|
||||
connector_type: The type of connector
|
||||
search_space_id: The search space ID
|
||||
user_id: The user ID
|
||||
identifier: Optional user identifier (email, workspace name, etc.)
|
||||
|
||||
Returns:
|
||||
Unique name like "Gmail - john@example.com" or "Gmail (2)"
|
||||
"""
|
||||
base = get_base_name_for_type(connector_type)
|
||||
|
||||
if identifier:
|
||||
return f"{base} - {identifier}"
|
||||
|
||||
# Fallback: use counter for uniqueness
|
||||
count = await count_connectors_of_type(session, connector_type, search_space_id, user_id)
|
||||
|
||||
if count == 0:
|
||||
return base
|
||||
return f"{base} ({count + 1})"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue