@microsoft/teamsfx 0.5.1-rc.0 → 0.5.2-alpha.1c67600f6.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 +151 -83
- package/dist/index.esm2017.js +152 -185
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +403 -344
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +159 -187
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +421 -360
- package/dist/index.node.cjs.js.map +1 -1
- package/package.json +3 -5
- package/types/teamsfx.d.ts +285 -231
package/dist/index.esm2017.mjs
CHANGED
|
@@ -63,6 +63,10 @@ var ErrorCode;
|
|
|
63
63
|
* Invalid response error.
|
|
64
64
|
*/
|
|
65
65
|
ErrorCode["InvalidResponse"] = "InvalidResponse";
|
|
66
|
+
/**
|
|
67
|
+
* Identity type error.
|
|
68
|
+
*/
|
|
69
|
+
ErrorCode["IdentityTypeNotSupported"] = "IdentityTypeNotSupported";
|
|
66
70
|
})(ErrorCode || (ErrorCode = {}));
|
|
67
71
|
/**
|
|
68
72
|
* @internal
|
|
@@ -82,6 +86,8 @@ ErrorMessage.NodejsRuntimeNotSupported = "{0} is not supported in Node.";
|
|
|
82
86
|
ErrorMessage.FailToAcquireTokenOnBehalfOfUser = "Failed to acquire access token on behalf of user: {0}";
|
|
83
87
|
// ChannelNotSupported Error
|
|
84
88
|
ErrorMessage.OnlyMSTeamsChannelSupported = "{0} is only supported in MS Teams Channel";
|
|
89
|
+
// IdentityTypeNotSupported Error
|
|
90
|
+
ErrorMessage.IdentityTypeNotSupported = "{0} identity is not supported in {1}";
|
|
85
91
|
/**
|
|
86
92
|
* Error class with code and message thrown by the SDK.
|
|
87
93
|
*
|
|
@@ -108,26 +114,6 @@ class ErrorWithCode extends Error {
|
|
|
108
114
|
}
|
|
109
115
|
}
|
|
110
116
|
|
|
111
|
-
// Copyright (c) Microsoft Corporation.
|
|
112
|
-
// Licensed under the MIT license.
|
|
113
|
-
/**
|
|
114
|
-
* Available resource type.
|
|
115
|
-
* @beta
|
|
116
|
-
*/
|
|
117
|
-
var ResourceType;
|
|
118
|
-
(function (ResourceType) {
|
|
119
|
-
/**
|
|
120
|
-
* SQL database.
|
|
121
|
-
*
|
|
122
|
-
*/
|
|
123
|
-
ResourceType[ResourceType["SQL"] = 0] = "SQL";
|
|
124
|
-
/**
|
|
125
|
-
* Rest API.
|
|
126
|
-
*
|
|
127
|
-
*/
|
|
128
|
-
ResourceType[ResourceType["API"] = 1] = "API";
|
|
129
|
-
})(ResourceType || (ResourceType = {}));
|
|
130
|
-
|
|
131
117
|
// Copyright (c) Microsoft Corporation.
|
|
132
118
|
// Licensed under the MIT license.
|
|
133
119
|
/**
|
|
@@ -370,131 +356,6 @@ function getScopesArray(scopes) {
|
|
|
370
356
|
function getAuthority(authorityHost, tenantId) {
|
|
371
357
|
const normalizedAuthorityHost = authorityHost.replace(/\/+$/g, "");
|
|
372
358
|
return normalizedAuthorityHost + "/" + tenantId;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* @internal
|
|
376
|
-
*/
|
|
377
|
-
const isNode = typeof process !== "undefined" &&
|
|
378
|
-
!!process.version &&
|
|
379
|
-
!!process.versions &&
|
|
380
|
-
!!process.versions.node;
|
|
381
|
-
|
|
382
|
-
// Copyright (c) Microsoft Corporation.
|
|
383
|
-
/**
|
|
384
|
-
* Global configuration instance
|
|
385
|
-
*
|
|
386
|
-
*/
|
|
387
|
-
let config;
|
|
388
|
-
/**
|
|
389
|
-
* Initialize configuration from environment variables or configuration object and set the global instance
|
|
390
|
-
*
|
|
391
|
-
* @param {Configuration} configuration - Optional configuration that overrides the default configuration values. The override depth is 1.
|
|
392
|
-
*
|
|
393
|
-
* @throws {@link ErrorCode|InvalidParameter} when configuration is not passed in browser environment
|
|
394
|
-
*
|
|
395
|
-
* @beta
|
|
396
|
-
*/
|
|
397
|
-
function loadConfiguration(configuration) {
|
|
398
|
-
internalLogger.info("load configuration");
|
|
399
|
-
// browser environment
|
|
400
|
-
if (!isNode) {
|
|
401
|
-
if (!configuration) {
|
|
402
|
-
const errorMsg = "You are running the code in browser. Configuration must be passed in.";
|
|
403
|
-
internalLogger.error(errorMsg);
|
|
404
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
405
|
-
}
|
|
406
|
-
config = configuration;
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
// node environment
|
|
410
|
-
let newAuthentication;
|
|
411
|
-
let newResources = [];
|
|
412
|
-
const defaultResourceName = "default";
|
|
413
|
-
if (configuration === null || configuration === void 0 ? void 0 : configuration.authentication) {
|
|
414
|
-
newAuthentication = configuration.authentication;
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
newAuthentication = {
|
|
418
|
-
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
419
|
-
tenantId: process.env.M365_TENANT_ID,
|
|
420
|
-
clientId: process.env.M365_CLIENT_ID,
|
|
421
|
-
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
422
|
-
simpleAuthEndpoint: process.env.SIMPLE_AUTH_ENDPOINT,
|
|
423
|
-
initiateLoginEndpoint: process.env.INITIATE_LOGIN_ENDPOINT,
|
|
424
|
-
applicationIdUri: process.env.M365_APPLICATION_ID_URI,
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
if (configuration === null || configuration === void 0 ? void 0 : configuration.resources) {
|
|
428
|
-
newResources = configuration.resources;
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
newResources = [
|
|
432
|
-
{
|
|
433
|
-
// SQL resource
|
|
434
|
-
type: ResourceType.SQL,
|
|
435
|
-
name: defaultResourceName,
|
|
436
|
-
properties: {
|
|
437
|
-
sqlServerEndpoint: process.env.SQL_ENDPOINT,
|
|
438
|
-
sqlUsername: process.env.SQL_USER_NAME,
|
|
439
|
-
sqlPassword: process.env.SQL_PASSWORD,
|
|
440
|
-
sqlDatabaseName: process.env.SQL_DATABASE_NAME,
|
|
441
|
-
sqlIdentityId: process.env.IDENTITY_ID,
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
// API resource
|
|
446
|
-
type: ResourceType.API,
|
|
447
|
-
name: defaultResourceName,
|
|
448
|
-
properties: {
|
|
449
|
-
endpoint: process.env.API_ENDPOINT,
|
|
450
|
-
},
|
|
451
|
-
},
|
|
452
|
-
];
|
|
453
|
-
}
|
|
454
|
-
config = {
|
|
455
|
-
authentication: newAuthentication,
|
|
456
|
-
resources: newResources,
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Get configuration for a specific resource.
|
|
461
|
-
* @param {ResourceType} resourceType - The type of resource
|
|
462
|
-
* @param {string} resourceName - The name of resource, default value is "default".
|
|
463
|
-
*
|
|
464
|
-
* @returns Resource configuration for target resource from global configuration instance.
|
|
465
|
-
*
|
|
466
|
-
* @throws {@link ErrorCode|InvalidConfiguration} when resource configuration with the specific type and name is not found
|
|
467
|
-
*
|
|
468
|
-
* @beta
|
|
469
|
-
*/
|
|
470
|
-
function getResourceConfiguration(resourceType, resourceName = "default") {
|
|
471
|
-
var _a;
|
|
472
|
-
internalLogger.info(`Get resource configuration of ${ResourceType[resourceType]} from ${resourceName}`);
|
|
473
|
-
const result = (_a = config.resources) === null || _a === void 0 ? void 0 : _a.find((item) => item.type === resourceType && item.name === resourceName);
|
|
474
|
-
if (result) {
|
|
475
|
-
return result.properties;
|
|
476
|
-
}
|
|
477
|
-
const errorMsg = formatString(ErrorMessage.MissingResourceConfiguration, ResourceType[resourceType], resourceName);
|
|
478
|
-
internalLogger.error(errorMsg);
|
|
479
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Get configuration for authentication.
|
|
483
|
-
*
|
|
484
|
-
* @returns Authentication configuration from global configuration instance, the value may be undefined if no authentication config exists in current environment.
|
|
485
|
-
*
|
|
486
|
-
* @throws {@link ErrorCode|InvalidConfiguration} when global configuration does not exist
|
|
487
|
-
*
|
|
488
|
-
* @beta
|
|
489
|
-
*/
|
|
490
|
-
function getAuthenticationConfiguration() {
|
|
491
|
-
internalLogger.info("Get authentication configuration");
|
|
492
|
-
if (config) {
|
|
493
|
-
return config.authentication;
|
|
494
|
-
}
|
|
495
|
-
const errorMsg = "Please call loadConfiguration() first before calling getAuthenticationConfiguration().";
|
|
496
|
-
internalLogger.error(errorMsg);
|
|
497
|
-
throw new ErrorWithCode(formatString(ErrorMessage.ConfigurationNotExists, errorMsg), ErrorCode.InvalidConfiguration);
|
|
498
359
|
}
|
|
499
360
|
|
|
500
361
|
/**
|
|
@@ -548,7 +409,7 @@ function parseCertificate(certificateContent) {
|
|
|
548
409
|
* @example
|
|
549
410
|
* ```typescript
|
|
550
411
|
* loadConfiguration(); // load configuration from environment variables
|
|
551
|
-
* const credential = new
|
|
412
|
+
* const credential = new AppCredential();
|
|
552
413
|
* ```
|
|
553
414
|
*
|
|
554
415
|
* @remarks
|
|
@@ -556,21 +417,23 @@ function parseCertificate(certificateContent) {
|
|
|
556
417
|
*
|
|
557
418
|
* @beta
|
|
558
419
|
*/
|
|
559
|
-
class
|
|
420
|
+
class AppCredential {
|
|
560
421
|
/**
|
|
561
|
-
* Constructor of
|
|
422
|
+
* Constructor of AppCredential.
|
|
562
423
|
*
|
|
563
424
|
* @remarks
|
|
564
425
|
* Only works in in server side.
|
|
565
426
|
*
|
|
427
|
+
* @param {AuthenticationConfiguration} authConfig - The authentication configuration. Use environment variables if not provided.
|
|
428
|
+
*
|
|
566
429
|
* @throws {@link ErrorCode|InvalidConfiguration} when client id, client secret or tenant id is not found in config.
|
|
567
430
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
568
431
|
*
|
|
569
432
|
* @beta
|
|
570
433
|
*/
|
|
571
|
-
constructor() {
|
|
434
|
+
constructor(authConfig) {
|
|
572
435
|
internalLogger.info("Create M365 tenant credential");
|
|
573
|
-
const config = this.loadAndValidateConfig();
|
|
436
|
+
const config = this.loadAndValidateConfig(authConfig);
|
|
574
437
|
this.msalClient = createConfidentialClientApplication(config);
|
|
575
438
|
}
|
|
576
439
|
/**
|
|
@@ -630,15 +493,13 @@ class M365TenantCredential {
|
|
|
630
493
|
}
|
|
631
494
|
/**
|
|
632
495
|
* Load and validate authentication configuration
|
|
496
|
+
*
|
|
497
|
+
* @param {AuthenticationConfiguration} authConfig - The authentication configuration. Use environment variables if not provided.
|
|
498
|
+
*
|
|
633
499
|
* @returns Authentication configuration
|
|
634
500
|
*/
|
|
635
|
-
loadAndValidateConfig() {
|
|
501
|
+
loadAndValidateConfig(config) {
|
|
636
502
|
internalLogger.verbose("Validate authentication configuration");
|
|
637
|
-
const config = getAuthenticationConfiguration();
|
|
638
|
-
if (!config) {
|
|
639
|
-
internalLogger.error(ErrorMessage.AuthenticationConfigurationNotExists);
|
|
640
|
-
throw new ErrorWithCode(ErrorMessage.AuthenticationConfigurationNotExists, ErrorCode.InvalidConfiguration);
|
|
641
|
-
}
|
|
642
503
|
if (config.clientId && (config.clientSecret || config.certificateContent) && config.tenantId) {
|
|
643
504
|
return config;
|
|
644
505
|
}
|
|
@@ -664,7 +525,6 @@ class M365TenantCredential {
|
|
|
664
525
|
*
|
|
665
526
|
* @example
|
|
666
527
|
* ```typescript
|
|
667
|
-
* loadConfiguration(); // load configuration from environment variables
|
|
668
528
|
* const credential = new OnBehalfOfUserCredential(ssoToken);
|
|
669
529
|
* ```
|
|
670
530
|
*
|
|
@@ -681,6 +541,7 @@ class OnBehalfOfUserCredential {
|
|
|
681
541
|
* Only works in in server side.
|
|
682
542
|
*
|
|
683
543
|
* @param {string} ssoToken - User token provided by Teams SSO feature.
|
|
544
|
+
* @param {AuthenticationConfiguration} config - The authentication configuration. Use environment variables if not provided.
|
|
684
545
|
*
|
|
685
546
|
* @throws {@link ErrorCode|InvalidConfiguration} when client id, client secret, certificate content, authority host or tenant id is not found in config.
|
|
686
547
|
* @throws {@link ErrorCode|InternalError} when SSO token is not valid.
|
|
@@ -688,20 +549,19 @@ class OnBehalfOfUserCredential {
|
|
|
688
549
|
*
|
|
689
550
|
* @beta
|
|
690
551
|
*/
|
|
691
|
-
constructor(ssoToken) {
|
|
692
|
-
var _a, _b, _c, _d, _e;
|
|
552
|
+
constructor(ssoToken, config) {
|
|
693
553
|
internalLogger.info("Get on behalf of user credential");
|
|
694
554
|
const missingConfigurations = [];
|
|
695
|
-
if (!
|
|
555
|
+
if (!config.clientId) {
|
|
696
556
|
missingConfigurations.push("clientId");
|
|
697
557
|
}
|
|
698
|
-
if (!
|
|
558
|
+
if (!config.authorityHost) {
|
|
699
559
|
missingConfigurations.push("authorityHost");
|
|
700
560
|
}
|
|
701
|
-
if (!
|
|
561
|
+
if (!config.clientSecret && !config.certificateContent) {
|
|
702
562
|
missingConfigurations.push("clientSecret or certificateContent");
|
|
703
563
|
}
|
|
704
|
-
if (!
|
|
564
|
+
if (!config.tenantId) {
|
|
705
565
|
missingConfigurations.push("tenantId");
|
|
706
566
|
}
|
|
707
567
|
if (missingConfigurations.length != 0) {
|
|
@@ -709,7 +569,7 @@ class OnBehalfOfUserCredential {
|
|
|
709
569
|
internalLogger.error(errorMsg);
|
|
710
570
|
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
711
571
|
}
|
|
712
|
-
this.msalClient = createConfidentialClientApplication(config
|
|
572
|
+
this.msalClient = createConfidentialClientApplication(config);
|
|
713
573
|
const decodedSsoToken = parseJwt(ssoToken);
|
|
714
574
|
this.ssoToken = {
|
|
715
575
|
token: ssoToken,
|
|
@@ -843,7 +703,7 @@ class TeamsUserCredential {
|
|
|
843
703
|
* Can only be used within Teams.
|
|
844
704
|
* @beta
|
|
845
705
|
*/
|
|
846
|
-
constructor() {
|
|
706
|
+
constructor(authConfig) {
|
|
847
707
|
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), ErrorCode.RuntimeNotSupported);
|
|
848
708
|
}
|
|
849
709
|
/**
|
|
@@ -886,7 +746,7 @@ class MsGraphAuthProvider {
|
|
|
886
746
|
/**
|
|
887
747
|
* Constructor of MsGraphAuthProvider.
|
|
888
748
|
*
|
|
889
|
-
* @param {
|
|
749
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth.
|
|
890
750
|
* @param {string | string[]} scopes - The list of scopes for which the token will have access.
|
|
891
751
|
*
|
|
892
752
|
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
@@ -895,8 +755,8 @@ class MsGraphAuthProvider {
|
|
|
895
755
|
*
|
|
896
756
|
* @beta
|
|
897
757
|
*/
|
|
898
|
-
constructor(
|
|
899
|
-
this.
|
|
758
|
+
constructor(teamsfx, scopes) {
|
|
759
|
+
this.teamsfx = teamsfx;
|
|
900
760
|
let scopesStr = defaultScope;
|
|
901
761
|
if (scopes) {
|
|
902
762
|
validateScopesType(scopes);
|
|
@@ -922,7 +782,7 @@ class MsGraphAuthProvider {
|
|
|
922
782
|
*/
|
|
923
783
|
async getAccessToken() {
|
|
924
784
|
internalLogger.info(`Get Graph Access token with scopes: '${this.scopes}'`);
|
|
925
|
-
const accessToken = await this.
|
|
785
|
+
const accessToken = await this.teamsfx.getCredential().getToken(this.scopes);
|
|
926
786
|
return new Promise((resolve, reject) => {
|
|
927
787
|
if (accessToken) {
|
|
928
788
|
resolve(accessToken.token);
|
|
@@ -979,7 +839,7 @@ class MsGraphAuthProvider {
|
|
|
979
839
|
* }
|
|
980
840
|
* ```
|
|
981
841
|
*
|
|
982
|
-
* @param {
|
|
842
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth.
|
|
983
843
|
* @param scopes - The array of Microsoft Token scope of access. Default value is `[.default]`.
|
|
984
844
|
*
|
|
985
845
|
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
@@ -988,9 +848,9 @@ class MsGraphAuthProvider {
|
|
|
988
848
|
*
|
|
989
849
|
* @beta
|
|
990
850
|
*/
|
|
991
|
-
function createMicrosoftGraphClient(
|
|
851
|
+
function createMicrosoftGraphClient(teamsfx, scopes) {
|
|
992
852
|
internalLogger.info("Create Microsoft Graph Client");
|
|
993
|
-
const authProvider = new MsGraphAuthProvider(
|
|
853
|
+
const authProvider = new MsGraphAuthProvider(teamsfx, scopes);
|
|
994
854
|
const graphClient = Client.initWithMiddleware({
|
|
995
855
|
authProvider,
|
|
996
856
|
});
|
|
@@ -999,172 +859,161 @@ function createMicrosoftGraphClient(credential, scopes) {
|
|
|
999
859
|
|
|
1000
860
|
// Copyright (c) Microsoft Corporation.
|
|
1001
861
|
/**
|
|
1002
|
-
*
|
|
1003
|
-
*
|
|
1004
|
-
|
|
862
|
+
* MSSQL default scope
|
|
863
|
+
* https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi
|
|
864
|
+
*/
|
|
865
|
+
const defaultSQLScope = "https://database.windows.net/";
|
|
866
|
+
/**
|
|
867
|
+
* Generate connection configuration consumed by tedious.
|
|
868
|
+
*
|
|
869
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth
|
|
870
|
+
* @param { string? } databaseName - specify database name to override default one if there are multiple databases.
|
|
871
|
+
*
|
|
872
|
+
* @returns Connection configuration of tedious for the SQL.
|
|
873
|
+
*
|
|
874
|
+
* @throws {@link ErrorCode|InvalidConfiguration} when SQL config resource configuration is invalid.
|
|
875
|
+
* @throws {@link ErrorCode|InternalError} when get user MSI token failed or MSI token is invalid.
|
|
876
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
1005
877
|
*
|
|
1006
878
|
* @beta
|
|
879
|
+
*/
|
|
880
|
+
async function getTediousConnectionConfig(teamsfx, databaseName) {
|
|
881
|
+
internalLogger.info("Get SQL configuration");
|
|
882
|
+
try {
|
|
883
|
+
isSQLConfigurationValid(teamsfx);
|
|
884
|
+
}
|
|
885
|
+
catch (err) {
|
|
886
|
+
throw err;
|
|
887
|
+
}
|
|
888
|
+
if (databaseName === "") {
|
|
889
|
+
internalLogger.warn(`SQL database name is empty string`);
|
|
890
|
+
}
|
|
891
|
+
const dbName = databaseName !== null && databaseName !== void 0 ? databaseName : (teamsfx.hasConfig("sqlDatabaseName") ? teamsfx.getConfig("sqlDatabaseName") : undefined);
|
|
892
|
+
if (!isMsiAuthentication(teamsfx)) {
|
|
893
|
+
const configWithUPS = generateDefaultConfig(teamsfx, dbName);
|
|
894
|
+
internalLogger.verbose("SQL configuration with username and password generated");
|
|
895
|
+
return configWithUPS;
|
|
896
|
+
}
|
|
897
|
+
try {
|
|
898
|
+
const configWithToken = await generateTokenConfig(teamsfx, dbName);
|
|
899
|
+
internalLogger.verbose("SQL configuration with MSI token generated");
|
|
900
|
+
return configWithToken;
|
|
901
|
+
}
|
|
902
|
+
catch (error) {
|
|
903
|
+
throw error;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* check configuration is an available configurations.
|
|
908
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth
|
|
1007
909
|
*
|
|
910
|
+
* @returns true - SQL configuration has a valid SQL endpoints, SQL username with password or identity ID.
|
|
911
|
+
* false - configuration is not valid.
|
|
912
|
+
* @internal
|
|
1008
913
|
*/
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
*/
|
|
1015
|
-
this.defaultSQLScope = "https://database.windows.net/";
|
|
914
|
+
function isSQLConfigurationValid(teamsfx) {
|
|
915
|
+
internalLogger.verbose("Check SQL configuration if valid");
|
|
916
|
+
if (!teamsfx.hasConfig("sqlServerEndpoint")) {
|
|
917
|
+
internalLogger.error("SQL configuration is not valid without SQL server endpoint exist");
|
|
918
|
+
throw new ErrorWithCode("SQL configuration error without SQL server endpoint exist", ErrorCode.InvalidConfiguration);
|
|
1016
919
|
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
* @returns Connection configuration of tedious for the SQL.
|
|
1023
|
-
*
|
|
1024
|
-
* @throws {@link ErrorCode|InvalidConfiguration} when SQL config resource configuration is invalid.
|
|
1025
|
-
* @throws {@link ErrorCode|InternalError} when get user MSI token failed or MSI token is invalid.
|
|
1026
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
1027
|
-
*
|
|
1028
|
-
* @beta
|
|
1029
|
-
*/
|
|
1030
|
-
async getConfig(databaseName) {
|
|
1031
|
-
internalLogger.info("Get SQL configuration");
|
|
1032
|
-
const configuration = getResourceConfiguration(ResourceType.SQL);
|
|
1033
|
-
if (!configuration) {
|
|
1034
|
-
const errMsg = "SQL resource configuration not exist";
|
|
1035
|
-
internalLogger.error(errMsg);
|
|
1036
|
-
throw new ErrorWithCode(errMsg, ErrorCode.InvalidConfiguration);
|
|
1037
|
-
}
|
|
1038
|
-
try {
|
|
1039
|
-
this.isSQLConfigurationValid(configuration);
|
|
1040
|
-
}
|
|
1041
|
-
catch (err) {
|
|
1042
|
-
throw err;
|
|
1043
|
-
}
|
|
1044
|
-
if (!this.isMsiAuthentication()) {
|
|
1045
|
-
const configWithUPS = this.generateDefaultConfig(configuration, databaseName);
|
|
1046
|
-
internalLogger.verbose("SQL configuration with username and password generated");
|
|
1047
|
-
return configWithUPS;
|
|
1048
|
-
}
|
|
1049
|
-
try {
|
|
1050
|
-
const configWithToken = await this.generateTokenConfig(configuration, databaseName);
|
|
1051
|
-
internalLogger.verbose("SQL configuration with MSI token generated");
|
|
1052
|
-
return configWithToken;
|
|
1053
|
-
}
|
|
1054
|
-
catch (error) {
|
|
1055
|
-
throw error;
|
|
1056
|
-
}
|
|
920
|
+
if (!(teamsfx.hasConfig("sqlUsername") && teamsfx.hasConfig("sqlPassword")) &&
|
|
921
|
+
!teamsfx.hasConfig("sqlIdentityId")) {
|
|
922
|
+
const errMsg = `SQL configuration is not valid without ${teamsfx.hasConfig("sqlIdentityId") ? "" : "identity id "} ${teamsfx.hasConfig("sqlUsername") ? "" : "SQL username "} ${teamsfx.hasConfig("sqlPassword") ? "" : "SQL password"} exist`;
|
|
923
|
+
internalLogger.error(errMsg);
|
|
924
|
+
throw new ErrorWithCode(errMsg, ErrorCode.InvalidConfiguration);
|
|
1057
925
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
internalLogger.verbose("Login with
|
|
1072
|
-
return
|
|
926
|
+
internalLogger.verbose("SQL configuration is valid");
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Check SQL use MSI identity or username and password.
|
|
930
|
+
*
|
|
931
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth
|
|
932
|
+
*
|
|
933
|
+
* @returns false - login with SQL MSI identity, true - login with username and password.
|
|
934
|
+
* @internal
|
|
935
|
+
*/
|
|
936
|
+
function isMsiAuthentication(teamsfx) {
|
|
937
|
+
internalLogger.verbose("Check connection config using MSI access token or username and password");
|
|
938
|
+
if (teamsfx.hasConfig("sqlUsername") && teamsfx.hasConfig("sqlPassword")) {
|
|
939
|
+
internalLogger.verbose("Login with username and password");
|
|
940
|
+
return false;
|
|
1073
941
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
942
|
+
internalLogger.verbose("Login with MSI identity");
|
|
943
|
+
return true;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Generate tedious connection configuration with default authentication type.
|
|
947
|
+
*
|
|
948
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth
|
|
949
|
+
* @param { string? } databaseName - specify database name to override default one if there are multiple databases.
|
|
950
|
+
*
|
|
951
|
+
* @returns Tedious connection configuration with username and password.
|
|
952
|
+
* @internal
|
|
953
|
+
*/
|
|
954
|
+
function generateDefaultConfig(teamsfx, databaseName) {
|
|
955
|
+
internalLogger.verbose(`SQL server ${teamsfx.getConfig("sqlServerEndpoint")}
|
|
956
|
+
, user name ${teamsfx.getConfig("sqlUsername")}
|
|
957
|
+
, database name ${databaseName}`);
|
|
958
|
+
const config = {
|
|
959
|
+
server: teamsfx.getConfig("sqlServerEndpoint"),
|
|
960
|
+
authentication: {
|
|
961
|
+
type: TediousAuthenticationType.default,
|
|
962
|
+
options: {
|
|
963
|
+
userName: teamsfx.getConfig("sqlUsername"),
|
|
964
|
+
password: teamsfx.getConfig("sqlPassword"),
|
|
965
|
+
},
|
|
966
|
+
},
|
|
967
|
+
options: {
|
|
968
|
+
database: databaseName,
|
|
969
|
+
encrypt: true,
|
|
970
|
+
},
|
|
971
|
+
};
|
|
972
|
+
return config;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Generate tedious connection configuration with azure-active-directory-access-token authentication type.
|
|
976
|
+
*
|
|
977
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth
|
|
978
|
+
*
|
|
979
|
+
* @returns Tedious connection configuration with access token.
|
|
980
|
+
* @internal
|
|
981
|
+
*/
|
|
982
|
+
async function generateTokenConfig(teamsfx, databaseName) {
|
|
983
|
+
internalLogger.verbose("Generate tedious config with MSI token");
|
|
984
|
+
let token;
|
|
985
|
+
try {
|
|
986
|
+
const credential = new ManagedIdentityCredential(teamsfx.getConfig("sqlIdentityId"));
|
|
987
|
+
token = await credential.getToken(defaultSQLScope);
|
|
1094
988
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
* @internal
|
|
1102
|
-
*/
|
|
1103
|
-
generateDefaultConfig(sqlConfig, databaseName) {
|
|
1104
|
-
if (databaseName === "") {
|
|
1105
|
-
internalLogger.warn(`SQL database name is empty string`);
|
|
1106
|
-
}
|
|
1107
|
-
const dbName = databaseName !== null && databaseName !== void 0 ? databaseName : sqlConfig.sqlDatabaseName;
|
|
1108
|
-
internalLogger.verbose(`SQL server ${sqlConfig.sqlServerEndpoint}, user name ${sqlConfig.sqlUsername}, database name ${dbName}`);
|
|
989
|
+
catch (error) {
|
|
990
|
+
const errMsg = "Get user MSI token failed";
|
|
991
|
+
internalLogger.error(errMsg);
|
|
992
|
+
throw new ErrorWithCode(errMsg, ErrorCode.InternalError);
|
|
993
|
+
}
|
|
994
|
+
if (token) {
|
|
1109
995
|
const config = {
|
|
1110
|
-
server:
|
|
996
|
+
server: teamsfx.getConfig("sqlServerEndpoint"),
|
|
1111
997
|
authentication: {
|
|
1112
|
-
type: TediousAuthenticationType.
|
|
998
|
+
type: TediousAuthenticationType.MSI,
|
|
1113
999
|
options: {
|
|
1114
|
-
|
|
1115
|
-
password: sqlConfig.sqlPassword,
|
|
1000
|
+
token: token.token,
|
|
1116
1001
|
},
|
|
1117
1002
|
},
|
|
1118
1003
|
options: {
|
|
1119
|
-
database:
|
|
1004
|
+
database: databaseName,
|
|
1120
1005
|
encrypt: true,
|
|
1121
1006
|
},
|
|
1122
1007
|
};
|
|
1008
|
+
internalLogger.verbose(`Generate token configuration success
|
|
1009
|
+
, server endpoint is ${teamsfx.getConfig("sqlServerEndpoint")}
|
|
1010
|
+
, database name is ${databaseName}`);
|
|
1123
1011
|
return config;
|
|
1124
1012
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
*
|
|
1130
|
-
* @returns Tedious connection configuration with access token.
|
|
1131
|
-
* @internal
|
|
1132
|
-
*/
|
|
1133
|
-
async generateTokenConfig(sqlConfig, databaseName) {
|
|
1134
|
-
internalLogger.verbose("Generate tedious config with MSI token");
|
|
1135
|
-
if (databaseName === "") {
|
|
1136
|
-
internalLogger.warn(`SQL database name is empty string`);
|
|
1137
|
-
}
|
|
1138
|
-
let token;
|
|
1139
|
-
try {
|
|
1140
|
-
const credential = new ManagedIdentityCredential(sqlConfig.sqlIdentityId);
|
|
1141
|
-
token = await credential.getToken(this.defaultSQLScope);
|
|
1142
|
-
}
|
|
1143
|
-
catch (error) {
|
|
1144
|
-
const errMsg = "Get user MSI token failed";
|
|
1145
|
-
internalLogger.error(errMsg);
|
|
1146
|
-
throw new ErrorWithCode(errMsg, ErrorCode.InternalError);
|
|
1147
|
-
}
|
|
1148
|
-
if (token) {
|
|
1149
|
-
const config = {
|
|
1150
|
-
server: sqlConfig.sqlServerEndpoint,
|
|
1151
|
-
authentication: {
|
|
1152
|
-
type: TediousAuthenticationType.MSI,
|
|
1153
|
-
options: {
|
|
1154
|
-
token: token.token,
|
|
1155
|
-
},
|
|
1156
|
-
},
|
|
1157
|
-
options: {
|
|
1158
|
-
database: databaseName !== null && databaseName !== void 0 ? databaseName : sqlConfig.sqlDatabaseName,
|
|
1159
|
-
encrypt: true,
|
|
1160
|
-
},
|
|
1161
|
-
};
|
|
1162
|
-
internalLogger.verbose(`Generate token configuration success, server endpoint is ${sqlConfig.sqlServerEndpoint}, database name is ${databaseName !== null && databaseName !== void 0 ? databaseName : sqlConfig.sqlDatabaseName}`);
|
|
1163
|
-
return config;
|
|
1164
|
-
}
|
|
1165
|
-
internalLogger.error(`Generate token configuration, server endpoint is ${sqlConfig.sqlServerEndpoint}, MSI token is not valid`);
|
|
1166
|
-
throw new ErrorWithCode("MSI token is not valid", ErrorCode.InternalError);
|
|
1167
|
-
}
|
|
1013
|
+
internalLogger.error(`Generate token configuration
|
|
1014
|
+
, server endpoint is ${teamsfx.getConfig("sqlServerEndpoint")}
|
|
1015
|
+
, MSI token is not valid`);
|
|
1016
|
+
throw new ErrorWithCode("MSI token is not valid", ErrorCode.InternalError);
|
|
1168
1017
|
}
|
|
1169
1018
|
/**
|
|
1170
1019
|
* tedious connection config authentication type.
|
|
@@ -1177,6 +1026,25 @@ var TediousAuthenticationType;
|
|
|
1177
1026
|
TediousAuthenticationType["MSI"] = "azure-active-directory-access-token";
|
|
1178
1027
|
})(TediousAuthenticationType || (TediousAuthenticationType = {}));
|
|
1179
1028
|
|
|
1029
|
+
// Copyright (c) Microsoft Corporation.
|
|
1030
|
+
// Licensed under the MIT license.
|
|
1031
|
+
/**
|
|
1032
|
+
* Identity type to use in authentication.
|
|
1033
|
+
*
|
|
1034
|
+
* @beta
|
|
1035
|
+
*/
|
|
1036
|
+
var IdentityType;
|
|
1037
|
+
(function (IdentityType) {
|
|
1038
|
+
/**
|
|
1039
|
+
* Represents the current user of Teams.
|
|
1040
|
+
*/
|
|
1041
|
+
IdentityType["User"] = "User";
|
|
1042
|
+
/**
|
|
1043
|
+
* Represents the application itself.
|
|
1044
|
+
*/
|
|
1045
|
+
IdentityType["App"] = "Application";
|
|
1046
|
+
})(IdentityType || (IdentityType = {}));
|
|
1047
|
+
|
|
1180
1048
|
// Copyright (c) Microsoft Corporation.
|
|
1181
1049
|
const invokeResponseType = "invokeResponse";
|
|
1182
1050
|
/**
|
|
@@ -1216,7 +1084,6 @@ class TokenExchangeInvokeResponse {
|
|
|
1216
1084
|
* const dialogState = convoState.createProperty('dialogState');
|
|
1217
1085
|
* const dialogs = new DialogSet(dialogState);
|
|
1218
1086
|
*
|
|
1219
|
-
* loadConfiguration();
|
|
1220
1087
|
* dialogs.add(new TeamsBotSsoPrompt('TeamsBotSsoPrompt', {
|
|
1221
1088
|
* scopes: ["User.Read"],
|
|
1222
1089
|
* }));
|
|
@@ -1245,6 +1112,7 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
|
1245
1112
|
/**
|
|
1246
1113
|
* Constructor of TeamsBotSsoPrompt.
|
|
1247
1114
|
*
|
|
1115
|
+
* @param {TeamsFx} teamsfx - Used to provide configuration and auth
|
|
1248
1116
|
* @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`.
|
|
1249
1117
|
* @param settings Settings used to configure the prompt.
|
|
1250
1118
|
*
|
|
@@ -1253,10 +1121,12 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
|
1253
1121
|
*
|
|
1254
1122
|
* @beta
|
|
1255
1123
|
*/
|
|
1256
|
-
constructor(dialogId, settings) {
|
|
1124
|
+
constructor(teamsfx, dialogId, settings) {
|
|
1257
1125
|
super(dialogId);
|
|
1126
|
+
this.teamsfx = teamsfx;
|
|
1258
1127
|
this.settings = settings;
|
|
1259
1128
|
validateScopesType(settings.scopes);
|
|
1129
|
+
this.loadAndValidateConfig();
|
|
1260
1130
|
internalLogger.info("Create a new Teams Bot SSO Prompt");
|
|
1261
1131
|
}
|
|
1262
1132
|
/**
|
|
@@ -1357,6 +1227,31 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
|
1357
1227
|
return Dialog.EndOfTurn;
|
|
1358
1228
|
}
|
|
1359
1229
|
}
|
|
1230
|
+
loadAndValidateConfig() {
|
|
1231
|
+
if (this.teamsfx.getIdentityType() !== IdentityType.User) {
|
|
1232
|
+
const errorMsg = formatString(ErrorMessage.IdentityTypeNotSupported, this.teamsfx.getIdentityType().toString(), "TeamsBotSsoPrompt");
|
|
1233
|
+
internalLogger.error(errorMsg);
|
|
1234
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.IdentityTypeNotSupported);
|
|
1235
|
+
}
|
|
1236
|
+
const missingConfigurations = [];
|
|
1237
|
+
if (!this.teamsfx.hasConfig("initiateLoginEndpoint")) {
|
|
1238
|
+
missingConfigurations.push("initiateLoginEndpoint");
|
|
1239
|
+
}
|
|
1240
|
+
if (!this.teamsfx.hasConfig("clientId")) {
|
|
1241
|
+
missingConfigurations.push("clientId");
|
|
1242
|
+
}
|
|
1243
|
+
if (!this.teamsfx.hasConfig("tenantId")) {
|
|
1244
|
+
missingConfigurations.push("tenantId");
|
|
1245
|
+
}
|
|
1246
|
+
if (!this.teamsfx.hasConfig("applicationIdUri")) {
|
|
1247
|
+
missingConfigurations.push("applicationIdUri");
|
|
1248
|
+
}
|
|
1249
|
+
if (missingConfigurations.length != 0) {
|
|
1250
|
+
const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingConfigurations.join(", "), "undefined");
|
|
1251
|
+
internalLogger.error(errorMsg);
|
|
1252
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1360
1255
|
/**
|
|
1361
1256
|
* Ensure bot is running in MS Teams since TeamsBotSsoPrompt is only supported in MS Teams channel.
|
|
1362
1257
|
* @param dc dialog context
|
|
@@ -1396,31 +1291,12 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
|
1396
1291
|
* @internal
|
|
1397
1292
|
*/
|
|
1398
1293
|
getSignInResource(loginHint) {
|
|
1399
|
-
var _a, _b, _c, _d, _e;
|
|
1400
1294
|
internalLogger.verbose("Get sign in authentication configuration");
|
|
1401
|
-
const
|
|
1402
|
-
if (!((_a = config === null || config === void 0 ? void 0 : config.authentication) === null || _a === void 0 ? void 0 : _a.initiateLoginEndpoint)) {
|
|
1403
|
-
missingConfigurations.push("initiateLoginEndpoint");
|
|
1404
|
-
}
|
|
1405
|
-
if (!((_b = config === null || config === void 0 ? void 0 : config.authentication) === null || _b === void 0 ? void 0 : _b.clientId)) {
|
|
1406
|
-
missingConfigurations.push("clientId");
|
|
1407
|
-
}
|
|
1408
|
-
if (!((_c = config === null || config === void 0 ? void 0 : config.authentication) === null || _c === void 0 ? void 0 : _c.tenantId)) {
|
|
1409
|
-
missingConfigurations.push("tenantId");
|
|
1410
|
-
}
|
|
1411
|
-
if (!((_d = config === null || config === void 0 ? void 0 : config.authentication) === null || _d === void 0 ? void 0 : _d.applicationIdUri)) {
|
|
1412
|
-
missingConfigurations.push("applicationIdUri");
|
|
1413
|
-
}
|
|
1414
|
-
if (missingConfigurations.length != 0) {
|
|
1415
|
-
const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingConfigurations.join(", "), "undefined");
|
|
1416
|
-
internalLogger.error(errorMsg);
|
|
1417
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
1418
|
-
}
|
|
1419
|
-
const signInLink = `${config.authentication.initiateLoginEndpoint}?scope=${encodeURI(this.settings.scopes.join(" "))}&clientId=${config.authentication.clientId}&tenantId=${config.authentication.tenantId}&loginHint=${loginHint}`;
|
|
1295
|
+
const signInLink = `${this.teamsfx.getConfig("initiateLoginEndpoint")}?scope=${encodeURI(this.settings.scopes.join(" "))}&clientId=${this.teamsfx.getConfig("clientId")}&tenantId=${this.teamsfx.getConfig("tenantId")}&loginHint=${loginHint}`;
|
|
1420
1296
|
internalLogger.verbose("Sign in link: " + signInLink);
|
|
1421
1297
|
const tokenExchangeResource = {
|
|
1422
1298
|
id: v4(),
|
|
1423
|
-
uri:
|
|
1299
|
+
uri: this.teamsfx.getConfig("applicationIdUri").replace(/\/$/, "") + "/access_as_user",
|
|
1424
1300
|
};
|
|
1425
1301
|
internalLogger.verbose("Token exchange resource uri: " + tokenExchangeResource.uri);
|
|
1426
1302
|
return {
|
|
@@ -1444,7 +1320,8 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
|
1444
1320
|
}
|
|
1445
1321
|
else {
|
|
1446
1322
|
const ssoToken = context.activity.value.token;
|
|
1447
|
-
|
|
1323
|
+
this.teamsfx.setSsoToken(ssoToken);
|
|
1324
|
+
const credential = this.teamsfx.getCredential();
|
|
1448
1325
|
let exchangedToken;
|
|
1449
1326
|
try {
|
|
1450
1327
|
exchangedToken = await credential.getToken(this.settings.scopes);
|
|
@@ -1508,5 +1385,187 @@ class TeamsBotSsoPrompt extends Dialog {
|
|
|
1508
1385
|
}
|
|
1509
1386
|
}
|
|
1510
1387
|
|
|
1511
|
-
|
|
1388
|
+
// Copyright (c) Microsoft Corporation.
|
|
1389
|
+
/**
|
|
1390
|
+
* A class providing credential and configuration.
|
|
1391
|
+
* @beta
|
|
1392
|
+
*/
|
|
1393
|
+
class TeamsFx {
|
|
1394
|
+
/**
|
|
1395
|
+
* Constructor of TeamsFx
|
|
1396
|
+
*
|
|
1397
|
+
* @param {IdentityType} identityType - Choose user or app identity
|
|
1398
|
+
* @param customConfig - key/value pairs of customized configuration that overrides default ones.
|
|
1399
|
+
*
|
|
1400
|
+
* @throws {@link ErrorCode|IdentityTypeNotSupported} when setting app identity in browser.
|
|
1401
|
+
*
|
|
1402
|
+
* @beta
|
|
1403
|
+
*/
|
|
1404
|
+
constructor(identityType, customConfig) {
|
|
1405
|
+
this.identityType = identityType !== null && identityType !== void 0 ? identityType : IdentityType.User;
|
|
1406
|
+
this.configuration = new Map();
|
|
1407
|
+
this.loadFromEnv();
|
|
1408
|
+
if (customConfig) {
|
|
1409
|
+
for (const key of Object.keys(customConfig)) {
|
|
1410
|
+
const value = customConfig[key];
|
|
1411
|
+
if (value) {
|
|
1412
|
+
this.configuration.set(key, value);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Identity type set by user.
|
|
1419
|
+
*
|
|
1420
|
+
* @returns identity type.
|
|
1421
|
+
* @beta
|
|
1422
|
+
*/
|
|
1423
|
+
getIdentityType() {
|
|
1424
|
+
return this.identityType;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Credential instance according to identity type choice.
|
|
1428
|
+
*
|
|
1429
|
+
* @remarks If user identity is chose, will return {@link TeamsUserCredential}
|
|
1430
|
+
* in browser environment and {@link OnBehalfOfUserCredential} in NodeJS. If app
|
|
1431
|
+
* identity is chose, will return {@link AppCredential}.
|
|
1432
|
+
*
|
|
1433
|
+
* @returns instance implements TokenCredential interface.
|
|
1434
|
+
* @beta
|
|
1435
|
+
*/
|
|
1436
|
+
getCredential() {
|
|
1437
|
+
if (this.identityType === IdentityType.User) {
|
|
1438
|
+
if (this.oboUserCredential) {
|
|
1439
|
+
return this.oboUserCredential;
|
|
1440
|
+
}
|
|
1441
|
+
const errorMsg = "SSO token is required to user identity. Please use setSsoToken().";
|
|
1442
|
+
internalLogger.error(errorMsg);
|
|
1443
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
1444
|
+
}
|
|
1445
|
+
else {
|
|
1446
|
+
if (!this.appCredential) {
|
|
1447
|
+
this.appCredential = new AppCredential(Object.fromEntries(this.configuration));
|
|
1448
|
+
}
|
|
1449
|
+
return this.appCredential;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Get user information.
|
|
1454
|
+
* @returns UserInfo object.
|
|
1455
|
+
* @beta
|
|
1456
|
+
*/
|
|
1457
|
+
async getUserInfo() {
|
|
1458
|
+
if (this.identityType !== IdentityType.User) {
|
|
1459
|
+
const errorMsg = formatString(ErrorMessage.IdentityTypeNotSupported, this.identityType.toString(), "TeamsFx");
|
|
1460
|
+
internalLogger.error(errorMsg);
|
|
1461
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.IdentityTypeNotSupported);
|
|
1462
|
+
}
|
|
1463
|
+
return Promise.resolve(this.getCredential().getUserInfo());
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* Popup login page to get user's access token with specific scopes.
|
|
1467
|
+
*
|
|
1468
|
+
* @remarks
|
|
1469
|
+
* Only works in Teams client APP. User will be redirected to the authorization page to login and consent.
|
|
1470
|
+
*
|
|
1471
|
+
* @example
|
|
1472
|
+
* ```typescript
|
|
1473
|
+
* await teamsfx.login(["https://graph.microsoft.com/User.Read"]); // single scope using string array
|
|
1474
|
+
* await teamsfx.login("https://graph.microsoft.com/User.Read"); // single scopes using string
|
|
1475
|
+
* await teamsfx.login(["https://graph.microsoft.com/User.Read", "Calendars.Read"]); // multiple scopes using string array
|
|
1476
|
+
* await teamsfx.login("https://graph.microsoft.com/User.Read Calendars.Read"); // multiple scopes using string
|
|
1477
|
+
* ```
|
|
1478
|
+
* @param scopes - The list of scopes for which the token will have access, before that, we will request user to consent.
|
|
1479
|
+
*
|
|
1480
|
+
* @throws {@link ErrorCode|InternalError} when failed to login with unknown error.
|
|
1481
|
+
* @throws {@link ErrorCode|ConsentFailed} when user canceled or failed to consent.
|
|
1482
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
1483
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
1484
|
+
*
|
|
1485
|
+
* @beta
|
|
1486
|
+
*/
|
|
1487
|
+
async login(scopes) {
|
|
1488
|
+
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "login"), ErrorCode.RuntimeNotSupported);
|
|
1489
|
+
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Set SSO token when using user identity in NodeJS.
|
|
1492
|
+
* @param {string} ssoToken - used for on behalf of user flow.
|
|
1493
|
+
* @returns self instance.
|
|
1494
|
+
* @beta
|
|
1495
|
+
*/
|
|
1496
|
+
setSsoToken(ssoToken) {
|
|
1497
|
+
if (this.identityType !== IdentityType.User) {
|
|
1498
|
+
throw new Error();
|
|
1499
|
+
}
|
|
1500
|
+
this.oboUserCredential = new OnBehalfOfUserCredential(ssoToken, Object.fromEntries(this.configuration));
|
|
1501
|
+
return this;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Usually used by service plugins to retrieve specific config
|
|
1505
|
+
* @param {string} key - configuration key.
|
|
1506
|
+
* @returns value in configuration.
|
|
1507
|
+
* @beta
|
|
1508
|
+
*/
|
|
1509
|
+
getConfig(key) {
|
|
1510
|
+
const value = this.configuration.get(key);
|
|
1511
|
+
if (!value) {
|
|
1512
|
+
const errorMsg = `Cannot find ${key} in configuration`;
|
|
1513
|
+
internalLogger.error(errorMsg);
|
|
1514
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
|
|
1515
|
+
}
|
|
1516
|
+
return value;
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Check the value of specific key.
|
|
1520
|
+
* @param {string} key - configuration key.
|
|
1521
|
+
* @returns true if corresponding value is not empty string.
|
|
1522
|
+
* @beta
|
|
1523
|
+
*/
|
|
1524
|
+
hasConfig(key) {
|
|
1525
|
+
const value = this.configuration.get(key);
|
|
1526
|
+
return !!value;
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Get all configurations.
|
|
1530
|
+
* @returns key value mappings.
|
|
1531
|
+
* @beta
|
|
1532
|
+
*/
|
|
1533
|
+
getConfigs() {
|
|
1534
|
+
const config = {};
|
|
1535
|
+
for (const key of this.configuration.keys()) {
|
|
1536
|
+
const value = this.configuration.get(key);
|
|
1537
|
+
if (value) {
|
|
1538
|
+
config[key] = value;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
return config;
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* Load configuration from environment variables.
|
|
1545
|
+
*/
|
|
1546
|
+
loadFromEnv() {
|
|
1547
|
+
const env = process.env;
|
|
1548
|
+
this.configuration.set("authorityHost", env.M365_AUTHORITY_HOST);
|
|
1549
|
+
this.configuration.set("tenantId", env.M365_TENANT_ID);
|
|
1550
|
+
this.configuration.set("clientId", env.M365_CLIENT_ID);
|
|
1551
|
+
this.configuration.set("clientSecret", env.M365_CLIENT_SECRET);
|
|
1552
|
+
this.configuration.set("initiateLoginEndpoint", env.INITIATE_LOGIN_ENDPOINT);
|
|
1553
|
+
this.configuration.set("applicationIdUri", env.M365_APPLICATION_ID_URI);
|
|
1554
|
+
this.configuration.set("apiEndpoint", env.API_ENDPOINT);
|
|
1555
|
+
this.configuration.set("apiName", env.API_NAME);
|
|
1556
|
+
this.configuration.set("sqlServerEndpoint", env.SQL_ENDPOINT);
|
|
1557
|
+
this.configuration.set("sqlUsername", env.SQL_USER_NAME);
|
|
1558
|
+
this.configuration.set("sqlPassword", env.SQL_PASSWORD);
|
|
1559
|
+
this.configuration.set("sqlDatabaseName", env.SQL_DATABASE_NAME);
|
|
1560
|
+
this.configuration.set("sqlIdentityId", env.IDENTITY_ID);
|
|
1561
|
+
Object.keys(env).forEach((key) => {
|
|
1562
|
+
const value = env[key];
|
|
1563
|
+
if (key.startsWith("TEAMSFX_") && value) {
|
|
1564
|
+
this.configuration.set(key.substring(8), value);
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
export { AppCredential, ErrorCode, ErrorWithCode, IdentityType, LogLevel, MsGraphAuthProvider, OnBehalfOfUserCredential, TeamsBotSsoPrompt, TeamsFx, TeamsUserCredential, createMicrosoftGraphClient, getLogLevel, getTediousConnectionConfig, setLogFunction, setLogLevel, setLogger };
|
|
1512
1571
|
//# sourceMappingURL=index.esm2017.mjs.map
|