Skip to content

Commit 9b4ad3a

Browse files
authored
Don't allow external channels to use the GitBook bot (#292)
* don't respond to requests in external channels * don't allow external channels in app mentions or messages * update comment * extract to function
1 parent 69b00d6 commit 9b4ad3a

File tree

4 files changed

+29
-14
lines changed

4 files changed

+29
-14
lines changed

integrations/slack/src/handlers/events.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { FetchEventCallback } from '@gitbook/runtime';
22

33
import { SlackRuntimeContext } from '../configuration';
4-
import { parseEventPayload } from '../utils';
4+
import { isAllowedToRespond, parseEventPayload } from '../utils';
55

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

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

2121
const handler = handlers[type];
2222

@@ -32,7 +32,10 @@ export function createSlackEventsHandler(
3232
}
3333

3434
// check for bot_id so that the bot doesn't trigger itself
35-
if (bot_id) {
35+
// check whether this was triggered from an external channel
36+
37+
// if (bot_id || isExternalChannel) {
38+
if (!isAllowedToRespond(eventPayload)) {
3639
return new Response(null, {
3740
status: 200,
3841
});

integrations/slack/src/handlers/handlers.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Logger } from '@gitbook/runtime';
22

3+
import type { SlashEvent } from './commands';
34
import { notifyOnlySupportedThreads, queryLens, saveThread } from '../actions';
45
import { SlackRuntimeContext } from '../configuration';
5-
import { isSaveThreadMessage, stripBotName } from '../utils';
6-
import type { SlashEvent } from './commands';
6+
import { isAllowedToRespond, isSaveThreadMessage, stripBotName } from '../utils';
77

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

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

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

7777
// check for bot_id so that the bot doesn't trigger itself
78-
if (['message', 'app_mention'].includes(type) && !bot_id) {
78+
if (['message', 'app_mention'].includes(type) && isAllowedToRespond(eventPayload)) {
7979
// strip out the bot-name in the mention and account for user mentions within the query
8080
// @ts-ignore
8181
const parsedMessage = stripBotName(text, eventPayload.authorizations[0]?.user_id);
@@ -111,4 +111,4 @@ export async function appMentionEventHandler(eventPayload: any, context: SlackRu
111111
});
112112
}
113113
}
114-
}
114+
}

integrations/slack/src/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export const handleFetchEvent: FetchEventCallback = async (request, context) =>
112112
verifySlackRequest,
113113
createSlackCommandsHandler({
114114
'/gitbook': queryLensSlashHandler,
115+
'/gitbookstaging': queryLensSlashHandler, // needed to allow our staging app to co-exist with the prod app
115116
}),
116117
acknowledgeSlackRequest
117118
);

integrations/slack/src/utils.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,12 @@ export async function getInstallationConfig(context, externalId) {
6767

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

7477
return event;
7578
}
@@ -119,3 +122,11 @@ export function isSaveThreadMessage(message: string) {
119122

120123
return false;
121124
}
125+
126+
// Checks whether we should respond to a slack event
127+
export function isAllowedToRespond(eventPayload: any) {
128+
const { bot_id } = eventPayload.event;
129+
const isExternalChannel = eventPayload.is_ext_shared_channel;
130+
131+
return !bot_id && !isExternalChannel;
132+
}

0 commit comments

Comments
 (0)