mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-24 21:38:09 +02:00
fix(connectors): gate folder listings for PAT access
This commit is contained in:
parent
3a0cd8c8cf
commit
cf840875c9
6 changed files with 40 additions and 19 deletions
|
|
@ -27,7 +27,6 @@ from app.config import config
|
|||
from app.db import (
|
||||
SearchSourceConnector,
|
||||
SearchSourceConnectorType,
|
||||
User,
|
||||
get_async_session,
|
||||
)
|
||||
from app.services.composio_service import (
|
||||
|
|
@ -36,12 +35,13 @@ from app.services.composio_service import (
|
|||
TOOLKIT_TO_CONNECTOR_TYPE,
|
||||
ComposioService,
|
||||
)
|
||||
from app.users import current_active_user, require_session_context
|
||||
from app.users import get_auth_context, require_session_context
|
||||
from app.utils.connector_naming import (
|
||||
count_connectors_of_type,
|
||||
get_base_name_for_type,
|
||||
)
|
||||
from app.utils.oauth_security import OAuthStateManager
|
||||
from app.utils.rbac import check_search_space_access
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -69,13 +69,16 @@ def get_state_manager() -> OAuthStateManager:
|
|||
|
||||
|
||||
@router.get("/composio/toolkits")
|
||||
async def list_composio_toolkits(user: User = Depends(current_active_user)):
|
||||
async def list_composio_toolkits(
|
||||
auth: AuthContext = Depends(require_session_context),
|
||||
):
|
||||
"""
|
||||
List available Composio toolkits.
|
||||
|
||||
Returns:
|
||||
JSON with list of available toolkits and their metadata.
|
||||
"""
|
||||
del auth
|
||||
if not ComposioService.is_enabled():
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
|
|
@ -647,7 +650,7 @@ async def list_composio_drive_folders(
|
|||
connector_id: int,
|
||||
parent_id: str | None = None,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
auth: AuthContext = Depends(get_auth_context),
|
||||
):
|
||||
"""
|
||||
List folders AND files in user's Google Drive via Composio.
|
||||
|
|
@ -662,6 +665,7 @@ async def list_composio_drive_folders(
|
|||
)
|
||||
|
||||
connector = None
|
||||
user = auth.user
|
||||
try:
|
||||
result = await session.execute(
|
||||
select(SearchSourceConnector).filter(
|
||||
|
|
@ -679,6 +683,8 @@ async def list_composio_drive_folders(
|
|||
detail="Composio Google Drive connector not found or access denied",
|
||||
)
|
||||
|
||||
await check_search_space_access(session, auth, connector.search_space_id)
|
||||
|
||||
composio_connected_account_id = connector.config.get(
|
||||
"composio_connected_account_id"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,17 +20,17 @@ from app.config import config
|
|||
from app.db import (
|
||||
SearchSourceConnector,
|
||||
SearchSourceConnectorType,
|
||||
User,
|
||||
get_async_session,
|
||||
)
|
||||
from app.schemas.discord_auth_credentials import DiscordAuthCredentialsBase
|
||||
from app.users import current_active_user, require_session_context
|
||||
from app.users import get_auth_context, require_session_context
|
||||
from app.utils.connector_naming import (
|
||||
check_duplicate_connector,
|
||||
extract_identifier_from_credentials,
|
||||
generate_unique_connector_name,
|
||||
)
|
||||
from app.utils.oauth_security import OAuthStateManager, TokenEncryption
|
||||
from app.utils.rbac import check_search_space_access
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -615,7 +615,7 @@ def _compute_channel_permissions(
|
|||
async def get_discord_channels(
|
||||
connector_id: int,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
auth: AuthContext = Depends(get_auth_context),
|
||||
):
|
||||
"""
|
||||
Get list of Discord text channels for a connector with permission info.
|
||||
|
|
@ -633,6 +633,7 @@ async def get_discord_channels(
|
|||
"""
|
||||
from sqlalchemy import select
|
||||
|
||||
user = auth.user
|
||||
try:
|
||||
# Get connector and verify ownership
|
||||
result = await session.execute(
|
||||
|
|
@ -651,6 +652,8 @@ async def get_discord_channels(
|
|||
detail="Discord connector not found or access denied",
|
||||
)
|
||||
|
||||
await check_search_space_access(session, auth, connector.search_space_id)
|
||||
|
||||
# Get credentials and decrypt bot token
|
||||
credentials = DiscordAuthCredentialsBase.from_dict(connector.config)
|
||||
token_encryption = get_token_encryption()
|
||||
|
|
|
|||
|
|
@ -27,16 +27,16 @@ from app.connectors.dropbox import DropboxClient, list_folder_contents
|
|||
from app.db import (
|
||||
SearchSourceConnector,
|
||||
SearchSourceConnectorType,
|
||||
User,
|
||||
get_async_session,
|
||||
)
|
||||
from app.users import current_active_user, require_session_context
|
||||
from app.users import get_auth_context, require_session_context
|
||||
from app.utils.connector_naming import (
|
||||
check_duplicate_connector,
|
||||
extract_identifier_from_credentials,
|
||||
generate_unique_connector_name,
|
||||
)
|
||||
from app.utils.oauth_security import OAuthStateManager, TokenEncryption
|
||||
from app.utils.rbac import check_search_space_access
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
|
@ -411,10 +411,11 @@ async def list_dropbox_folders(
|
|||
connector_id: int,
|
||||
parent_path: str = "",
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
auth: AuthContext = Depends(get_auth_context),
|
||||
):
|
||||
"""List folders and files in user's Dropbox."""
|
||||
connector = None
|
||||
user = auth.user
|
||||
try:
|
||||
result = await session.execute(
|
||||
select(SearchSourceConnector).filter(
|
||||
|
|
@ -430,6 +431,8 @@ async def list_dropbox_folders(
|
|||
status_code=404, detail="Dropbox connector not found or access denied"
|
||||
)
|
||||
|
||||
await check_search_space_access(session, auth, connector.search_space_id)
|
||||
|
||||
dropbox_client = DropboxClient(session, connector_id)
|
||||
items, error = await list_folder_contents(dropbox_client, path=parent_path)
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,9 @@ from app.connectors.google_gmail_connector import fetch_google_user_email
|
|||
from app.db import (
|
||||
SearchSourceConnector,
|
||||
SearchSourceConnectorType,
|
||||
User,
|
||||
get_async_session,
|
||||
)
|
||||
from app.users import current_active_user, require_session_context
|
||||
from app.users import get_auth_context, require_session_context
|
||||
from app.utils.connector_naming import (
|
||||
check_duplicate_connector,
|
||||
generate_unique_connector_name,
|
||||
|
|
@ -47,6 +46,7 @@ from app.utils.oauth_security import (
|
|||
TokenEncryption,
|
||||
generate_code_verifier,
|
||||
)
|
||||
from app.utils.rbac import check_search_space_access
|
||||
|
||||
# Relax token scope validation for Google OAuth
|
||||
os.environ["OAUTHLIB_RELAX_TOKEN_SCOPE"] = "1"
|
||||
|
|
@ -478,7 +478,7 @@ async def list_google_drive_folders(
|
|||
connector_id: int,
|
||||
parent_id: str | None = None,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
auth: AuthContext = Depends(get_auth_context),
|
||||
):
|
||||
"""
|
||||
List folders AND files in user's Google Drive with hierarchical support.
|
||||
|
|
@ -498,6 +498,7 @@ async def list_google_drive_folders(
|
|||
]
|
||||
}
|
||||
"""
|
||||
user = auth.user
|
||||
try:
|
||||
# Get connector and verify ownership
|
||||
result = await session.execute(
|
||||
|
|
@ -516,6 +517,8 @@ async def list_google_drive_folders(
|
|||
detail="Google Drive connector not found or access denied",
|
||||
)
|
||||
|
||||
await check_search_space_access(session, auth, connector.search_space_id)
|
||||
|
||||
# Initialize Drive client (credentials will be loaded on first API call)
|
||||
drive_client = GoogleDriveClient(session, connector_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,16 +27,16 @@ from app.connectors.onedrive import OneDriveClient, list_folder_contents
|
|||
from app.db import (
|
||||
SearchSourceConnector,
|
||||
SearchSourceConnectorType,
|
||||
User,
|
||||
get_async_session,
|
||||
)
|
||||
from app.users import current_active_user, require_session_context
|
||||
from app.users import get_auth_context, require_session_context
|
||||
from app.utils.connector_naming import (
|
||||
check_duplicate_connector,
|
||||
extract_identifier_from_credentials,
|
||||
generate_unique_connector_name,
|
||||
)
|
||||
from app.utils.oauth_security import OAuthStateManager, TokenEncryption
|
||||
from app.utils.rbac import check_search_space_access
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
|
@ -418,10 +418,11 @@ async def list_onedrive_folders(
|
|||
connector_id: int,
|
||||
parent_id: str | None = None,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
auth: AuthContext = Depends(get_auth_context),
|
||||
):
|
||||
"""List folders and files in user's OneDrive."""
|
||||
connector = None
|
||||
user = auth.user
|
||||
try:
|
||||
result = await session.execute(
|
||||
select(SearchSourceConnector).filter(
|
||||
|
|
@ -437,6 +438,8 @@ async def list_onedrive_folders(
|
|||
status_code=404, detail="OneDrive connector not found or access denied"
|
||||
)
|
||||
|
||||
await check_search_space_access(session, auth, connector.search_space_id)
|
||||
|
||||
onedrive_client = OneDriveClient(session, connector_id)
|
||||
items, error = await list_folder_contents(onedrive_client, parent_id=parent_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,17 +22,17 @@ from app.config import config
|
|||
from app.db import (
|
||||
SearchSourceConnector,
|
||||
SearchSourceConnectorType,
|
||||
User,
|
||||
get_async_session,
|
||||
)
|
||||
from app.schemas.slack_auth_credentials import SlackAuthCredentialsBase
|
||||
from app.users import current_active_user, require_session_context
|
||||
from app.users import get_auth_context, require_session_context
|
||||
from app.utils.connector_naming import (
|
||||
check_duplicate_connector,
|
||||
extract_identifier_from_credentials,
|
||||
generate_unique_connector_name,
|
||||
)
|
||||
from app.utils.oauth_security import OAuthStateManager, TokenEncryption
|
||||
from app.utils.rbac import check_search_space_access
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -530,7 +530,7 @@ async def refresh_slack_token(
|
|||
async def get_slack_channels(
|
||||
connector_id: int,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
user: User = Depends(current_active_user),
|
||||
auth: AuthContext = Depends(get_auth_context),
|
||||
) -> list[dict[str, Any]]:
|
||||
"""
|
||||
Get list of Slack channels with bot membership status.
|
||||
|
|
@ -546,6 +546,7 @@ async def get_slack_channels(
|
|||
Returns:
|
||||
List of channels with id, name, is_private, and is_member fields
|
||||
"""
|
||||
user = auth.user
|
||||
try:
|
||||
# Get the connector and verify ownership
|
||||
result = await session.execute(
|
||||
|
|
@ -564,6 +565,8 @@ async def get_slack_channels(
|
|||
detail="Slack connector not found or access denied",
|
||||
)
|
||||
|
||||
await check_search_space_access(session, auth, connector.search_space_id)
|
||||
|
||||
# Get credentials and decrypt bot token
|
||||
credentials = SlackAuthCredentialsBase.from_dict(connector.config)
|
||||
token_encryption = get_token_encryption()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue