Skip to content

Commit ebfa19e

Browse files
port: save conversation state before sending card (#3635) (#3640)
Fixes #3634 Co-authored-by: Steven Gum <14935595+stevengum@users.noreply.github.com> Co-authored-by: Steven Gum <14935595+stevengum@users.noreply.github.com>
1 parent 4199f06 commit ebfa19e

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

libraries/botbuilder-dialogs-adaptive/src/input/oauthInput.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@
55
* Copyright (c) Microsoft Corporation. All rights reserved.
66
* Licensed under the MIT License.
77
*/
8+
import { InputDialog, InputDialogConfiguration, InputState } from './inputDialog';
9+
import { TextTemplate } from '../templates';
10+
11+
import {
12+
ConversationState,
13+
tokenExchangeOperationName,
14+
tokenResponseEventName,
15+
verifyStateOperationName,
16+
} from 'botbuilder';
17+
818
import {
919
Expression,
1020
IntExpression,
1121
IntExpressionConverter,
1222
StringExpression,
1323
StringExpressionConverter,
1424
} from 'adaptive-expressions';
25+
1526
import {
1627
Activity,
1728
ActivityTypes,
@@ -23,6 +34,7 @@ import {
2334
TokenResponse,
2435
TurnContext,
2536
} from 'botbuilder';
37+
2638
import {
2739
Converter,
2840
ConverterFactory,
@@ -37,9 +49,6 @@ import {
3749
ThisPath,
3850
TurnPath,
3951
} from 'botbuilder-dialogs';
40-
import { verifyStateOperationName, tokenExchangeOperationName, tokenResponseEventName } from 'botbuilder';
41-
import { InputDialog, InputDialogConfiguration, InputState } from './inputDialog';
42-
import { TextTemplate } from '../templates';
4352

4453
export const channels: any = {
4554
console: 'console',
@@ -326,9 +335,6 @@ export class OAuthInput extends InputDialog implements OAuthInputConfiguration {
326335
return adapter.signOutUser(dc.context, this.connectionName.getValue(dc.state));
327336
}
328337

329-
/**
330-
* @protected
331-
*/
332338
protected onComputeId(): string {
333339
return `OAuthInput[${this.prompt && this.prompt.toString()}]`;
334340
}
@@ -343,27 +349,41 @@ export class OAuthInput extends InputDialog implements OAuthInputConfiguration {
343349
throw new Error('Method not implemented.');
344350
}
345351

346-
/**
347-
* @private
348-
*/
349352
private async sendOAuthCard(dc: DialogContext, prompt?: string | Partial<Activity>): Promise<void> {
350-
let title: string =
353+
// Save state prior to sending OAuthCard: the invoke response for a token exchange from the root bot could come
354+
// in before this method ends or could land in another instance in scale-out scenarios, which means that if the
355+
// state is not saved, the OAuthInput would not be at the top of the stack, and the token exchange invoke would
356+
// get discarded.
357+
const conversationState = dc.context.turnState.get<ConversationState>('ConversationState');
358+
if (conversationState) {
359+
await conversationState.saveChanges(dc.context, false);
360+
}
361+
362+
// Prepare oauth card
363+
let title =
351364
(await new TextTemplate<DialogStateManager>(this.title.expressionText).bind(dc, dc.state)) ??
352365
this.title.getValue(dc.state);
366+
353367
if (title?.startsWith('=')) {
354368
title = Expression.parse(title).tryEvaluate(dc.state)?.value;
355369
}
356-
let text: string =
370+
371+
let text =
357372
(await new TextTemplate<DialogStateManager>(this.text.expressionText).bind(dc, dc.state)) ??
358373
this.text.getValue(dc.state);
374+
359375
if (text?.startsWith('=')) {
360376
text = Expression.parse(text).tryEvaluate(dc.state)?.value;
361377
}
378+
362379
const settings: OAuthPromptSettings = {
363380
connectionName: this.connectionName?.getValue(dc.state),
364381
title,
365382
text,
366383
};
384+
385+
// Send OAuthCard to root bot. The root bot could attempt to do a token exchange or if it cannot do token
386+
// exchange for this connection it will let the card get to the user to allow them to sign in.
367387
return OAuthPrompt.sendOAuthCard(settings, dc.context, prompt);
368388
}
369389

0 commit comments

Comments
 (0)