feat(core.gbapp): New bot management (CRUD) from SharePoint packages.
This commit is contained in:
parent
4a3d47281e
commit
9a961e72a1
8 changed files with 181 additions and 106 deletions
7
package-lock.json
generated
7
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "botserver",
|
"name": "botserver",
|
||||||
"version": "1.5.5",
|
"version": "1.6.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -6061,6 +6061,11 @@
|
||||||
"methods": "^1.0.0"
|
"methods": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"express-remove-route": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-remove-route/-/express-remove-route-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-HnYRseCiPw1aPCLaK9Sy6rwjC1Q="
|
||||||
|
},
|
||||||
"extend": {
|
"extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
"botbuilder-choices": "4.0.0-preview1.2",
|
"botbuilder-choices": "4.0.0-preview1.2",
|
||||||
"botbuilder-dialogs": "4.4.0",
|
"botbuilder-dialogs": "4.4.0",
|
||||||
"botbuilder-prompts": "4.0.0-preview1.2",
|
"botbuilder-prompts": "4.0.0-preview1.2",
|
||||||
"botlib": "^1.2.1",
|
"botlib": "1.2.2",
|
||||||
"chai": "4.2.0",
|
"chai": "4.2.0",
|
||||||
"child_process": "1.0.2",
|
"child_process": "1.0.2",
|
||||||
"chokidar": "3.0.0",
|
"chokidar": "3.0.0",
|
||||||
|
@ -76,6 +76,7 @@
|
||||||
"empty-dir": "^2.0.0",
|
"empty-dir": "^2.0.0",
|
||||||
"express": "4.16.4",
|
"express": "4.16.4",
|
||||||
"express-promise-router": "3.0.3",
|
"express-promise-router": "3.0.3",
|
||||||
|
"express-remove-route": "^1.0.0",
|
||||||
"fs-extra": "8.0.0",
|
"fs-extra": "8.0.0",
|
||||||
"ip": "1.1.5",
|
"ip": "1.1.5",
|
||||||
"js-beautify": "1.10.0",
|
"js-beautify": "1.10.0",
|
||||||
|
|
|
@ -57,7 +57,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
const packageName = text.split(' ')[1];
|
const packageName = text.split(' ')[1];
|
||||||
const importer = new GBImporter(min.core);
|
const importer = new GBImporter(min.core);
|
||||||
const deployer = new GBDeployer(min.core, importer);
|
const deployer = new GBDeployer(min.core, importer);
|
||||||
await deployer.undeployPackageFromLocalPath(min.instance, urlJoin('packages', packageName));
|
await deployer.undeployPackageFromLocalPath(min.instance, urlJoin(GBDeployer.workFolder, packageName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static isSharePointPath(path: string) {
|
public static isSharePointPath(path: string) {
|
||||||
|
@ -79,7 +79,7 @@ export class AdminDialog extends IGBDialog {
|
||||||
let siteName = text.split(' ')[1];
|
let siteName = text.split(' ')[1];
|
||||||
let folderName = text.split(' ')[2];
|
let folderName = text.split(' ')[2];
|
||||||
|
|
||||||
let localFolder = Path.join('tmp', Path.basename(folderName));
|
let localFolder = Path.join('work', Path.basename(folderName));
|
||||||
await s.downloadFolder(localFolder, siteName, folderName,
|
await s.downloadFolder(localFolder, siteName, folderName,
|
||||||
GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD'))
|
GBConfigService.get('CLOUD_USERNAME'), GBConfigService.get('CLOUD_PASSWORD'))
|
||||||
await deployer.deployPackage(min, localFolder);
|
await deployer.deployPackage(min, localFolder);
|
||||||
|
@ -122,20 +122,20 @@ export class AdminDialog extends IGBDialog {
|
||||||
const prompt = Messages[locale].authenticate;
|
const prompt = Messages[locale].authenticate;
|
||||||
|
|
||||||
return await step.prompt('textPrompt', prompt);
|
return await step.prompt('textPrompt', prompt);
|
||||||
},
|
// },
|
||||||
async step => {
|
// async step => {
|
||||||
const locale = step.context.activity.locale;
|
// const locale = step.context.activity.locale;
|
||||||
const sensitive = step.result;
|
// const sensitive = step.result;
|
||||||
|
|
||||||
if (sensitive === GBConfigService.get('ADMIN_PASS')) {
|
// if (sensitive === GBConfigService.get('ADMIN_PASS')) {
|
||||||
await step.context.sendActivity(Messages[locale].welcome);
|
// await step.context.sendActivity(Messages[locale].welcome);
|
||||||
|
|
||||||
return await step.prompt('textPrompt', Messages[locale].which_task);
|
// return await step.prompt('textPrompt', Messages[locale].which_task);
|
||||||
} else {
|
// } else {
|
||||||
await step.context.sendActivity(Messages[locale].wrong_password);
|
// await step.context.sendActivity(Messages[locale].wrong_password);
|
||||||
|
|
||||||
return await step.endDialog();
|
// return await step.endDialog();
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
async step => {
|
async step => {
|
||||||
const locale: string = step.context.activity.locale;
|
const locale: string = step.context.activity.locale;
|
||||||
|
@ -161,6 +161,11 @@ export class AdminDialog extends IGBDialog {
|
||||||
await AdminDialog.rebuildIndexPackageCommand(min, deployer);
|
await AdminDialog.rebuildIndexPackageCommand(min, deployer);
|
||||||
await step.context.sendActivity('Finished importing of that .gbkb package. Thanks.');
|
await step.context.sendActivity('Finished importing of that .gbkb package. Thanks.');
|
||||||
return await step.replaceDialog('/admin', { firstRun: false });
|
return await step.replaceDialog('/admin', { firstRun: false });
|
||||||
|
} else if (cmdName === 'undeployPackage') {
|
||||||
|
await step.context.sendActivity('The package is being *undeployed*...');
|
||||||
|
await AdminDialog.undeployPackageCommand(text, min);
|
||||||
|
await step.context.sendActivity('Package *undeployed*.');
|
||||||
|
return await step.replaceDialog('/admin', { firstRun: false });
|
||||||
} else if (cmdName === 'rebuildIndex') {
|
} else if (cmdName === 'rebuildIndex') {
|
||||||
await AdminDialog.rebuildIndexPackageCommand(min, deployer);
|
await AdminDialog.rebuildIndexPackageCommand(min, deployer);
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async botExists(botId, group, endpoint) {
|
public async botExists(botId, group) {
|
||||||
const baseUrl = `https://management.azure.com/`;
|
const baseUrl = `https://management.azure.com/`;
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
@ -227,17 +227,11 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||||
const httpClient = new ServiceClient();
|
const httpClient = new ServiceClient();
|
||||||
|
|
||||||
const parameters = {
|
|
||||||
properties: {
|
|
||||||
endpoint: endpoint
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||||
this.provider
|
this.provider
|
||||||
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||||
const url = urlJoin(baseUrl, query);
|
const url = urlJoin(baseUrl, query);
|
||||||
const req = AzureDeployerService.createRequestObject(url, accessToken, 'GET', JSON.stringify(parameters));
|
const req = AzureDeployerService.createRequestObject(url, accessToken, 'GET', undefined);
|
||||||
const res = await httpClient.sendRequest(req);
|
const res = await httpClient.sendRequest(req);
|
||||||
// CHECK
|
// CHECK
|
||||||
if (!JSON.parse(res.bodyAsText).id) {
|
if (!JSON.parse(res.bodyAsText).id) {
|
||||||
|
@ -307,6 +301,28 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
||||||
GBLog.info(`Bot proxy updated at: ${endpoint}.`);
|
GBLog.info(`Bot proxy updated at: ${endpoint}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deleteBot(botId: string, group) {
|
||||||
|
const baseUrl = `https://management.azure.com/`;
|
||||||
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||||
|
|
||||||
|
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||||
|
const httpClient = new ServiceClient();
|
||||||
|
|
||||||
|
const query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
|
||||||
|
this.provider
|
||||||
|
}/botServices/${botId}?api-version=${this.apiVersion}`;
|
||||||
|
const url = urlJoin(baseUrl, query);
|
||||||
|
const req = AzureDeployerService.createRequestObject(url, accessToken, 'DELETE', undefined);
|
||||||
|
const res = await httpClient.sendRequest(req);
|
||||||
|
|
||||||
|
if (res.bodyAsText !== "") {
|
||||||
|
throw res.bodyAsText;
|
||||||
|
}
|
||||||
|
GBLog.info(`Bot ${botId} was deleted from the provider.`);
|
||||||
|
}
|
||||||
|
|
||||||
public async openStorageFirewall(groupName, serverName) {
|
public async openStorageFirewall(groupName, serverName) {
|
||||||
const username = GBConfigService.get('CLOUD_USERNAME');
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
const password = GBConfigService.get('CLOUD_PASSWORD');
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
|
|
@ -279,6 +279,12 @@ STORAGE_SYNC=true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deleteInstance(botId:string) {
|
||||||
|
const options = { where: {} };
|
||||||
|
options.where = { botId: botId };
|
||||||
|
await GuaribasInstance.destroy(options);
|
||||||
|
}
|
||||||
|
|
||||||
public async saveInstance(fullInstance: any) {
|
public async saveInstance(fullInstance: any) {
|
||||||
const options = { where: {} };
|
const options = { where: {} };
|
||||||
options.where = { botId: fullInstance.botId };
|
options.where = { botId: fullInstance.botId };
|
||||||
|
|
|
@ -43,6 +43,7 @@ const WaitUntil = require('wait-until');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
const graph = require('@microsoft/microsoft-graph-client');
|
const graph = require('@microsoft/microsoft-graph-client');
|
||||||
|
const emptyDir = require('empty-dir');
|
||||||
|
|
||||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBInstance, IGBPackage } from 'botlib';
|
||||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||||
|
@ -54,6 +55,8 @@ import { KBService } from './../../kb.gbapp/services/KBService';
|
||||||
import { GBConfigService } from './GBConfigService';
|
import { GBConfigService } from './GBConfigService';
|
||||||
import { GBImporter } from './GBImporterService';
|
import { GBImporter } from './GBImporterService';
|
||||||
import { GBVMService } from './GBVMService';
|
import { GBVMService } from './GBVMService';
|
||||||
|
import { min } from 'moment';
|
||||||
|
import { GBMinService } from './GBMinService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -62,9 +65,9 @@ import { GBVMService } from './GBVMService';
|
||||||
|
|
||||||
export class GBDeployer {
|
export class GBDeployer {
|
||||||
public static deployFolder = 'packages';
|
public static deployFolder = 'packages';
|
||||||
|
public static workFolder = 'work';
|
||||||
public core: IGBCoreService;
|
public core: IGBCoreService;
|
||||||
public importer: GBImporter;
|
public importer: GBImporter;
|
||||||
public workDir: string = './work';
|
|
||||||
|
|
||||||
constructor(core: IGBCoreService, importer: GBImporter) {
|
constructor(core: IGBCoreService, importer: GBImporter) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
|
@ -93,7 +96,7 @@ export class GBDeployer {
|
||||||
(resolve: any, reject: any): any => {
|
(resolve: any, reject: any): any => {
|
||||||
GBLog.info(`PWD ${process.env.PWD}...`);
|
GBLog.info(`PWD ${process.env.PWD}...`);
|
||||||
let totalPackages = 0;
|
let totalPackages = 0;
|
||||||
let paths = [urlJoin(process.env.PWD, GBDeployer.deployFolder)];
|
let paths = [urlJoin(process.env.PWD, GBDeployer.deployFolder), urlJoin(process.env.PWD, GBDeployer.workFolder)];
|
||||||
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
const additionalPath = GBConfigService.get('ADDITIONAL_DEPLOY_PATH');
|
||||||
if (additionalPath !== undefined && additionalPath !== '') {
|
if (additionalPath !== undefined && additionalPath !== '') {
|
||||||
paths = paths.concat(additionalPath.toLowerCase().split(';'));
|
paths = paths.concat(additionalPath.toLowerCase().split(';'));
|
||||||
|
@ -165,7 +168,7 @@ export class GBDeployer {
|
||||||
* Deploys a bot to the storage.
|
* Deploys a bot to the storage.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async deployBot(localPath: string, proxyAddress: string): Promise<void> {
|
public async deployBot(localPath: string, publicAddress: string): Promise<void> {
|
||||||
const packageName = Path.basename(localPath);
|
const packageName = Path.basename(localPath);
|
||||||
|
|
||||||
const service = new AzureDeployerService(this);
|
const service = new AzureDeployerService(this);
|
||||||
|
@ -177,17 +180,17 @@ export class GBDeployer {
|
||||||
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||||
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||||
|
|
||||||
if (await service.botExists(instance.botId, group, proxyAddress)) {
|
if (await service.botExists(instance.botId, group)) {
|
||||||
instance = await service.updateBot(
|
await service.updateBot(
|
||||||
instance,
|
instance.botId,
|
||||||
accessToken,
|
group,
|
||||||
instance.title,
|
instance.title,
|
||||||
instance.description,
|
instance.description,
|
||||||
proxyAddress
|
`${publicAddress}/api/messages/${instance.botId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
instance = Object.assign(instance, GBServer.globals.bootInstance);
|
||||||
instance = await service.internalDeployBot(
|
instance = await service.internalDeployBot(
|
||||||
instance,
|
instance,
|
||||||
accessToken,
|
accessToken,
|
||||||
|
@ -195,7 +198,7 @@ export class GBDeployer {
|
||||||
instance.title,
|
instance.title,
|
||||||
group,
|
group,
|
||||||
instance.description,
|
instance.description,
|
||||||
`${proxyAddress}/api/messages/${instance.botId}`,
|
`${publicAddress}/api/messages/${instance.botId}`,
|
||||||
'global',
|
'global',
|
||||||
instance.nlpAppId,
|
instance.nlpAppId,
|
||||||
instance.nlpKey,
|
instance.nlpKey,
|
||||||
|
@ -203,10 +206,40 @@ export class GBDeployer {
|
||||||
instance.marketplacePassword,
|
instance.marketplacePassword,
|
||||||
subscriptionId
|
subscriptionId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await GBServer.globals.minService.mountBot(instance);
|
||||||
}
|
}
|
||||||
await this.core.saveInstance(instance);
|
await this.core.saveInstance(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deploys a bot to the storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public async undeployBot(botId: string, packageName: string): Promise<void> {
|
||||||
|
const service = new AzureDeployerService(this);
|
||||||
|
|
||||||
|
const username = GBConfigService.get('CLOUD_USERNAME');
|
||||||
|
const password = GBConfigService.get('CLOUD_PASSWORD');
|
||||||
|
const group = GBConfigService.get('CLOUD_GROUP');
|
||||||
|
const subscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID');
|
||||||
|
const accessToken = await GBAdminService.getADALTokenFromUsername(username, password);
|
||||||
|
|
||||||
|
if (await service.botExists(botId, group)) {
|
||||||
|
|
||||||
|
await service.deleteBot(
|
||||||
|
botId, group
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
GBServer.globals.minService.unmountBot(botId);
|
||||||
|
await this.core.deleteInstance(botId);
|
||||||
|
const packageFolder = urlJoin(process.env.PWD, 'work', packageName);
|
||||||
|
await emptyDir(packageFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
public async deployPackageToStorage(instanceId: number, packageName: string): Promise<GuaribasPackage> {
|
||||||
return GuaribasPackage.create({
|
return GuaribasPackage.create({
|
||||||
packageName: packageName,
|
packageName: packageName,
|
||||||
|
@ -233,6 +266,7 @@ export class GBDeployer {
|
||||||
switch (packageType) {
|
switch (packageType) {
|
||||||
case '.gbot':
|
case '.gbot':
|
||||||
await this.deployBot(localPath, GBServer.globals.publicAddress);
|
await this.deployBot(localPath, GBServer.globals.publicAddress);
|
||||||
|
break;
|
||||||
|
|
||||||
case '.gbkb':
|
case '.gbkb':
|
||||||
const service = new KBService(this.core.sequelize);
|
const service = new KBService(this.core.sequelize);
|
||||||
|
@ -257,7 +291,13 @@ export class GBDeployer {
|
||||||
|
|
||||||
const p = await this.getPackageByName(instance.instanceId, packageName);
|
const p = await this.getPackageByName(instance.instanceId, packageName);
|
||||||
|
|
||||||
|
|
||||||
switch (packageType) {
|
switch (packageType) {
|
||||||
|
case '.gbot':
|
||||||
|
const packageObject = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||||
|
await this.undeployBot(packageObject.botId, packageName);
|
||||||
|
break;
|
||||||
|
|
||||||
case '.gbkb':
|
case '.gbkb':
|
||||||
const service = new KBService(this.core.sequelize);
|
const service = new KBService(this.core.sequelize);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ import urlJoin = require('url-join');
|
||||||
const { DialogSet, TextPrompt } = require('botbuilder-dialogs');
|
const { DialogSet, TextPrompt } = require('botbuilder-dialogs');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const request = require('request-promise-native');
|
const request = require('request-promise-native');
|
||||||
|
const removeRoute = require('express-remove-route');
|
||||||
const AuthenticationContext = require('adal-node').AuthenticationContext;
|
const AuthenticationContext = require('adal-node').AuthenticationContext;
|
||||||
import { AutoSaveStateMiddleware, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
|
import { AutoSaveStateMiddleware, BotFrameworkAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
|
||||||
import { ConfirmPrompt, WaterfallDialog } from 'botbuilder-dialogs';
|
import { ConfirmPrompt, WaterfallDialog } from 'botbuilder-dialogs';
|
||||||
|
@ -76,6 +77,7 @@ export class GBMinService {
|
||||||
public conversationalService: IGBConversationalService;
|
public conversationalService: IGBConversationalService;
|
||||||
public adminService: IGBAdminService;
|
public adminService: IGBAdminService;
|
||||||
public deployer: GBDeployer;
|
public deployer: GBDeployer;
|
||||||
|
private static uiPackage = 'default.gbui';
|
||||||
|
|
||||||
public corePackage = 'core.gbai';
|
public corePackage = 'core.gbai';
|
||||||
|
|
||||||
|
@ -108,79 +110,73 @@ export class GBMinService {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async buildMin(
|
public async buildMin(
|
||||||
bootInstance: IGBInstance,
|
|
||||||
server: any,
|
|
||||||
appPackages: IGBPackage[],
|
|
||||||
sysPackages: IGBPackage[],
|
|
||||||
instances: IGBInstance[],
|
instances: IGBInstance[],
|
||||||
deployer: GBDeployer,
|
|
||||||
proxyAddress: string
|
|
||||||
) {
|
) {
|
||||||
const uiPackage = 'default.gbui';
|
|
||||||
|
|
||||||
// Serves default UI on root address '/' if web enabled.
|
// Serves default UI on root address '/' if web enabled.
|
||||||
if (process.env.DISABLE_WEB !== 'true') {
|
if (process.env.DISABLE_WEB !== 'true') {
|
||||||
server.use('/', express.static(urlJoin(GBDeployer.deployFolder, uiPackage, 'build')));
|
GBServer.globals.server.use('/', express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build')));
|
||||||
|
}
|
||||||
|
// Serves the bot information object via HTTP so clients can get
|
||||||
|
// instance information stored on server.
|
||||||
|
if (process.env.DISABLE_WEB !== 'true') {
|
||||||
|
GBServer.globals.server.get('/instances/:botId', (req, res) => {
|
||||||
|
(async () => {
|
||||||
|
await this.handleGetInstanceFroClient(req, res);
|
||||||
|
})();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
instances.map(async instance => {
|
instances.map(async instance => {
|
||||||
// Gets the authorization key for each instance from Bot Service.
|
// Gets the authorization key for each instance from Bot Service.
|
||||||
|
|
||||||
const webchatToken = await this.getWebchatToken(instance);
|
await this.mountBot(instance);
|
||||||
|
})
|
||||||
// Serves the bot information object via HTTP so clients can get
|
);
|
||||||
// instance information stored on server.
|
|
||||||
|
|
||||||
if (process.env.DISABLE_WEB !== 'true') {
|
|
||||||
server.get('/instances/:botId', (req, res) => {
|
|
||||||
(async () => {
|
|
||||||
await this.sendInstanceToClient(req, bootInstance, res, webchatToken);
|
|
||||||
})();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build bot adapter.
|
public async unmountBot(botId: string) {
|
||||||
|
const url = `/api/messages/${botId}`;
|
||||||
|
removeRoute(GBServer.globals.server,url);
|
||||||
|
|
||||||
const { min, adapter, conversationState } = await this.buildBotAdapter(instance, proxyAddress, sysPackages);
|
const uiUrl = `/${botId}`;
|
||||||
|
removeRoute(GBServer.globals.server, uiUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async mountBot(instance: IGBInstance) {
|
||||||
|
|
||||||
|
// Build bot adapter.
|
||||||
|
const { min, adapter, conversationState } = await this.buildBotAdapter(instance, GBServer.globals.publicAddress, GBServer.globals.sysPackages);
|
||||||
|
|
||||||
// Install default VBA module.
|
// Install default VBA module.
|
||||||
|
//this.deployer.deployPackage(min, 'packages/default.gbdialog');
|
||||||
// DISABLED: deployer.deployPackage(min, 'packages/default.gbdialog');
|
|
||||||
|
|
||||||
// Call the loadBot context.activity for all packages.
|
// Call the loadBot context.activity for all packages.
|
||||||
|
this.invokeLoadBot(GBServer.globals.appPackages, GBServer.globals.sysPackages, min, GBServer.globals.server);
|
||||||
this.invokeLoadBot(appPackages, sysPackages, min, server);
|
|
||||||
|
|
||||||
// Serves individual URL for each bot conversational interface...
|
// Serves individual URL for each bot conversational interface...
|
||||||
|
|
||||||
const url = `/api/messages/${instance.botId}`;
|
const url = `/api/messages/${instance.botId}`;
|
||||||
server.post(url, async (req, res) => {
|
GBServer.globals.server.post(url, async (req, res) => {
|
||||||
await this.receiver(adapter, req, res, conversationState, min, instance, appPackages);
|
await this.receiver(adapter, req, res, conversationState, min, instance, GBServer.globals.appPackages);
|
||||||
});
|
});
|
||||||
GBLog.info(`GeneralBots(${instance.engineName}) listening on: ${url}.`);
|
GBLog.info(`GeneralBots(${instance.engineName}) listening on: ${url}.`);
|
||||||
|
|
||||||
// Serves individual URL for each bot user interface.
|
// Serves individual URL for each bot user interface.
|
||||||
|
|
||||||
if (process.env.DISABLE_WEB !== 'true') {
|
if (process.env.DISABLE_WEB !== 'true') {
|
||||||
const uiUrl = `/${instance.botId}`;
|
const uiUrl = `/${instance.botId}`;
|
||||||
server.use(uiUrl, express.static(urlJoin(GBDeployer.deployFolder, uiPackage, 'build')));
|
GBServer.globals.server.use(uiUrl, express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build')));
|
||||||
|
GBLog.info(`Bot UI ${GBMinService.uiPackage} accessible at: ${uiUrl}.`);
|
||||||
GBLog.info(`Bot UI ${uiPackage} accessible at: ${uiUrl}.`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clients get redirected here in order to create an OAuth authorize url and redirect them to AAD.
|
// Clients get redirected here in order to create an OAuth authorize url and redirect them to AAD.
|
||||||
// There they will authenticate and give their consent to allow this app access to
|
// There they will authenticate and give their consent to allow this app access to
|
||||||
// some resource they own.
|
// some resource they own.
|
||||||
|
this.handleOAuthRequests(GBServer.globals.server, min);
|
||||||
this.handleOAuthRequests(server, min);
|
|
||||||
|
|
||||||
// After consent is granted AAD redirects here. The ADAL library
|
// After consent is granted AAD redirects here. The ADAL library
|
||||||
// is invoked via the AuthenticationContext and retrieves an
|
// is invoked via the AuthenticationContext and retrieves an
|
||||||
// access token that can be used to access the user owned resource.
|
// access token that can be used to access the user owned resource.
|
||||||
|
this.handleOAuthTokenRequests(GBServer.globals.server, min, instance);
|
||||||
this.handleOAuthTokenRequests(server, min, instance);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) {
|
private handleOAuthTokenRequests(server: any, min: GBMinInstance, instance: IGBInstance) {
|
||||||
|
@ -235,13 +231,14 @@ export class GBMinService {
|
||||||
/**
|
/**
|
||||||
* Returns the instance object to clients requesting bot info.
|
* Returns the instance object to clients requesting bot info.
|
||||||
*/
|
*/
|
||||||
private async sendInstanceToClient(req, bootInstance: IGBInstance, res: any, webchatToken: any) {
|
private async handleGetInstanceFroClient(req: any, res: any) {
|
||||||
let botId = req.params.botId;
|
let botId = req.params.botId;
|
||||||
if (botId === '[default]' || botId === undefined) {
|
if (botId === '[default]' || botId === undefined) {
|
||||||
botId = GBConfigService.get('BOT_ID');
|
botId = GBConfigService.get('BOT_ID');
|
||||||
}
|
}
|
||||||
const instance = await this.core.loadInstance(botId);
|
const instance = await this.core.loadInstance(botId);
|
||||||
if (instance !== null) {
|
if (instance !== null) {
|
||||||
|
const webchatToken = await this.getWebchatToken(instance);
|
||||||
const speechToken = instance.speechKey != null ? await this.getSTSToken(instance) : null;
|
const speechToken = instance.speechKey != null ? await this.getSTSToken(instance) : null;
|
||||||
let theme = instance.theme;
|
let theme = instance.theme;
|
||||||
if (theme === undefined) {
|
if (theme === undefined) {
|
||||||
|
|
25
src/app.ts
25
src/app.ts
|
@ -58,6 +58,9 @@ export class RootData {
|
||||||
public publicAddress: string;
|
public publicAddress: string;
|
||||||
public server: any;
|
public server: any;
|
||||||
public sysPackages: any[];
|
public sysPackages: any[];
|
||||||
|
public appPackages: any[];
|
||||||
|
minService: GBMinService;
|
||||||
|
bootInstance: IGBInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,12 +118,12 @@ export class GBServer {
|
||||||
|
|
||||||
// Creates a boot instance or load it from storage.
|
// Creates a boot instance or load it from storage.
|
||||||
|
|
||||||
let bootInstance: IGBInstance;
|
|
||||||
try {
|
try {
|
||||||
await core.initStorage();
|
await core.initStorage();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLog.verbose(`Error initializing storage: ${error}`);
|
GBLog.verbose(`Error initializing storage: ${error}`);
|
||||||
bootInstance = await core.createBootInstance(core, azureDeployer, GBServer.globals.publicAddress);
|
GBServer.globals.bootInstance = await core.createBootInstance(core, azureDeployer, GBServer.globals.publicAddress);
|
||||||
await core.initStorage();
|
await core.initStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +135,8 @@ export class GBServer {
|
||||||
const sysPackages = core.loadSysPackages(core);
|
const sysPackages = core.loadSysPackages(core);
|
||||||
await core.checkStorage(azureDeployer);
|
await core.checkStorage(azureDeployer);
|
||||||
await deployer.deployPackages(core, server, appPackages);
|
await deployer.deployPackages(core, server, appPackages);
|
||||||
|
GBServer.globals.sysPackages = sysPackages;
|
||||||
|
GBServer.globals.appPackages = appPackages;
|
||||||
|
|
||||||
// Loads boot bot and other instances.
|
// Loads boot bot and other instances.
|
||||||
|
|
||||||
|
@ -141,24 +146,24 @@ export class GBServer {
|
||||||
'boot.gbot',
|
'boot.gbot',
|
||||||
'packages/boot.gbot'
|
'packages/boot.gbot'
|
||||||
);
|
);
|
||||||
if (bootInstance === undefined) {
|
if (GBServer.globals.bootInstance === undefined) {
|
||||||
bootInstance = packageInstance;
|
GBServer.globals.bootInstance = packageInstance;
|
||||||
}
|
}
|
||||||
// tslint:disable-next-line:prefer-object-spread
|
// tslint:disable-next-line:prefer-object-spread
|
||||||
const fullInstance = Object.assign(packageInstance, bootInstance);
|
const fullInstance = Object.assign(packageInstance, GBServer.globals.bootInstance);
|
||||||
await core.saveInstance(fullInstance);
|
await core.saveInstance(fullInstance);
|
||||||
let instances: IGBInstance[] = await core.loadAllInstances(core, azureDeployer,
|
let instances: IGBInstance[] = await core.loadAllInstances(core, azureDeployer,
|
||||||
GBServer.globals.publicAddress);
|
GBServer.globals.publicAddress);
|
||||||
instances = await core.ensureInstances(instances, bootInstance, core);
|
instances = await core.ensureInstances(instances, GBServer.globals.bootInstance, core);
|
||||||
if (bootInstance !== undefined) {
|
if (GBServer.globals.bootInstance !== undefined) {
|
||||||
bootInstance = instances[0];
|
GBServer.globals.bootInstance = instances[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds minimal service infrastructure.
|
// Builds minimal service infrastructure.
|
||||||
|
|
||||||
const minService: GBMinService = new GBMinService(core, conversationalService, adminService, deployer);
|
const minService: GBMinService = new GBMinService(core, conversationalService, adminService, deployer);
|
||||||
await minService.buildMin(bootInstance, server, appPackages, sysPackages, instances,
|
GBServer.globals.minService = minService;
|
||||||
deployer, GBServer.globals.publicAddress);
|
await minService.buildMin( instances);
|
||||||
|
|
||||||
// Deployment of local applications for the first time.
|
// Deployment of local applications for the first time.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue