@microsoft/teamsfx 1.1.2-alpha.7eddd6cf4.0 → 1.1.2-alpha.9bd0cb559.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,13 +3,14 @@ import { ConfidentialClientApplication } from '@azure/msal-node';
3
3
  import { createHash } from 'crypto';
4
4
  import { Client } from '@microsoft/microsoft-graph-client';
5
5
  import { ManagedIdentityCredential } from '@azure/identity';
6
- import { ActivityTypes, Channels, TeamsInfo, CardFactory, ActionTypes, MessageFactory, StatusCodes, verifyStateOperationName, tokenExchangeOperationName, TurnContext, BotFrameworkAdapter } from 'botbuilder';
7
- import { Dialog } from 'botbuilder-dialogs';
6
+ import { ActivityTypes, Channels, TeamsInfo, CardFactory, ActionTypes, MessageFactory, StatusCodes, verifyStateOperationName, tokenExchangeOperationName, TurnContext, TeamsActivityHandler, MemoryStorage, UserState, ConversationState, BotFrameworkAdapter } from 'botbuilder';
7
+ import { Dialog, ComponentDialog, WaterfallDialog, DialogSet, DialogTurnStatus } from 'botbuilder-dialogs';
8
8
  import { v4 } from 'uuid';
9
9
  import axios from 'axios';
10
10
  import { Agent } from 'https';
11
11
  import * as path from 'path';
12
12
  import * as fs from 'fs';
13
+ import { __rest } from 'tslib';
13
14
  import { AdaptiveCards } from '@microsoft/adaptivecards-tools';
14
15
 
15
16
  // Copyright (c) Microsoft Corporation.
@@ -39,6 +40,30 @@ var ErrorCode;
39
40
  * Channel is not supported error.
40
41
  */
41
42
  ErrorCode["ChannelNotSupported"] = "ChannelNotSupported";
43
+ /**
44
+ * Failed to retrieve sso token
45
+ */
46
+ ErrorCode["FailedToRetrieveSsoToken"] = "FailedToRetrieveSsoToken";
47
+ /**
48
+ * Failed to process sso handler
49
+ */
50
+ ErrorCode["FailedToProcessSsoHandler"] = "FailedToProcessSsoHandler";
51
+ /**
52
+ * Cannot find command
53
+ */
54
+ ErrorCode["CannotFindCommand"] = "CannotFindCommand";
55
+ /**
56
+ * Failed to run sso step
57
+ */
58
+ ErrorCode["FailedToRunSsoStep"] = "FailedToRunSsoStep";
59
+ /**
60
+ * Failed to run dedup step
61
+ */
62
+ ErrorCode["FailedToRunDedupStep"] = "FailedToRunDedupStep";
63
+ /**
64
+ * Sso activity handler is undefined
65
+ */
66
+ ErrorCode["SsoActivityHandlerIsUndefined"] = "SsoActivityHandlerIsUndefined";
42
67
  /**
43
68
  * Runtime is not supported error.
44
69
  */
@@ -94,6 +119,15 @@ ErrorMessage.NodejsRuntimeNotSupported = "{0} is not supported in Node.";
94
119
  ErrorMessage.FailToAcquireTokenOnBehalfOfUser = "Failed to acquire access token on behalf of user: {0}";
95
120
  // ChannelNotSupported Error
96
121
  ErrorMessage.OnlyMSTeamsChannelSupported = "{0} is only supported in MS Teams Channel";
122
+ ErrorMessage.FailedToProcessSsoHandler = "Failed to process sso handler: {0}";
123
+ // FailedToRetrieveSsoToken Error
124
+ ErrorMessage.FailedToRetrieveSsoToken = "Failed to retrieve sso token, user failed to finish the AAD consent flow.";
125
+ // CannotFindCommand Error
126
+ ErrorMessage.CannotFindCommand = "Cannot find command: {0}";
127
+ ErrorMessage.FailedToRunSsoStep = "Failed to run dialog to retrieve sso token: {0}";
128
+ ErrorMessage.FailedToRunDedupStep = "Failed to run dialog to remove duplicated messages: {0}";
129
+ // SsoActivityHandlerIsUndefined Error
130
+ ErrorMessage.SsoActivityHandlerIsNull = "Sso command can only be used or added when sso activity handler is not undefined";
97
131
  // IdentityTypeNotSupported Error
98
132
  ErrorMessage.IdentityTypeNotSupported = "{0} identity is not supported in {1}";
99
133
  // AuthorizationInfoError
@@ -2122,41 +2156,80 @@ class CardActionBot {
2122
2156
  * @internal
2123
2157
  */
2124
2158
  class CommandResponseMiddleware {
2125
- constructor(handlers) {
2159
+ constructor(handlers, ssoHandlers, activityHandler) {
2126
2160
  this.commandHandlers = [];
2127
- if (handlers && handlers.length > 0) {
2128
- this.commandHandlers.push(...handlers);
2161
+ this.ssoCommandHandlers = [];
2162
+ handlers = handlers !== null && handlers !== void 0 ? handlers : [];
2163
+ ssoHandlers = ssoHandlers !== null && ssoHandlers !== void 0 ? ssoHandlers : [];
2164
+ this.hasSsoCommand = ssoHandlers.length > 0;
2165
+ this.ssoActivityHandler = activityHandler;
2166
+ if (this.hasSsoCommand && !this.ssoActivityHandler) {
2167
+ internalLogger.error(ErrorMessage.SsoActivityHandlerIsNull);
2168
+ throw new ErrorWithCode(ErrorMessage.SsoActivityHandlerIsNull, ErrorCode.SsoActivityHandlerIsUndefined);
2169
+ }
2170
+ this.commandHandlers.push(...handlers);
2171
+ for (const ssoHandler of ssoHandlers) {
2172
+ this.addSsoCommand(ssoHandler);
2129
2173
  }
2130
2174
  }
2175
+ addSsoCommand(ssoHandler) {
2176
+ var _a;
2177
+ (_a = this.ssoActivityHandler) === null || _a === void 0 ? void 0 : _a.addCommand(async (context, tokenResponse, message) => {
2178
+ const matchResult = this.shouldTrigger(ssoHandler.triggerPatterns, message.text);
2179
+ message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2180
+ const response = await ssoHandler.handleCommandReceived(context, message, tokenResponse);
2181
+ await this.processResponse(context, response);
2182
+ }, ssoHandler.triggerPatterns);
2183
+ this.ssoCommandHandlers.push(ssoHandler);
2184
+ this.commandHandlers.push(ssoHandler);
2185
+ this.hasSsoCommand = true;
2186
+ }
2131
2187
  async onTurn(context, next) {
2188
+ var _a, _b;
2132
2189
  if (context.activity.type === ActivityTypes.Message) {
2133
2190
  // Invoke corresponding command handler for the command response
2134
2191
  const commandText = this.getActivityText(context.activity);
2135
- const message = {
2136
- text: commandText,
2137
- };
2138
2192
  for (const handler of this.commandHandlers) {
2139
2193
  const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
2140
2194
  // It is important to note that the command bot will stop processing handlers
2141
2195
  // when the first command handler is matched.
2142
2196
  if (!!matchResult) {
2143
- message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2144
- const response = await handler.handleCommandReceived(context, message);
2145
- if (typeof response === "string") {
2146
- await context.sendActivity(response);
2197
+ if (this.isSsoExecutionHandler(handler)) {
2198
+ await ((_a = this.ssoActivityHandler) === null || _a === void 0 ? void 0 : _a.run(context));
2147
2199
  }
2148
2200
  else {
2149
- const replyActivity = response;
2150
- if (replyActivity) {
2151
- await context.sendActivity(replyActivity);
2152
- }
2201
+ const message = {
2202
+ text: commandText,
2203
+ };
2204
+ message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2205
+ const response = await handler.handleCommandReceived(context, message);
2206
+ await this.processResponse(context, response);
2153
2207
  }
2154
2208
  break;
2155
2209
  }
2156
2210
  }
2157
2211
  }
2212
+ else {
2213
+ if (this.hasSsoCommand) {
2214
+ await ((_b = this.ssoActivityHandler) === null || _b === void 0 ? void 0 : _b.run(context));
2215
+ }
2216
+ }
2158
2217
  await next();
2159
2218
  }
2219
+ async processResponse(context, response) {
2220
+ if (typeof response === "string") {
2221
+ await context.sendActivity(response);
2222
+ }
2223
+ else {
2224
+ const replyActivity = response;
2225
+ if (replyActivity) {
2226
+ await context.sendActivity(replyActivity);
2227
+ }
2228
+ }
2229
+ }
2230
+ isSsoExecutionHandler(handler) {
2231
+ return this.ssoCommandHandlers.indexOf(handler) >= 0;
2232
+ }
2160
2233
  matchPattern(pattern, text) {
2161
2234
  if (text) {
2162
2235
  if (typeof pattern === "string") {
@@ -2206,14 +2279,15 @@ class CommandBot {
2206
2279
  * @param adapter The bound `BotFrameworkAdapter`.
2207
2280
  * @param options - initialize options
2208
2281
  */
2209
- constructor(adapter, options) {
2210
- this.middleware = new CommandResponseMiddleware(options === null || options === void 0 ? void 0 : options.commands);
2282
+ constructor(adapter, options, ssoCommandActivityHandler, ssoConfig) {
2283
+ this.ssoConfig = ssoConfig;
2284
+ this.middleware = new CommandResponseMiddleware(options === null || options === void 0 ? void 0 : options.commands, options === null || options === void 0 ? void 0 : options.ssoCommands, ssoCommandActivityHandler);
2211
2285
  this.adapter = adapter.use(this.middleware);
2212
2286
  }
2213
2287
  /**
2214
2288
  * Registers a command into the command bot.
2215
2289
  *
2216
- * @param command The command to registered.
2290
+ * @param command The command to register.
2217
2291
  */
2218
2292
  registerCommand(command) {
2219
2293
  if (command) {
@@ -2223,13 +2297,41 @@ class CommandBot {
2223
2297
  /**
2224
2298
  * Registers commands into the command bot.
2225
2299
  *
2226
- * @param commands The command to registered.
2300
+ * @param commands The commands to register.
2227
2301
  */
2228
2302
  registerCommands(commands) {
2229
2303
  if (commands) {
2230
2304
  this.middleware.commandHandlers.push(...commands);
2231
2305
  }
2232
2306
  }
2307
+ /**
2308
+ * Registers a sso command into the command bot.
2309
+ *
2310
+ * @param command The command to register.
2311
+ */
2312
+ registerSsoCommand(ssoCommand) {
2313
+ this.validateSsoActivityHandler();
2314
+ this.middleware.addSsoCommand(ssoCommand);
2315
+ }
2316
+ /**
2317
+ * Registers commands into the command bot.
2318
+ *
2319
+ * @param commands The commands to register.
2320
+ */
2321
+ registerSsoCommands(ssoCommands) {
2322
+ if (ssoCommands.length > 0) {
2323
+ this.validateSsoActivityHandler();
2324
+ for (const ssoCommand of ssoCommands) {
2325
+ this.middleware.addSsoCommand(ssoCommand);
2326
+ }
2327
+ }
2328
+ }
2329
+ validateSsoActivityHandler() {
2330
+ if (!this.middleware.ssoActivityHandler) {
2331
+ internalLogger.error(ErrorMessage.SsoActivityHandlerIsNull);
2332
+ throw new ErrorWithCode(ErrorMessage.SsoActivityHandlerIsNull, ErrorCode.SsoActivityHandlerIsUndefined);
2333
+ }
2334
+ }
2233
2335
  }
2234
2336
 
2235
2337
  // Copyright (c) Microsoft Corporation.
@@ -2797,6 +2899,345 @@ class NotificationBot {
2797
2899
  }
2798
2900
  }
2799
2901
 
2902
+ // Copyright (c) Microsoft Corporation.
2903
+ let DIALOG_NAME = "BotSsoExecutionDialog";
2904
+ let TEAMS_SSO_PROMPT_ID = "TeamsFxSsoPrompt";
2905
+ let COMMAND_ROUTE_DIALOG = "CommandRouteDialog";
2906
+ /**
2907
+ * Sso execution dialog, use to handle sso command
2908
+ */
2909
+ class BotSsoExecutionDialog extends ComponentDialog {
2910
+ /**
2911
+ * Creates a new instance of the BotSsoExecutionDialog.
2912
+ * @param dedupStorage Helper storage to remove duplicated messages
2913
+ * @param settings The list of scopes for which the token will have access
2914
+ * @param teamsfx {@link TeamsFx} instance for authentication
2915
+ */
2916
+ constructor(dedupStorage, ssoPromptSettings, teamsfx, dialogName) {
2917
+ super(dialogName !== null && dialogName !== void 0 ? dialogName : DIALOG_NAME);
2918
+ this.dedupStorageKeys = [];
2919
+ // Map to store the commandId and triggerPatterns, key: commandId, value: triggerPatterns
2920
+ this.commandMapping = new Map();
2921
+ if (dialogName) {
2922
+ DIALOG_NAME = dialogName;
2923
+ TEAMS_SSO_PROMPT_ID = dialogName + TEAMS_SSO_PROMPT_ID;
2924
+ COMMAND_ROUTE_DIALOG = dialogName + COMMAND_ROUTE_DIALOG;
2925
+ }
2926
+ this.initialDialogId = COMMAND_ROUTE_DIALOG;
2927
+ this.dedupStorage = dedupStorage;
2928
+ this.dedupStorageKeys = [];
2929
+ const ssoDialog = new TeamsBotSsoPrompt(teamsfx, TEAMS_SSO_PROMPT_ID, ssoPromptSettings);
2930
+ this.addDialog(ssoDialog);
2931
+ const commandRouteDialog = new WaterfallDialog(COMMAND_ROUTE_DIALOG, [
2932
+ this.commandRouteStep.bind(this),
2933
+ ]);
2934
+ this.addDialog(commandRouteDialog);
2935
+ }
2936
+ /**
2937
+ * Add TeamsFxBotSsoCommandHandler instance
2938
+ * @param handler {@link BotSsoExecutionDialogHandler} callback function
2939
+ * @param triggerPatterns The trigger pattern
2940
+ */
2941
+ addCommand(handler, triggerPatterns) {
2942
+ const commandId = this.getCommandHash(triggerPatterns);
2943
+ const dialog = new WaterfallDialog(commandId, [
2944
+ this.ssoStep.bind(this),
2945
+ this.dedupStep.bind(this),
2946
+ async (stepContext) => {
2947
+ const tokenResponse = stepContext.result.tokenResponse;
2948
+ const context = stepContext.context;
2949
+ const message = stepContext.result.message;
2950
+ try {
2951
+ if (tokenResponse) {
2952
+ await handler(context, tokenResponse, message);
2953
+ }
2954
+ else {
2955
+ throw new Error(ErrorMessage.FailedToRetrieveSsoToken);
2956
+ }
2957
+ return await stepContext.endDialog();
2958
+ }
2959
+ catch (error) {
2960
+ const errorMsg = formatString(ErrorMessage.FailedToProcessSsoHandler, error.message);
2961
+ internalLogger.error(errorMsg);
2962
+ return await stepContext.endDialog(new ErrorWithCode(errorMsg, ErrorCode.FailedToProcessSsoHandler));
2963
+ }
2964
+ },
2965
+ ]);
2966
+ this.commandMapping.set(commandId, triggerPatterns);
2967
+ this.addDialog(dialog);
2968
+ }
2969
+ getCommandHash(patterns) {
2970
+ const expressions = Array.isArray(patterns) ? patterns : [patterns];
2971
+ const patternStr = expressions.join();
2972
+ const patternStrWithoutSpecialChar = patternStr.replace(/[^a-zA-Z0-9]/g, "");
2973
+ const hash = createHash("sha256").update(patternStr).digest("hex").toLowerCase();
2974
+ return patternStrWithoutSpecialChar + hash;
2975
+ }
2976
+ /**
2977
+ * The run method handles the incoming activity (in the form of a DialogContext) and passes it through the dialog system.
2978
+ *
2979
+ * @param context The context object for the current turn.
2980
+ * @param accessor The instance of StatePropertyAccessor for dialog system.
2981
+ */
2982
+ async run(context, accessor) {
2983
+ const dialogSet = new DialogSet(accessor);
2984
+ dialogSet.add(this);
2985
+ const dialogContext = await dialogSet.createContext(context);
2986
+ this.ensureMsTeamsChannel(dialogContext);
2987
+ const results = await dialogContext.continueDialog();
2988
+ if (results && results.status === DialogTurnStatus.empty) {
2989
+ await dialogContext.beginDialog(this.id);
2990
+ }
2991
+ else if (results &&
2992
+ results.status === DialogTurnStatus.complete &&
2993
+ results.result instanceof Error) {
2994
+ throw results.result;
2995
+ }
2996
+ }
2997
+ getActivityText(activity) {
2998
+ let text = activity.text;
2999
+ const removedMentionText = TurnContext.removeRecipientMention(activity);
3000
+ if (removedMentionText) {
3001
+ text = removedMentionText
3002
+ .toLowerCase()
3003
+ .replace(/\n|\r\n/g, "")
3004
+ .trim();
3005
+ }
3006
+ return text;
3007
+ }
3008
+ async commandRouteStep(stepContext) {
3009
+ const turnContext = stepContext.context;
3010
+ const text = this.getActivityText(turnContext.activity);
3011
+ const commandId = this.getMatchesCommandId(text);
3012
+ if (commandId) {
3013
+ return await stepContext.beginDialog(commandId);
3014
+ }
3015
+ const errorMsg = formatString(ErrorMessage.CannotFindCommand, turnContext.activity.text);
3016
+ internalLogger.error(errorMsg);
3017
+ throw new ErrorWithCode(errorMsg, ErrorCode.CannotFindCommand);
3018
+ }
3019
+ async ssoStep(stepContext) {
3020
+ try {
3021
+ const turnContext = stepContext.context;
3022
+ const text = this.getActivityText(turnContext.activity);
3023
+ const message = {
3024
+ text,
3025
+ };
3026
+ stepContext.options.commandMessage = message;
3027
+ return await stepContext.beginDialog(TEAMS_SSO_PROMPT_ID);
3028
+ }
3029
+ catch (error) {
3030
+ const errorMsg = formatString(ErrorMessage.FailedToRunSsoStep, error.message);
3031
+ internalLogger.error(errorMsg);
3032
+ return await stepContext.endDialog(new ErrorWithCode(errorMsg, ErrorCode.FailedToRunSsoStep));
3033
+ }
3034
+ }
3035
+ async dedupStep(stepContext) {
3036
+ const tokenResponse = stepContext.result;
3037
+ if (!tokenResponse) {
3038
+ internalLogger.error(ErrorMessage.FailedToRetrieveSsoToken);
3039
+ return await stepContext.endDialog(new ErrorWithCode(ErrorMessage.FailedToRetrieveSsoToken, ErrorCode.FailedToRunSsoStep));
3040
+ }
3041
+ try {
3042
+ // Only dedup after ssoStep to make sure that all Teams client would receive the login request
3043
+ if (tokenResponse && (await this.shouldDedup(stepContext.context))) {
3044
+ return Dialog.EndOfTurn;
3045
+ }
3046
+ return await stepContext.next({
3047
+ tokenResponse,
3048
+ message: stepContext.options.commandMessage,
3049
+ });
3050
+ }
3051
+ catch (error) {
3052
+ const errorMsg = formatString(ErrorMessage.FailedToRunDedupStep, error.message);
3053
+ internalLogger.error(errorMsg);
3054
+ return await stepContext.endDialog(new ErrorWithCode(errorMsg, ErrorCode.FailedToRunDedupStep));
3055
+ }
3056
+ }
3057
+ /**
3058
+ * Called when the component is ending.
3059
+ *
3060
+ * @param context Context for the current turn of conversation.
3061
+ */
3062
+ async onEndDialog(context) {
3063
+ const conversationId = context.activity.conversation.id;
3064
+ const currentDedupKeys = this.dedupStorageKeys.filter((key) => key.indexOf(conversationId) > 0);
3065
+ await this.dedupStorage.delete(currentDedupKeys);
3066
+ this.dedupStorageKeys = this.dedupStorageKeys.filter((key) => key.indexOf(conversationId) < 0);
3067
+ }
3068
+ /**
3069
+ * If a user is signed into multiple Teams clients, the Bot might receive a "signin/tokenExchange" from each client.
3070
+ * Each token exchange request for a specific user login will have an identical activity.value.Id.
3071
+ * Only one of these token exchange requests should be processed by the bot. For a distributed bot in production,
3072
+ * this requires a distributed storage to ensure only one token exchange is processed.
3073
+ * @param context Context for the current turn of conversation.
3074
+ * @returns boolean value indicate whether the message should be removed
3075
+ */
3076
+ async shouldDedup(context) {
3077
+ const storeItem = {
3078
+ eTag: context.activity.value.id,
3079
+ };
3080
+ const key = this.getStorageKey(context);
3081
+ const storeItems = { [key]: storeItem };
3082
+ try {
3083
+ await this.dedupStorage.write(storeItems);
3084
+ this.dedupStorageKeys.push(key);
3085
+ }
3086
+ catch (err) {
3087
+ if (err instanceof Error && err.message.indexOf("eTag conflict")) {
3088
+ return true;
3089
+ }
3090
+ throw err;
3091
+ }
3092
+ return false;
3093
+ }
3094
+ getStorageKey(context) {
3095
+ if (!context || !context.activity || !context.activity.conversation) {
3096
+ throw new Error("Invalid context, can not get storage key!");
3097
+ }
3098
+ const activity = context.activity;
3099
+ const channelId = activity.channelId;
3100
+ const conversationId = activity.conversation.id;
3101
+ if (activity.type !== ActivityTypes.Invoke || activity.name !== tokenExchangeOperationName) {
3102
+ throw new Error("TokenExchangeState can only be used with Invokes of signin/tokenExchange.");
3103
+ }
3104
+ const value = activity.value;
3105
+ if (!value || !value.id) {
3106
+ throw new Error("Invalid signin/tokenExchange. Missing activity.value.id.");
3107
+ }
3108
+ return `${channelId}/${conversationId}/${value.id}`;
3109
+ }
3110
+ matchPattern(pattern, text) {
3111
+ if (text) {
3112
+ if (typeof pattern === "string") {
3113
+ const regExp = new RegExp(pattern, "i");
3114
+ return regExp.test(text);
3115
+ }
3116
+ if (pattern instanceof RegExp) {
3117
+ const matches = text.match(pattern);
3118
+ return matches !== null && matches !== void 0 ? matches : false;
3119
+ }
3120
+ }
3121
+ return false;
3122
+ }
3123
+ isPatternMatched(patterns, text) {
3124
+ const expressions = Array.isArray(patterns) ? patterns : [patterns];
3125
+ for (const ex of expressions) {
3126
+ const matches = this.matchPattern(ex, text);
3127
+ return !!matches;
3128
+ }
3129
+ return false;
3130
+ }
3131
+ getMatchesCommandId(text) {
3132
+ for (const command of this.commandMapping) {
3133
+ const pattern = command[1];
3134
+ if (this.isPatternMatched(pattern, text)) {
3135
+ return command[0];
3136
+ }
3137
+ }
3138
+ return undefined;
3139
+ }
3140
+ /**
3141
+ * Ensure bot is running in MS Teams since TeamsBotSsoPrompt is only supported in MS Teams channel.
3142
+ * @param dc dialog context
3143
+ * @throws {@link ErrorCode|ChannelNotSupported} if bot channel is not MS Teams
3144
+ * @internal
3145
+ */
3146
+ ensureMsTeamsChannel(dc) {
3147
+ if (dc.context.activity.channelId != Channels.Msteams) {
3148
+ const errorMsg = formatString(ErrorMessage.OnlyMSTeamsChannelSupported, "SSO execution dialog");
3149
+ internalLogger.error(errorMsg);
3150
+ throw new ErrorWithCode(errorMsg, ErrorCode.ChannelNotSupported);
3151
+ }
3152
+ }
3153
+ }
3154
+
3155
+ // Copyright (c) Microsoft Corporation.
3156
+ /**
3157
+ * Default SSO execution activity handler
3158
+ */
3159
+ class DefaultBotSsoExecutionActivityHandler extends TeamsActivityHandler {
3160
+ /**
3161
+ * Creates a new instance of the DefaultBotSsoExecutionActivityHandler.
3162
+ * @param ssoConfig configuration for SSO command bot
3163
+ *
3164
+ * @remarks
3165
+ * In the constructor, it uses BotSsoConfig parameter which from {@link ConversationBot} options to initialize {@link BotSsoExecutionDialog}.
3166
+ * It also need to register an event handler for the message event which trigger {@link BotSsoExecutionDialog} instance.
3167
+ */
3168
+ constructor(ssoConfig) {
3169
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3170
+ super();
3171
+ const memoryStorage = new MemoryStorage();
3172
+ const userState = (_b = (_a = ssoConfig.dialog) === null || _a === void 0 ? void 0 : _a.userState) !== null && _b !== void 0 ? _b : new UserState(memoryStorage);
3173
+ const conversationState = (_d = (_c = ssoConfig.dialog) === null || _c === void 0 ? void 0 : _c.conversationState) !== null && _d !== void 0 ? _d : new ConversationState(memoryStorage);
3174
+ const dedupStorage = (_f = (_e = ssoConfig.dialog) === null || _e === void 0 ? void 0 : _e.dedupStorage) !== null && _f !== void 0 ? _f : memoryStorage;
3175
+ const _l = ssoConfig.aad, { scopes } = _l, customConfig = __rest(_l, ["scopes"]);
3176
+ const settings = {
3177
+ scopes: scopes,
3178
+ timeout: (_h = (_g = ssoConfig.dialog) === null || _g === void 0 ? void 0 : _g.ssoPromptConfig) === null || _h === void 0 ? void 0 : _h.timeout,
3179
+ endOnInvalidMessage: (_k = (_j = ssoConfig.dialog) === null || _j === void 0 ? void 0 : _j.ssoPromptConfig) === null || _k === void 0 ? void 0 : _k.endOnInvalidMessage,
3180
+ };
3181
+ const teamsfx = new TeamsFx(IdentityType.User, Object.assign({}, customConfig));
3182
+ this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, teamsfx);
3183
+ this.conversationState = conversationState;
3184
+ this.dialogState = conversationState.createProperty("DialogState");
3185
+ this.userState = userState;
3186
+ this.onMessage(async (context, next) => {
3187
+ await this.ssoExecutionDialog.run(context, this.dialogState);
3188
+ await next();
3189
+ });
3190
+ }
3191
+ /**
3192
+ * Add TeamsFxBotSsoCommandHandler instance to SSO execution dialog
3193
+ * @param handler {@link BotSsoExecutionDialogHandler} callback function
3194
+ * @param triggerPatterns The trigger pattern
3195
+ *
3196
+ * @remarks
3197
+ * This function is used to add SSO command to {@link BotSsoExecutionDialog} instance.
3198
+ */
3199
+ addCommand(handler, triggerPatterns) {
3200
+ this.ssoExecutionDialog.addCommand(handler, triggerPatterns);
3201
+ }
3202
+ /**
3203
+ * Called to initiate the event emission process.
3204
+ * @param context The context object for the current turn.
3205
+ */
3206
+ async run(context) {
3207
+ try {
3208
+ await super.run(context);
3209
+ }
3210
+ finally {
3211
+ await this.conversationState.saveChanges(context, false);
3212
+ await this.userState.saveChanges(context, false);
3213
+ }
3214
+ }
3215
+ /**
3216
+ * Receives invoke activities with Activity name of 'signin/verifyState'.
3217
+ * @param context A context object for this turn.
3218
+ * @param query Signin state (part of signin action auth flow) verification invoke query.
3219
+ * @returns A promise that represents the work queued.
3220
+ *
3221
+ * @remarks
3222
+ * It should trigger {@link BotSsoExecutionDialog} instance to handle signin process
3223
+ */
3224
+ async handleTeamsSigninVerifyState(context, query) {
3225
+ await this.ssoExecutionDialog.run(context, this.dialogState);
3226
+ }
3227
+ /**
3228
+ * Receives invoke activities with Activity name of 'signin/tokenExchange'
3229
+ * @param context A context object for this turn.
3230
+ * @param query Signin state (part of signin action auth flow) verification invoke query
3231
+ * @returns A promise that represents the work queued.
3232
+ *
3233
+ * @remark
3234
+ * It should trigger {@link BotSsoExecutionDialog} instance to handle signin process
3235
+ */
3236
+ async handleTeamsSigninTokenExchange(context, query) {
3237
+ await this.ssoExecutionDialog.run(context, this.dialogState);
3238
+ }
3239
+ }
3240
+
2800
3241
  // Copyright (c) Microsoft Corporation.
2801
3242
  /**
2802
3243
  * Provide utilities for bot conversation, including:
@@ -2859,20 +3300,30 @@ class ConversationBot {
2859
3300
  * @param options - initialize options
2860
3301
  */
2861
3302
  constructor(options) {
2862
- var _a, _b, _c;
3303
+ var _a, _b, _c, _d;
2863
3304
  if (options.adapter) {
2864
3305
  this.adapter = options.adapter;
2865
3306
  }
2866
3307
  else {
2867
3308
  this.adapter = this.createDefaultAdapter(options.adapterConfig);
2868
3309
  }
2869
- if ((_a = options.command) === null || _a === void 0 ? void 0 : _a.enabled) {
2870
- this.command = new CommandBot(this.adapter, options.command);
3310
+ let ssoCommandActivityHandler;
3311
+ if (options === null || options === void 0 ? void 0 : options.ssoConfig) {
3312
+ if ((_a = options.ssoConfig.dialog) === null || _a === void 0 ? void 0 : _a.CustomBotSsoExecutionActivityHandler) {
3313
+ ssoCommandActivityHandler =
3314
+ new options.ssoConfig.dialog.CustomBotSsoExecutionActivityHandler(options.ssoConfig);
3315
+ }
3316
+ else {
3317
+ ssoCommandActivityHandler = new DefaultBotSsoExecutionActivityHandler(options.ssoConfig);
3318
+ }
3319
+ }
3320
+ if ((_b = options.command) === null || _b === void 0 ? void 0 : _b.enabled) {
3321
+ this.command = new CommandBot(this.adapter, options.command, ssoCommandActivityHandler, options.ssoConfig);
2871
3322
  }
2872
- if ((_b = options.notification) === null || _b === void 0 ? void 0 : _b.enabled) {
3323
+ if ((_c = options.notification) === null || _c === void 0 ? void 0 : _c.enabled) {
2873
3324
  this.notification = new NotificationBot(this.adapter, options.notification);
2874
3325
  }
2875
- if ((_c = options.cardAction) === null || _c === void 0 ? void 0 : _c.enabled) {
3326
+ if ((_d = options.cardAction) === null || _d === void 0 ? void 0 : _d.enabled) {
2876
3327
  this.cardAction = new CardActionBot(this.adapter, options.cardAction);
2877
3328
  }
2878
3329
  }
@@ -3061,5 +3512,5 @@ class MessageBuilder {
3061
3512
  }
3062
3513
  }
3063
3514
 
3064
- export { AdaptiveCardResponse, ApiKeyLocation, ApiKeyProvider, AppCredential, BasicAuthProvider, BearerTokenAuthProvider, CardActionBot, CertificateAuthProvider, Channel, CommandBot, ConversationBot, ErrorCode, ErrorWithCode, IdentityType, InvokeResponseErrorCode, InvokeResponseFactory, LogLevel, Member, MessageBuilder, MsGraphAuthProvider, NotificationBot, NotificationTargetType, OnBehalfOfUserCredential, TeamsBotInstallation, TeamsBotSsoPrompt, TeamsFx, TeamsUserCredential, createApiClient, createMicrosoftGraphClient, createPemCertOption, createPfxCertOption, getLogLevel, getTediousConnectionConfig, sendAdaptiveCard, sendMessage, setLogFunction, setLogLevel, setLogger };
3515
+ export { AdaptiveCardResponse, ApiKeyLocation, ApiKeyProvider, AppCredential, BasicAuthProvider, BearerTokenAuthProvider, BotSsoExecutionDialog, CardActionBot, CertificateAuthProvider, Channel, CommandBot, ConversationBot, DefaultBotSsoExecutionActivityHandler, ErrorCode, ErrorWithCode, IdentityType, InvokeResponseErrorCode, InvokeResponseFactory, LogLevel, Member, MessageBuilder, MsGraphAuthProvider, NotificationBot, NotificationTargetType, OnBehalfOfUserCredential, TeamsBotInstallation, TeamsBotSsoPrompt, TeamsFx, TeamsUserCredential, createApiClient, createMicrosoftGraphClient, createPemCertOption, createPfxCertOption, getLogLevel, getTediousConnectionConfig, sendAdaptiveCard, sendMessage, setLogFunction, setLogLevel, setLogger };
3065
3516
  //# sourceMappingURL=index.esm2017.mjs.map