diff --git a/package-lock.json b/package-lock.json index be868e97..a9ded449 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "async-promises": "0.2.3", "async-retry": "1.3.3", "basic-auth": "2.0.1", + "bcrypt": "^5.1.1", "billboard.js": "3.13.0", "bluebird": "3.7.2", "body-parser": "1.20.2", @@ -12921,6 +12922,20 @@ "node": ">=10.0.0" } }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -12930,6 +12945,12 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/bcrypt/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", diff --git a/package.json b/package.json index 1d336460..434aefc4 100644 --- a/package.json +++ b/package.json @@ -114,6 +114,7 @@ "async-promises": "0.2.3", "async-retry": "1.3.3", "basic-auth": "2.0.1", + "bcrypt": "^5.1.1", "billboard.js": "3.13.0", "bluebird": "3.7.2", "body-parser": "1.20.2", diff --git a/packages/admin.gbapp/dialogs/AdminDialog.ts b/packages/admin.gbapp/dialogs/AdminDialog.ts index d9eec786..7a9a536e 100644 --- a/packages/admin.gbapp/dialogs/AdminDialog.ts +++ b/packages/admin.gbapp/dialogs/AdminDialog.ts @@ -47,6 +47,7 @@ import { SecService } from '../../security.gbapp/services/SecService.js'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js'; import { GBServer } from '../../../src/app.js'; import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js'; +import { GBUtil } from 'src/util.js'; class AdminDialog extends IGBDialog { @@ -86,7 +87,7 @@ class AdminDialog extends IGBDialog { const locale = step.context.activity.locale; const sensitive = step.context.activity['originalText']; - if (sensitive === min.instance.adminPass) { + if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) { await min.conversationalService.sendText(min, step, Messages[locale].welcome); return await step.endDialog(true); @@ -120,7 +121,7 @@ class AdminDialog extends IGBDialog { const locale = step.context.activity.locale; const sensitive = step.context.activity['originalText']; - if (sensitive === min.instance.adminPass) { + if (await GBUtil.comparePassword( sensitive, min.instance.adminPass)) { await min.conversationalService.sendText(min, step, Messages[locale].welcome); return await min.conversationalService.prompt(min, step, Messages[locale].which_task); diff --git a/packages/azuredeployer.gbapp/dialogs/StartDialog.ts b/packages/azuredeployer.gbapp/dialogs/StartDialog.ts index 999d2fc6..c8f919f4 100644 --- a/packages/azuredeployer.gbapp/dialogs/StartDialog.ts +++ b/packages/azuredeployer.gbapp/dialogs/StartDialog.ts @@ -111,7 +111,7 @@ export class StartDialog { instance.cloudLocation = location; instance.marketplaceId = appId; instance.marketplacePassword = appPassword; - instance.adminPass = GBAdminService.getRndPassword(); + instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword()); return { instance, credentials, subscriptionId , installationDeployer}; } diff --git a/packages/azuredeployer.gbapp/services/AzureDeployerService.ts b/packages/azuredeployer.gbapp/services/AzureDeployerService.ts index 1d590c48..6d15180e 100644 --- a/packages/azuredeployer.gbapp/services/AzureDeployerService.ts +++ b/packages/azuredeployer.gbapp/services/AzureDeployerService.ts @@ -518,7 +518,7 @@ export class AzureDeployerService implements IGBInstallationDeployer { instance.nlpAuthoringKey = authoringKey; instance.marketplaceId = appId; instance.marketplacePassword = appPassword; - instance.adminPass = GBAdminService.getRndPassword(); + instance.adminPass = await GBUtil.hashPassword(GBAdminService.getRndPassword()); const credentials = await GBAdminService.getADALCredentialsFromUsername(username, password); // tslint:disable-next-line:no-http-string @@ -986,7 +986,6 @@ export class AzureDeployerService implements IGBInstallationDeployer { appSettings: [ { name: 'WEBSITES_CONTAINER_START_TIME_LIMIT', value: `${WebSiteResponseTimeout}` }, { name: 'WEBSITE_NODE_DEFAULT_VERSION', value: await GBAdminService.getNodeVersion() }, - { name: 'ADMIN_PASS', value: `${instance.adminPass}` }, { name: 'BOT_ID', value: `${instance.botId}` }, { name: 'CLOUD_SUBSCRIPTIONID', value: `${instance.cloudSubscriptionId}` }, { name: 'CLOUD_LOCATION', value: `${instance.cloudLocation}` }, diff --git a/packages/core.gbapp/services/GBCoreService.ts b/packages/core.gbapp/services/GBCoreService.ts index 1a4339a2..b8273850 100644 --- a/packages/core.gbapp/services/GBCoreService.ts +++ b/packages/core.gbapp/services/GBCoreService.ts @@ -323,7 +323,6 @@ export class GBCoreService implements IGBCoreService { public async writeEnv(instance: IGBInstance) { const env = ` ADDITIONAL_DEPLOY_PATH= -ADMIN_PASS=${instance.adminPass} BOT_ID=${instance.botId} CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId} CLOUD_LOCATION=${instance.cloudLocation} diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index db05dd96..03256936 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -241,7 +241,7 @@ export class GBDeployer implements IGBDeployer { instance.marketplacePassword = await service.createApplicationSecret(accessToken, (application as any).id); } - instance.adminPass = GBAdminService.getRndPassword(); + instance.adminPass =await GBUtil.hashPassword( GBAdminService.getRndPassword()); instance.title = botId; instance.activationCode = instance.botId.substring(0, 15); instance.state = 'active'; diff --git a/packages/core.gbapp/services/GBImporterService.ts b/packages/core.gbapp/services/GBImporterService.ts index d6036033..3edcc6bf 100644 --- a/packages/core.gbapp/services/GBImporterService.ts +++ b/packages/core.gbapp/services/GBImporterService.ts @@ -78,7 +78,7 @@ export class GBImporter { if (!instance) { instance = {}; instance.state = 'active'; - instance.adminPass = GBConfigService.get('ADMIN_PASS'); + instance.adminPass = await GBUtil.hashPassword( GBConfigService.get('ADMIN_PASS')); instance.botId = GBConfigService.get('BOT_ID'); instance.cloudSubscriptionId = GBConfigService.get('CLOUD_SUBSCRIPTIONID'); instance.cloudLocation = GBConfigService.get('CLOUD_LOCATION'); diff --git a/packages/saas.gbapp/service/MainService.ts b/packages/saas.gbapp/service/MainService.ts index 04b9b98d..f37b6080 100755 --- a/packages/saas.gbapp/service/MainService.ts +++ b/packages/saas.gbapp/service/MainService.ts @@ -159,7 +159,6 @@ export class MainService {

