UNPKG

7.22 kBJavaScriptView Raw
1"use strict";
2/**
3 * @module botbuilder
4 */
5/**
6 * Copyright (c) Microsoft Corporation. All rights reserved.
7 * Licensed under the MIT License.
8 */
9var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
10 return new (P || (P = Promise))(function (resolve, reject) {
11 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
14 step((generator = generator.apply(thisArg, _arguments || [])).next());
15 });
16};
17Object.defineProperty(exports, "__esModule", { value: true });
18const axios_1 = require("axios");
19const botframework_connector_1 = require("botframework-connector");
20const botFrameworkAdapter_1 = require("./botFrameworkAdapter");
21/**
22 * HttpClient for calling skills from a Node.js BotBuilder V4 SDK bot.
23 */
24class BotFrameworkHttpClient {
25 constructor(credentialProvider, channelService) {
26 if (!credentialProvider) {
27 throw new Error('BotFrameworkHttpClient(): missing credentialProvider');
28 }
29 this.credentialProvider = credentialProvider;
30 this.channelService = channelService || process.env[botframework_connector_1.AuthenticationConstants.ChannelService];
31 }
32 postActivity(fromBotId, toBotId, toUrl, serviceUrl, conversationId, activity) {
33 return __awaiter(this, void 0, void 0, function* () {
34 const appCredentials = yield this.getAppCredentials(fromBotId, toBotId);
35 if (!appCredentials) {
36 throw new Error('BotFrameworkHttpClient.postActivity(): Unable to get appCredentials to connect to the skill');
37 }
38 if (!activity) {
39 throw new Error('BotFrameworkHttpClient.postActivity(): missing activity');
40 }
41 if (activity.conversation === undefined) {
42 throw new Error('BotFrameworkHttpClient.postActivity(): Activity must have a ConversationReference');
43 }
44 // Get token for the skill call
45 const token = appCredentials.appId ? yield appCredentials.getToken() : null;
46 // Capture current activity settings before changing them.
47 // TODO: DO we need to set the activity ID? (events that are created manually don't have it).
48 const originalConversationId = activity.conversation.id;
49 const originalServiceUrl = activity.serviceUrl;
50 const originalRelatesTo = activity.relatesTo;
51 const originalRecipient = activity.recipient;
52 try {
53 activity.relatesTo = {
54 serviceUrl: activity.serviceUrl,
55 activityId: activity.id,
56 channelId: activity.channelId,
57 conversation: {
58 id: activity.conversation.id,
59 name: activity.conversation.name,
60 conversationType: activity.conversation.conversationType,
61 aadObjectId: activity.conversation.aadObjectId,
62 isGroup: activity.conversation.isGroup,
63 properties: activity.conversation.properties,
64 role: activity.conversation.role,
65 tenantId: activity.conversation.tenantId
66 },
67 bot: null
68 };
69 activity.conversation.id = conversationId;
70 activity.serviceUrl = serviceUrl;
71 // Fixes: https://github.com/microsoft/botframework-sdk/issues/5785
72 if (!activity.recipient) {
73 activity.recipient = {};
74 }
75 const config = {
76 headers: {
77 Accept: 'application/json',
78 'Content-Type': 'application/json',
79 'User-Agent': botFrameworkAdapter_1.USER_AGENT
80 },
81 validateStatus: () => true
82 };
83 if (token) {
84 config.headers['Authorization'] = `Bearer ${token}`;
85 }
86 const response = yield axios_1.default.post(toUrl, activity, config);
87 const invokeResponse = { status: response.status, body: response.data };
88 return invokeResponse;
89 }
90 finally {
91 // Restore activity properties.
92 activity.conversation.id = originalConversationId;
93 activity.serviceUrl = originalServiceUrl;
94 activity.relatesTo = originalRelatesTo;
95 activity.recipient = originalRecipient;
96 }
97 });
98 }
99 buildCredentials(appId, oAuthScope) {
100 return __awaiter(this, void 0, void 0, function* () {
101 const appPassword = yield this.credentialProvider.getAppPassword(appId);
102 let appCredentials;
103 if (botframework_connector_1.JwtTokenValidation.isGovernment(this.channelService)) {
104 appCredentials = new botframework_connector_1.MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
105 appCredentials.oAuthEndpoint = botframework_connector_1.GovernmentConstants.ToChannelFromBotLoginUrl;
106 }
107 else {
108 appCredentials = new botframework_connector_1.MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
109 }
110 return appCredentials;
111 });
112 }
113 /**
114 * Gets the application credentials. App Credentials are cached so as to ensure we are not refreshing
115 * token every time.
116 * @private
117 * @param appId The application identifier (AAD Id for the bot).
118 * @param oAuthScope The scope for the token, skills will use the Skill App Id.
119 */
120 getAppCredentials(appId, oAuthScope) {
121 return __awaiter(this, void 0, void 0, function* () {
122 if (!appId) {
123 return new botframework_connector_1.MicrosoftAppCredentials('', '');
124 }
125 const cacheKey = `${appId}${oAuthScope}`;
126 let appCredentials = BotFrameworkHttpClient.appCredentialMapCache.get(cacheKey);
127 if (appCredentials) {
128 return appCredentials;
129 }
130 // Credentials not found in cache, build them
131 appCredentials = (yield this.buildCredentials(appId, oAuthScope));
132 // Cache the credentials for later use
133 BotFrameworkHttpClient.appCredentialMapCache.set(cacheKey, appCredentials);
134 return appCredentials;
135 });
136 }
137}
138/**
139 * Cache for appCredentials to speed up token acquisition (a token is not requested unless is expired)
140 * AppCredentials are cached using appId + scope (this last parameter is only used if the app credentials are used to call a skill)
141 */
142BotFrameworkHttpClient.appCredentialMapCache = new Map();
143exports.BotFrameworkHttpClient = BotFrameworkHttpClient;
144//# sourceMappingURL=botFrameworkHttpClient.js.map
\No newline at end of file