@microsoft/teamsfx 1.1.2-alpha.988c78cba.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.
- package/dist/index.esm2017.js +180 -17
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +492 -32
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +192 -17
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +513 -29
- package/dist/index.node.cjs.js.map +1 -1
- package/package.json +3 -3
- package/types/teamsfx.d.ts +336 -29
package/dist/index.esm2017.mjs
CHANGED
|
@@ -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
|
|
@@ -694,10 +728,13 @@ class TeamsUserCredential {
|
|
|
694
728
|
}
|
|
695
729
|
/**
|
|
696
730
|
* Popup login page to get user's access token with specific scopes.
|
|
731
|
+
*
|
|
732
|
+
* @param {string[]} resources - The optional list of resources for full trust Teams apps.
|
|
733
|
+
*
|
|
697
734
|
* @remarks
|
|
698
735
|
* Can only be used within Teams.
|
|
699
736
|
*/
|
|
700
|
-
async login(scopes) {
|
|
737
|
+
async login(scopes, resources) {
|
|
701
738
|
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
|
|
702
739
|
}
|
|
703
740
|
/**
|
|
@@ -710,10 +747,13 @@ class TeamsUserCredential {
|
|
|
710
747
|
}
|
|
711
748
|
/**
|
|
712
749
|
* Get basic user info from SSO token
|
|
750
|
+
*
|
|
751
|
+
* @param {string[]} resources - The optional list of resources for full trust Teams apps.
|
|
752
|
+
*
|
|
713
753
|
* @remarks
|
|
714
754
|
* Can only be used within Teams.
|
|
715
755
|
*/
|
|
716
|
-
getUserInfo() {
|
|
756
|
+
getUserInfo(resources) {
|
|
717
757
|
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
|
|
718
758
|
}
|
|
719
759
|
}
|
|
@@ -1661,8 +1701,9 @@ class TeamsFx {
|
|
|
1661
1701
|
this.configuration = new Map();
|
|
1662
1702
|
this.loadFromEnv();
|
|
1663
1703
|
if (customConfig) {
|
|
1664
|
-
|
|
1665
|
-
|
|
1704
|
+
const myConfig = Object.assign({}, customConfig);
|
|
1705
|
+
for (const key of Object.keys(myConfig)) {
|
|
1706
|
+
const value = myConfig[key];
|
|
1666
1707
|
if (value) {
|
|
1667
1708
|
this.configuration.set(key, value);
|
|
1668
1709
|
}
|
|
@@ -1704,9 +1745,10 @@ class TeamsFx {
|
|
|
1704
1745
|
}
|
|
1705
1746
|
/**
|
|
1706
1747
|
* Get user information.
|
|
1748
|
+
* @param {string[]} resources - The optional list of resources for full trust Teams apps.
|
|
1707
1749
|
* @returns UserInfo object.
|
|
1708
1750
|
*/
|
|
1709
|
-
async getUserInfo() {
|
|
1751
|
+
async getUserInfo(resources) {
|
|
1710
1752
|
if (this.identityType !== IdentityType.User) {
|
|
1711
1753
|
const errorMsg = formatString(ErrorMessage.IdentityTypeNotSupported, this.identityType.toString(), "TeamsFx");
|
|
1712
1754
|
internalLogger.error(errorMsg);
|
|
@@ -1728,13 +1770,14 @@ class TeamsFx {
|
|
|
1728
1770
|
* await teamsfx.login("https://graph.microsoft.com/User.Read Calendars.Read"); // multiple scopes using string
|
|
1729
1771
|
* ```
|
|
1730
1772
|
* @param scopes - The list of scopes for which the token will have access, before that, we will request user to consent.
|
|
1773
|
+
* @param {string[]} resources - The optional list of resources for full trust Teams apps.
|
|
1731
1774
|
*
|
|
1732
1775
|
* @throws {@link ErrorCode|InternalError} when failed to login with unknown error.
|
|
1733
1776
|
* @throws {@link ErrorCode|ConsentFailed} when user canceled or failed to consent.
|
|
1734
1777
|
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
1735
1778
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
1736
1779
|
*/
|
|
1737
|
-
async login(scopes) {
|
|
1780
|
+
async login(scopes, resources) {
|
|
1738
1781
|
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "login"), ErrorCode.RuntimeNotSupported);
|
|
1739
1782
|
}
|
|
1740
1783
|
/**
|
|
@@ -2113,41 +2156,80 @@ class CardActionBot {
|
|
|
2113
2156
|
* @internal
|
|
2114
2157
|
*/
|
|
2115
2158
|
class CommandResponseMiddleware {
|
|
2116
|
-
constructor(handlers) {
|
|
2159
|
+
constructor(handlers, ssoHandlers, activityHandler) {
|
|
2117
2160
|
this.commandHandlers = [];
|
|
2118
|
-
|
|
2119
|
-
|
|
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);
|
|
2120
2173
|
}
|
|
2121
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
|
+
}
|
|
2122
2187
|
async onTurn(context, next) {
|
|
2188
|
+
var _a, _b;
|
|
2123
2189
|
if (context.activity.type === ActivityTypes.Message) {
|
|
2124
2190
|
// Invoke corresponding command handler for the command response
|
|
2125
2191
|
const commandText = this.getActivityText(context.activity);
|
|
2126
|
-
const message = {
|
|
2127
|
-
text: commandText,
|
|
2128
|
-
};
|
|
2129
2192
|
for (const handler of this.commandHandlers) {
|
|
2130
2193
|
const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
|
|
2131
2194
|
// It is important to note that the command bot will stop processing handlers
|
|
2132
2195
|
// when the first command handler is matched.
|
|
2133
2196
|
if (!!matchResult) {
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
if (typeof response === "string") {
|
|
2137
|
-
await context.sendActivity(response);
|
|
2197
|
+
if (this.isSsoExecutionHandler(handler)) {
|
|
2198
|
+
await ((_a = this.ssoActivityHandler) === null || _a === void 0 ? void 0 : _a.run(context));
|
|
2138
2199
|
}
|
|
2139
2200
|
else {
|
|
2140
|
-
const
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
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);
|
|
2144
2207
|
}
|
|
2145
2208
|
break;
|
|
2146
2209
|
}
|
|
2147
2210
|
}
|
|
2148
2211
|
}
|
|
2212
|
+
else {
|
|
2213
|
+
if (this.hasSsoCommand) {
|
|
2214
|
+
await ((_b = this.ssoActivityHandler) === null || _b === void 0 ? void 0 : _b.run(context));
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2149
2217
|
await next();
|
|
2150
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
|
+
}
|
|
2151
2233
|
matchPattern(pattern, text) {
|
|
2152
2234
|
if (text) {
|
|
2153
2235
|
if (typeof pattern === "string") {
|
|
@@ -2197,14 +2279,15 @@ class CommandBot {
|
|
|
2197
2279
|
* @param adapter The bound `BotFrameworkAdapter`.
|
|
2198
2280
|
* @param options - initialize options
|
|
2199
2281
|
*/
|
|
2200
|
-
constructor(adapter, options) {
|
|
2201
|
-
this.
|
|
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);
|
|
2202
2285
|
this.adapter = adapter.use(this.middleware);
|
|
2203
2286
|
}
|
|
2204
2287
|
/**
|
|
2205
2288
|
* Registers a command into the command bot.
|
|
2206
2289
|
*
|
|
2207
|
-
* @param command The command to
|
|
2290
|
+
* @param command The command to register.
|
|
2208
2291
|
*/
|
|
2209
2292
|
registerCommand(command) {
|
|
2210
2293
|
if (command) {
|
|
@@ -2214,13 +2297,41 @@ class CommandBot {
|
|
|
2214
2297
|
/**
|
|
2215
2298
|
* Registers commands into the command bot.
|
|
2216
2299
|
*
|
|
2217
|
-
* @param commands The
|
|
2300
|
+
* @param commands The commands to register.
|
|
2218
2301
|
*/
|
|
2219
2302
|
registerCommands(commands) {
|
|
2220
2303
|
if (commands) {
|
|
2221
2304
|
this.middleware.commandHandlers.push(...commands);
|
|
2222
2305
|
}
|
|
2223
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
|
+
}
|
|
2224
2335
|
}
|
|
2225
2336
|
|
|
2226
2337
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -2788,6 +2899,345 @@ class NotificationBot {
|
|
|
2788
2899
|
}
|
|
2789
2900
|
}
|
|
2790
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
|
+
|
|
2791
3241
|
// Copyright (c) Microsoft Corporation.
|
|
2792
3242
|
/**
|
|
2793
3243
|
* Provide utilities for bot conversation, including:
|
|
@@ -2850,20 +3300,30 @@ class ConversationBot {
|
|
|
2850
3300
|
* @param options - initialize options
|
|
2851
3301
|
*/
|
|
2852
3302
|
constructor(options) {
|
|
2853
|
-
var _a, _b, _c;
|
|
3303
|
+
var _a, _b, _c, _d;
|
|
2854
3304
|
if (options.adapter) {
|
|
2855
3305
|
this.adapter = options.adapter;
|
|
2856
3306
|
}
|
|
2857
3307
|
else {
|
|
2858
3308
|
this.adapter = this.createDefaultAdapter(options.adapterConfig);
|
|
2859
3309
|
}
|
|
2860
|
-
|
|
2861
|
-
|
|
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);
|
|
2862
3322
|
}
|
|
2863
|
-
if ((
|
|
3323
|
+
if ((_c = options.notification) === null || _c === void 0 ? void 0 : _c.enabled) {
|
|
2864
3324
|
this.notification = new NotificationBot(this.adapter, options.notification);
|
|
2865
3325
|
}
|
|
2866
|
-
if ((
|
|
3326
|
+
if ((_d = options.cardAction) === null || _d === void 0 ? void 0 : _d.enabled) {
|
|
2867
3327
|
this.cardAction = new CardActionBot(this.adapter, options.cardAction);
|
|
2868
3328
|
}
|
|
2869
3329
|
}
|
|
@@ -3052,5 +3512,5 @@ class MessageBuilder {
|
|
|
3052
3512
|
}
|
|
3053
3513
|
}
|
|
3054
3514
|
|
|
3055
|
-
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 };
|
|
3056
3516
|
//# sourceMappingURL=index.esm2017.mjs.map
|