Digite /publish do seu WhatsApp para publicar os pacotes. Seu número está autorizado na pasta ${botName}.gbot/Config.xlsx
-
Guarde a senha raiz: ${instance.adminPass} em um local seguro, use-a para realizar o /publish via Web (WhatsApp dispensa senha).

O arquivo .zip em anexo pode ser importado no Teams conforme instruções em:
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload. diff --git a/src/util.ts b/src/util.ts index 32dea274..5e510daf 100644 --- a/src/util.ts +++ b/src/util.ts @@ -12,6 +12,8 @@ import SwaggerClient from 'swagger-client'; import fs from 'fs/promises'; import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService.js'; import path from 'path'; +import bcrypt from 'bcrypt'; +const saltRounds = 10; // The higher the number, the more secure but slower import { VerbosityLevel, getDocument } from 'pdfjs-dist/legacy/build/pdf.mjs'; import urljoin from 'url-join'; import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService.js'; @@ -27,6 +29,29 @@ import { QueryTypes } from '@sequelize/core'; * Utility class containing various helper functions for the General Bots project. */ export class GBUtil { + + + // When creating/updating a user (hashing before saving to DB) + public async static hashPassword(password) { + try { + const hash = await bcrypt.hash(password, saltRounds); + return hash; + } catch (err) { + console.error('Error hashing password:', err); + throw err; + } + } + + // When comparing passwords (like during login) + public async static comparePassword(inputPassword, hashedPassword) { + try { + return await bcrypt.compare(inputPassword, hashedPassword); + } catch (err) { + console.error('Error comparing passwords:', err); + throw err; + } + } + /** * Repeats a character a specified number of times. * @param {string} chr - The character to repeat.