diff --git a/src/apps/app_sdk/auth.ts b/src/apps/app_sdk/auth.ts index 4ffcd1b7..a3b91054 100644 --- a/src/apps/app_sdk/auth.ts +++ b/src/apps/app_sdk/auth.ts @@ -2,10 +2,11 @@ import * as process from 'node:process'; import { parseBool } from '@waha/helpers'; import * as basicAuth from 'express-basic-auth'; +import { Auth } from '@waha/core/auth/config'; export function BullAuthMiddleware() { - let username = process.env.WAHA_DASHBOARD_USERNAME || ''; - let password = process.env.WAHA_DASHBOARD_PASSWORD || ''; + let username = Auth.dashboard.username.value || ''; + let password = Auth.dashboard.password.value || ''; if (process.env.WAHA_DASHBOARD_ENABLED) { const enabled = parseBool(process.env.WAHA_DASHBOARD_ENABLED); if (!enabled) { diff --git a/src/apps/apps.module.ts b/src/apps/apps.module.ts index 157b9e06..17a91a9f 100644 --- a/src/apps/apps.module.ts +++ b/src/apps/apps.module.ts @@ -13,6 +13,7 @@ import { ChatwootLocalesController } from '@waha/apps/chatwoot/api/chatwoot.loca import { ChatWootExports } from '@waha/apps/chatwoot/chatwoot.module'; import { parseBool } from '@waha/helpers'; import { RMutexModule } from '@waha/modules/rmutex'; +import { Auth } from '@waha/core/auth/config'; const IMPORTS = [ BullModule.forRoot({ @@ -93,11 +94,11 @@ const AppsDisabled = { }; function checkApiKey() { - const key = process.env.WHATSAPP_API_KEY || process.env.WAHA_API_KEY; + const key = Auth.key.value; if (!key) { return; } - const plain = process.env.WAHA_API_KEY_PLAIN; + const plain = Auth.keyplain.value; if (!plain) { throw Error( 'WAHA_API_KEY set, please provide WAHA_API_KEY_PLAIN when WAHA_APPS_ENABLED', diff --git a/src/apps/chatwoot/session/WAHASelf.ts b/src/apps/chatwoot/session/WAHASelf.ts index a4943da4..5233d810 100644 --- a/src/apps/chatwoot/session/WAHASelf.ts +++ b/src/apps/chatwoot/session/WAHASelf.ts @@ -11,13 +11,14 @@ import { } from '@waha/structures/chatting.dto'; import { SessionInfo } from '@waha/structures/sessions.dto'; import axios, { AxiosInstance } from 'axios'; +import { Auth } from '@waha/core/auth/config'; export class WAHASelf { public client: AxiosInstance; constructor() { // Set 'X-Api-Key' - const key = process.env.WAHA_API_KEY_PLAIN; + const key = Auth.keyplain.value; const port = parseInt(process.env.PORT) || parseInt(process.env.WHATSAPP_API_PORT) || diff --git a/src/config.service.ts b/src/config.service.ts index 61183b3b..6d57a3c0 100644 --- a/src/config.service.ts +++ b/src/config.service.ts @@ -5,6 +5,7 @@ import { IgnoreJidConfig } from '@waha/core/utils/jids'; import { parseBool } from './helpers'; import { WebhookConfig } from './structures/webhooks.config.dto'; +import { Auth } from '@waha/core/auth/config'; @Injectable() export class WhatsappConfigService implements OnApplicationBootstrap { @@ -139,10 +140,7 @@ export class WhatsappConfigService implements OnApplicationBootstrap { } getApiKey(): string | undefined { - return ( - this.configService.get('WHATSAPP_API_KEY', '') || - this.configService.get('WAHA_API_KEY', '') - ); + return Auth.key.value; } getExcludedPaths(): string[] { diff --git a/src/core/auth/ApiKeyAuthFactory.ts b/src/core/auth/ApiKeyAuthFactory.ts index fea0ee43..d5d0d640 100644 --- a/src/core/auth/ApiKeyAuthFactory.ts +++ b/src/core/auth/ApiKeyAuthFactory.ts @@ -6,11 +6,15 @@ import { NoAuth, PlainApiKeyAuth, } from '@waha/core/auth/auth'; +import { ReportGeneratedValue } from '@waha/core/auth/config'; export function ApiKeyAuthFactory( config: WhatsappConfigService, logger: LoggerService, ): IApiKeyAuth { + setTimeout(() => { + ReportGeneratedValue(); + }, 4000); const apiKey = config.getApiKey(); if (!apiKey) { setTimeout(() => { diff --git a/src/core/auth/config.ts b/src/core/auth/config.ts new file mode 100644 index 00000000..511b4c83 --- /dev/null +++ b/src/core/auth/config.ts @@ -0,0 +1,151 @@ +import { parseBool } from '@waha/helpers'; +import { CacheSync } from '@waha/utils/Cache'; +import { LoggerService } from '@nestjs/common'; + +export interface SValue { + param: string; + value: string | null; + generated: boolean; +} + +function rand() { + return crypto.randomUUID().toString().replace(/-/g, ''); +} + +function FromEnv( + param: string, + skip: boolean, + adefault: string, + search: any[], +): SValue { + let value = process.env[param]; + const common = search.includes(value); + if (common && !skip) { + // Use generated value for the setting + return { + param: param, + value: adefault, + generated: true, + }; + } + + return { + param: param, + value: value, + generated: false, + }; +} + +const keys = [ + '', + null, + undefined, + '123', + '321', + 'waha', + 'admin', + '00000000000000000000000000000000', + 'sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648', +]; + +const nulls = ['', null, undefined]; + +interface UserPassword { + username: SValue; + password: SValue; +} + +export class AuthConfig { + public key: SValue; + public keyplain: SValue; + public dashboard: UserPassword; + public swagger: UserPassword; + + constructor() { + if (process.env.WHATSAPP_API_KEY) { + process.env.WAHA_API_KEY = process.env.WHATSAPP_API_KEY; + } + this.key = FromEnv( + 'WAHA_API_KEY', + parseBool(process.env.WAHA_NO_API_KEY), + rand(), + keys, + ); + + this.keyplain = FromEnv( + 'WAHA_API_KEY_PLAIN', + false, + this.key.value?.startsWith('sha512:') ? null : this.key.value, + [], + ); + + this.dashboard = this.getDashboard(); + this.swagger = this.getSwagger(); + } + + private getDashboard(): UserPassword { + const password = FromEnv( + 'WAHA_DASHBOARD_PASSWORD', + parseBool(process.env.WAHA_DASHBOARD_NO_PASSWORD), + rand(), + keys, + ); + const username = FromEnv( + 'WAHA_DASHBOARD_USERNAME', + false, + 'admin', + password.value ? nulls : [], + ); + return { + username: username, + password: password, + }; + } + + private getSwagger(): UserPassword { + const password = FromEnv( + 'WHATSAPP_SWAGGER_PASSWORD', + parseBool(process.env.WHATSAPP_SWAGGER_NO_PASSWORD), + this.dashboard.password.value, + keys, + ); + const username = FromEnv( + 'WHATSAPP_SWAGGER_USERNAME', + false, + 'admin', + password.value ? nulls : [], + ); + return { + username: username, + password: password, + }; + } +} + +export const Auth = new AuthConfig(); + +export function ReportGeneratedValue() { + let values = [ + Auth.key, + Auth.dashboard.username, + Auth.dashboard.password, + Auth.swagger.username, + Auth.swagger.password, + ]; + values = values.filter((key) => key.generated); + if (values.length === 0) { + return; + } + console.warn('👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇'); + console.warn('====== YOUR GENERATED CREDENTIALS ======'); + console.warn( + 'Save those variable into .env file or set environment variables to use it the next time, otherwise it is random values on each start', + ); + console.warn(''); + for (const key of values) { + console.warn(`${key.param}=${key.value}`); + } + console.warn(''); + console.warn('====== YOUR GENERATED CREDENTIALS ======'); + console.warn('☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️☝️ '); +} diff --git a/src/core/config/DashboardConfigServiceCore.ts b/src/core/config/DashboardConfigServiceCore.ts index bf15c7d3..8101f99b 100644 --- a/src/core/config/DashboardConfigServiceCore.ts +++ b/src/core/config/DashboardConfigServiceCore.ts @@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { InjectPinoLogger, PinoLogger } from 'nestjs-pino'; import { parseBool } from '../../helpers'; +import { Auth } from '@waha/core/auth/config'; @Injectable() export class DashboardConfigServiceCore { @@ -20,8 +21,8 @@ export class DashboardConfigServiceCore { } get credentials(): [string, string] | null { - const user = this.configService.get('WAHA_DASHBOARD_USERNAME', ''); - const password = this.configService.get('WAHA_DASHBOARD_PASSWORD', ''); + const user = Auth.dashboard.username.value || ''; + const password = Auth.dashboard.password.value || ''; if (!user && !password) { return null; } diff --git a/src/core/config/SwaggerConfigServiceCore.ts b/src/core/config/SwaggerConfigServiceCore.ts index 7bb224f4..2682f815 100644 --- a/src/core/config/SwaggerConfigServiceCore.ts +++ b/src/core/config/SwaggerConfigServiceCore.ts @@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { InjectPinoLogger, PinoLogger } from 'nestjs-pino'; import { parseBool } from '../../helpers'; +import { Auth } from '@waha/core/auth/config'; @Injectable() export class SwaggerConfigServiceCore { @@ -26,14 +27,8 @@ export class SwaggerConfigServiceCore { } get credentials(): [string, string] | undefined { - const user = this.configService.get( - 'WHATSAPP_SWAGGER_USERNAME', - undefined, - ); - const password = this.configService.get( - 'WHATSAPP_SWAGGER_PASSWORD', - undefined, - ); + const user = Auth.swagger.username.value; + const password = Auth.swagger.password.value; if (!user && !password) { return null; }