Skip to content

Commit 63bd0f2

Browse files
committed
lint
1 parent 852432d commit 63bd0f2

File tree

6 files changed

+67
-119
lines changed

6 files changed

+67
-119
lines changed

backend/onyx/configs/constants.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import socket
44
from enum import auto
55
from enum import Enum
6-
from typing import Union
76

87

98
ONYX_DEFAULT_APPLICATION_NAME = "Onyx"
109
ONYX_SLACK_URL = "https://join.slack.com/t/onyx-dot-app/shared_invite/zt-2twesxdr6-5iQitKZQpgq~hYIZ~dv3KA"
10+
SLACK_USER_TOKEN_PREFIX = "xoxp-"
11+
SLACK_BOT_TOKEN_PREFIX = "xoxb-"
1112
ONYX_EMAILABLE_LOGO_MAX_DIM = 512
1213

1314
SOURCE_TYPE = "source_type"
@@ -209,7 +210,7 @@ class DocumentSource(str, Enum):
209210
class FederatedConnectorSource(str, Enum):
210211
FEDERATED_SLACK = "federated_slack"
211212

212-
def to_non_federated_source(self) -> Union[DocumentSource, None]:
213+
def to_non_federated_source(self) -> DocumentSource | None:
213214
if self == FederatedConnectorSource.FEDERATED_SLACK:
214215
return DocumentSource.SLACK
215216
return None

backend/onyx/context/search/federated/slack_search.py

Lines changed: 51 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,42 @@
4141
HIGHLIGHT_END_CHAR = "\ue001"
4242

4343

44+
def _should_skip_channel(
45+
channel_id: str,
46+
allowed_private_channel: str | None,
47+
bot_token: str | None,
48+
access_token: str,
49+
include_dm: bool,
50+
) -> bool:
51+
"""
52+
Determine if a channel should be skipped if in bot context. When an allowed_private_channel is passed in,
53+
all other private channels are filtered out except that specific one.
54+
"""
55+
if bot_token and not include_dm:
56+
try:
57+
# Use bot token if available (has full permissions), otherwise fall back to user token
58+
token_to_use = bot_token or access_token
59+
channel_client = WebClient(token=token_to_use)
60+
channel_info = channel_client.conversations_info(channel=channel_id)
61+
62+
if isinstance(channel_info.data, dict) and not _is_public_channel(
63+
channel_info.data
64+
):
65+
# This is a private channel - filter it out
66+
if channel_id != allowed_private_channel:
67+
logger.debug(
68+
f"Skipping message from private channel {channel_id} "
69+
f"(not the allowed private channel: {allowed_private_channel})"
70+
)
71+
return True
72+
except Exception as e:
73+
logger.warning(
74+
f"Could not determine channel type for {channel_id}, filtering out: {e}"
75+
)
76+
return True
77+
return False
78+
79+
4480
def build_slack_queries(query: SearchQuery, llm: LLM) -> list[str]:
4581
# get time filter
4682
time_filter = ""
@@ -82,12 +118,6 @@ def _is_public_channel(channel_info: dict[str, Any]) -> bool:
82118
is_channel and not is_private and not is_group and not is_mpim and not is_im
83119
)
84120

85-
# Add detailed logging for debugging
86-
logger.debug(
87-
f"Channel info: is_channel={is_channel}, is_private={is_private}, "
88-
f"is_group={is_group}, is_mpim={is_mpim}, is_im={is_im}, is_public={is_public}"
89-
)
90-
91121
return is_public
92122

93123

