mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-10 20:35:17 +02:00
fix: restore duplicate check for non-OAuth connectors
This commit is contained in:
parent
f1a715e04e
commit
5f0013c109
7 changed files with 26 additions and 10 deletions
|
|
@ -16,7 +16,6 @@ from sqlalchemy.future import select
|
|||
|
||||
from app.config import config
|
||||
from app.db import SearchSourceConnector
|
||||
from app.routes.linear_add_connector_route import refresh_linear_token
|
||||
from app.schemas.linear_auth_credentials import LinearAuthCredentialsBase
|
||||
from app.utils.oauth_security import TokenEncryption
|
||||
|
||||
|
|
@ -169,6 +168,9 @@ class LinearConnector:
|
|||
f"Connector {self._connector_id} not found; cannot refresh token."
|
||||
)
|
||||
|
||||
# Lazy import to avoid circular dependency
|
||||
from app.routes.linear_add_connector_route import refresh_linear_token
|
||||
|
||||
# Refresh token
|
||||
connector = await refresh_linear_token(self._session, connector)
|
||||
|
||||
|
|
@ -640,4 +642,3 @@ class LinearConnector:
|
|||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
return iso_date
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,6 @@ async def airtable_callback(
|
|||
status_code=400, detail="No access token received from Airtable"
|
||||
)
|
||||
|
||||
# Fetch user email before encrypting credentials
|
||||
user_email = await fetch_airtable_user_email(access_token)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ async def calendar_callback(
|
|||
creds = flow.credentials
|
||||
creds_dict = json.loads(creds.to_json())
|
||||
|
||||
# Fetch user email before encrypting credentials
|
||||
# Fetch user email
|
||||
user_email = fetch_google_user_email(creds)
|
||||
|
||||
# Encrypt sensitive credentials before storing
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ async def drive_callback(
|
|||
creds = flow.credentials
|
||||
creds_dict = json.loads(creds.to_json())
|
||||
|
||||
# Fetch user email before encrypting credentials
|
||||
# Fetch user email
|
||||
user_email = fetch_google_user_email(creds)
|
||||
|
||||
# Encrypt sensitive credentials before storing
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ async def gmail_callback(
|
|||
creds = flow.credentials
|
||||
creds_dict = json.loads(creds.to_json())
|
||||
|
||||
# Fetch user email before encrypting credentials
|
||||
# Fetch user email
|
||||
user_email = fetch_google_user_email(creds)
|
||||
|
||||
# Encrypt sensitive credentials before storing
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ async def linear_callback(
|
|||
status_code=400, detail="No access token received from Linear"
|
||||
)
|
||||
|
||||
# Fetch organization name before encrypting credentials
|
||||
# Fetch organization name
|
||||
org_name = await fetch_linear_organization_name(access_token)
|
||||
|
||||
# Calculate expiration time (UTC, tz-aware)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ PUT /search-source-connectors/{connector_id} - Update a specific connector
|
|||
DELETE /search-source-connectors/{connector_id} - Delete a specific connector
|
||||
POST /search-source-connectors/{connector_id}/index - Index content from a connector to a search space
|
||||
|
||||
Note: Each search space can have multiple connectors of the same type per user (uniqueness is no longer enforced, you may connect several accounts of the same type).
|
||||
Note: OAuth connectors (Gmail, Drive, Slack, etc.) support multiple accounts per search space.
|
||||
Non-OAuth connectors (BookStack, GitHub, etc.) are limited to one per search space.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
|
@ -111,7 +112,7 @@ async def create_search_source_connector(
|
|||
Create a new search source connector.
|
||||
Requires CONNECTORS_CREATE permission.
|
||||
|
||||
Each search space can have multiple connectors of the same type (e.g., multiple Gmail, Slack, etc. accounts).
|
||||
Each search space can have only one connector of each type (based on search_space_id and connector_type).
|
||||
The config must contain the appropriate keys for the connector type.
|
||||
"""
|
||||
try:
|
||||
|
|
@ -124,6 +125,21 @@ async def create_search_source_connector(
|
|||
"You don't have permission to create connectors in this search space",
|
||||
)
|
||||
|
||||
# Check if a connector with the same type already exists for this search space
|
||||
# (for non-OAuth connectors that don't support multiple accounts)
|
||||
result = await session.execute(
|
||||
select(SearchSourceConnector).filter(
|
||||
SearchSourceConnector.search_space_id == search_space_id,
|
||||
SearchSourceConnector.connector_type == connector.connector_type,
|
||||
)
|
||||
)
|
||||
existing_connector = result.scalars().first()
|
||||
if existing_connector:
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail=f"A connector with type {connector.connector_type} already exists in this search space.",
|
||||
)
|
||||
|
||||
# Prepare connector data
|
||||
connector_data = connector.model_dump()
|
||||
|
||||
|
|
@ -169,7 +185,7 @@ async def create_search_source_connector(
|
|||
await session.rollback()
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail=f"Integrity error: {e!s}",
|
||||
detail=f"Integrity error: A connector with this type already exists in this search space. {e!s}",
|
||||
) from e
|
||||
except HTTPException:
|
||||
await session.rollback()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue