new(admin.gbapp): MSGraph now used to download .gbkb artifacts.
This commit is contained in:
parent
face6c59ef
commit
6b1bc00e41
6 changed files with 120 additions and 65 deletions
|
@ -192,17 +192,9 @@ export class GBAdminService implements IGBAdminService {
|
|||
// .gbot packages are handled using storage API, so no download
|
||||
// of local resources is required.
|
||||
|
||||
|
||||
if (!localFolder.endsWith('.gbot') && !process.env.DONT_DOWNLOAD) {
|
||||
GBLog.warn(`${GBConfigService.get('CLOUD_USERNAME')} must be authorized on SharePoint related site to download to: ${localFolder}`);
|
||||
await s.downloadFolder(
|
||||
localFolder,
|
||||
siteName,
|
||||
folderName,
|
||||
GBConfigService.get('CLOUD_USERNAME'),
|
||||
GBConfigService.get('CLOUD_PASSWORD')
|
||||
);
|
||||
}
|
||||
await deployer['downloadFolder'](min,
|
||||
Path.join('work', `${min.instance.botId}.gbai`),
|
||||
Path.basename(folderName));
|
||||
await deployer.deployPackage(min, localFolder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
|
||||
const parameters = {
|
||||
properties: {
|
||||
description: description,
|
||||
description: `${description}`,
|
||||
displayName: name,
|
||||
endpoint: endpoint,
|
||||
iconUrl: iconUrl
|
||||
|
|
|
@ -70,23 +70,6 @@ export class SystemKeywords {
|
|||
this.deployer = deployer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrives token and initialize drive client API.
|
||||
*/
|
||||
private async internalGetDriveClient() {
|
||||
let token = await this.min.adminService.acquireElevatedToken(this.min.instance.instanceId);
|
||||
let siteId = process.env.STORAGE_SITE_ID;
|
||||
let libraryId = process.env.STORAGE_LIBRARY;
|
||||
|
||||
let client = MicrosoftGraph.Client.init({
|
||||
authProvider: done => {
|
||||
done(null, token);
|
||||
}
|
||||
});
|
||||
const baseUrl = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}`;
|
||||
return [baseUrl, client];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrives the content of a given URL.
|
||||
*/
|
||||
|
@ -175,7 +158,7 @@ export class SystemKeywords {
|
|||
public async set(file: string, address: string, value: any): Promise<any> {
|
||||
GBLog.info(`BASIC: Defining '${address}' in '${file}' to '${value}' (SET). `);
|
||||
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
|
||||
const botId = this.min.instance.botId;
|
||||
const path = `/${botId}.gbai/${botId}.gbdata`;
|
||||
|
@ -223,7 +206,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async save(file: string, ...args): Promise<any> {
|
||||
GBLog.info(`BASIC: Saving '${file}' (SAVE). Args: ${args.join(',')}.`);
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const botId = this.min.instance.botId;
|
||||
const path = `/${botId}.gbai/${botId}.gbdata`;
|
||||
|
||||
|
@ -257,7 +240,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async get(file: string, address: string): Promise<any> {
|
||||
GBLog.info(`BASIC: GET '${address}' in '${file}'.`);
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const botId = this.min.instance.botId;
|
||||
const path = `/${botId}.gbai/${botId}.gbdata`;
|
||||
|
||||
|
@ -293,7 +276,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async find(file: string, ...args): Promise<any> {
|
||||
GBLog.info(`BASIC: FIND running on ${file} and args: ${JSON.stringify(args)}...`);
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const botId = this.min.instance.botId;
|
||||
const path = `/${botId}.gbai/${botId}.gbdata`;
|
||||
|
||||
|
@ -313,7 +296,7 @@ export class SystemKeywords {
|
|||
.get();
|
||||
|
||||
let results = await client
|
||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:Z100')`)
|
||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:Z2000')`)
|
||||
.get();
|
||||
|
||||
// Increments columnIndex by looping until find a column match.
|
||||
|
@ -380,7 +363,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async createFolder(name: string) {
|
||||
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const botId = this.min.instance.botId;
|
||||
let path = `/${botId}.gbai/${botId}.gbdata`;
|
||||
|
||||
|
@ -436,7 +419,7 @@ export class SystemKeywords {
|
|||
*
|
||||
*/
|
||||
public async shareFolder(folderReference, email: string, message: string) {
|
||||
let [, client] = await this.internalGetDriveClient();
|
||||
let [, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const driveId = folderReference.parentReference.driveId;
|
||||
const itemId = folderReference.id;
|
||||
const body = {
|
||||
|
@ -462,7 +445,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async copyFile(src, dest) {
|
||||
GBLog.info(`BASIC: BEGINING COPY '${src}' to '${dest}'`);
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const botId = this.min.instance.botId;
|
||||
|
||||
// Normalizes all slashes.
|
||||
|
@ -531,7 +514,7 @@ export class SystemKeywords {
|
|||
*/
|
||||
public async convert(src, dest) {
|
||||
GBLog.info(`BASIC: CONVERT '${src}' to '${dest}'`);
|
||||
let [baseUrl, client] = await this.internalGetDriveClient();
|
||||
let [baseUrl, client] = await GBDeployer.internalGetDriveClient(this.min);
|
||||
const botId = this.min.instance.botId;
|
||||
|
||||
// Normalizes all slashes.
|
||||
|
@ -616,9 +599,9 @@ export class SystemKeywords {
|
|||
*
|
||||
*/
|
||||
public async sendEmail(to, subject, body) {
|
||||
|
||||
|
||||
// tslint:disable-next-line:no-console
|
||||
|
||||
|
||||
GBLog.info(`[E-mail]: to:${to}, subject: ${subject}, body: ${body}.`);
|
||||
const emailToken = process.env.EMAIL_API_KEY;
|
||||
|
||||
|
@ -626,7 +609,7 @@ export class SystemKeywords {
|
|||
sgMail.setApiKey(emailToken);
|
||||
const msg = {
|
||||
to: to,
|
||||
from: process.env.EMAIL_FROM,
|
||||
from: process.env.EMAIL_FROM,
|
||||
subject: subject,
|
||||
text: body,
|
||||
html: body
|
||||
|
@ -642,8 +625,6 @@ export class SystemKeywords {
|
|||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls any REST API by using GET HTTP method.
|
||||
*
|
||||
|
@ -651,14 +632,14 @@ export class SystemKeywords {
|
|||
*
|
||||
*/
|
||||
public async getByHttp(url: string) {
|
||||
const options = {
|
||||
uri: url
|
||||
};
|
||||
const options = {
|
||||
uri: url
|
||||
};
|
||||
|
||||
let result = await request.get(options);
|
||||
GBLog.info(`[GET]: ${url} : ${result}`);
|
||||
return JSON.parse(result);
|
||||
}
|
||||
let result = await request.get(options);
|
||||
GBLog.info(`[GET]: ${url} : ${result}`);
|
||||
return JSON.parse(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls any REST API by using POST HTTP method.
|
||||
|
@ -670,18 +651,18 @@ export class SystemKeywords {
|
|||
*
|
||||
*/
|
||||
public async postByHttp(url: string, data) {
|
||||
const options = {
|
||||
uri: url,
|
||||
json: true,
|
||||
body: data
|
||||
};
|
||||
const options = {
|
||||
uri: url,
|
||||
json: true,
|
||||
body: data
|
||||
};
|
||||
|
||||
let result = await request.post(options);
|
||||
GBLog.info(`[POST]: ${url} (${data}): ${result}`);
|
||||
return JSON.parse(result);
|
||||
}
|
||||
let result = await request.post(options);
|
||||
GBLog.info(`[POST]: ${url} (${data}): ${result}`);
|
||||
return JSON.parse(result);
|
||||
}
|
||||
|
||||
public async numberOnly(text: string) {
|
||||
return text.replace(/\D/gi, '');
|
||||
}
|
||||
return text.replace(/\D/gi, '');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ import urlJoin = require('url-join');
|
|||
const Fs = require('fs');
|
||||
const express = require('express');
|
||||
const child_process = require('child_process');
|
||||
const graph = require('@microsoft/microsoft-graph-client');
|
||||
const rimraf = require('rimraf');
|
||||
const request = require('request-promise-native');
|
||||
|
||||
import { GBError, GBLog, GBMinInstance, IGBCoreService, IGBDeployer, IGBInstance, IGBPackage } from 'botlib';
|
||||
import { AzureSearch } from 'pragmatismo-io-framework';
|
||||
|
@ -98,6 +98,23 @@ export class GBDeployer implements IGBDeployer {
|
|||
return `Server=tcp:${instance.storageServer},1433;Database=${instance.storageName};User ID=${instance.storageUsername};Password=${instance.storagePassword};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrives token and initialize drive client API.
|
||||
*/
|
||||
public static async internalGetDriveClient(min: GBMinInstance) {
|
||||
let token = await min.adminService.acquireElevatedToken(min.instance.instanceId);
|
||||
let siteId = process.env.STORAGE_SITE_ID;
|
||||
let libraryId = process.env.STORAGE_LIBRARY;
|
||||
|
||||
let client = MicrosoftGraph.Client.init({
|
||||
authProvider: done => {
|
||||
done(null, token);
|
||||
}
|
||||
});
|
||||
const baseUrl = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}`;
|
||||
return [baseUrl, client];
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs package deployment in all .gbai or default.
|
||||
*/
|
||||
|
@ -422,6 +439,71 @@ export class GBDeployer implements IGBDeployer {
|
|||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all para from tabular file Config.xlsx.
|
||||
*/
|
||||
public async downloadFolder(min: GBMinInstance, localPath: string, remotePath: string,
|
||||
baseUrl: string = null, client = null): Promise<any> {
|
||||
if (!baseUrl) {
|
||||
[baseUrl, client] = await GBDeployer.internalGetDriveClient(min);
|
||||
|
||||
remotePath = remotePath.replace(/\\/gi, '/');
|
||||
const parts = remotePath.split('/');
|
||||
|
||||
// Creates each subfolder.
|
||||
|
||||
let pathBase = localPath;
|
||||
if (!Fs.existsSync(pathBase)) {
|
||||
Fs.mkdirSync(pathBase);
|
||||
}
|
||||
|
||||
await CollectionUtil.asyncForEach(parts, async item => {
|
||||
pathBase = Path.join(pathBase, item);
|
||||
if (!Fs.existsSync(pathBase)) {
|
||||
Fs.mkdirSync(pathBase);
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieves all files in remote folder.
|
||||
|
||||
const botId = min.instance.botId;
|
||||
const path = urlJoin(`/${botId}.gbai`, remotePath);
|
||||
let url = `${baseUrl}/drive/root:${path}:/children`;
|
||||
|
||||
const res = await client
|
||||
.api(url)
|
||||
.get();
|
||||
const documents = res.value;
|
||||
if (documents === undefined || documents.length === 0) {
|
||||
GBLog.info(`${remotePath} is an empty folder.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Download files or navigate to directory to recurse.
|
||||
|
||||
await CollectionUtil.asyncForEach(documents, async item => {
|
||||
|
||||
const itemPath = Path.join(localPath, remotePath, item.name);
|
||||
|
||||
if (item.folder) {
|
||||
if (!Fs.existsSync(itemPath)) {
|
||||
Fs.mkdirSync(itemPath);
|
||||
}
|
||||
const nextFolder = urlJoin(remotePath, item.name);
|
||||
await this.downloadFolder(min, localPath, nextFolder);
|
||||
} else {
|
||||
GBLog.info(`Downloading ${itemPath}...`);
|
||||
const url = item['@microsoft.graph.downloadUrl'];
|
||||
const options = {
|
||||
uri: url,
|
||||
encoding: null
|
||||
};
|
||||
const response = await request({ uri: url, encoding: null });
|
||||
Fs.writeFileSync(itemPath, response, { encoding: null });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* UndDeploys a bot to the storage.
|
||||
*/
|
||||
|
@ -561,7 +643,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
|
||||
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
||||
Promise.reject(err);
|
||||
break;
|
||||
|
|
|
@ -157,7 +157,7 @@ export class GBMinService {
|
|||
try {
|
||||
await this.mountBot(instance);
|
||||
} catch (error) {
|
||||
GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}`);
|
||||
GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ export class GBServer {
|
|||
}
|
||||
|
||||
GBLog.info(`The Bot Server is in RUNNING mode...`);
|
||||
|
||||
|
||||
// Opens Navigator.
|
||||
|
||||
// TODO: Config: core.openBrowserInDevelopment();
|
||||
|
|
Loading…
Add table
Reference in a new issue