@@ -96,9 +126,9 @@ def query_slack(
96126
original_query: SearchQuery,
97127
access_token: str,
98128
limit: int | None = None,
99-
allowed_private_channel: str | None = None, # Add allowed private channel parameter
100-
bot_token: str | None = None, # Add bot token parameter for channel info calls
101-
include_dm: bool = False, # Whether to include direct messages
129+
allowed_private_channel: str | None = None,
130+
bot_token: str | None = None,
131+
include_dm: bool = False,
102132
) -> list[SlackMessage]:
103133
# query slack
104134
slack_client = WebClient(token=access_token)
@@ -151,72 +181,11 @@ def query_slack(
151181
continue
152182

153183
# Apply channel filtering if needed
154-
if allowed_private_channel is not None:
155-
# Private channel context: only allow the specific private channel + public channels
156-
if channel_id == allowed_private_channel:
157-
# This is the allowed private channel - keep it
158-
pass
159-
else:
160-
# Check if this is a public channel
161-
try:
162-
# Use bot token if available (has full permissions), otherwise fall back to user token
163-
token_to_use = bot_token if bot_token else access_token
164-
channel_client = WebClient(token=token_to_use)
165-
channel_info = channel_client.conversations_info(channel=channel_id)
166-
167-
if isinstance(channel_info.data, dict) and _is_public_channel(
168-
channel_info.data
169-
):
170-
# This is a public channel - keep it
171-
pass
172-
else:
173-
# This is another private channel - filter it out
174-
filtered_count += 1
175-
logger.debug(
176-
f"Skipping message from private channel {channel_id} "
177-
f"(not the allowed private channel: {allowed_private_channel})"
178-
)
179-
continue
180-
except Exception as e:
181-
logger.warning(
182-
f"Could not determine channel type for {channel_id}, filtering out: {e}"
183-
)
184-
filtered_count += 1
185-
continue
186-
elif include_dm:
187-
# Include direct messages - no filtering needed
188-
pass
189-
elif (
190-
allowed_private_channel is None and not include_dm and bot_token is not None
184+
if _should_skip_channel(
185+
channel_id, allowed_private_channel, bot_token, access_token, include_dm
191186
):
192-
# Slack bot context (has bot_token but no specific channel context): apply default filtering (only public channels)
193-
try:
194-
# Use bot token if available (has full permissions), otherwise fall back to user token
195-
token_to_use = bot_token if bot_token else access_token
196-
channel_client = WebClient(token=token_to_use)
197-
channel_info = channel_client.conversations_info(channel=channel_id)
198-
199-
if isinstance(channel_info.data, dict) and _is_public_channel(
200-
channel_info.data
201-
):
202-
# This is a public channel - keep it
203-
pass
204-
else:
205-
# This is a private channel - filter it out
206-
filtered_count += 1
207-
logger.debug(
208-
f"Skipping message from private channel {channel_id} (only public channels allowed in Slack bot context)"
209-
)
210-
continue
211-
except Exception as e:
212-
logger.warning(
213-
f"Could not determine channel type for {channel_id}, filtering out: {e}"
214-
)
215-
filtered_count += 1
216-
continue
217-
else:
218-
# Web chat federated search: no filtering - include all channels
219-
pass
187+
filtered_count += 1
188+
continue
220189

221190
# generate thread id and document id
222191
thread_id = (
@@ -453,22 +422,14 @@ def slack_retrieval(
453422
if not slack_messages:
454423
return []
455424

456-
# Check if we're in a bot context by looking at the access token prefix
457-
if access_token.startswith("xoxp-"):
458-
logger.info(
459-
"Bot context detected (user OAuth token): skipping thread context to avoid additional scope requirements"
460-
)
461-
# Use original message text without thread context
462-
else:
463-
thread_texts: list[str] = run_functions_tuples_in_parallel(
464-
[
465-
(get_contextualized_thread_text, (slack_message, access_token))
466-
for slack_message in slack_messages
467-
]
468-
)
469-
for slack_message, thread_text in zip(slack_messages, thread_texts):
470-
slack_message.text = thread_text
471-
# else: use original message text without thread context
425+
thread_texts: list[str] = run_functions_tuples_in_parallel(
426+
[
427+
(get_contextualized_thread_text, (slack_message, access_token))
428+
for slack_message in slack_messages
429+
]
430+
)
431+
for slack_message, thread_text in zip(slack_messages, thread_texts):
432+
slack_message.text = thread_text
472433

473434
# get the highlighted texts from shortest to longest
474435
highlighted_texts: set[str] = set()

backend/onyx/db/slack_bot.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,3 @@ def remove_slack_bot(
7878

7979
def fetch_slack_bots(db_session: Session) -> Sequence[SlackBot]:
8080
return db_session.scalars(select(SlackBot)).all()
81-
82-
83-
def fetch_slack_bot_tokens(
84-
db_session: Session, slack_bot_id: int
85-
) -> dict[str, str | None] | None:
86-
slack_bot = db_session.scalar(select(SlackBot).where(SlackBot.id == slack_bot_id))
87-
if not slack_bot:
88-
return None
89-
return {
90-
"app_token": slack_bot.app_token,
91-
"bot_token": slack_bot.bot_token,
92-
"user_token": slack_bot.user_token,
93-
}

backend/onyx/server/manage/validate_tokens.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import requests
22
from fastapi import HTTPException
33

4+
from onyx.configs.constants import SLACK_USER_TOKEN_PREFIX
5+
46
SLACK_API_URL = "https://slack.com/api/auth.test"
57
SLACK_CONNECTIONS_OPEN_URL = "https://slack.com/api/apps.connections.open"
68

@@ -43,20 +45,25 @@ def validate_app_token(app_token: str) -> bool:
4345
return True
4446

4547

46-
def validate_user_token(user_token: str | None) -> bool:
48+
def validate_user_token(user_token: str | None) -> None:
4749
"""
4850
Validate that the user_token is a valid user OAuth token (xoxp-...)
4951
and not a bot token (xoxb-...)
52+
Args:
53+
user_token: The user OAuth token to validate.
54+
Returns:
55+
None is valid and will return successfully.
56+
Raises:
57+
HTTPException: If the token is invalid or missing required fields
5058
"""
5159
if user_token is None:
5260
# user_token is optional, so None is valid
53-
return True
61+
return
5462

55-
# Check token format - user tokens should start with xoxp-
56-
if not user_token.startswith("xoxp-"):
63+
if not user_token.startswith(SLACK_USER_TOKEN_PREFIX):
5764
raise HTTPException(
5865
status_code=400,
59-
detail="Invalid user token format. User OAuth tokens must start with 'xoxp-'",
66+
detail=f"Invalid user token format. User OAuth tokens must start with '{SLACK_USER_TOKEN_PREFIX}'",
6067
)
6168

6269
# Test the token with Slack API to ensure it's valid
@@ -74,5 +81,3 @@ def validate_user_token(user_token: str | None) -> bool:
7481
status_code=400,
7582
detail=f"Invalid user token: {data.get('error', 'Unknown error')}",
7683
)
77-
78-
return True

package-lock.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

web/src/app/admin/bots/SlackTokensForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export const SlackTokensForm = ({
125125
name="user_token"
126126
label="Slack User Token (Optional)"
127127
type="password"
128-
subtext="Optional: User OAuth token with search:read.public scope for enhanced public channel access"
128+
subtext="Optional: User OAuth token for enhanced private channel access"
129129
/>
130130
<div className="flex justify-end w-full mt-4">
131131
<Button

0 commit comments

Comments
 (0)