Compare commits
No commits in common. "ba750a289f66b306ede023a2af46e8da5292f265" and "61d8cfe93c3702f9120875545ef82a9cafef58fe" have entirely different histories.
ba750a289f
...
61d8cfe93c
9 changed files with 234 additions and 322 deletions
|
@ -1028,7 +1028,7 @@ export class GBVMService extends GBService {
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (GBConfigService.get('GBVM') !== false) {
|
if (!GBConfigService.get('GBVM')) {
|
||||||
return await (async () => {
|
return await (async () => {
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
sandbox['resolve'] = resolve;
|
sandbox['resolve'] = resolve;
|
||||||
|
|
|
@ -86,7 +86,7 @@ export class GBConfigService {
|
||||||
value = this.getServerPort();
|
value = this.getServerPort();
|
||||||
break;
|
break;
|
||||||
case 'GBVM':
|
case 'GBVM':
|
||||||
value = true;
|
value = false;
|
||||||
break;
|
break;
|
||||||
case 'STORAGE_NAME':
|
case 'STORAGE_NAME':
|
||||||
value = null;
|
value = null;
|
||||||
|
|
|
@ -113,7 +113,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.adminService = new GBAdminService(this);
|
this.adminService = new GBAdminService(this);
|
||||||
}
|
}
|
||||||
public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) { }
|
public async ensureInstances(instances: IGBInstance[], bootInstance: any, core: IGBCoreService) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets database config and connect to storage. Currently two databases
|
* Gets database config and connect to storage. Currently two databases
|
||||||
|
@ -121,60 +121,60 @@ export class GBCoreService implements IGBCoreService {
|
||||||
*/
|
*/
|
||||||
public async initStorage(): Promise<any> {
|
public async initStorage(): Promise<any> {
|
||||||
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
this.dialect = GBConfigService.get('STORAGE_DIALECT');
|
||||||
|
|
||||||
let port: number | undefined;
|
let port: number | undefined;
|
||||||
let host: string | undefined;
|
let host: string | undefined;
|
||||||
let database: string | undefined;
|
let database: string | undefined;
|
||||||
let username: string | undefined;
|
let username: string | undefined;
|
||||||
let password: string | undefined;
|
let password: string | undefined;
|
||||||
let storage: string | undefined;
|
let storage: string | undefined;
|
||||||
|
|
||||||
|
|
||||||
if (!['mssql', 'postgres', 'sqlite'].includes(this.dialect)) {
|
if (!['mssql', 'postgres', 'sqlite'].includes(this.dialect)) {
|
||||||
throw new Error(`Unknown or unsupported dialect: ${this.dialect}.`);
|
throw new Error(`Unknown or unsupported dialect: ${this.dialect}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this.dialect === 'mssql' || this.dialect === 'postgres') {
|
if (this.dialect === 'mssql' || this.dialect === 'postgres') {
|
||||||
host = GBConfigService.get('STORAGE_SERVER');
|
host = GBConfigService.get('STORAGE_SERVER');
|
||||||
database = GBConfigService.get('STORAGE_NAME');
|
database = GBConfigService.get('STORAGE_NAME');
|
||||||
username = GBConfigService.get('STORAGE_USERNAME');
|
username = GBConfigService.get('STORAGE_USERNAME');
|
||||||
password = GBConfigService.get('STORAGE_PASSWORD');
|
password = GBConfigService.get('STORAGE_PASSWORD');
|
||||||
|
|
||||||
const portStr = GBConfigService.get('STORAGE_PORT');
|
const portStr = GBConfigService.get('STORAGE_PORT');
|
||||||
port = portStr ? parseInt(portStr, 10) : undefined;
|
port = portStr ? parseInt(portStr, 10) : undefined;
|
||||||
|
|
||||||
if (!host || !database || !username || !password || !port) {
|
if (!host || !database || !username || !password || !port) {
|
||||||
throw new Error(`Missing required configuration for ${this.dialect}.`);
|
throw new Error(`Missing required configuration for ${this.dialect}.`);
|
||||||
}
|
}
|
||||||
} else if (this.dialect === 'sqlite') {
|
} else if (this.dialect === 'sqlite') {
|
||||||
storage = GBConfigService.get('STORAGE_FILE');
|
storage = GBConfigService.get('STORAGE_FILE');
|
||||||
|
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
throw new Error('STORAGE_FILE is required for SQLite.');
|
throw new Error('STORAGE_FILE is required for SQLite.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(await GBUtil.exists(storage))) {
|
if (!(await GBUtil.exists(storage))) {
|
||||||
process.env.STORAGE_SYNC = 'true';
|
process.env.STORAGE_SYNC = 'true';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const logging: boolean | Function =
|
const logging: boolean | Function =
|
||||||
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
GBConfigService.get('STORAGE_LOGGING') === 'true'
|
||||||
? (str: string): void => {
|
? (str: string): void => {
|
||||||
GBLogEx.info(0, str);
|
GBLogEx.info(0, str);
|
||||||
}
|
}
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
|
||||||
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
const encrypt: boolean = GBConfigService.get('STORAGE_ENCRYPT') === 'true';
|
||||||
|
|
||||||
|
|
||||||
const acquireStr = GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT');
|
const acquireStr = GBConfigService.get('STORAGE_ACQUIRE_TIMEOUT');
|
||||||
const acquire = acquireStr ? parseInt(acquireStr, 10) : 10000; // Valor padrão de 10 segundos
|
const acquire = acquireStr ? parseInt(acquireStr, 10) : 10000; // Valor padrão de 10 segundos
|
||||||
|
|
||||||
|
|
||||||
const sequelizeOptions: SequelizeOptions = {
|
const sequelizeOptions: SequelizeOptions = {
|
||||||
define: {
|
define: {
|
||||||
freezeTableName: true,
|
freezeTableName: true,
|
||||||
|
@ -185,7 +185,7 @@ export class GBCoreService implements IGBCoreService {
|
||||||
logging: logging as boolean,
|
logging: logging as boolean,
|
||||||
dialect: this.dialect as Dialect,
|
dialect: this.dialect as Dialect,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
quoteIdentifiers: this.dialect === 'postgres',
|
quoteIdentifiers: this.dialect === 'postgres',
|
||||||
dialectOptions: this.dialect === 'mssql' ? {
|
dialectOptions: this.dialect === 'mssql' ? {
|
||||||
options: {
|
options: {
|
||||||
trustServerCertificate: true,
|
trustServerCertificate: true,
|
||||||
|
@ -200,11 +200,11 @@ export class GBCoreService implements IGBCoreService {
|
||||||
acquire: acquire,
|
acquire: acquire,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
this.sequelize = new Sequelize(database, username, password, sequelizeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks wheather storage is acessible or not and opens firewall
|
* Checks wheather storage is acessible or not and opens firewall
|
||||||
* in case of any connection block.
|
* in case of any connection block.
|
||||||
|
@ -338,7 +338,7 @@ STORAGE_SYNC_ALTER=true
|
||||||
ENDPOINT_UPDATE=true
|
ENDPOINT_UPDATE=true
|
||||||
`;
|
`;
|
||||||
|
|
||||||
await fs.writeFile('.env', env);
|
await fs.writeFile('.env', env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -548,7 +548,7 @@ ENDPOINT_UPDATE=true
|
||||||
* Verifies that an complex global password has been specified
|
* Verifies that an complex global password has been specified
|
||||||
* before starting the server.
|
* before starting the server.
|
||||||
*/
|
*/
|
||||||
public ensureAdminIsSecured() { }
|
public ensureAdminIsSecured() {}
|
||||||
|
|
||||||
public async createBootInstance(
|
public async createBootInstance(
|
||||||
core: GBCoreService,
|
core: GBCoreService,
|
||||||
|
@ -703,27 +703,27 @@ ENDPOINT_UPDATE=true
|
||||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
||||||
// Handles calls for BASIC persistence on sheet files.
|
// Handles calls for BASIC persistence on sheet files.
|
||||||
GBLog.info(`Defining Config.xlsx variable ${name}= '${value}'...`);
|
GBLog.info(`Defining Config.xlsx variable ${name}= '${value}'...`);
|
||||||
|
|
||||||
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
const maxLines = 512;
|
const maxLines = 512;
|
||||||
const file = 'Config.xlsx';
|
const file = 'Config.xlsx';
|
||||||
const packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
const packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
||||||
|
|
||||||
let document = await new SystemKeywords().internalGetDocument(client, baseUrl, packagePath, file);
|
let document = await new SystemKeywords().internalGetDocument(client, baseUrl, packagePath, file);
|
||||||
|
|
||||||
// Creates book session that will be discarded.
|
// Creates book session that will be discarded.
|
||||||
let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get();
|
||||||
|
|
||||||
// Get the current rows in column A
|
// Get the current rows in column A
|
||||||
let results = await client
|
let results = await client
|
||||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A${maxLines}')`)
|
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A${maxLines}')`)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
const rows = results.values;
|
const rows = results.values;
|
||||||
let address = '';
|
let address = '';
|
||||||
let lastEmptyRow = -1;
|
let lastEmptyRow = -1;
|
||||||
let isEdit = false;
|
let isEdit = false;
|
||||||
|
|
||||||
// Loop through column A to find the row where name matches, or find the next empty row
|
// Loop through column A to find the row where name matches, or find the next empty row
|
||||||
for (let i = 7; i <= rows.length; i++) {
|
for (let i = 7; i <= rows.length; i++) {
|
||||||
let result = rows[i - 1][0];
|
let result = rows[i - 1][0];
|
||||||
|
@ -732,27 +732,27 @@ ENDPOINT_UPDATE=true
|
||||||
isEdit = true; // We are in editing mode
|
isEdit = true; // We are in editing mode
|
||||||
break;
|
break;
|
||||||
} else if (!result && lastEmptyRow === -1) {
|
} else if (!result && lastEmptyRow === -1) {
|
||||||
lastEmptyRow = i; // Store the first empty row if no match is found
|
lastEmptyRow = i ; // Store the first empty row if no match is found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no match was found and there's an empty row, add a new entry
|
// If no match was found and there's an empty row, add a new entry
|
||||||
if (!isEdit && lastEmptyRow !== -1) {
|
if (!isEdit && lastEmptyRow !== -1) {
|
||||||
address = `A${lastEmptyRow}:B${lastEmptyRow}`; // Add new entry in columns A and B
|
address = `A${lastEmptyRow}:B${lastEmptyRow}`; // Add new entry in columns A and B
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the request body based on whether it's an edit or add operation
|
// Prepare the request body based on whether it's an edit or add operation
|
||||||
let body = { values: isEdit ? [[value]] : [[name, value]] };
|
let body = { values: isEdit ? [[value]] : [[name, value]] };
|
||||||
|
|
||||||
// Update or add the new value in the found address
|
// Update or add the new value in the found address
|
||||||
await client
|
await client
|
||||||
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
|
||||||
.patch(body);
|
.patch(body);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
let packagePath = GBUtil.getGBAIPath(min.botId, `gbot`);
|
||||||
const config = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, 'config.csv');
|
const config = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, 'config.csv');
|
||||||
|
|
||||||
const db = await csvdb(config, ['name', 'value'], ',');
|
const db = await csvdb(config, ['name', 'value'], ',');
|
||||||
if (await db.get({ name: name })) {
|
if (await db.get({ name: name })) {
|
||||||
await db.edit({ name: name }, { name, value });
|
await db.edit({ name: name }, { name, value });
|
||||||
|
@ -761,7 +761,7 @@ ENDPOINT_UPDATE=true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
|
* Get a dynamic param from instance. Dynamic params are defined in Config.xlsx
|
||||||
* and loaded into the work folder from comida command.
|
* and loaded into the work folder from comida command.
|
||||||
|
@ -863,7 +863,7 @@ ENDPOINT_UPDATE=true
|
||||||
public async ensureFolders(instances, deployer: GBDeployer) {
|
public async ensureFolders(instances, deployer: GBDeployer) {
|
||||||
const storageMode = process.env.GB_MODE;
|
const storageMode = process.env.GB_MODE;
|
||||||
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
let libraryPath = GBConfigService.get('STORAGE_LIBRARY');
|
||||||
|
|
||||||
if (storageMode === 'gbcluster') {
|
if (storageMode === 'gbcluster') {
|
||||||
const minioClient = new Client({
|
const minioClient = new Client({
|
||||||
endPoint: process.env.DRIVE_SERVER,
|
endPoint: process.env.DRIVE_SERVER,
|
||||||
|
@ -872,58 +872,54 @@ ENDPOINT_UPDATE=true
|
||||||
accessKey: process.env.DRIVE_ACCESSKEY,
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
secretKey: process.env.DRIVE_SECRET,
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
const bucketStream = await minioClient.listBuckets();
|
const bucketStream = await minioClient.listBuckets();
|
||||||
|
|
||||||
for await (const bucket of bucketStream) {
|
for await (const bucket of bucketStream) {
|
||||||
if (bucket.name.endsWith('.gbai') && bucket.name.startsWith(process.env.DRIVE_ORG_PREFIX)) {
|
if (bucket.name.endsWith('.gbai') && bucket.name.startsWith(process.env.DRIVE_ORG_PREFIX)) {
|
||||||
|
|
||||||
const botId = bucket.name.replace('.gbai', '').replace(process.env.DRIVE_ORG_PREFIX, '');
|
const botId = bucket.name.replace('.gbai', '').replace(process.env.DRIVE_ORG_PREFIX, '');
|
||||||
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!(await GBUtil.exists(libraryPath))) {
|
if (!(await GBUtil.exists(libraryPath))) {
|
||||||
mkdirp.sync(libraryPath);
|
mkdirp.sync(libraryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
await this.syncBotStorage(instances, 'default', deployer, libraryPath);
|
||||||
|
|
||||||
const files = await fs.readdir(libraryPath);
|
const files = await fs.readdir(libraryPath);
|
||||||
await CollectionUtil.asyncForEach(files, async (file) => {
|
await CollectionUtil.asyncForEach(files, async (file) => {
|
||||||
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
if (file.trim().toLowerCase() !== 'default.gbai' && file.charAt(0) !== '_') {
|
||||||
let botId = file.replace(/\.gbai/, '');
|
let botId = file.replace(/\.gbai/, '');
|
||||||
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
await this.syncBotStorage(instances, botId, deployer, libraryPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
private async syncBotStorage(instances: any, botId: any, deployer: GBDeployer, libraryPath: string) {
|
||||||
|
|
||||||
|
|
||||||
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
let instance = instances.find(p => p.botId.toLowerCase().trim() === botId.toLowerCase().trim());
|
||||||
|
|
||||||
if (process.env.GB_MODE === 'local') {
|
if (!instance) {
|
||||||
if (!instance) {
|
GBLog.info(`Importing package ${botId}.gbai...`);
|
||||||
GBLog.info(`Importing package ${botId}.gbai...`);
|
|
||||||
|
|
||||||
// Creates a bot.
|
// Creates a bot.
|
||||||
|
|
||||||
let mobile = null,
|
let mobile = null,
|
||||||
email = null;
|
email = null;
|
||||||
|
|
||||||
instance = await deployer.deployBlankBot(botId, mobile, email);
|
instance = await deployer.deployBlankBot(botId, mobile, email);
|
||||||
instances.push(instance);
|
instances.push(instance);
|
||||||
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
const gbaiPath = path.join(libraryPath, `${botId}.gbai`);
|
||||||
|
|
||||||
if (!(await GBUtil.exists(gbaiPath))) {
|
if (!(await GBUtil.exists(gbaiPath))) {
|
||||||
fs.mkdir(gbaiPath, { recursive: true });
|
fs.mkdir(gbaiPath, { recursive: true });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
|
|
|
@ -49,7 +49,7 @@ import { GBServer } from '../../../src/app.js';
|
||||||
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||||
import Excel from 'exceljs';
|
import Excel from 'exceljs';
|
||||||
import asyncPromise from 'async-promises';
|
import asyncPromise from 'async-promises';
|
||||||
import { GuaribasInstance, GuaribasPackage } from '../models/GBModel.js';
|
import { GuaribasPackage } from '../models/GBModel.js';
|
||||||
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
import { GBAdminService } from './../../admin.gbapp/services/GBAdminService.js';
|
||||||
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
import { AzureDeployerService } from './../../azuredeployer.gbapp/services/AzureDeployerService.js';
|
||||||
import { KBService } from './../../kb.gbapp/services/KBService.js';
|
import { KBService } from './../../kb.gbapp/services/KBService.js';
|
||||||
|
@ -234,7 +234,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
const service = await AzureDeployerService.createInstance(this);
|
const service = await AzureDeployerService.createInstance(this);
|
||||||
const application = await service.createApplication(accessToken, botId);
|
const application = await service.createApplication(accessToken, botId);
|
||||||
|
|
||||||
// Fills new instance base information and get App secret.
|
// Fills new instance base information and get App secret.
|
||||||
|
|
||||||
instance.marketplaceId = (application as any).appId;
|
instance.marketplaceId = (application as any).appId;
|
||||||
|
@ -269,24 +269,11 @@ export class GBDeployer implements IGBDeployer {
|
||||||
* Verifies if bot exists on bot catalog.
|
* Verifies if bot exists on bot catalog.
|
||||||
*/
|
*/
|
||||||
public async botExists(botId: string): Promise<boolean> {
|
public async botExists(botId: string): Promise<boolean> {
|
||||||
|
const service = await AzureDeployerService.createInstance(this);
|
||||||
|
|
||||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
return await service.botExists(botId);
|
||||||
const where = { botId: botId };
|
|
||||||
|
|
||||||
return await GuaribasInstance.findOne({
|
|
||||||
where: where
|
|
||||||
}) !== null;
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
const service = await AzureDeployerService.createInstance(this);
|
|
||||||
|
|
||||||
return await service.botExists(botId);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs all tasks of deploying a new bot on the cloud.
|
* Performs all tasks of deploying a new bot on the cloud.
|
||||||
*/
|
*/
|
||||||
|
@ -482,13 +469,13 @@ export class GBDeployer implements IGBDeployer {
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
await asyncPromise.eachSeries(rows, async (line: any) => {
|
await asyncPromise.eachSeries(rows, async (line: any) => {
|
||||||
if (line && line.length > 0) {
|
if (line && line.length > 0) {
|
||||||
const key = line[1];
|
const key = line[1];
|
||||||
let value = line[2];
|
let value = line[2];
|
||||||
|
|
||||||
|
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
if (value.text) { value = value.text };
|
if (value.text) { value = value.text };
|
||||||
obj[key] = value;
|
obj[key] = value;
|
||||||
|
@ -503,7 +490,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async downloadFolder(
|
public async downloadFolder(
|
||||||
min: GBMinInstance,
|
min: GBMinInstance,
|
||||||
localPath: string,
|
localPath: string,
|
||||||
|
@ -512,7 +499,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
client = null
|
client = null
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const storageMode = process.env.GB_MODE;
|
const storageMode = process.env.GB_MODE;
|
||||||
|
|
||||||
if (storageMode === 'gbcluster') {
|
if (storageMode === 'gbcluster') {
|
||||||
const minioClient = new Client({
|
const minioClient = new Client({
|
||||||
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
endPoint: process.env.DRIVE_SERVER || 'localhost',
|
||||||
|
@ -521,31 +508,31 @@ export class GBDeployer implements IGBDeployer {
|
||||||
accessKey: process.env.DRIVE_ACCESSKEY,
|
accessKey: process.env.DRIVE_ACCESSKEY,
|
||||||
secretKey: process.env.DRIVE_SECRET,
|
secretKey: process.env.DRIVE_SECRET,
|
||||||
});
|
});
|
||||||
|
|
||||||
const bucketName = process.env.DRIVE_ORG_PREFIX + min.botId + '.gbai';
|
const bucketName = process.env.DRIVE_BUCKETPREFIX + min.botId + '.gbai';
|
||||||
|
|
||||||
if (!(await GBUtil.exists(localPath))) {
|
if (!(await GBUtil.exists(localPath))) {
|
||||||
await fs.mkdir(localPath, { recursive: true });
|
await fs.mkdir(localPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const objectsStream = minioClient.listObjects(bucketName, remotePath, true);
|
const objectsStream = minioClient.listObjects(bucketName, remotePath, true);
|
||||||
for await (const obj of objectsStream) {
|
for await (const obj of objectsStream) {
|
||||||
const itemPath = path.join(localPath, obj.name);
|
const itemPath = path.join(localPath, obj.name);
|
||||||
|
|
||||||
if (obj.name.endsWith('/')) {
|
if (obj.name.endsWith('/')) {
|
||||||
if (!(await GBUtil.exists(itemPath))) {
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
await fs.mkdir(itemPath, { recursive: true });
|
await fs.mkdir(itemPath, { recursive: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let download = true;
|
let download = true;
|
||||||
|
|
||||||
if (await GBUtil.exists(itemPath)) {
|
if (await GBUtil.exists(itemPath)) {
|
||||||
const stats = await fs.stat(itemPath);
|
const stats = await fs.stat(itemPath);
|
||||||
if (stats.mtime >= new Date(obj.lastModified)) {
|
if (stats.mtime >= new Date(obj.lastModified)) {
|
||||||
download = false;
|
download = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download) {
|
if (download) {
|
||||||
await minioClient.fGetObject(bucketName, obj.name, itemPath);
|
await minioClient.fGetObject(bucketName, obj.name, itemPath);
|
||||||
await fs.utimes(itemPath, new Date(), new Date(obj.lastModified));
|
await fs.utimes(itemPath, new Date(), new Date(obj.lastModified));
|
||||||
|
@ -555,42 +542,42 @@ export class GBDeployer implements IGBDeployer {
|
||||||
} else {
|
} else {
|
||||||
if (!baseUrl) {
|
if (!baseUrl) {
|
||||||
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
|
||||||
|
|
||||||
remotePath = remotePath.replace(/\\/gi, '/');
|
remotePath = remotePath.replace(/\\/gi, '/');
|
||||||
const parts = remotePath.split('/');
|
const parts = remotePath.split('/');
|
||||||
|
|
||||||
let pathBase = localPath;
|
let pathBase = localPath;
|
||||||
if (!(await GBUtil.exists(pathBase))) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
await fs.mkdir(pathBase, { recursive: true });
|
await fs.mkdir(pathBase, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(parts, async (item) => {
|
await CollectionUtil.asyncForEach(parts, async (item) => {
|
||||||
pathBase = path.join(pathBase, item);
|
pathBase = path.join(pathBase, item);
|
||||||
if (!(await GBUtil.exists(pathBase))) {
|
if (!(await GBUtil.exists(pathBase))) {
|
||||||
await fs.mkdir(pathBase, { recursive: true });
|
await fs.mkdir(pathBase, { recursive: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let packagePath = GBUtil.getGBAIPath(min.botId);
|
let packagePath = GBUtil.getGBAIPath(min.botId);
|
||||||
packagePath = urlJoin(packagePath, remotePath);
|
packagePath = urlJoin(packagePath, remotePath);
|
||||||
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
let url = `${baseUrl}/drive/root:/${packagePath}:/children`;
|
||||||
|
|
||||||
let documents;
|
let documents;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await client.api(url).get();
|
const res = await client.api(url).get();
|
||||||
documents = res.value;
|
documents = res.value;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
GBLogEx.info(min, `Error downloading: ${error.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (documents === undefined || documents.length === 0) {
|
if (documents === undefined || documents.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(documents, async (item) => {
|
await CollectionUtil.asyncForEach(documents, async (item) => {
|
||||||
const itemPath = path.join(localPath, remotePath, item.name);
|
const itemPath = path.join(localPath, remotePath, item.name);
|
||||||
|
|
||||||
if (item.folder) {
|
if (item.folder) {
|
||||||
if (!(await GBUtil.exists(itemPath))) {
|
if (!(await GBUtil.exists(itemPath))) {
|
||||||
await fs.mkdir(itemPath, { recursive: true });
|
await fs.mkdir(itemPath, { recursive: true });
|
||||||
|
@ -599,17 +586,17 @@ export class GBDeployer implements IGBDeployer {
|
||||||
await this.downloadFolder(min, localPath, nextFolder);
|
await this.downloadFolder(min, localPath, nextFolder);
|
||||||
} else {
|
} else {
|
||||||
let download = true;
|
let download = true;
|
||||||
|
|
||||||
if (await GBUtil.exists(itemPath)) {
|
if (await GBUtil.exists(itemPath)) {
|
||||||
const stats = await fs.stat(itemPath);
|
const stats = await fs.stat(itemPath);
|
||||||
if (new Date(stats.mtime) >= new Date(item.lastModifiedDateTime)) {
|
if (new Date(stats.mtime) >= new Date(item.lastModifiedDateTime)) {
|
||||||
download = false;
|
download = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download) {
|
if (download) {
|
||||||
const url = item['@microsoft.graph.downloadUrl'];
|
const url = item['@microsoft.graph.downloadUrl'];
|
||||||
|
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
await fs.writeFile(itemPath, new Uint8Array(await response.arrayBuffer()), { encoding: null });
|
await fs.writeFile(itemPath, new Uint8Array(await response.arrayBuffer()), { encoding: null });
|
||||||
await fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
await fs.utimes(itemPath, new Date(), new Date(item.lastModifiedDateTime));
|
||||||
|
@ -618,7 +605,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -670,7 +657,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
await this.cleanupPackage(min.instance, packageName);
|
await this.cleanupPackage(min.instance, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GBConfigService.get('GB_MODE') === 'local') {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
const filePath = path.join(GBConfigService.get('STORAGE_LIBRARY'), gbai, packageName);
|
||||||
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
await GBUtil.copyIfNewerRecursive(filePath, packageWorkFolder);
|
||||||
} else {
|
} else {
|
||||||
|
@ -727,7 +714,7 @@ export class GBDeployer implements IGBDeployer {
|
||||||
con['storageDriver'] = min.core.getParam<string>(min.instance, `${connectionName} Driver`, null);
|
con['storageDriver'] = min.core.getParam<string>(min.instance, `${connectionName} Driver`, null);
|
||||||
con['storageTables'] = min.core.getParam<string>(min.instance, `${connectionName} Tables`, null);
|
con['storageTables'] = min.core.getParam<string>(min.instance, `${connectionName} Tables`, null);
|
||||||
const storageName = min.core.getParam<string>(min.instance, `${connectionName} Name`, null);
|
const storageName = min.core.getParam<string>(min.instance, `${connectionName} Name`, null);
|
||||||
|
|
||||||
let file = min.core.getParam<string>(min.instance, `${connectionName} File`, null);
|
let file = min.core.getParam<string>(min.instance, `${connectionName} File`, null);
|
||||||
|
|
||||||
if (storageName) {
|
if (storageName) {
|
||||||
|
|
|
@ -1269,7 +1269,7 @@ export class GBMinService {
|
||||||
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
if (GBConfigService.get('GB_MODE') !== 'legacy') {
|
||||||
const context = adapter['createContext'](req);
|
const context = adapter['createContext'](req);
|
||||||
context['_activity'] = context.activity.body;
|
context['_activity'] = context.activity.body;
|
||||||
await adapter['processActivity'](req, res, handler);
|
await handler(context);
|
||||||
|
|
||||||
// Return status
|
// Return status
|
||||||
res.status(200);
|
res.status(200);
|
||||||
|
|
|
@ -35,7 +35,6 @@ import { Messages } from '../strings.js';
|
||||||
import { MainService } from '../service/MainService.js';
|
import { MainService } from '../service/MainService.js';
|
||||||
import { SaaSPackage } from '../index.js';
|
import { SaaSPackage } from '../index.js';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { GBOService } from '../service/GBOService.js';
|
|
||||||
|
|
||||||
export class NewUserDialog extends IGBDialog {
|
export class NewUserDialog extends IGBDialog {
|
||||||
static getBotNameDialog(min: GBMinInstance) {
|
static getBotNameDialog(min: GBMinInstance) {
|
||||||
|
@ -84,7 +83,7 @@ export class NewUserDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
const locale = 'en-US';
|
const locale = 'en-US';
|
||||||
await step.context.sendActivity('Aqui estão alguns modelos para você escolher:');
|
await step.context.sendActivity('Aqui estão alguns modelos para você escolher:');
|
||||||
let gboService = new GBOService();
|
let gboService = min.gbappServices['gboService'];
|
||||||
const list = await gboService.listTemplates(min);
|
const list = await gboService.listTemplates(min);
|
||||||
|
|
||||||
let templateMessage = undefined;
|
let templateMessage = undefined;
|
||||||
|
@ -102,9 +101,8 @@ export class NewUserDialog extends IGBDialog {
|
||||||
async step => {
|
async step => {
|
||||||
const list = step.activeDialog.state.options.templateList;
|
const list = step.activeDialog.state.options.templateList;
|
||||||
let template = null;
|
let template = null;
|
||||||
let gboService = new GBOService();
|
|
||||||
await CollectionUtil.asyncForEach(list, async item => {
|
await CollectionUtil.asyncForEach(list, async item => {
|
||||||
|
let gboService = min.gbappServices['gboService'];
|
||||||
if (gboService.kmpSearch(step.context.activity.originalText, item.name) != -1) {
|
if (gboService.kmpSearch(step.context.activity.originalText, item.name) != -1) {
|
||||||
template = item.name;
|
template = item.name;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +114,7 @@ export class NewUserDialog extends IGBDialog {
|
||||||
return await step.replaceDialog('/welcome_saas_bottemplate', step.activeDialog.state.options);
|
return await step.replaceDialog('/welcome_saas_bottemplate', step.activeDialog.state.options);
|
||||||
} else {
|
} else {
|
||||||
step.activeDialog.state.options.templateName = template;
|
step.activeDialog.state.options.templateName = template;
|
||||||
|
debugger;
|
||||||
await NewUserDialog.createBot(step, min, true);
|
await NewUserDialog.createBot(step, min, true);
|
||||||
|
|
||||||
return await step.replaceDialog('/ask', { isReturning: true });
|
return await step.replaceDialog('/ask', { isReturning: true });
|
||||||
|
@ -252,7 +250,7 @@ export class NewUserDialog extends IGBDialog {
|
||||||
'12',
|
'12',
|
||||||
'99',
|
'99',
|
||||||
'1234',
|
'1234',
|
||||||
'ai-search.gbai',
|
'crawlergbot.gbai',
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ import { GBOnlineSubscription } from './model/MainModel.js'
|
||||||
import { MSSubscriptionService } from './service/MSSubscription.js'
|
import { MSSubscriptionService } from './service/MSSubscription.js'
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import { NewUserDialog } from './dialog/NewUserDialog.js'
|
import { NewUserDialog } from './dialog/NewUserDialog.js'
|
||||||
import { GBOService } from './service/GBOService.js'
|
|
||||||
|
|
||||||
export class SaaSPackage implements IGBPackage {
|
export class SaaSPackage implements IGBPackage {
|
||||||
sysPackages: IGBPackage[]
|
sysPackages: IGBPackage[]
|
||||||
|
@ -110,7 +109,7 @@ export class SaaSPackage implements IGBPackage {
|
||||||
|
|
||||||
async loadBot(min: GBMinInstance): Promise<void> {
|
async loadBot(min: GBMinInstance): Promise<void> {
|
||||||
|
|
||||||
let gboService = new GBOService();
|
let gboService = min.gbappServices['gboService'];
|
||||||
|
|
||||||
// Gets the sendToDevice method of whatsapp.gblib and setups scheduler.
|
// Gets the sendToDevice method of whatsapp.gblib and setups scheduler.
|
||||||
|
|
||||||
|
|
|
@ -32,27 +32,26 @@
|
||||||
|
|
||||||
import { GBMinInstance, GBLog } from "botlib";
|
import { GBMinInstance, GBLog } from "botlib";
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import MicrosoftGraph from "@microsoft/microsoft-graph-client";
|
const MicrosoftGraph = require("@microsoft/microsoft-graph-client");
|
||||||
|
const Juno = require('juno-payment-node');
|
||||||
import sgMail from '@sendgrid/mail';
|
const sgMail = require('@sendgrid/mail');
|
||||||
import { default as PasswordGenerator } from 'strict-password-generator';
|
const PasswordGenerator = require('strict-password-generator').default;
|
||||||
import { promises as fs } from 'fs';
|
|
||||||
import { existsSync } from 'fs';
|
|
||||||
|
|
||||||
import { GBConfigService } from "../../core.gbapp/services/GBConfigService.js";
|
|
||||||
import path from "path";
|
|
||||||
import { Client } from "minio";
|
|
||||||
|
|
||||||
|
|
||||||
export class GBOService {
|
export class GBOService {
|
||||||
|
|
||||||
public isValidCardNumber(ccNumber) {
|
public isValidCardNumber(ccNumber) {
|
||||||
|
let card = new Juno.Card();
|
||||||
|
return card.validateNumber(ccNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isValidSecurityCode(ccNumber, cvcNumber) {
|
public isValidSecurityCode(ccNumber, cvcNumber) {
|
||||||
|
let card = new Juno.Card();
|
||||||
|
return card.validateCvc(ccNumber, cvcNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isValidExpireDate(month, year) {
|
public isValidExpireDate(month, year) {
|
||||||
|
let card = new Juno.Card();
|
||||||
|
return card.validateExpireDate(month, year);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendEmail(token: string, to: string, from: string,
|
public async sendEmail(token: string, to: string, from: string,
|
||||||
|
@ -78,147 +77,137 @@ export class GBOService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createSubFolderAtRoot(token: string, name: string,
|
||||||
public async listTemplates(min: GBMinInstance) {
|
siteId: string, libraryId: string) {
|
||||||
if (GBConfigService.get('GB_MODE') === 'legacy') {
|
return new Promise<any>((resolve, reject) => {
|
||||||
let templateLibraryId = process.env.SAAS_TEMPLATE_LIBRARY;
|
|
||||||
let siteId = process.env.STORAGE_SITE_ID;
|
|
||||||
|
|
||||||
let token =
|
|
||||||
await (min.adminService as any).acquireElevatedToken(min.instance.instanceId, true);
|
|
||||||
|
|
||||||
let client = MicrosoftGraph.Client.init({
|
let client = MicrosoftGraph.Client.init({
|
||||||
authProvider: done => {
|
authProvider: done => {
|
||||||
done(null, token);
|
done(null, token);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const packagePath = `/`;
|
const body = {
|
||||||
let res = await client.api(
|
"name": name,
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/root/children`)
|
"folder": {},
|
||||||
|
"@microsoft.graph.conflictBehavior": "rename"
|
||||||
|
}
|
||||||
|
client.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root/children`)
|
||||||
|
.post(body, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public async createSubFolderAt(token: string, parentPath: string, name: string,
|
||||||
|
siteId: string, libraryId: string) {
|
||||||
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
let client = MicrosoftGraph.Client.init({
|
||||||
|
authProvider: done => {
|
||||||
|
done(null, token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const body = {
|
||||||
|
"name": name,
|
||||||
|
"folder": {},
|
||||||
|
"@microsoft.graph.conflictBehavior": "rename"
|
||||||
|
}
|
||||||
|
client.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${parentPath}:/children`)
|
||||||
|
.post(body, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listTemplates(min: GBMinInstance) {
|
||||||
|
|
||||||
|
let templateLibraryId = process.env.SAAS_TEMPLATE_LIBRARY;
|
||||||
|
let siteId = process.env.STORAGE_SITE_ID;
|
||||||
|
|
||||||
|
let token =
|
||||||
|
await (min.adminService as any).acquireElevatedToken(min.instance.instanceId, true);
|
||||||
|
|
||||||
|
let client = MicrosoftGraph.Client.init({
|
||||||
|
authProvider: done => {
|
||||||
|
done(null, token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const packagePath = `/`;
|
||||||
|
let res = await client.api(
|
||||||
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/root/children`)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
return res.value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async copyTemplates(min: GBMinInstance, gbaiDest, templateName: string, kind: string, botName: string) {
|
||||||
|
|
||||||
|
let token =
|
||||||
|
await (min.adminService as any).acquireElevatedToken(min.instance.instanceId, true);
|
||||||
|
|
||||||
|
let siteId = process.env.STORAGE_SITE_ID;
|
||||||
|
let templateLibraryId = process.env.SAAS_TEMPLATE_LIBRARY;
|
||||||
|
let libraryId = process.env.STORAGE_LIBRARY;
|
||||||
|
|
||||||
|
let client = MicrosoftGraph.Client.init({
|
||||||
|
authProvider: done => {
|
||||||
|
done(null, token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const body =
|
||||||
|
{
|
||||||
|
"parentReference": { driveId: gbaiDest.parentReference.driveId, id: gbaiDest.id },
|
||||||
|
"name": `${botName}.${kind}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const packageName = `${templateName.split('.')[0]}.${kind}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const src = await client.api(
|
||||||
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/root:/${templateName}/${packageName}`)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
return res.value;
|
return await client.api(
|
||||||
}
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/items/${src.id}/copy`)
|
||||||
else {
|
.post(body);
|
||||||
|
|
||||||
const templatesDir = path.join(process.env.PWD, 'templates');
|
} catch (error) {
|
||||||
const gbaiDirectories = [];
|
|
||||||
|
|
||||||
// Read all entries in the templates directory
|
if (error.code === "itemNotFound") {
|
||||||
const entries = await fs.readdir(templatesDir, { withFileTypes: true });
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
} else if (error.code === "nameAlreadyExists") {
|
||||||
// Check if it's a directory and ends with .gbai
|
|
||||||
if (entry.isDirectory() && entry.name.endsWith('.gbai')) {
|
|
||||||
gbaiDirectories.push({ name: entry.name });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gbaiDirectories;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async copyTemplates(min: GBMinInstance, gbaiDest: any, templateName: string, kind: string, botName: string): Promise<void> {
|
|
||||||
const storageMode = process.env.GB_MODE;
|
|
||||||
|
|
||||||
if (storageMode === 'legacy') {
|
let src = await client.api(
|
||||||
// Microsoft Graph (SharePoint) Implementation
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/root:/${templateName}/${packageName}:/children`)
|
||||||
const token = await (min.adminService as any).acquireElevatedToken(min.instance.instanceId, true);
|
.get();
|
||||||
const siteId = process.env.STORAGE_SITE_ID;
|
const dstName = `${botName}.gbai/${botName}.${kind}`;
|
||||||
const templateLibraryId = process.env.SAAS_TEMPLATE_LIBRARY;
|
let dst = await client.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${dstName}`)
|
||||||
const libraryId = process.env.STORAGE_LIBRARY;
|
.get();
|
||||||
|
|
||||||
const client = MicrosoftGraph.Client.init({
|
await CollectionUtil.asyncForEach(src.value, async item => {
|
||||||
authProvider: (done) => done(null, token)
|
|
||||||
});
|
|
||||||
|
|
||||||
const packageName = `${templateName.split('.')[0]}.${kind}`;
|
const body =
|
||||||
const destinationName = `${botName}.${kind}`;
|
{
|
||||||
|
"parentReference": { driveId: dst.parentReference.driveId, id: dst.id }
|
||||||
try {
|
|
||||||
// Try direct copy first
|
|
||||||
const src = await client.api(
|
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/root:/${templateName}/${packageName}`
|
|
||||||
).get();
|
|
||||||
|
|
||||||
await client.api(
|
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/items/${src.id}/copy`
|
|
||||||
).post({
|
|
||||||
parentReference: {
|
|
||||||
driveId: gbaiDest.parentReference.driveId,
|
|
||||||
id: gbaiDest.id
|
|
||||||
},
|
|
||||||
name: destinationName
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code === "nameAlreadyExists") {
|
|
||||||
// Handle existing destination by copying contents individually
|
|
||||||
const srcItems = await client.api(
|
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/root:/${templateName}/${packageName}:/children`
|
|
||||||
).get();
|
|
||||||
|
|
||||||
const dstPath = `${botName}.gbai/${destinationName}`;
|
|
||||||
const dst = await client.api(
|
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:/${dstPath}`
|
|
||||||
).get();
|
|
||||||
|
|
||||||
await CollectionUtil.asyncForEach(srcItems.value, async (item) => {
|
|
||||||
await client.api(
|
|
||||||
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/items/${item.id}/copy`
|
|
||||||
).post({
|
|
||||||
parentReference: {
|
|
||||||
driveId: dst.parentReference.driveId,
|
|
||||||
id: dst.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
GBLog.error(`Failed to copy templates: ${error.message}`);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (storageMode === 'gbcluster') {
|
|
||||||
|
|
||||||
// MinIO Implementation
|
|
||||||
const minioClient = new Client({
|
|
||||||
endPoint: process.env.DRIVE_SERVER,
|
|
||||||
port: parseInt(process.env.DRIVE_PORT),
|
|
||||||
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
|
||||||
accessKey: process.env.DRIVE_ACCESSKEY,
|
|
||||||
secretKey: process.env.DRIVE_SECRET,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const bucketName = `${process.env.DRIVE_ORG_PREFIX}${botName}.gbai`;
|
|
||||||
const packageName = `${templateName.split('.')[0]}.${kind}`;
|
|
||||||
const localTemplatePath = path.join(process.env.PWD, 'templates', templateName, packageName);
|
|
||||||
const minioDestinationPath = `${botName}.${kind}`;
|
|
||||||
|
|
||||||
const uploadDirectory = async (localPath: string, minioPath: string = '') => {
|
|
||||||
|
|
||||||
// Ensure the bucket exists in local file system
|
|
||||||
if (existsSync(localPath)) {
|
|
||||||
|
|
||||||
const entries = await fs.readdir(localPath, { withFileTypes: true });
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
|
||||||
const fullLocalPath = path.join(localPath, entry.name);
|
|
||||||
const objectName = path.posix.join(minioPath, entry.name);
|
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
await uploadDirectory(fullLocalPath, objectName);
|
|
||||||
} else {
|
|
||||||
const fileContent = await fs.readFile(fullLocalPath);
|
|
||||||
await minioClient.putObject(bucketName, objectName, fileContent);
|
|
||||||
GBLog.info(`Uploaded ${objectName} to MinIO bucket ${bucketName}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
await client.api(
|
||||||
else {
|
`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${templateLibraryId}/drive/items/${item.id}/copy`)
|
||||||
GBLog.verbose(`Package ${localPath} does not exist on templates.`);
|
.post(body);
|
||||||
}
|
});
|
||||||
};
|
}
|
||||||
|
else {
|
||||||
await uploadDirectory(localTemplatePath, minioDestinationPath);
|
GBLog.error(error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,56 +351,4 @@ export class GBOService {
|
||||||
|
|
||||||
return documents[0];
|
return documents[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createRootFolder(token: string, name: string,
|
|
||||||
siteId: string, libraryId: string) {
|
|
||||||
const storageMode = process.env.GB_MODE;
|
|
||||||
|
|
||||||
if (storageMode === 'gbcluster') {
|
|
||||||
// Minio implementation
|
|
||||||
const minioClient = new Client({
|
|
||||||
endPoint: process.env.DRIVE_SERVER,
|
|
||||||
port: parseInt(process.env.DRIVE_PORT),
|
|
||||||
useSSL: process.env.DRIVE_USE_SSL === 'true',
|
|
||||||
accessKey: process.env.DRIVE_ACCESSKEY,
|
|
||||||
secretKey: process.env.DRIVE_SECRET,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Ensure bucket exists
|
|
||||||
|
|
||||||
name = `${process.env.DRIVE_ORG_PREFIX}${name}`;
|
|
||||||
const bucketExists = await minioClient.bucketExists(name);
|
|
||||||
if (!bucketExists) {
|
|
||||||
await minioClient.makeBucket(name);
|
|
||||||
}
|
|
||||||
return { name: name, folder: {} }; // Return similar structure to MS Graph
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Original MS Graph implementation
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
let client = MicrosoftGraph.Client.init({
|
|
||||||
authProvider: done => {
|
|
||||||
done(null, token);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const body = {
|
|
||||||
"name": name,
|
|
||||||
"folder": {},
|
|
||||||
"@microsoft.graph.conflictBehavior": "rename"
|
|
||||||
}
|
|
||||||
client.api(`https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root/children`)
|
|
||||||
.post(body, (err, res) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resolve(res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,6 @@ import { GBOnlineSubscription } from '../model/MainModel.js';
|
||||||
import { GBMinInstance, GBLog } from 'botlib';
|
import { GBMinInstance, GBLog } from 'botlib';
|
||||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
import { GBOService } from './GBOService.js';
|
|
||||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
|
||||||
|
|
||||||
export class MainService {
|
export class MainService {
|
||||||
async createSubscriptionMSFT(email: string, plan: string, offer: string, quantity: number, additionalData: any) { }
|
async createSubscriptionMSFT(email: string, plan: string, offer: string, quantity: number, additionalData: any) { }
|
||||||
|
@ -106,15 +104,12 @@ export class MainService {
|
||||||
subscription.externalSubscriptionId = externalSubscriptionId;
|
subscription.externalSubscriptionId = externalSubscriptionId;
|
||||||
await subscription.save();
|
await subscription.save();
|
||||||
|
|
||||||
let token =
|
let token = await (min.adminService.acquireElevatedToken as any)(min.instance.instanceId, true);
|
||||||
GBConfigService.get('GB_MODE') === 'legacy'?
|
|
||||||
await (min.adminService.acquireElevatedToken as any)(min.instance.instanceId, true) :
|
|
||||||
null;
|
|
||||||
|
|
||||||
let siteId = process.env.STORAGE_SITE_ID;
|
let siteId = process.env.STORAGE_SITE_ID;
|
||||||
let libraryId = process.env.STORAGE_LIBRARY;
|
let libraryId = process.env.STORAGE_LIBRARY;
|
||||||
let gboService = new GBOService();
|
let gboService = min.gbappServices['gboService'];
|
||||||
|
|
||||||
let sleep = ms => {
|
let sleep = ms => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
|
@ -123,15 +118,15 @@ export class MainService {
|
||||||
|
|
||||||
|
|
||||||
GBLog.info( 'Creating .gbai folder ...');
|
GBLog.info( 'Creating .gbai folder ...');
|
||||||
let item = await gboService.createRootFolder(token, `${botName}.gbai`, siteId, libraryId);
|
let item = await gboService.createSubFolderAtRoot(token, `${botName}.gbai`, siteId, libraryId);
|
||||||
|
await sleep(1000);
|
||||||
|
|
||||||
GBLog.info( 'Copying Templates...');
|
GBLog.info( 'Copying Templates...');
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbkb', botName);
|
await gboService.copyTemplates(min, item, 'Shared.gbai', 'gbkb', botName);
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbot', botName);
|
await gboService.copyTemplates(min, item, 'Shared.gbai', 'gbot', botName);
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbtheme', botName);
|
await gboService.copyTemplates(min, item, 'Shared.gbai', 'gbtheme', botName);
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbdialog', botName);
|
await gboService.copyTemplates(min, item, 'Shared.gbai', 'gbdialog', botName);
|
||||||
// await gboService.copyTemplates(min, item, 'shared.gbai', 'gbdata', botName);
|
await gboService.copyTemplates(min, item, 'Shared.gbai', 'gbdata', botName);
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbkb', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbkb', botName);
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbot', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbot', botName);
|
||||||
await gboService.copyTemplates(min, item, templateName, 'gbtheme', botName);
|
await gboService.copyTemplates(min, item, templateName, 'gbtheme', botName);
|
||||||
|
|
Loading…
Add table
Reference in a new issue