@microsoft/teamsfx 2.2.3-alpha.9b38c38b5.0 → 2.2.3-alpha.a0d5ed36e.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/README.md +165 -115
- package/dist/index.esm2017.js +84 -62
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +120 -48
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +95 -108
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +281 -211
- package/dist/index.node.cjs.js.map +1 -1
- package/package.json +26 -10
- package/types/teamsfx.d.ts +35 -5
package/dist/index.esm2017.mjs
CHANGED
@@ -10,7 +10,6 @@ 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';
|
14
13
|
import { AdaptiveCards } from '@microsoft/adaptivecards-tools';
|
15
14
|
|
16
15
|
// Copyright (c) Microsoft Corporation.
|
@@ -396,6 +395,7 @@ function getAuthority(authorityHost, tenantId) {
|
|
396
395
|
return normalizedAuthorityHost + "/" + tenantId;
|
397
396
|
}
|
398
397
|
|
398
|
+
// Copyright (c) Microsoft Corporation.
|
399
399
|
/**
|
400
400
|
* @internal
|
401
401
|
*/
|
@@ -713,16 +713,16 @@ class TeamsUserCredential {
|
|
713
713
|
* @remarks
|
714
714
|
* Can only be used within Teams.
|
715
715
|
*/
|
716
|
-
|
717
|
-
|
716
|
+
login(scopes, resources) {
|
717
|
+
return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
|
718
718
|
}
|
719
719
|
/**
|
720
720
|
* Get access token from credential.
|
721
721
|
* @remarks
|
722
722
|
* Can only be used within Teams.
|
723
723
|
*/
|
724
|
-
|
725
|
-
|
724
|
+
getToken(scopes, options) {
|
725
|
+
return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
|
726
726
|
}
|
727
727
|
/**
|
728
728
|
* Get basic user info from SSO token
|
@@ -733,14 +733,16 @@ class TeamsUserCredential {
|
|
733
733
|
* Can only be used within Teams.
|
734
734
|
*/
|
735
735
|
getUserInfo(resources) {
|
736
|
-
|
736
|
+
return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported));
|
737
737
|
}
|
738
738
|
}
|
739
739
|
|
740
740
|
// Copyright (c) Microsoft Corporation.
|
741
741
|
const defaultScope = "https://graph.microsoft.com/.default";
|
742
|
+
// eslint-disable-next-line no-secrets/no-secrets
|
742
743
|
/**
|
743
744
|
* Microsoft Graph auth provider for Teams Framework
|
745
|
+
* @deprecated Use `TokenCredentialAuthenticationProvider` from `@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials` instead.
|
744
746
|
*/
|
745
747
|
class MsGraphAuthProvider {
|
746
748
|
constructor(credentialOrTeamsFx, scopes) {
|
@@ -769,7 +771,7 @@ class MsGraphAuthProvider {
|
|
769
771
|
*
|
770
772
|
*/
|
771
773
|
async getAccessToken() {
|
772
|
-
internalLogger.info(`Get Graph Access token with scopes: '${this.scopes}'`);
|
774
|
+
internalLogger.info(`Get Graph Access token with scopes: '${this.scopes.toString()}'`);
|
773
775
|
let accessToken;
|
774
776
|
if (this.credentialOrTeamsFx.getCredential) {
|
775
777
|
accessToken = await this.credentialOrTeamsFx
|
@@ -795,6 +797,14 @@ class MsGraphAuthProvider {
|
|
795
797
|
// Copyright (c) Microsoft Corporation.
|
796
798
|
/**
|
797
799
|
* Get Microsoft graph client.
|
800
|
+
* @deprecated Use `TokenCredentialAuthenticationProvider` and `Client.initWithMiddleware` instead.
|
801
|
+
* ```typescript
|
802
|
+
* const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: scope });
|
803
|
+
* const graph = Client.initWithMiddleware({
|
804
|
+
* authProvider: authProvider,
|
805
|
+
* });
|
806
|
+
* ```
|
807
|
+
*
|
798
808
|
* @example
|
799
809
|
* Get Microsoft graph client by TokenCredential
|
800
810
|
* ```typescript
|
@@ -852,6 +862,14 @@ function createMicrosoftGraphClient(teamsfx, scopes) {
|
|
852
862
|
// eslint-disable-next-line no-secrets/no-secrets
|
853
863
|
/**
|
854
864
|
* Get Microsoft graph client.
|
865
|
+
* @deprecated Use `TokenCredentialAuthenticationProvider` and `Client.initWithMiddleware` instead.
|
866
|
+
* ```typescript
|
867
|
+
* const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: scope });
|
868
|
+
* const graph = Client.initWithMiddleware({
|
869
|
+
* authProvider: authProvider,
|
870
|
+
* });
|
871
|
+
* ```
|
872
|
+
*
|
855
873
|
* @example
|
856
874
|
* Get Microsoft graph client by TokenCredential
|
857
875
|
* ```typescript
|
@@ -1007,7 +1025,7 @@ function isMsiAuthentication(teamsfx) {
|
|
1007
1025
|
function generateDefaultConfig(teamsfx, databaseName) {
|
1008
1026
|
internalLogger.verbose(`SQL server ${teamsfx.getConfig("sqlServerEndpoint")}
|
1009
1027
|
, user name ${teamsfx.getConfig("sqlUsername")}
|
1010
|
-
, database name ${databaseName}`);
|
1028
|
+
, database name ${databaseName ? databaseName : ""}`);
|
1011
1029
|
const config = {
|
1012
1030
|
server: teamsfx.getConfig("sqlServerEndpoint"),
|
1013
1031
|
authentication: {
|
@@ -1060,7 +1078,7 @@ async function generateTokenConfig(teamsfx, databaseName) {
|
|
1060
1078
|
};
|
1061
1079
|
internalLogger.verbose(`Generate token configuration success
|
1062
1080
|
, server endpoint is ${teamsfx.getConfig("sqlServerEndpoint")}
|
1063
|
-
, database name is ${databaseName}`);
|
1081
|
+
, database name is ${databaseName ? databaseName : ""}`);
|
1064
1082
|
return config;
|
1065
1083
|
}
|
1066
1084
|
internalLogger.error(`Generate token configuration
|
@@ -1328,7 +1346,8 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
1328
1346
|
async sendOAuthCardAsync(context) {
|
1329
1347
|
internalLogger.verbose("Send OAuth card to get SSO token");
|
1330
1348
|
const account = await TeamsInfo.getMember(context, context.activity.from.id);
|
1331
|
-
internalLogger.verbose("Get Teams member account user principal name: " +
|
1349
|
+
internalLogger.verbose("Get Teams member account user principal name: " +
|
1350
|
+
(account.userPrincipalName ? account.userPrincipalName : ""));
|
1332
1351
|
const loginHint = account.userPrincipalName ? account.userPrincipalName : "";
|
1333
1352
|
const signInResource = this.getSignInResource(loginHint);
|
1334
1353
|
const card = CardFactory.oauthCard("", "Teams SSO Sign In", "Sign In", signInResource.signInLink, signInResource.tokenExchangeResource);
|
@@ -1528,18 +1547,18 @@ class BasicAuthProvider {
|
|
1528
1547
|
* @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when Authorization header or auth property already exists in request configuration.
|
1529
1548
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
1530
1549
|
*/
|
1531
|
-
|
1550
|
+
AddAuthenticationInfo(config) {
|
1532
1551
|
if (config.headers && config.headers["Authorization"]) {
|
1533
|
-
|
1552
|
+
return Promise.reject(new ErrorWithCode(ErrorMessage.AuthorizationHeaderAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists));
|
1534
1553
|
}
|
1535
1554
|
if (config.auth) {
|
1536
|
-
|
1555
|
+
return Promise.reject(new ErrorWithCode(ErrorMessage.BasicCredentialAlreadyExists, ErrorCode.AuthorizationInfoAlreadyExists));
|
1537
1556
|
}
|
1538
1557
|
config.auth = {
|
1539
1558
|
username: this.userName,
|
1540
1559
|
password: this.password,
|
1541
1560
|
};
|
1542
|
-
return config;
|
1561
|
+
return Promise.resolve(config);
|
1543
1562
|
}
|
1544
1563
|
}
|
1545
1564
|
|
@@ -1579,14 +1598,14 @@ class ApiKeyProvider {
|
|
1579
1598
|
* @throws {@link ErrorCode|AuthorizationInfoAlreadyExists} - when API key already exists in request header or url query parameter.
|
1580
1599
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
1581
1600
|
*/
|
1582
|
-
|
1601
|
+
AddAuthenticationInfo(config) {
|
1583
1602
|
switch (this.keyLocation) {
|
1584
1603
|
case ApiKeyLocation.Header:
|
1585
1604
|
if (!config.headers) {
|
1586
1605
|
config.headers = {};
|
1587
1606
|
}
|
1588
1607
|
if (config.headers[this.keyName]) {
|
1589
|
-
|
1608
|
+
return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInHeader, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists));
|
1590
1609
|
}
|
1591
1610
|
config.headers[this.keyName] = this.keyValue;
|
1592
1611
|
break;
|
@@ -1600,12 +1619,12 @@ class ApiKeyProvider {
|
|
1600
1619
|
urlHasDefinedApiKey = url.searchParams.has(this.keyName);
|
1601
1620
|
}
|
1602
1621
|
if (config.params[this.keyName] || urlHasDefinedApiKey) {
|
1603
|
-
|
1622
|
+
return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateApiKeyInQueryParam, this.keyName), ErrorCode.AuthorizationInfoAlreadyExists));
|
1604
1623
|
}
|
1605
1624
|
config.params[this.keyName] = this.keyValue;
|
1606
1625
|
break;
|
1607
1626
|
}
|
1608
|
-
return config;
|
1627
|
+
return Promise.resolve(config);
|
1609
1628
|
}
|
1610
1629
|
}
|
1611
1630
|
/**
|
@@ -1652,7 +1671,7 @@ class CertificateAuthProvider {
|
|
1652
1671
|
*
|
1653
1672
|
* @throws {@link ErrorCode|InvalidParameter} - when custom httpsAgent in the request has duplicate properties with certOption provided in constructor.
|
1654
1673
|
*/
|
1655
|
-
|
1674
|
+
AddAuthenticationInfo(config) {
|
1656
1675
|
if (!config.httpsAgent) {
|
1657
1676
|
config.httpsAgent = new Agent(this.certOption);
|
1658
1677
|
}
|
@@ -1660,12 +1679,12 @@ class CertificateAuthProvider {
|
|
1660
1679
|
const existingProperties = new Set(Object.keys(config.httpsAgent.options));
|
1661
1680
|
for (const property of Object.keys(this.certOption)) {
|
1662
1681
|
if (existingProperties.has(property)) {
|
1663
|
-
|
1682
|
+
return Promise.reject(new ErrorWithCode(formatString(ErrorMessage.DuplicateHttpsOptionProperty, property), ErrorCode.InvalidParameter));
|
1664
1683
|
}
|
1665
1684
|
}
|
1666
1685
|
Object.assign(config.httpsAgent.options, this.certOption);
|
1667
1686
|
}
|
1668
|
-
return config;
|
1687
|
+
return Promise.resolve(config);
|
1669
1688
|
}
|
1670
1689
|
}
|
1671
1690
|
/**
|
@@ -1734,6 +1753,8 @@ const ReservedKey = new Set([
|
|
1734
1753
|
]);
|
1735
1754
|
/**
|
1736
1755
|
* A class providing credential and configuration.
|
1756
|
+
* @deprecated Please use {@link TeamsUserCredential}
|
1757
|
+
* in browser environment and {@link OnBehalfOfUserCredential} or {@link AppCredential} in NodeJS.
|
1737
1758
|
*/
|
1738
1759
|
class TeamsFx {
|
1739
1760
|
/**
|
@@ -1963,6 +1984,7 @@ var InvokeResponseErrorCode;
|
|
1963
1984
|
InvokeResponseErrorCode[InvokeResponseErrorCode["InternalServerError"] = 500] = "InternalServerError";
|
1964
1985
|
})(InvokeResponseErrorCode || (InvokeResponseErrorCode = {}));
|
1965
1986
|
|
1987
|
+
// Copyright (c) Microsoft Corporation.
|
1966
1988
|
/**
|
1967
1989
|
* Available response type for an adaptive card invoke response.
|
1968
1990
|
* @internal
|
@@ -1977,7 +1999,7 @@ var InvokeResponseType;
|
|
1977
1999
|
* Provides methods for formatting various invoke responses a bot can send to respond to an invoke request.
|
1978
2000
|
*
|
1979
2001
|
* @remarks
|
1980
|
-
* All of these functions return an
|
2002
|
+
* All of these functions return an `InvokeResponse` object, which can be
|
1981
2003
|
* passed as input to generate a new `invokeResponse` activity.
|
1982
2004
|
*
|
1983
2005
|
* This example sends an invoke response that contains an adaptive card.
|
@@ -2402,6 +2424,7 @@ function cloneConversation(conversation) {
|
|
2402
2424
|
*/
|
2403
2425
|
function getKey(reference) {
|
2404
2426
|
var _a, _b;
|
2427
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
2405
2428
|
return `_${(_a = reference.conversation) === null || _a === void 0 ? void 0 : _a.tenantId}_${(_b = reference.conversation) === null || _b === void 0 ? void 0 : _b.id}`;
|
2406
2429
|
}
|
2407
2430
|
/**
|
@@ -2719,7 +2742,7 @@ class Channel$1 {
|
|
2719
2742
|
async sendMessage(text, onError) {
|
2720
2743
|
const response = {};
|
2721
2744
|
await this.parent.adapter.continueConversation(this.parent.conversationReference, async (context) => {
|
2722
|
-
const conversation =
|
2745
|
+
const conversation = this.newConversation(context);
|
2723
2746
|
await this.parent.adapter.continueConversation(conversation, async (ctx) => {
|
2724
2747
|
try {
|
2725
2748
|
const res = await ctx.sendActivity(text);
|
@@ -2748,7 +2771,7 @@ class Channel$1 {
|
|
2748
2771
|
async sendAdaptiveCard(card, onError) {
|
2749
2772
|
const response = {};
|
2750
2773
|
await this.parent.adapter.continueConversation(this.parent.conversationReference, async (context) => {
|
2751
|
-
const conversation =
|
2774
|
+
const conversation = this.newConversation(context);
|
2752
2775
|
await this.parent.adapter.continueConversation(conversation, async (ctx) => {
|
2753
2776
|
try {
|
2754
2777
|
const res = await ctx.sendActivity({
|
@@ -2771,7 +2794,7 @@ class Channel$1 {
|
|
2771
2794
|
/**
|
2772
2795
|
* @internal
|
2773
2796
|
*/
|
2774
|
-
|
2797
|
+
newConversation(context) {
|
2775
2798
|
const reference = TurnContext.getConversationReference(context.activity);
|
2776
2799
|
const channelConversation = cloneConversation(reference);
|
2777
2800
|
channelConversation.conversation.id = this.info.id || "";
|
@@ -3200,6 +3223,38 @@ var SearchScope$1;
|
|
3200
3223
|
SearchScope[SearchScope["All"] = 7] = "All";
|
3201
3224
|
})(SearchScope$1 || (SearchScope$1 = {}));
|
3202
3225
|
|
3226
|
+
/******************************************************************************
|
3227
|
+
Copyright (c) Microsoft Corporation.
|
3228
|
+
|
3229
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
3230
|
+
purpose with or without fee is hereby granted.
|
3231
|
+
|
3232
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
3233
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
3234
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
3235
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
3236
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
3237
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
3238
|
+
PERFORMANCE OF THIS SOFTWARE.
|
3239
|
+
***************************************************************************** */
|
3240
|
+
|
3241
|
+
function __rest(s, e) {
|
3242
|
+
var t = {};
|
3243
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
3244
|
+
t[p] = s[p];
|
3245
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
3246
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
3247
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
3248
|
+
t[p[i]] = s[p[i]];
|
3249
|
+
}
|
3250
|
+
return t;
|
3251
|
+
}
|
3252
|
+
|
3253
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
3254
|
+
var e = new Error(message);
|
3255
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
3256
|
+
};
|
3257
|
+
|
3203
3258
|
// Copyright (c) Microsoft Corporation.
|
3204
3259
|
let DIALOG_NAME = "BotSsoExecutionDialog";
|
3205
3260
|
let TEAMS_SSO_PROMPT_ID = "TeamsFxSsoPrompt";
|
@@ -3481,8 +3536,7 @@ class DefaultBotSsoExecutionActivityHandler extends TeamsActivityHandler {
|
|
3481
3536
|
timeout: (_h = (_g = ssoConfig.dialog) === null || _g === void 0 ? void 0 : _g.ssoPromptConfig) === null || _h === void 0 ? void 0 : _h.timeout,
|
3482
3537
|
endOnInvalidMessage: (_k = (_j = ssoConfig.dialog) === null || _j === void 0 ? void 0 : _j.ssoPromptConfig) === null || _k === void 0 ? void 0 : _k.endOnInvalidMessage,
|
3483
3538
|
};
|
3484
|
-
|
3485
|
-
this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, teamsfx);
|
3539
|
+
this.ssoExecutionDialog = new BotSsoExecutionDialog(dedupStorage, settings, customConfig, customConfig.initiateLoginEndpoint);
|
3486
3540
|
this.conversationState = conversationState;
|
3487
3541
|
this.dialogState = conversationState.createProperty("DialogState");
|
3488
3542
|
this.userState = userState;
|
@@ -3533,7 +3587,7 @@ class DefaultBotSsoExecutionActivityHandler extends TeamsActivityHandler {
|
|
3533
3587
|
* @param query Signin state (part of signin action auth flow) verification invoke query
|
3534
3588
|
* @returns A promise that represents the work queued.
|
3535
3589
|
*
|
3536
|
-
* @
|
3590
|
+
* @remarks
|
3537
3591
|
* It should trigger {@link BotSsoExecutionDialog} instance to handle signin process
|
3538
3592
|
*/
|
3539
3593
|
async handleTeamsSigninTokenExchange(context, query) {
|
@@ -3643,9 +3697,12 @@ class ConversationBot$1 {
|
|
3643
3697
|
// the default error handler
|
3644
3698
|
adapter.onTurnError = async (context, error) => {
|
3645
3699
|
// This check writes out errors to console.
|
3700
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
3646
3701
|
console.error(`[onTurnError] unhandled error: ${error}`);
|
3647
3702
|
// Send a trace activity, which will be displayed in Bot Framework Emulator
|
3648
|
-
await context.sendTraceActivity("OnTurnError Trace",
|
3703
|
+
await context.sendTraceActivity("OnTurnError Trace",
|
3704
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
3705
|
+
`${error}`, "https://www.botframework.com/schemas/error", "TurnError");
|
3649
3706
|
// Send a message to the user
|
3650
3707
|
await context.sendActivity(`The bot encountered unhandled error: ${error.message}`);
|
3651
3708
|
await context.sendActivity("To continue to run this bot, please fix the bot source code.");
|
@@ -3924,6 +3981,7 @@ async function executionWithTokenAndConfig(context, authConfig, initiateLoginEnd
|
|
3924
3981
|
}
|
3925
3982
|
/**
|
3926
3983
|
* execution in message extension with SSO token.
|
3984
|
+
* @deprecated Use {@link executionWithTokenAndConfig} instead.
|
3927
3985
|
*
|
3928
3986
|
* @param {TurnContext} context - The context object for the current turn.
|
3929
3987
|
* @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
|
@@ -3972,7 +4030,7 @@ async function executionWithToken(context, config, scopes, logic) {
|
|
3972
4030
|
// eslint-disable-next-line no-secrets/no-secrets
|
3973
4031
|
/**
|
3974
4032
|
* Users execute query in message extension with SSO or access token.
|
3975
|
-
*
|
4033
|
+
* @deprecated Use {@link handleMessageExtensionQueryWithSSO} instead.
|
3976
4034
|
*
|
3977
4035
|
* @param {TurnContext} context - The context object for the current turn.
|
3978
4036
|
* @param {AuthenticationConfiguration} config - User custom the message extension authentication configuration.
|
@@ -4245,11 +4303,11 @@ class Channel {
|
|
4245
4303
|
/**
|
4246
4304
|
* @internal
|
4247
4305
|
*/
|
4248
|
-
|
4306
|
+
newConversation(context) {
|
4249
4307
|
const reference = TurnContext.getConversationReference(context.activity);
|
4250
4308
|
const channelConversation = cloneConversation(reference);
|
4251
4309
|
channelConversation.conversation.id = this.info.id || "";
|
4252
|
-
return channelConversation;
|
4310
|
+
return Promise.resolve(channelConversation);
|
4253
4311
|
}
|
4254
4312
|
}
|
4255
4313
|
/**
|
@@ -4556,6 +4614,27 @@ class NotificationBot {
|
|
4556
4614
|
}
|
4557
4615
|
return new TeamsBotInstallation(this.adapter, conversationReference, this.botAppId);
|
4558
4616
|
}
|
4617
|
+
/**
|
4618
|
+
* Validate the installation by getting paged memebers.
|
4619
|
+
*
|
4620
|
+
* @param conversationReference The bound `ConversationReference`.
|
4621
|
+
* @returns Returns false if recieves `BotNotInConversationRoster` error, otherwise returns true.
|
4622
|
+
*/
|
4623
|
+
async validateInstallation(conversationReference) {
|
4624
|
+
let isValid = true;
|
4625
|
+
await this.adapter.continueConversationAsync(this.botAppId, conversationReference, async (context) => {
|
4626
|
+
try {
|
4627
|
+
// try get member to see if the installation is still valid
|
4628
|
+
await TeamsInfo.getPagedMembers(context, 1);
|
4629
|
+
}
|
4630
|
+
catch (error) {
|
4631
|
+
if (error.code === "BotNotInConversationRoster") {
|
4632
|
+
isValid = false;
|
4633
|
+
}
|
4634
|
+
}
|
4635
|
+
});
|
4636
|
+
return isValid;
|
4637
|
+
}
|
4559
4638
|
/**
|
4560
4639
|
* Gets a pagined list of targets where the bot is installed.
|
4561
4640
|
*
|
@@ -4567,7 +4646,7 @@ class NotificationBot {
|
|
4567
4646
|
*
|
4568
4647
|
* @returns An array of {@link TeamsBotInstallation} with paged data and continuation token.
|
4569
4648
|
*/
|
4570
|
-
async getPagedInstallations(pageSize, continuationToken) {
|
4649
|
+
async getPagedInstallations(pageSize, continuationToken, validationEnabled = true) {
|
4571
4650
|
if (this.conversationReferenceStore === undefined || this.adapter === undefined) {
|
4572
4651
|
throw new Error("NotificationBot has not been initialized.");
|
4573
4652
|
}
|
@@ -4575,19 +4654,12 @@ class NotificationBot {
|
|
4575
4654
|
const targets = [];
|
4576
4655
|
for (const reference of references.data) {
|
4577
4656
|
// validate connection
|
4578
|
-
let valid
|
4579
|
-
|
4580
|
-
try
|
4581
|
-
|
4582
|
-
|
4583
|
-
|
4584
|
-
catch (error) {
|
4585
|
-
if (error.code === "BotNotInConversationRoster") {
|
4586
|
-
valid = false;
|
4587
|
-
}
|
4588
|
-
}
|
4589
|
-
});
|
4590
|
-
if (valid) {
|
4657
|
+
let valid;
|
4658
|
+
if (validationEnabled) {
|
4659
|
+
// try get member to see if the installation is still valid
|
4660
|
+
valid = await this.validateInstallation(reference);
|
4661
|
+
}
|
4662
|
+
if (!validationEnabled || (validationEnabled && valid)) {
|
4591
4663
|
targets.push(new TeamsBotInstallation(this.adapter, reference, this.botAppId));
|
4592
4664
|
}
|
4593
4665
|
else {
|
@@ -4849,9 +4921,9 @@ class ConversationBot {
|
|
4849
4921
|
// the default error handler
|
4850
4922
|
adapter.onTurnError = async (context, error) => {
|
4851
4923
|
// This check writes out errors to console.
|
4852
|
-
console.error(`[onTurnError] unhandled error
|
4924
|
+
console.error(`[onTurnError] unhandled error`, error);
|
4853
4925
|
// Send a trace activity, which will be displayed in Bot Framework Emulator
|
4854
|
-
await context.sendTraceActivity("OnTurnError Trace",
|
4926
|
+
await context.sendTraceActivity("OnTurnError Trace", error instanceof Error ? error.message : error, "https://www.botframework.com/schemas/error", "TurnError");
|
4855
4927
|
// Send a message to the user
|
4856
4928
|
await context.sendActivity(`The bot encountered unhandled error: ${error.message}`);
|
4857
4929
|
await context.sendActivity("To continue to run this bot, please fix the bot source code.");
|