Skip to content

Commit

Permalink
Fix context.team_id for view interactions in a Slack Connect channel (#…
Browse files Browse the repository at this point in the history
…1615)

* Added app_installed_team_id handling
  • Loading branch information
WilliamBergamin authored Oct 5, 2022
1 parent be8a041 commit 6c0de60
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 15 deletions.
58 changes: 57 additions & 1 deletion src/App-basic-features.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1150,13 +1150,69 @@ describe('App basic features', () => {
];

// Act
await Promise.all(receiverEvents.map((event) => fakeReceiver.sendEvent(event)));
await Promise.all(
receiverEvents.map((event) => fakeReceiver.sendEvent(event)),
);

// Assert
assert.isTrue(fakeLogger.info.called);
assert.isTrue(ackInMiddlewareCalled);
});
});

describe('context', () => {
it('should be able to use the app_installed_team_id when provided by the payload', async () => {
// Arrange
const fakeAxiosPost = sinon.fake.resolves({});
overrides = buildOverrides([
withNoopWebClient(),
withAxiosPost(fakeAxiosPost),
]);
const MockApp = await importApp(overrides);

// Act
const app = new MockApp({
receiver: fakeReceiver,
authorize: sinon.fake.resolves(dummyAuthorizationResult),
});

app.view('view-id', async ({ ack, context, view }) => {
assert.equal('T-installed-workspace', context.teamId);
assert.notEqual('T-installed-workspace', view.team_id);
await ack();
});
app.error(fakeErrorHandler);

let ackCalled = false;

const receiverEvent = {
ack: async () => {
ackCalled = true;
},
body: {
type: 'view_submission',
team: {},
user: {},
view: {
id: 'V111',
type: 'modal',
callback_id: 'view-id',
state: {},
title: {},
close: {},
submit: {},
app_installed_team_id: 'T-installed-workspace',
},
},
};

// Act
await fakeReceiver.sendEvent(receiverEvent);

// Assert
assert.isTrue(ackCalled);
});
});
});
});

Expand Down
45 changes: 31 additions & 14 deletions src/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1368,29 +1368,46 @@ function buildSource<IsEnterpriseInstall extends boolean>(
return (body as SlackCommandMiddlewareArgs['body']).team_id;
}

const parseTeamId = (
bodyAs:
| SlackAction
| SlackViewAction
| SlackShortcut
| KnownOptionsPayloadFromType<OptionsSource>,
): string | undefined => {
// When the app is installed using org-wide deployment, team property will be null
if (typeof bodyAs.team !== 'undefined' && bodyAs.team !== null) {
return bodyAs.team.id;
}

// This is the only place where this function might return undefined
return bodyAs.user.team_id;
};

if (type === IncomingEventType.ViewAction) {
// view_submission/closed payloads can have `view.app_installed_team_id` when a modal view that was opened
// in a different workspace via some operations inside a Slack Connect channel.

const bodyAsView = body as SlackViewMiddlewareArgs['body'];

if (bodyAsView.view.app_installed_team_id) {
return bodyAsView.view.app_installed_team_id;
}

return parseTeamId(bodyAsView);
}

if (
type === IncomingEventType.Action ||
type === IncomingEventType.Options ||
type === IncomingEventType.ViewAction ||
type === IncomingEventType.Shortcut
) {
const bodyAsActionOrOptionsOrViewActionOrShortcut = body as (
const bodyAsActionOrOptionsOrShortcut = body as (
| SlackActionMiddlewareArgs
| SlackOptionsMiddlewareArgs
| SlackViewMiddlewareArgs
| SlackShortcutMiddlewareArgs
)['body'];

// When the app is installed using org-wide deployment, team property will be null
if (
typeof bodyAsActionOrOptionsOrViewActionOrShortcut.team !== 'undefined' &&
bodyAsActionOrOptionsOrViewActionOrShortcut.team !== null
) {
return bodyAsActionOrOptionsOrViewActionOrShortcut.team.id;
}

// This is the only place where this function might return undefined
return bodyAsActionOrOptionsOrViewActionOrShortcut.user.team_id;
return parseTeamId(bodyAsActionOrOptionsOrShortcut);
}

return assertNever(type);
Expand Down

0 comments on commit 6c0de60

Please sign in to comment.