mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-02 19:55:18 +02:00
feat(gateway): add Slack and Telegram gateway configuration and enablement checks
This commit is contained in:
parent
fc2467be3d
commit
799a83239f
6 changed files with 168 additions and 62 deletions
|
|
@ -17,7 +17,7 @@ REDIS_APP_URL=redis://localhost:6379/0
|
|||
|
||||
# Telegram Gateway
|
||||
# TELEGRAM_WEBHOOK_SECRET must be 1-256 chars and contain only A-Z, a-z, 0-9, _ or -
|
||||
# GATEWAY_TELEGRAM_INTAKE_MODE: webhook for production, longpoll for single-replica self-host fallback, disabled to skip Telegram intake
|
||||
# GATEWAY_TELEGRAM_INTAKE_MODE: `webhook` for production, `longpoll` for single-replica self-host fallback, `disabled` to skip Telegram intake
|
||||
TELEGRAM_SHARED_BOT_TOKEN=
|
||||
TELEGRAM_SHARED_BOT_USERNAME=
|
||||
TELEGRAM_WEBHOOK_SECRET=
|
||||
|
|
@ -25,7 +25,7 @@ GATEWAY_BASE_URL=http://localhost:8000
|
|||
GATEWAY_TELEGRAM_INTAKE_MODE=webhook
|
||||
|
||||
# WhatsApp Gateway
|
||||
# GATEWAY_WHATSAPP_INTAKE_MODE: cloud for Meta Cloud API, baileys for self-hosted bridge, disabled to skip WhatsApp intake
|
||||
# GATEWAY_WHATSAPP_INTAKE_MODE: `cloud` for Meta Cloud API, `baileys` for self-hosted bridge, `disabled` to skip WhatsApp intake
|
||||
GATEWAY_WHATSAPP_INTAKE_MODE=disabled
|
||||
WHATSAPP_SHARED_BUSINESS_TOKEN=
|
||||
WHATSAPP_SHARED_PHONE_NUMBER_ID=
|
||||
|
|
@ -149,6 +149,7 @@ NOTION_REDIRECT_URI=http://localhost:8000/api/v1/auth/notion/connector/callback
|
|||
SLACK_CLIENT_ID=your_slack_client_id_here
|
||||
SLACK_CLIENT_SECRET=your_slack_client_secret_here
|
||||
SLACK_REDIRECT_URI=http://localhost:8000/api/v1/auth/slack/connector/callback
|
||||
GATEWAY_SLACK_ENABLED=FALSE
|
||||
GATEWAY_SLACK_SIGNING_SECRET=your_slack_signing_secret_here
|
||||
GATEWAY_SLACK_REDIRECT_URI=http://localhost:8000/api/v1/gateway/slack/callback
|
||||
|
||||
|
|
|
|||
|
|
@ -572,6 +572,7 @@ class Config:
|
|||
)
|
||||
GATEWAY_SLACK_CLIENT_ID = os.getenv("SLACK_CLIENT_ID")
|
||||
GATEWAY_SLACK_CLIENT_SECRET = os.getenv("SLACK_CLIENT_SECRET")
|
||||
GATEWAY_SLACK_ENABLED = os.getenv("GATEWAY_SLACK_ENABLED", "FALSE").upper() == "TRUE"
|
||||
GATEWAY_SLACK_SIGNING_SECRET = os.getenv("GATEWAY_SLACK_SIGNING_SECRET")
|
||||
GATEWAY_SLACK_REDIRECT_URI = os.getenv("GATEWAY_SLACK_REDIRECT_URI")
|
||||
GATEWAY_DISCORD_ENABLED = (
|
||||
|
|
|
|||
|
|
@ -188,6 +188,36 @@ def _is_inactive_whatsapp_account(account: ExternalChatAccount) -> bool:
|
|||
)
|
||||
|
||||
|
||||
def _telegram_gateway_enabled() -> bool:
|
||||
return (
|
||||
config.GATEWAY_TELEGRAM_INTAKE_MODE != "disabled"
|
||||
and bool(config.TELEGRAM_SHARED_BOT_TOKEN)
|
||||
and bool(config.TELEGRAM_SHARED_BOT_USERNAME)
|
||||
and (
|
||||
config.GATEWAY_TELEGRAM_INTAKE_MODE != "webhook"
|
||||
or bool(config.TELEGRAM_WEBHOOK_SECRET)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _slack_gateway_enabled() -> bool:
|
||||
return bool(
|
||||
config.GATEWAY_SLACK_ENABLED
|
||||
and config.GATEWAY_SLACK_CLIENT_ID
|
||||
and config.GATEWAY_SLACK_CLIENT_SECRET
|
||||
and config.GATEWAY_SLACK_SIGNING_SECRET
|
||||
)
|
||||
|
||||
|
||||
def _discord_gateway_enabled() -> bool:
|
||||
return bool(
|
||||
config.GATEWAY_DISCORD_ENABLED
|
||||
and config.DISCORD_CLIENT_ID
|
||||
and config.DISCORD_CLIENT_SECRET
|
||||
and config.DISCORD_BOT_TOKEN
|
||||
)
|
||||
|
||||
|
||||
def _classify_telegram_event(payload: dict[str, Any]) -> str:
|
||||
if "message" in payload:
|
||||
return "message"
|
||||
|
|
@ -208,7 +238,7 @@ async def install_slack_gateway(
|
|||
user: User = Depends(current_active_user),
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
) -> dict[str, str]:
|
||||
if not config.GATEWAY_SLACK_CLIENT_ID:
|
||||
if not _slack_gateway_enabled():
|
||||
raise HTTPException(status_code=500, detail="Slack gateway OAuth is not configured")
|
||||
await check_search_space_access(session, user, search_space_id)
|
||||
state = _get_state_manager().generate_secure_state(search_space_id, user.id)
|
||||
|
|
@ -242,7 +272,7 @@ async def slack_gateway_callback(
|
|||
return _slack_frontend_redirect(space_id or 0, error="slack_gateway_oauth_denied")
|
||||
if not code or state_data is None:
|
||||
raise HTTPException(status_code=400, detail="Invalid Slack gateway OAuth callback")
|
||||
if not config.GATEWAY_SLACK_CLIENT_ID or not config.GATEWAY_SLACK_CLIENT_SECRET:
|
||||
if not _slack_gateway_enabled():
|
||||
raise HTTPException(status_code=500, detail="Slack gateway OAuth is not configured")
|
||||
|
||||
user_id = UUID(state_data["user_id"])
|
||||
|
|
@ -357,7 +387,7 @@ async def install_discord_gateway(
|
|||
user: User = Depends(current_active_user),
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
) -> dict[str, str]:
|
||||
if not config.DISCORD_CLIENT_ID:
|
||||
if not _discord_gateway_enabled():
|
||||
raise HTTPException(status_code=500, detail="Discord gateway OAuth is not configured")
|
||||
await check_search_space_access(session, user, search_space_id)
|
||||
state = _get_state_manager().generate_secure_state(search_space_id, user.id)
|
||||
|
|
@ -393,10 +423,8 @@ async def discord_gateway_callback(
|
|||
return _discord_frontend_redirect(space_id or 0, error="discord_gateway_oauth_denied")
|
||||
if not code or state_data is None:
|
||||
raise HTTPException(status_code=400, detail="Invalid Discord gateway OAuth callback")
|
||||
if not config.DISCORD_CLIENT_ID or not config.DISCORD_CLIENT_SECRET:
|
||||
if not _discord_gateway_enabled():
|
||||
raise HTTPException(status_code=500, detail="Discord gateway OAuth is not configured")
|
||||
if not config.DISCORD_BOT_TOKEN:
|
||||
raise HTTPException(status_code=500, detail="Discord gateway bot token is not configured")
|
||||
|
||||
user_id = UUID(state_data["user_id"])
|
||||
token_payload = {
|
||||
|
|
@ -518,6 +546,9 @@ async def slack_webhook(
|
|||
request: Request,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
) -> Response:
|
||||
if not _slack_gateway_enabled():
|
||||
return Response(status_code=200)
|
||||
|
||||
body = await request.body()
|
||||
if not verify_slack_signature(
|
||||
signing_secret=config.GATEWAY_SLACK_SIGNING_SECRET or "",
|
||||
|
|
@ -594,6 +625,9 @@ async def telegram_webhook(
|
|||
account_id: int,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
) -> Response:
|
||||
if not _telegram_gateway_enabled():
|
||||
return Response(status_code=200)
|
||||
|
||||
request_id = f"gateway_{uuid.uuid4().hex[:16]}"
|
||||
try:
|
||||
payload = await request.json()
|
||||
|
|
@ -644,6 +678,8 @@ async def start_binding(
|
|||
await check_search_space_access(session, user, body.search_space_id)
|
||||
code = generate_pairing_code()
|
||||
if body.platform == ExternalChatPlatform.TELEGRAM:
|
||||
if not _telegram_gateway_enabled():
|
||||
raise HTTPException(status_code=400, detail="Telegram gateway is disabled")
|
||||
account = await get_or_create_system_telegram_account(session)
|
||||
username = account.bot_username or config.TELEGRAM_SHARED_BOT_USERNAME
|
||||
if not username:
|
||||
|
|
@ -730,6 +766,8 @@ async def list_connections(
|
|||
active_whatsapp_mode = _active_whatsapp_account_mode()
|
||||
if platform == ExternalChatPlatform.WHATSAPP and active_whatsapp_mode is None:
|
||||
return []
|
||||
if platform == ExternalChatPlatform.TELEGRAM and not _telegram_gateway_enabled():
|
||||
return []
|
||||
|
||||
filters = [
|
||||
ExternalChatBinding.user_id == user.id,
|
||||
|
|
@ -741,15 +779,18 @@ async def list_connections(
|
|||
filters.append(ExternalChatAccount.platform == platform)
|
||||
if platform == ExternalChatPlatform.WHATSAPP and active_whatsapp_mode is not None:
|
||||
filters.append(ExternalChatAccount.mode == active_whatsapp_mode)
|
||||
elif active_whatsapp_mode is None:
|
||||
filters.append(ExternalChatAccount.platform != ExternalChatPlatform.WHATSAPP)
|
||||
else:
|
||||
filters.append(
|
||||
or_(
|
||||
ExternalChatAccount.platform != ExternalChatPlatform.WHATSAPP,
|
||||
ExternalChatAccount.mode == active_whatsapp_mode,
|
||||
if not _telegram_gateway_enabled():
|
||||
filters.append(ExternalChatAccount.platform != ExternalChatPlatform.TELEGRAM)
|
||||
if active_whatsapp_mode is None:
|
||||
filters.append(ExternalChatAccount.platform != ExternalChatPlatform.WHATSAPP)
|
||||
else:
|
||||
filters.append(
|
||||
or_(
|
||||
ExternalChatAccount.platform != ExternalChatPlatform.WHATSAPP,
|
||||
ExternalChatAccount.mode == active_whatsapp_mode,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
result = await session.execute(
|
||||
select(ExternalChatBinding, ExternalChatAccount)
|
||||
|
|
@ -873,6 +914,18 @@ async def list_platforms(
|
|||
]
|
||||
|
||||
|
||||
@router.get("/config")
|
||||
async def get_gateway_config(
|
||||
user: User = Depends(current_active_user),
|
||||
) -> dict[str, bool | str]:
|
||||
return {
|
||||
"telegram_enabled": _telegram_gateway_enabled(),
|
||||
"whatsapp_intake_mode": config.GATEWAY_WHATSAPP_INTAKE_MODE,
|
||||
"slack_enabled": _slack_gateway_enabled(),
|
||||
"discord_enabled": _discord_gateway_enabled(),
|
||||
}
|
||||
|
||||
|
||||
@router.patch("/bindings/{binding_id}/search-space")
|
||||
async def update_binding_search_space(
|
||||
binding_id: int,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue