@microsoft/teamsfx 2.2.3-alpha.9b38c38b5.0 → 2.2.3-beta.2023080907.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.
@@ -396,6 +396,7 @@ function getAuthority(authorityHost, tenantId) {
396
396
  return normalizedAuthorityHost + "/" + tenantId;
397
397
  }
398
398
 
399
+ // Copyright (c) Microsoft Corporation.
399
400
  /**
400
401
  * @internal
401
402
  */
@@ -713,16 +714,16 @@ class TeamsUserCredential {
713
714
  * @remarks
714
715
  * Can only be used within Teams.
715
716
  */
716
- async login(scopes, resources) {
717
- throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
717
+ login(scopes, resources) {
718
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
718
719
  }
719
720
  /**
720
721
  * Get access token from credential.
721
722
  * @remarks
722
723
  * Can only be used within Teams.
723
724
  */
724
- async getToken(scopes, options) {
725
- throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
725
+ getToken(scopes, options) {
726
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
726
727
  }
727
728
  /**
728
729
  * Get basic user info from SSO token
@@ -733,14 +734,16 @@ class TeamsUserCredential {
733
734
  * Can only be used within Teams.
734
735
  */
735
736
  getUserInfo(resources) {
736
- throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
737
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
737
738
  }
738
739
  }
739
740
 
740
741
  // Copyright (c) Microsoft Corporation.
741
742
  const defaultScope = "https://graph.microsoft.com/.default";
743
+ // eslint-disable-next-line no-secrets/no-secrets
742
744
  /**
743
745
  * Microsoft Graph auth provider for Teams Framework
746
+ * @deprecated Use `TokenCredentialAuthenticationProvider` from `@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials` instead.
744
747
  */
745
748
  class MsGraphAuthProvider {
746
749
  constructor(credentialOrTeamsFx, scopes) {
@@ -769,7 +772,7 @@ class MsGraphAuthProvider {
769
772
  *
770
773
  */
771
774
  async getAccessToken() {
772
- internalLogger.info(`Get Graph Access token with scopes: '${this.scopes}'`);
775
+ internalLogger.info(`Get Graph Access token with scopes: '${this.scopes.toString()}'`);
773
776
  let accessToken;
774
777
  if (this.credentialOrTeamsFx.getCredential) {
775
778
  accessToken = await this.credentialOrTeamsFx
@@ -795,6 +798,14 @@ class MsGraphAuthProvider {
795
798
  // Copyright (c) Microsoft Corporation.
796
799
  /**
797
800
  * Get Microsoft graph client.
801
+ * @deprecated Use `TokenCredentialAuthenticationProvider` and `Client.initWithMiddleware` instead.
802
+ * ```typescript
803
+ * const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: scope });
804
+ * const graph = Client.initWithMiddleware({
805
+ * authProvider: authProvider,
806
+ * });
807
+ * ```
808
+ *
798
809
  * @example
799
810
  * Get Microsoft graph client by TokenCredential
800
811
  * ```typescript
@@ -852,6 +863,14 @@ function createMicrosoftGraphClient(teamsfx, scopes) {
852
863
  // eslint-disable-next-line no-secrets/no-secrets
853
864
  /**
854
865
  * Get Microsoft graph client.
866
+ * @deprecated Use `TokenCredentialAuthenticationProvider` and `Client.initWithMiddleware` instead.
867
+ * ```typescript
868
+ * const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: scope });
869
+ * const graph = Client.initWithMiddleware({
870
+ * authProvider: authProvider,
871
+ * });
872
+ * ```
873
+ *
855
874
  * @example
856
875
  * Get Microsoft graph client by TokenCredential
857
876
  * ```typescript
@@ -1007,7 +1026,7 @@ function isMsiAuthentication(teamsfx) {
1007
1026
  function generateDefaultConfig(teamsfx, databaseName) {
1008
1027
  internalLogger.verbose(`SQL server ${teamsfx.getConfig("sqlServerEndpoint")}
1009
1028
  , user name ${teamsfx.getConfig("sqlUsername")}
1010
- , database name ${databaseName}`);
1029
+ , database name ${databaseName ? databaseName : ""}`);
1011
1030
  const config = {
1012
1031
  server: teamsfx.getConfig("sqlServerEndpoint"),
1013
1032
  authentication: {
@@ -1060,7 +1079,7 @@ async function generateTokenConfig(teamsfx, databaseName) {
1060
1079
  };
1061
1080
  internalLogger.verbose(`Generate token configuration success
1062
1081
  , server endpoint is ${teamsfx.getConfig("sqlServerEndpoint")}
1063
- , database name is ${databaseName}`);
1082
+ , database name is ${databaseName ? databaseName : ""}`);
1064
1083
  return config;
1065
1084
  }
1066
1085
  internalLogger.error(`Generate token configuration
@@ -1328,7 +1347,8 @@ class TeamsBotSsoPrompt extends Dialog {
1328
1347
  async sendOAuthCardAsync(context) {
1329
1348
  internalLogger.verbose("Send OAuth card to get SSO token");
1330
1349
  const account = await TeamsInfo.getMember(context, context.activity.from.id);
1331
- internalLogger.verbose("Get Teams member account user principal name: " + account.userPrincipalName);
1350
+ internalLogger.verbose("Get Teams member account user principal name: " +
1351
+ (account.userPrincipalName ? account.userPrincipalName : ""));
1332
1352
  const loginHint = account.userPrincipalName ? account.userPrincipalName : "";
1333
1353
  const signInResource = this.getSignInResource(loginHint);
1334
1354
  const card = CardFactory.oauthCard("", "Teams SSO Sign In", "Sign In", signInResource.signInLink, signInResource.tokenExchangeResource);
@@ -1528,18 +1548,18 @@ class BasicAuthProvider {
1528
1548
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when Authorization header or auth property already exists in request configuration.
1529
1549
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1530
1550
  */
1531
- async AddAuthenticationInfo(config) {
1551
+ AddAuthenticationInfo(config) {
1532
1552
  if (config.headers && config.headers["Authorization"]) {
1533
- throw new ErrorWithCode(ErrorMessage.AuthorizationHeaderAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists);
1553
+ return Promise.reject(new ErrorWithCode(ErrorMessage.AuthorizationHeaderAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists));
1534
1554
  }
1535
1555
  if (config.auth) {
1536
- throw new ErrorWithCode(ErrorMessage.BasicCredentialAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists);
1556
+ return Promise.reject(new ErrorWithCode(ErrorMessage.BasicCredentialAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists));
1537
1557
  }
1538
1558
  config.auth = {
1539
1559
  username: this.userName,
1540
1560
  password: this.password,
1541
1561
  };
1542
- return config;
1562
+ return Promise.resolve(config);
1543
1563
  }
1544
1564
  }
1545
1565
 
@@ -1579,14 +1599,14 @@ class ApiKeyProvider {
1579
1599
  * @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when API key already exists in request header or url query parameter.
1580
1600
  * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
1581
1601
  */
1582
- async AddAuthenticationInfo(config) {
1602
+ AddAuthenticationInfo(config) {
1583
1603
  switch (this.keyLocation) {
1584
1604
  case ApiKeyLocation.Header:
1585
1605
  if (!config.headers) {
1586
1606
  config.headers = {};
1587
1607
  }
1588
1608
  if (config.headers[this.keyName]) {
1589
- throw new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInHeader, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists);
1609
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInHeader, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists));
1590
1610
  }
1591
1611
  config.headers[this.keyName] = this.keyValue;
1592
1612
  break;
@@ -1600,12 +1620,12 @@ class ApiKeyProvider {
1600
1620
  urlHasDefinedApiKey = url.searchParams.has(this.keyName);
1601
1621
  }
1602
1622
  if (config.params[this.keyName] || urlHasDefinedApiKey) {
1603
- throw new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInQueryParam, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists);
1623
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInQueryParam, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists));
1604
1624
  }
1605
1625
  config.params[this.keyName] = this.keyValue;
1606
1626
  break;
1607
1627
  }
1608
- return config;
1628
+ return Promise.resolve(config);
1609
1629
  }
1610
1630
  }
1611
1631
  /**
@@ -1652,7 +1672,7 @@ class CertificateAuthProvider {
1652
1672
  *
1653
1673
  * @throws {@link ErrorCode|InvalidParameter} - when custom httpsAgent in the request has duplicate properties with certOption provided in constructor.
1654
1674
  */
1655
- async AddAuthenticationInfo(config) {
1675
+ AddAuthenticationInfo(config) {
1656
1676
  if (!config.httpsAgent) {
1657
1677
  config.httpsAgent = new Agent(this.certOption);
1658
1678
  }
@@ -1660,12 +1680,12 @@ class CertificateAuthProvider {
1660
1680
  const existingProperties = new Set(Object.keys(config.httpsAgent.options));
1661
1681
  for (const property of Object.keys(this.certOption)) {
1662
1682
  if (existingProperties.has(property)) {
1663
- throw new ErrorWithCode(formatString(ErrorMessage.DuplicateHttpsOptionProperty, property), ErrorCode.InvalidParameter);
1683
+ return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateHttpsOptionProperty, property), ErrorCode.InvalidParameter));
1664
1684
  }
1665
1685
  }
1666
1686
  Object.assign(config.httpsAgent.options, this.certOption);
1667
1687
  }
1668
- return config;
1688
+ return Promise.resolve(config);
1669
1689
  }
1670
1690
  }
1671
1691
  /**
@@ -1734,6 +1754,8 @@ const ReservedKey = new Set([
1734
1754
  ]);
1735
1755
  /**
1736
1756
  * A class providing credential and configuration.
1757
+ * @deprecated Please use {@link TeamsUserCredential}
1758
+ * in browser environment and {@link OnBehalfOfUserCredential} or {@link AppCredential} in NodeJS.
1737
1759
  */
1738
1760
  class TeamsFx {
1739
1761
  /**
@@ -2719,7 +2741,7 @@ class Channel$1 {
2719
2741
  async sendMessage(text, onError) {
2720
2742
  const response = {};
2721
2743
  await this.parent.adapter.continueConversation(this.parent.conversationReference, async (context) => {
2722
- const conversation = await this.newConversation(context);
2744
+ const conversation = this.newConversation(context);
2723
2745
  await this.parent.adapter.continueConversation(conversation, async (ctx) => {
2724
2746
  try {
2725
2747
  const res = await ctx.sendActivity(text);
@@ -2748,7 +2770,7 @@ class Channel$1 {
2748
2770
  async sendAdaptiveCard(card, onError) {
2749
2771
  const response = {};
2750
2772
  await this.parent.adapter.continueConversation(this.parent.conversationReference, async (context) => {
2751
- const conversation = await this.newConversation(context);
2773
+ const conversation = this.newConversation(context);
2752
2774
  await this.parent.adapter.continueConversation(conversation, async (ctx) => {
2753
2775
  try {
2754
2776
  const res = await ctx.sendActivity({
@@ -2771,7 +2793,7 @@ class Channel$1 {
2771
2793
  /**
2772
2794
  * @internal
2773
2795
  */
2774
- async newConversation(context) {
2796
+ newConversation(context) {
2775
2797
  const reference = TurnContext.getConversationReference(context.activity);
2776
2798
  const channelConversation = cloneConversation(reference);
2777
2799
  channelConversation.conversation.id = this.info.id || "";
@@ -3481,8 +3503,7 @@ class DefaultBotSsoExecutionActivityHandler extends TeamsActivityHandler {
3481
3503
  timeout: (_h = (_g = ssoConfig.dialog) === null || _g === void 0 ? void 0 : _g.ssoPromptConfig) === null || _h === void 0 ? void 0 : _h.timeout,
3482
3504
  endOnInvalidMessage: (_k = (_j = ssoConfig.dialog) === null || _j === void 0 ? void 0 : _j.ssoPromptConfig) === null || _k === void 0 ? void 0 : _k.endOnInvalidMessage,
3483
3505
  };
3484
- const teamsfx = new TeamsFx(IdentityType.User, Object.assign({}, customConfig));
3485
- this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, teamsfx);
3506
+ this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, customConfig, customConfig.initiateLoginEndpoint);
3486
3507
  this.conversationState = conversationState;
3487
3508
  this.dialogState = conversationState.createProperty("DialogState");
3488
3509
  this.userState = userState;
@@ -3924,6 +3945,7 @@ async function executionWithTokenAndConfig(context, authConfig, initiateLoginEnd
3924
3945
  }
3925
3946
  /**
3926
3947
  * execution in message extension with SSO token.
3948
+ * @deprecated Use {@link executionWithTokenAndConfig} instead.
3927
3949
  *
3928
3950
  * @param {TurnContext} context - The context object for the current turn.
3929
3951
  * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
@@ -3972,7 +3994,7 @@ async function executionWithToken(context, config, scopes, logic) {
3972
3994
  // eslint-disable-next-line no-secrets/no-secrets
3973
3995
  /**
3974
3996
  * Users execute query in message extension with SSO or access token.
3975
- *
3997
+ * @deprecated Use {@link handleMessageExtensionQueryWithSSO} instead.
3976
3998
  *
3977
3999
  * @param {TurnContext} context - The context object for the current turn.
3978
4000
  * @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
@@ -4245,11 +4267,11 @@ class Channel {
4245
4267
  /**
4246
4268
  * @internal
4247
4269
  */
4248
- async newConversation(context) {
4270
+ newConversation(context) {
4249
4271
  const reference = TurnContext.getConversationReference(context.activity);
4250
4272
  const channelConversation = cloneConversation(reference);
4251
4273
  channelConversation.conversation.id = this.info.id || "";
4252
- return channelConversation;
4274
+ return Promise.resolve(channelConversation);
4253
4275
  }
4254
4276
  }
4255
4277
  /**
@@ -4556,6 +4578,27 @@ class NotificationBot {
4556
4578
  }
4557
4579
  return new TeamsBotInstallation(this.adapter, conversationReference, this.botAppId);
4558
4580
  }
4581
+ /**
4582
+ * Validate the installation by getting paged memebers.
4583
+ *
4584
+ * @param conversationReference The bound `ConversationReference`.
4585
+ * @returns Returns false if recieves `BotNotInConversationRoster` error, otherwise returns true.
4586
+ */
4587
+ async validateInstallation(conversationReference) {
4588
+ let isValid = true;
4589
+ await this.adapter.continueConversationAsync(this.botAppId, conversationReference, async (context) => {
4590
+ try {
4591
+ // try get member to see if the installation is still valid
4592
+ await TeamsInfo.getPagedMembers(context, 1);
4593
+ }
4594
+ catch (error) {
4595
+ if (error.code === "BotNotInConversationRoster") {
4596
+ isValid = false;
4597
+ }
4598
+ }
4599
+ });
4600
+ return isValid;
4601
+ }
4559
4602
  /**
4560
4603
  * Gets a pagined list of targets where the bot is installed.
4561
4604
  *
@@ -4567,7 +4610,7 @@ class NotificationBot {
4567
4610
  *
4568
4611
  * @returns An array of {@link TeamsBotInstallation} with paged data and continuation token.
4569
4612
  */
4570
- async getPagedInstallations(pageSize, continuationToken) {
4613
+ async getPagedInstallations(pageSize, continuationToken, validationEnabled = true) {
4571
4614
  if (this.conversationReferenceStore === undefined || this.adapter === undefined) {
4572
4615
  throw new Error("NotificationBot has not been initialized.");
4573
4616
  }
@@ -4575,19 +4618,12 @@ class NotificationBot {
4575
4618
  const targets = [];
4576
4619
  for (const reference of references.data) {
4577
4620
  // validate connection
4578
- let valid = true;
4579
- await this.adapter.continueConversationAsync(this.botAppId, reference, async (context) => {
4580
- try {
4581
- // try get member to see if the installation is still valid
4582
- await TeamsInfo.getPagedMembers(context, 1);
4583
- }
4584
- catch (error) {
4585
- if (error.code === "BotNotInConversationRoster") {
4586
- valid = false;
4587
- }
4588
- }
4589
- });
4590
- if (valid) {
4621
+ let valid;
4622
+ if (validationEnabled) {
4623
+ // try get member to see if the installation is still valid
4624
+ valid = await this.validateInstallation(reference);
4625
+ }
4626
+ if (!validationEnabled || (validationEnabled && valid)) {
4591
4627
  targets.push(new TeamsBotInstallation(this.adapter, reference, this.botAppId));
4592
4628
  }
4593
4629
  else {
@@ -4849,9 +4885,9 @@ class ConversationBot {
4849
4885
  // the default error handler
4850
4886
  adapter.onTurnError = async (context, error) => {
4851
4887
  // This check writes out errors to console.
4852
- console.error(`[onTurnError] unhandled error: ${error}`);
4888
+ console.error(`[onTurnError] unhandled error`, error);
4853
4889
  // Send a trace activity, which will be displayed in Bot Framework Emulator
4854
- await context.sendTraceActivity("OnTurnError Trace", `${error}`, "https://www.botframework.com/schemas/error", "TurnError");
4890
+ await context.sendTraceActivity("OnTurnError Trace", error instanceof Error ? error.message : error, "https://www.botframework.com/schemas/error", "TurnError");
4855
4891
  // Send a message to the user
4856
4892
  await context.sendActivity(`The bot encountered unhandled error: ${error.message}`);
4857
4893
  await context.sendActivity("To continue to run this bot, please fix the bot source code.");