@microsoft/teamsfx 1.1.2-alpha.9bd0cb559.0 → 1.1.2-alpha.9d488528e.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.
@@ -138,6 +138,7 @@ ErrorMessage.EmptyParameter = "Parameter {0} is empty";
138
138
  ErrorMessage.DuplicateHttpsOptionProperty = "Axios HTTPS agent already defined value for property {0}";
139
139
  ErrorMessage.DuplicateApiKeyInHeader = "The request already defined api key in request header with name {0}.";
140
140
  ErrorMessage.DuplicateApiKeyInQueryParam = "The request already defined api key in query parameter with name {0}.";
141
+ ErrorMessage.OnlySupportInQueryActivity = "The handleMessageExtensionQueryWithToken only support in handleTeamsMessagingExtensionQuery with composeExtension/query type.";
141
142
  /**
142
143
  * Error class with code and message thrown by the SDK.
143
144
  */
@@ -2181,7 +2182,6 @@ class CommandResponseMiddleware {
2181
2182
  await this.processResponse(context, response);
2182
2183
  }, ssoHandler.triggerPatterns);
2183
2184
  this.ssoCommandHandlers.push(ssoHandler);
2184
- this.commandHandlers.push(ssoHandler);
2185
2185
  this.hasSsoCommand = true;
2186
2186
  }
2187
2187
  async onTurn(context, next) {
@@ -2189,23 +2189,29 @@ class CommandResponseMiddleware {
2189
2189
  if (context.activity.type === ActivityTypes.Message) {
2190
2190
  // Invoke corresponding command handler for the command response
2191
2191
  const commandText = this.getActivityText(context.activity);
2192
+ let alreadyProcessed = false;
2192
2193
  for (const handler of this.commandHandlers) {
2193
2194
  const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
2194
2195
  // It is important to note that the command bot will stop processing handlers
2195
2196
  // when the first command handler is matched.
2196
2197
  if (!!matchResult) {
2197
- if (this.isSsoExecutionHandler(handler)) {
2198
+ const message = {
2199
+ text: commandText,
2200
+ };
2201
+ message.matches = Array.isArray(matchResult) ? matchResult : void 0;
2202
+ const response = await handler.handleCommandReceived(context, message);
2203
+ await this.processResponse(context, response);
2204
+ alreadyProcessed = true;
2205
+ break;
2206
+ }
2207
+ }
2208
+ if (!alreadyProcessed) {
2209
+ for (const handler of this.ssoCommandHandlers) {
2210
+ const matchResult = this.shouldTrigger(handler.triggerPatterns, commandText);
2211
+ if (!!matchResult) {
2198
2212
  await ((_a = this.ssoActivityHandler) === null || _a === void 0 ? void 0 : _a.run(context));
2213
+ break;
2199
2214
  }
2200
- else {
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);
2207
- }
2208
- break;
2209
2215
  }
2210
2216
  }
2211
2217
  }
@@ -2227,9 +2233,6 @@ class CommandResponseMiddleware {
2227
2233
  }
2228
2234
  }
2229
2235
  }
2230
- isSsoExecutionHandler(handler) {
2231
- return this.ssoCommandHandlers.indexOf(handler) >= 0;
2232
- }
2233
2236
  matchPattern(pattern, text) {
2234
2237
  if (text) {
2235
2238
  if (typeof pattern === "string") {
@@ -2806,6 +2809,10 @@ class TeamsBotInstallation {
2806
2809
  * @returns an array of channels if bot is installed into a team, otherwise returns an empty array.
2807
2810
  */
2808
2811
  async channels() {
2812
+ const channels = [];
2813
+ if (this.type !== NotificationTargetType.Channel) {
2814
+ return channels;
2815
+ }
2809
2816
  let teamsChannels = [];
2810
2817
  await this.adapter.continueConversation(this.conversationReference, async (context) => {
2811
2818
  const teamId = getTeamsBotInstallationId(context);
@@ -2813,7 +2820,6 @@ class TeamsBotInstallation {
2813
2820
  teamsChannels = await TeamsInfo.getTeamChannels(context, teamId);
2814
2821
  }
2815
2822
  });
2816
- const channels = [];
2817
2823
  for (const channel of teamsChannels) {
2818
2824
  channels.push(new Channel(this, channel));
2819
2825
  }
@@ -2838,6 +2844,24 @@ class TeamsBotInstallation {
2838
2844
  });
2839
2845
  return members;
2840
2846
  }
2847
+ /**
2848
+ * Get team details from this bot installation
2849
+ *
2850
+ * @returns the team details if bot is installed into a team, otherwise returns undefined.
2851
+ */
2852
+ async getTeamDetails() {
2853
+ if (this.type !== NotificationTargetType.Channel) {
2854
+ return undefined;
2855
+ }
2856
+ let teamDetails;
2857
+ await this.adapter.continueConversation(this.conversationReference, async (context) => {
2858
+ const teamId = getTeamsBotInstallationId(context);
2859
+ if (teamId !== undefined) {
2860
+ teamDetails = await TeamsInfo.getTeamDetails(context, teamId);
2861
+ }
2862
+ });
2863
+ return teamDetails;
2864
+ }
2841
2865
  }
2842
2866
  /**
2843
2867
  * Provide utilities to send notification to varies targets (e.g., member, group, channel).
@@ -2897,7 +2921,121 @@ class NotificationBot {
2897
2921
  }
2898
2922
  return targets;
2899
2923
  }
2900
- }
2924
+ /**
2925
+ * Returns the first {@link Member} where predicate is true, and undefined otherwise.
2926
+ *
2927
+ * @param predicate find calls predicate once for each member of the installation,
2928
+ * until it finds one where predicate returns true. If such a member is found, find
2929
+ * immediately returns that member. Otherwise, find returns undefined.
2930
+ * @param scope the scope to find members from the installations
2931
+ * (personal chat, group chat, Teams channel).
2932
+ * @returns the first {@link Member} where predicate is true, and undefined otherwise.
2933
+ */
2934
+ async findMember(predicate, scope) {
2935
+ for (const target of await this.installations()) {
2936
+ if (this.matchSearchScope(target, scope)) {
2937
+ for (const member of await target.members()) {
2938
+ if (await predicate(member)) {
2939
+ return member;
2940
+ }
2941
+ }
2942
+ }
2943
+ }
2944
+ return;
2945
+ }
2946
+ /**
2947
+ * Returns the first {@link Channel} where predicate is true, and undefined otherwise.
2948
+ *
2949
+ * @param predicate find calls predicate once for each channel of the installation,
2950
+ * until it finds one where predicate returns true. If such a channel is found, find
2951
+ * immediately returns that channel. Otherwise, find returns undefined.
2952
+ * @returns the first {@link Channel} where predicate is true, and undefined otherwise.
2953
+ */
2954
+ async findChannel(predicate) {
2955
+ for (const target of await this.installations()) {
2956
+ if (target.type === NotificationTargetType.Channel) {
2957
+ const teamDetails = await target.getTeamDetails();
2958
+ for (const channel of await target.channels()) {
2959
+ if (await predicate(channel, teamDetails)) {
2960
+ return channel;
2961
+ }
2962
+ }
2963
+ }
2964
+ }
2965
+ return;
2966
+ }
2967
+ /**
2968
+ * Returns all {@link Member} where predicate is true, and empty array otherwise.
2969
+ *
2970
+ * @param predicate find calls predicate for each member of the installation.
2971
+ * @param scope the scope to find members from the installations
2972
+ * (personal chat, group chat, Teams channel).
2973
+ * @returns an array of {@link Member} where predicate is true, and empty array otherwise.
2974
+ */
2975
+ async findAllMembers(predicate, scope) {
2976
+ const members = [];
2977
+ for (const target of await this.installations()) {
2978
+ if (this.matchSearchScope(target, scope)) {
2979
+ for (const member of await target.members()) {
2980
+ if (await predicate(member)) {
2981
+ members.push(member);
2982
+ }
2983
+ }
2984
+ }
2985
+ }
2986
+ return members;
2987
+ }
2988
+ /**
2989
+ * Returns all {@link Channel} where predicate is true, and empty array otherwise.
2990
+ *
2991
+ * @param predicate find calls predicate for each channel of the installation.
2992
+ * @returns an array of {@link Channel} where predicate is true, and empty array otherwise.
2993
+ */
2994
+ async findAllChannels(predicate) {
2995
+ const channels = [];
2996
+ for (const target of await this.installations()) {
2997
+ if (target.type === NotificationTargetType.Channel) {
2998
+ const teamDetails = await target.getTeamDetails();
2999
+ for (const channel of await target.channels()) {
3000
+ if (await predicate(channel, teamDetails)) {
3001
+ channels.push(channel);
3002
+ }
3003
+ }
3004
+ }
3005
+ }
3006
+ return channels;
3007
+ }
3008
+ matchSearchScope(target, scope) {
3009
+ scope = scope !== null && scope !== void 0 ? scope : SearchScope.All;
3010
+ return ((target.type === NotificationTargetType.Channel && (scope & SearchScope.Channel) !== 0) ||
3011
+ (target.type === NotificationTargetType.Group && (scope & SearchScope.Group) !== 0) ||
3012
+ (target.type === NotificationTargetType.Person && (scope & SearchScope.Person) !== 0));
3013
+ }
3014
+ }
3015
+ /**
3016
+ * The search scope when calling {@link NotificationBot.findMember} and {@link NotificationBot.findAllMembers}.
3017
+ * The search scope is a flagged enum and it can be combined with `|`.
3018
+ * For example, to search from personal chat and group chat, use `SearchScope.Person | SearchScope.Group`.
3019
+ */
3020
+ var SearchScope;
3021
+ (function (SearchScope) {
3022
+ /**
3023
+ * Search members from the installations in personal chat only.
3024
+ */
3025
+ SearchScope[SearchScope["Person"] = 1] = "Person";
3026
+ /**
3027
+ * Search members from the installations in group chat only.
3028
+ */
3029
+ SearchScope[SearchScope["Group"] = 2] = "Group";
3030
+ /**
3031
+ * Search members from the installations in Teams channel only.
3032
+ */
3033
+ SearchScope[SearchScope["Channel"] = 4] = "Channel";
3034
+ /**
3035
+ * Search members from all installations including personal chat, group chat and Teams channel.
3036
+ */
3037
+ SearchScope[SearchScope["All"] = 7] = "All";
3038
+ })(SearchScope || (SearchScope = {}));
2901
3039
 
2902
3040
  // Copyright (c) Microsoft Corporation.
2903
3041
  let DIALOG_NAME = "BotSsoExecutionDialog";
@@ -3512,5 +3650,105 @@ class MessageBuilder {
3512
3650
  }
3513
3651
  }
