mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-05-18 15:50:13 +02:00
* added missing dependency, missing api key placeholder, updated docs * Apply black formatting and validate bot token functionality * acknowledging black formatting * added the validation to update tokens as well * Made the token validation errors looks nicer * getting rif of duplicate dependency
318 lines
12 KiB
Python
318 lines
12 KiB
Python
from fastapi import APIRouter
|
|
from fastapi import Depends
|
|
from fastapi import HTTPException
|
|
from sqlalchemy.orm import Session
|
|
|
|
from onyx.auth.users import current_admin_user
|
|
from onyx.configs.constants import MilestoneRecordType
|
|
from onyx.db.constants import SLACK_BOT_PERSONA_PREFIX
|
|
from onyx.db.engine import get_current_tenant_id
|
|
from onyx.db.engine import get_session
|
|
from onyx.db.models import ChannelConfig
|
|
from onyx.db.models import User
|
|
from onyx.db.persona import get_persona_by_id
|
|
from onyx.db.slack_bot import fetch_slack_bot
|
|
from onyx.db.slack_bot import fetch_slack_bots
|
|
from onyx.db.slack_bot import insert_slack_bot
|
|
from onyx.db.slack_bot import remove_slack_bot
|
|
from onyx.db.slack_bot import update_slack_bot
|
|
from onyx.db.slack_channel_config import create_slack_channel_persona
|
|
from onyx.db.slack_channel_config import fetch_slack_channel_config
|
|
from onyx.db.slack_channel_config import fetch_slack_channel_configs
|
|
from onyx.db.slack_channel_config import insert_slack_channel_config
|
|
from onyx.db.slack_channel_config import remove_slack_channel_config
|
|
from onyx.db.slack_channel_config import update_slack_channel_config
|
|
from onyx.onyxbot.slack.config import validate_channel_name
|
|
from onyx.server.manage.models import SlackBot
|
|
from onyx.server.manage.models import SlackBotCreationRequest
|
|
from onyx.server.manage.models import SlackChannelConfig
|
|
from onyx.server.manage.models import SlackChannelConfigCreationRequest
|
|
from onyx.server.manage.validate_tokens import validate_app_token
|
|
from onyx.server.manage.validate_tokens import validate_bot_token
|
|
from onyx.utils.telemetry import create_milestone_and_report
|
|
|
|
|
|
router = APIRouter(prefix="/manage")
|
|
|
|
|
|
def _form_channel_config(
|
|
db_session: Session,
|
|
slack_channel_config_creation_request: SlackChannelConfigCreationRequest,
|
|
current_slack_channel_config_id: int | None,
|
|
) -> ChannelConfig:
|
|
raw_channel_name = slack_channel_config_creation_request.channel_name
|
|
respond_tag_only = slack_channel_config_creation_request.respond_tag_only
|
|
respond_member_group_list = (
|
|
slack_channel_config_creation_request.respond_member_group_list
|
|
)
|
|
answer_filters = slack_channel_config_creation_request.answer_filters
|
|
follow_up_tags = slack_channel_config_creation_request.follow_up_tags
|
|
|
|
if not raw_channel_name:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="Must provide at least one channel name",
|
|
)
|
|
|
|
try:
|
|
cleaned_channel_name = validate_channel_name(
|
|
db_session=db_session,
|
|
channel_name=raw_channel_name,
|
|
current_slack_channel_config_id=current_slack_channel_config_id,
|
|
current_slack_bot_id=slack_channel_config_creation_request.slack_bot_id,
|
|
)
|
|
except ValueError as e:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=str(e),
|
|
)
|
|
|
|
if respond_tag_only and respond_member_group_list:
|
|
raise ValueError(
|
|
"Cannot set OnyxBot to only respond to tags only and "
|
|
"also respond to a predetermined set of users."
|
|
)
|
|
|
|
channel_config: ChannelConfig = {
|
|
"channel_name": cleaned_channel_name,
|
|
}
|
|
if respond_tag_only is not None:
|
|
channel_config["respond_tag_only"] = respond_tag_only
|
|
if respond_member_group_list:
|
|
channel_config["respond_member_group_list"] = respond_member_group_list
|
|
if answer_filters:
|
|
channel_config["answer_filters"] = answer_filters
|
|
if follow_up_tags is not None:
|
|
channel_config["follow_up_tags"] = follow_up_tags
|
|
|
|
channel_config[
|
|
"show_continue_in_web_ui"
|
|
] = slack_channel_config_creation_request.show_continue_in_web_ui
|
|
|
|
channel_config[
|
|
"respond_to_bots"
|
|
] = slack_channel_config_creation_request.respond_to_bots
|
|
|
|
return channel_config
|
|
|
|
|
|
@router.post("/admin/slack-app/channel")
|
|
def create_slack_channel_config(
|
|
slack_channel_config_creation_request: SlackChannelConfigCreationRequest,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> SlackChannelConfig:
|
|
channel_config = _form_channel_config(
|
|
db_session=db_session,
|
|
slack_channel_config_creation_request=slack_channel_config_creation_request,
|
|
current_slack_channel_config_id=None,
|
|
)
|
|
|
|
persona_id = None
|
|
if slack_channel_config_creation_request.persona_id is not None:
|
|
persona_id = slack_channel_config_creation_request.persona_id
|
|
elif slack_channel_config_creation_request.document_sets:
|
|
persona_id = create_slack_channel_persona(
|
|
db_session=db_session,
|
|
channel_name=channel_config["channel_name"],
|
|
document_set_ids=slack_channel_config_creation_request.document_sets,
|
|
existing_persona_id=None,
|
|
).id
|
|
|
|
slack_channel_config_model = insert_slack_channel_config(
|
|
slack_bot_id=slack_channel_config_creation_request.slack_bot_id,
|
|
persona_id=persona_id,
|
|
channel_config=channel_config,
|
|
standard_answer_category_ids=slack_channel_config_creation_request.standard_answer_categories,
|
|
db_session=db_session,
|
|
enable_auto_filters=slack_channel_config_creation_request.enable_auto_filters,
|
|
)
|
|
return SlackChannelConfig.from_model(slack_channel_config_model)
|
|
|
|
|
|
@router.patch("/admin/slack-app/channel/{slack_channel_config_id}")
|
|
def patch_slack_channel_config(
|
|
slack_channel_config_id: int,
|
|
slack_channel_config_creation_request: SlackChannelConfigCreationRequest,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> SlackChannelConfig:
|
|
channel_config = _form_channel_config(
|
|
db_session=db_session,
|
|
slack_channel_config_creation_request=slack_channel_config_creation_request,
|
|
current_slack_channel_config_id=slack_channel_config_id,
|
|
)
|
|
|
|
persona_id = None
|
|
if slack_channel_config_creation_request.persona_id is not None:
|
|
persona_id = slack_channel_config_creation_request.persona_id
|
|
elif slack_channel_config_creation_request.document_sets:
|
|
existing_slack_channel_config = fetch_slack_channel_config(
|
|
db_session=db_session, slack_channel_config_id=slack_channel_config_id
|
|
)
|
|
if existing_slack_channel_config is None:
|
|
raise HTTPException(
|
|
status_code=404,
|
|
detail="Slack channel config not found",
|
|
)
|
|
|
|
existing_persona_id = existing_slack_channel_config.persona_id
|
|
if existing_persona_id is not None:
|
|
persona = get_persona_by_id(
|
|
persona_id=existing_persona_id,
|
|
user=None,
|
|
db_session=db_session,
|
|
is_for_edit=False,
|
|
)
|
|
|
|
if not persona.name.startswith(SLACK_BOT_PERSONA_PREFIX):
|
|
# Don't update actual non-slackbot specific personas
|
|
# Since this one specified document sets, we have to create a new persona
|
|
# for this OnyxBot config
|
|
existing_persona_id = None
|
|
else:
|
|
existing_persona_id = existing_slack_channel_config.persona_id
|
|
|
|
persona_id = create_slack_channel_persona(
|
|
db_session=db_session,
|
|
channel_name=channel_config["channel_name"],
|
|
document_set_ids=slack_channel_config_creation_request.document_sets,
|
|
existing_persona_id=existing_persona_id,
|
|
enable_auto_filters=slack_channel_config_creation_request.enable_auto_filters,
|
|
).id
|
|
|
|
slack_channel_config_model = update_slack_channel_config(
|
|
db_session=db_session,
|
|
slack_channel_config_id=slack_channel_config_id,
|
|
persona_id=persona_id,
|
|
channel_config=channel_config,
|
|
standard_answer_category_ids=slack_channel_config_creation_request.standard_answer_categories,
|
|
enable_auto_filters=slack_channel_config_creation_request.enable_auto_filters,
|
|
)
|
|
return SlackChannelConfig.from_model(slack_channel_config_model)
|
|
|
|
|
|
@router.delete("/admin/slack-app/channel/{slack_channel_config_id}")
|
|
def delete_slack_channel_config(
|
|
slack_channel_config_id: int,
|
|
db_session: Session = Depends(get_session),
|
|
user: User | None = Depends(current_admin_user),
|
|
) -> None:
|
|
remove_slack_channel_config(
|
|
db_session=db_session,
|
|
slack_channel_config_id=slack_channel_config_id,
|
|
user=user,
|
|
)
|
|
|
|
|
|
@router.get("/admin/slack-app/channel")
|
|
def list_slack_channel_configs(
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> list[SlackChannelConfig]:
|
|
slack_channel_config_models = fetch_slack_channel_configs(db_session=db_session)
|
|
return [
|
|
SlackChannelConfig.from_model(slack_channel_config_model)
|
|
for slack_channel_config_model in slack_channel_config_models
|
|
]
|
|
|
|
|
|
@router.post("/admin/slack-app/bots")
|
|
def create_bot(
|
|
slack_bot_creation_request: SlackBotCreationRequest,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
tenant_id: str | None = Depends(get_current_tenant_id),
|
|
) -> SlackBot:
|
|
validate_app_token(slack_bot_creation_request.app_token)
|
|
validate_bot_token(slack_bot_creation_request.bot_token)
|
|
|
|
slack_bot_model = insert_slack_bot(
|
|
db_session=db_session,
|
|
name=slack_bot_creation_request.name,
|
|
enabled=slack_bot_creation_request.enabled,
|
|
bot_token=slack_bot_creation_request.bot_token,
|
|
app_token=slack_bot_creation_request.app_token,
|
|
)
|
|
|
|
create_milestone_and_report(
|
|
user=None,
|
|
distinct_id=tenant_id or "N/A",
|
|
event_type=MilestoneRecordType.CREATED_ONYX_BOT,
|
|
properties=None,
|
|
db_session=db_session,
|
|
)
|
|
|
|
return SlackBot.from_model(slack_bot_model)
|
|
|
|
|
|
@router.patch("/admin/slack-app/bots/{slack_bot_id}")
|
|
def patch_bot(
|
|
slack_bot_id: int,
|
|
slack_bot_creation_request: SlackBotCreationRequest,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> SlackBot:
|
|
validate_bot_token(slack_bot_creation_request.bot_token)
|
|
validate_app_token(slack_bot_creation_request.app_token)
|
|
slack_bot_model = update_slack_bot(
|
|
db_session=db_session,
|
|
slack_bot_id=slack_bot_id,
|
|
name=slack_bot_creation_request.name,
|
|
enabled=slack_bot_creation_request.enabled,
|
|
bot_token=slack_bot_creation_request.bot_token,
|
|
app_token=slack_bot_creation_request.app_token,
|
|
)
|
|
return SlackBot.from_model(slack_bot_model)
|
|
|
|
|
|
@router.delete("/admin/slack-app/bots/{slack_bot_id}")
|
|
def delete_bot(
|
|
slack_bot_id: int,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> None:
|
|
remove_slack_bot(
|
|
db_session=db_session,
|
|
slack_bot_id=slack_bot_id,
|
|
)
|
|
|
|
|
|
@router.get("/admin/slack-app/bots/{slack_bot_id}")
|
|
def get_bot_by_id(
|
|
slack_bot_id: int,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> SlackBot:
|
|
slack_bot_model = fetch_slack_bot(
|
|
db_session=db_session,
|
|
slack_bot_id=slack_bot_id,
|
|
)
|
|
return SlackBot.from_model(slack_bot_model)
|
|
|
|
|
|
@router.get("/admin/slack-app/bots")
|
|
def list_bots(
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> list[SlackBot]:
|
|
slack_bot_models = fetch_slack_bots(db_session=db_session)
|
|
return [
|
|
SlackBot.from_model(slack_bot_model) for slack_bot_model in slack_bot_models
|
|
]
|
|
|
|
|
|
@router.get("/admin/slack-app/bots/{bot_id}/config")
|
|
def list_bot_configs(
|
|
bot_id: int,
|
|
db_session: Session = Depends(get_session),
|
|
_: User | None = Depends(current_admin_user),
|
|
) -> list[SlackChannelConfig]:
|
|
slack_bot_config_models = fetch_slack_channel_configs(
|
|
db_session=db_session, slack_bot_id=bot_id
|
|
)
|
|
return [
|
|
SlackChannelConfig.from_model(slack_bot_config_model)
|
|
for slack_bot_config_model in slack_bot_config_models
|
|
]
|