diff --git a/src/App.spec.ts b/src/App.spec.ts index e7cf7c31a..708afd7a7 100644 --- a/src/App.spec.ts +++ b/src/App.spec.ts @@ -659,6 +659,62 @@ describe('App', () => { return overrides; } + describe('authorize', () => { + it('should extract valid enterprise_id in a shared channel #935', async () => { + // Arrange + const fakeAxiosPost = sinon.fake.resolves({}); + const overrides = buildOverrides([withNoopWebClient(), withAxiosPost(fakeAxiosPost)]); + const App = await importApp(overrides); // eslint-disable-line @typescript-eslint/naming-convention, no-underscore-dangle, id-blacklist, id-match + + // Act + let workedAsExpected = false; + const app = new App({ + receiver: fakeReceiver, + authorize: async ({ enterpriseId }) => { + if (enterpriseId !== undefined) { + throw new Error('the enterprise_id must be undefined in this scenario'); + } + return dummyAuthorizationResult; + }, + }); + app.event('message', async () => { + workedAsExpected = true; + }); + await fakeReceiver.sendEvent({ + ack: noop, + body: { + team_id: 'T_connected_grid_workspace', + enterprise_id: 'E_org_id', + api_app_id: 'A111', + event: { + type: 'message', + text: ':wave: Hi, this is my first message in a Slack Connect channel!', + user: 'U111', + ts: '1622099033.001500', + team: 'T_this_non_grid_workspace', + channel: 'C111', + channel_type: 'channel', + }, + type: 'event_callback', + authorizations: [ + { + enterprise_id: null, + team_id: 'T_this_non_grid_workspace', + user_id: 'U_authed_user', + is_bot: true, + is_enterprise_install: false, + }, + ], + is_ext_shared_channel: true, + event_context: '2-message-T_connected_grid_workspace-A111-C111', + }, + }); + + // Assert + assert.isTrue(workedAsExpected); + }); + }); + describe('routing', () => { function createReceiverEvents(): ReceiverEvent[] { return [ diff --git a/src/App.ts b/src/App.ts index 0574396f4..182bdef57 100644 --- a/src/App.ts +++ b/src/App.ts @@ -992,12 +992,10 @@ function buildSource( const enterpriseId: string | undefined = (() => { if (type === IncomingEventType.Event) { const bodyAsEvent = body as SlackEventMiddlewareArgs['body']; - if ( - Array.isArray(bodyAsEvent.authorizations) && - bodyAsEvent.authorizations[0] !== undefined && - bodyAsEvent.authorizations[0].enterprise_id !== null - ) { - return bodyAsEvent.authorizations[0].enterprise_id; + if (Array.isArray(bodyAsEvent.authorizations) && bodyAsEvent.authorizations[0] !== undefined) { + // The enteprise_id here can be null when the workspace is not in an Enterprise Grid + const theId = bodyAsEvent.authorizations[0].enterprise_id; + return theId !== null ? theId : undefined; } return bodyAsEvent.enterprise_id; } diff --git a/src/types/events/base-events.ts b/src/types/events/base-events.ts index 11d22498a..548f95415 100644 --- a/src/types/events/base-events.ts +++ b/src/types/events/base-events.ts @@ -648,10 +648,73 @@ export interface TokensRevokedEvent { export interface UserChangeEvent { type: 'user_change'; - // TODO: incomplete, this should probably be a reference to a User shape from @slack/types. - // https://api.slack.com/types/user user: { id: string; + team_id: string; + name: string; + deleted: boolean; + color: string; + real_name: string; + tz: string; + tz_label: string; + tz_offset: number; + profile: { + title: string; + phone: string; + skype: string; + real_name: string; + real_name_normalized: string; + display_name: string; + display_name_normalized: string; + status_text: string; + status_text_canonical: string; + status_emoji: string; + status_expiration: number; + avatar_hash: string; + first_name: string; + last_name: string; + email: string; + image_original?: string; + is_custom_image?: boolean; + image_24: string; + image_32: string; + image_48: string; + image_72: string; + image_192: string; + image_512: string; + image_1024?: string; + team: string; + fields: + | { + [key: string]: { + value: string; + alt: string; + }; + } + | [] + | null; + }; + is_admin: boolean; + is_owner: boolean; + is_primary_owner: boolean; + is_restricted: boolean; + is_ultra_restricted: boolean; + is_bot: boolean; + is_stranger?: boolean; + updated: string; + is_email_confirmed: boolean; + is_app_user: boolean; + is_invited_user?: boolean; + has_2fa?: boolean; + locale: string; + enterprise_user?: { + id: string; + enterprise_id: string; + enterprise_name: string; + is_admin: boolean; + is_owner: boolean; + teams: string[]; + }; }; }