3514
3652
 
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 };
3653
+ // Copyright (c) Microsoft Corporation.
3654
+ /**
3655
+ * Retrieve the OAuth Sign in Link to use in the MessagingExtensionResult Suggested Actions.
3656
+ * This method only work on MessageExtension with Query now.
3657
+ *
3658
+ * @param {TeamsFx} teamsfx - Used to provide configuration and auth.
3659
+ * @param {string | string[]} scopes - The list of scopes for which the token will have access.
3660
+ *
3661
+ * @returns SignIn link CardAction with 200 status code.
3662
+ */
3663
+ function getSignInResponseForMessageExtension(teamsfx, scopes) {
3664
+ const scopesArray = getScopesArray(scopes);
3665
+ const signInLink = `${teamsfx.getConfig("initiateLoginEndpoint")}?scope=${encodeURI(scopesArray.join(" "))}&clientId=${teamsfx.getConfig("clientId")}&tenantId=${teamsfx.getConfig("tenantId")}`;
3666
+ return {
3667
+ composeExtension: {
3668
+ type: "silentAuth",
3669
+ suggestedActions: {
3670
+ actions: [
3671
+ {
3672
+ type: "openUrl",
3673
+ value: signInLink,
3674
+ title: "Message Extension OAuth",
3675
+ },
3676
+ ],
3677
+ },
3678
+ },
3679
+ };
3680
+ }
3681
+ /**
3682
+ * execution in message extension with SSO token.
3683
+ *
3684
+ * @param {TurnContext} context - The context object for the current turn.
3685
+ * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
3686
+ * @param {string[]} scopes - The list of scopes for which the token will have access.
3687
+ * @param {function} logic - Business logic when executing the query in message extension with SSO or access token.
3688
+ *
3689
+ * @throws {@link ErrorCode|InternalError} when failed to get access token with unknown error.
3690
+ * @throws {@link ErrorCode|TokenExpiredError} when SSO token has already expired.
3691
+ * @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth server.
3692
+ * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
3693
+ * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
3694
+ *
3695
+ * @returns A MessageExtension Response for the activity. If the logic not return any, return void instead.
3696
+ */
3697
+ async function executionWithToken(context, config, scopes, logic) {
3698
+ const valueObj = context.activity.value;
3699
+ if (!valueObj.authentication || !valueObj.authentication.token) {
3700
+ internalLogger.verbose("No AccessToken in request, return silentAuth for AccessToken");
3701
+ return getSignInResponseForMessageExtension(new TeamsFx(IdentityType.User, config), scopes);
3702
+ }
3703
+ try {
3704
+ const teamsfx = new TeamsFx(IdentityType.User, config).setSsoToken(valueObj.authentication.token);
3705
+ const token = await teamsfx.getCredential().getToken(scopes);
3706
+ const ssoTokenExpiration = parseJwt(valueObj.authentication.token).exp;
3707
+ const tokenRes = {
3708
+ ssoToken: valueObj.authentication.token,
3709
+ ssoTokenExpiration: new Date(ssoTokenExpiration * 1000).toISOString(),
3710
+ token: token.token,
3711
+ expiration: token.expiresOnTimestamp.toString(),
3712
+ connectionName: "",
3713
+ };
3714
+ if (logic) {
3715
+ return await logic(tokenRes);
3716
+ }
3717
+ }
3718
+ catch (err) {
3719
+ if (err instanceof ErrorWithCode && err.code === ErrorCode.UiRequiredError) {
3720
+ internalLogger.verbose("User not consent yet, return 412 to user consent first.");
3721
+ const response = { status: 412 };
3722
+ await context.sendActivity({ value: response, type: ActivityTypes.InvokeResponse });
3723
+ return;
3724
+ }
3725
+ throw err;
3726
+ }
3727
+ }
3728
+ /**
3729
+ * Users execute query in message extension with SSO or access token.
3730
+ *
3731
+ * @param {TurnContext} context - The context object for the current turn.
3732
+ * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
3733
+ * @param {string| string[]} scopes - The list of scopes for which the token will have access.
3734
+ * @param {function} logic - Business logic when executing the query in message extension with SSO or access token.
3735
+ *
3736
+ * @throws {@link ErrorCode|InternalError} when User invoke not response to message extension query.
3737
+ * @throws {@link ErrorCode|InternalError} when failed to get access token with unknown error.
3738
+ * @throws {@link ErrorCode|TokenExpiredError} when SSO token has already expired.
3739
+ * @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth server.
3740
+ * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
3741
+ * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
3742
+ *
3743
+ * @returns A MessageExtension Response for the activity. If the logic not return any, return void instead.
3744
+ */
3745
+ async function handleMessageExtensionQueryWithToken(context, config, scopes, logic) {
3746
+ if (context.activity.name != "composeExtension/query") {
3747
+ internalLogger.error(ErrorMessage.OnlySupportInQueryActivity);
3748
+ throw new ErrorWithCode(formatString(ErrorMessage.OnlySupportInQueryActivity), ErrorCode.FailedOperation);
3749
+ }
3750
+ return await executionWithToken(context, config !== null && config !== void 0 ? config : {}, scopes, logic);
3751
+ }
3752
+
3753
+ export { AdaptiveCardResponse, ApiKeyLocation, ApiKeyProvider, AppCredential, BasicAuthProvider, BearerTokenAuthProvider, BotSsoExecutionDialog, CardActionBot, CertificateAuthProvider, Channel, CommandBot, ConversationBot, ErrorCode, ErrorWithCode, IdentityType, InvokeResponseErrorCode, InvokeResponseFactory, LogLevel, Member, MessageBuilder, MsGraphAuthProvider, NotificationBot, NotificationTargetType, OnBehalfOfUserCredential, SearchScope, TeamsBotInstallation, TeamsBotSsoPrompt, TeamsFx, TeamsUserCredential, createApiClient, createMicrosoftGraphClient, createPemCertOption, createPfxCertOption, getLogLevel, getTediousConnectionConfig, handleMessageExtensionQueryWithToken, sendAdaptiveCard, sendMessage, setLogFunction, setLogLevel, setLogger };
3516
3754
  //# sourceMappingURL=index.esm2017.mjs.map