Skip to content

Commit

Permalink
Don't allow external channels to use the GitBook bot (#292)
Browse files Browse the repository at this point in the history
* don't respond to requests in external channels

* don't allow external channels in app mentions or messages

* update comment

* extract to function
  • Loading branch information
scazan authored Nov 13, 2023
1 parent 69b00d6 commit 9b4ad3a
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 14 deletions.
9 changes: 6 additions & 3 deletions integrations/slack/src/handlers/events.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FetchEventCallback } from '@gitbook/runtime';

import { SlackRuntimeContext } from '../configuration';
import { parseEventPayload } from '../utils';
import { isAllowedToRespond, parseEventPayload } from '../utils';

/**
* Handle an event from Slack.
Expand All @@ -16,7 +16,7 @@ export function createSlackEventsHandler(
const eventPayload = await parseEventPayload(request);

// url_verification doesn't have an event object
const { type, bot_id } = eventPayload.event ?? eventPayload;
const { type } = eventPayload.event ?? eventPayload;

const handler = handlers[type];

Expand All @@ -32,7 +32,10 @@ export function createSlackEventsHandler(
}

// check for bot_id so that the bot doesn't trigger itself
if (bot_id) {
// check whether this was triggered from an external channel

// if (bot_id || isExternalChannel) {
if (!isAllowedToRespond(eventPayload)) {
return new Response(null, {
status: 200,
});
Expand Down
16 changes: 8 additions & 8 deletions integrations/slack/src/handlers/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Logger } from '@gitbook/runtime';

import type { SlashEvent } from './commands';
import { notifyOnlySupportedThreads, queryLens, saveThread } from '../actions';
import { SlackRuntimeContext } from '../configuration';
import { isSaveThreadMessage, stripBotName } from '../utils';
import type { SlashEvent } from './commands';
import { isAllowedToRespond, isSaveThreadMessage, stripBotName } from '../utils';

const logger = Logger('slack:api');

Expand Down Expand Up @@ -38,11 +38,11 @@ export async function queryLensSlashHandler(slashEvent: SlashEvent, context: Sla
* Handle an Event request and route it to the GitBook Lens' query function.
*/
export async function messageEventHandler(eventPayload: any, context: SlackRuntimeContext) {
// pull out required params from the slashEvent for queryLens
const { type, text, bot_id, thread_ts, channel, user, team } = eventPayload.event;
// pull out required params from the event for queryLens
const { type, text, thread_ts, channel, user, team } = eventPayload.event;

// check for bot_id so that the bot doesn't trigger itself
if (['message', 'app_mention'].includes(type) && !bot_id) {
if (['message', 'app_mention'].includes(type) && isAllowedToRespond(eventPayload)) {
// strip out the bot-name in the mention and account for user mentions within the query
// @ts-ignore
const parsedQuery = stripBotName(text, eventPayload.authorizations[0]?.user_id);
Expand Down Expand Up @@ -72,10 +72,10 @@ export async function messageEventHandler(eventPayload: any, context: SlackRunti
*/
export async function appMentionEventHandler(eventPayload: any, context: SlackRuntimeContext) {
// pull out required params from the slashEvent for queryLens
const { type, text, bot_id, thread_ts, channel, user, team } = eventPayload.event;
const { type, text, thread_ts, channel, user, team } = eventPayload.event;

// check for bot_id so that the bot doesn't trigger itself
if (['message', 'app_mention'].includes(type) && !bot_id) {
if (['message', 'app_mention'].includes(type) && isAllowedToRespond(eventPayload)) {
// strip out the bot-name in the mention and account for user mentions within the query
// @ts-ignore
const parsedMessage = stripBotName(text, eventPayload.authorizations[0]?.user_id);
Expand Down Expand Up @@ -111,4 +111,4 @@ export async function appMentionEventHandler(eventPayload: any, context: SlackRu
});
}
}
}
}
1 change: 1 addition & 0 deletions integrations/slack/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const handleFetchEvent: FetchEventCallback = async (request, context) =>
verifySlackRequest,
createSlackCommandsHandler({
'/gitbook': queryLensSlashHandler,
'/gitbookstaging': queryLensSlashHandler, // needed to allow our staging app to co-exist with the prod app
}),
acknowledgeSlackRequest
);
Expand Down
17 changes: 14 additions & 3 deletions integrations/slack/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,12 @@ export async function getInstallationConfig(context, externalId) {

export async function parseEventPayload(req: Request) {
// Clone the request so its body is still available to the fallback
const event = await req
.clone()
.json<{ event?: { type: string; [key: string]: any }; type?: string }>(); // TODO: untyping this for now
const event = await req.clone().json<{
event?: { type: string; [key: string]: any };
type?: string;
bot_id?: string;
is_ext_shared_channel?: boolean;
}>(); // TODO: untyping this for now

return event;
}
Expand Down Expand Up @@ -119,3 +122,11 @@ export function isSaveThreadMessage(message: string) {

return false;
}

// Checks whether we should respond to a slack event
export function isAllowedToRespond(eventPayload: any) {
const { bot_id } = eventPayload.event;
const isExternalChannel = eventPayload.is_ext_shared_channel;

return !bot_id && !isExternalChannel;
}

0 comments on commit 9b4ad3a

Please sign in to comment.