-
Notifications
You must be signed in to change notification settings - Fork 5k
Durante o processo de logout de uma instância, as chaves associadas a… #2191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Durante o processo de logout de uma instância, as chaves associadas a… #2191
Conversation
…o estado criptográfico não estavam sendo removidas corretamente do Redis. Dessa forma, quando uma nova conexão era estabelecida reutilizando o mesmo instanceName, o Baileys carregava chaves antigas e inválidas, incompatíveis com o novo conjunto de credenciais (creds) gerado na reconexão. Essa inconsistência gerava o seguinte sintoma prático: A instância autenticava com sucesso; Contudo, ao tentar enviar mensagens, entrava em estado de bloqueio, exibindo o status “aguardando mensagem” indefinidamente.
Reviewer's GuideEnsures proper cleanup of authentication credentials on instance logout by adding removeCreds methods to all auth state handlers and invoking them during the logout flow to prevent stale keys from persisting. Sequence diagram for updated logout credential cleanup processsequenceDiagram
participant "BaileysStartupService"
participant "AuthStateProvider"
participant "useMultiFileAuthStateRedisDb"
participant "useMultiFileAuthStatePrisma"
participant "Redis/DB/Provider"
"BaileysStartupService"->>"AuthStateProvider": Call authStateProvider(instance.id)
"BaileysStartupService"->>"AuthStateProvider": Call removeCreds()
"AuthStateProvider"->>"Redis/DB/Provider": Remove session keys
"BaileysStartupService"->>"useMultiFileAuthStateRedisDb": Call useMultiFileAuthStateRedisDb(instance.id, cache)
"BaileysStartupService"->>"useMultiFileAuthStateRedisDb": Call removeCreds()
"useMultiFileAuthStateRedisDb"->>"Redis/DB/Provider": Delete Redis keys
"BaileysStartupService"->>"useMultiFileAuthStatePrisma": Call useMultiFileAuthStatePrisma(instance.id, cache)
"BaileysStartupService"->>"useMultiFileAuthStatePrisma": Call removeCreds()
"useMultiFileAuthStatePrisma"->>"Redis/DB/Provider": Delete DB/Redis keys
ER diagram for credential removal from Redis and DB on logouterDiagram
INSTANCE {
string id
string sessionId
}
REDIS {
string key
string value
}
DB {
string sessionId
string creds
}
INSTANCE ||--o{ REDIS : "removes keys on logout"
INSTANCE ||--o{ DB : "removes creds on logout"
Class diagram for updated auth state handlers with removeCreds methodclassDiagram
class AuthStateProvider {
+providerFiles: ProviderFiles
+authStateProvider(instance: string): AuthState
}
class AuthState {
+state: AuthenticationState
+saveCreds(): Promise<void>
+removeCreds(): Promise<void>
}
class useMultiFileAuthStatePrisma {
+state: AuthenticationState
+saveCreds(): Promise<void>
+removeCreds(): Promise<void>
}
class useMultiFileAuthStateRedisDb {
+state: AuthenticationState
+saveCreds(): Promise<void>
+removeCreds(): Promise<void>
}
AuthStateProvider --> AuthState
useMultiFileAuthStatePrisma --|> AuthState
useMultiFileAuthStateRedisDb --|> AuthState
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- There’s significant duplication in the removeCreds implementation across Prisma, Redis, and file providers—consider extracting a shared helper to DRY up the code.
- Review the logger instantiations and naming (e.g. Redis file using the Prisma logger name) and standardize log levels for consistency.
- In BaileysStartupService, you could consolidate the three separate removeCreds calls into a unified loop or strategy to avoid repetitive authState loading.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- There’s significant duplication in the removeCreds implementation across Prisma, Redis, and file providers—consider extracting a shared helper to DRY up the code.
- Review the logger instantiations and naming (e.g. Redis file using the Prisma logger name) and standardize log levels for consistency.
- In BaileysStartupService, you could consolidate the three separate removeCreds calls into a unified loop or strategy to avoid repetitive authState loading.
## Individual Comments
### Comment 1
<location> `src/utils/use-multi-file-auth-state-provider-files.ts:93-99` </location>
<code_context>
return response;
};
+ const removeCreds = async () => {
+
+ const [response, error] = await this.providerFiles.removeSession(instance);
+ if (error) {
+ // this.logger.error(['removeData', error?.message, error?.stack]);
+ return;
+ }
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** removeCreds swallows errors silently; consider logging or surfacing them.
Errors from providerFiles.removeSession are currently ignored. If downstream consumers rely on error handling, log or propagate these errors.
```suggestion
const removeCreds = async () => {
const [response, error] = await this.providerFiles.removeSession(instance);
if (error) {
if (this.logger) {
this.logger.error(['removeCreds', error?.message, error?.stack]);
} else {
console.error('removeCreds error:', error);
}
throw error;
}
```
</issue_to_address>
### Comment 2
<location> `src/utils/use-multi-file-auth-state-provider-files.ts:152` </location>
<code_context>
}
}
+const logger = new Logger('useMultiFileAuthStatePrisma');
+
export default async function useMultiFileAuthStatePrisma(
</code_context>
<issue_to_address>
**suggestion:** Logger instance name may be misleading in this context.
Consider renaming the logger to match the provider file's purpose for improved traceability.
</issue_to_address>
### Comment 3
<location> `src/utils/use-multi-file-auth-state-redis-db.ts:41-48` </location>
<code_context>
+ async function removeCreds(): Promise<any> {
+ try {
+
+ logger.warn({ action: 'redis.delete', instanceName });
+
+ return await cache.delete(instanceName);
</code_context>
<issue_to_address>
**suggestion:** Consider using logger.info for successful deletion and logger.warn only for errors.
Use logger.info to indicate successful deletion, and reserve logger.warn or logger.error for error cases to improve log clarity.
```suggestion
try {
logger.info({ action: 'redis.delete', instanceName });
await cache.delete(instanceName);
} catch (err) {
logger.warn({ action: 'redis.delete.failed', instanceName, error: err });
return;
}
```
</issue_to_address>
### Comment 4
<location> `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:273-276` </location>
<code_context>
+ const cache = this.configService.get<CacheConf>('CACHE');
+ const provider = this.configService.get<ProviderSession>('PROVIDER');
+
+ if (provider?.ENABLED) {
+ const authState = await this.authStateProvider.authStateProvider(this.instance.id);
+
+ await authState.removeCreds()
+ }
+
</code_context>
<issue_to_address>
**suggestion:** Consider handling errors from removeCreds to avoid silent failures.
Currently, errors from removeCreds are ignored. Consider logging or handling these errors to improve reliability and traceability.
</issue_to_address>
### Comment 5
<location> `src/utils/use-multi-file-auth-state-prisma.ts:149-168` </location>
<code_context>
</code_context>
<issue_to_address>
**issue (code-quality):** Avoid function declarations, favouring function assignment expressions, inside blocks. ([`avoid-function-declarations-in-blocks`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/avoid-function-declarations-in-blocks))
<details><summary>Explanation</summary>Function declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers.
Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you
should use function expressions, which create functions in-scope.
</details>
</issue_to_address>
### Comment 6
<location> `src/utils/use-multi-file-auth-state-redis-db.ts:40-49` </location>
<code_context>
</code_context>
<issue_to_address>
**issue (code-quality):** Avoid function declarations, favouring function assignment expressions, inside blocks. ([`avoid-function-declarations-in-blocks`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/avoid-function-declarations-in-blocks))
<details><summary>Explanation</summary>Function declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers.
Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you
should use function expressions, which create functions in-scope.
</details>
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const removeCreds = async () => { | ||
|
|
||
| const [response, error] = await this.providerFiles.removeSession(instance); | ||
| if (error) { | ||
| // this.logger.error(['removeData', error?.message, error?.stack]); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): removeCreds swallows errors silently; consider logging or surfacing them.
Errors from providerFiles.removeSession are currently ignored. If downstream consumers rely on error handling, log or propagate these errors.
| const removeCreds = async () => { | |
| const [response, error] = await this.providerFiles.removeSession(instance); | |
| if (error) { | |
| // this.logger.error(['removeData', error?.message, error?.stack]); | |
| return; | |
| } | |
| const removeCreds = async () => { | |
| const [response, error] = await this.providerFiles.removeSession(instance); | |
| if (error) { | |
| if (this.logger) { | |
| this.logger.error(['removeCreds', error?.message, error?.stack]); | |
| } else { | |
| console.error('removeCreds error:', error); | |
| } | |
| throw error; | |
| } |
| try { | ||
|
|
||
| logger.warn({ action: 'redis.delete', instanceName }); | ||
|
|
||
| return await cache.delete(instanceName); | ||
| } catch { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider using logger.info for successful deletion and logger.warn only for errors.
Use logger.info to indicate successful deletion, and reserve logger.warn or logger.error for error cases to improve log clarity.
| try { | |
| logger.warn({ action: 'redis.delete', instanceName }); | |
| return await cache.delete(instanceName); | |
| } catch { | |
| return; | |
| } | |
| try { | |
| logger.info({ action: 'redis.delete', instanceName }); | |
| await cache.delete(instanceName); | |
| } catch (err) { | |
| logger.warn({ action: 'redis.delete.failed', instanceName, error: err }); | |
| return; | |
| } |
| async function removeCreds(): Promise<any> { | ||
|
|
||
| const cacheConfig = configService.get<CacheConf>('CACHE'); | ||
|
|
||
| // Redis | ||
| try { | ||
| if (cacheConfig.REDIS.ENABLED) { | ||
| await cache.delete(sessionId); | ||
| logger.info({ action: 'redis.delete', sessionId }); | ||
|
|
||
| return | ||
| } | ||
| } catch (err) { | ||
| logger.warn({ action: 'redis.delete', sessionId, err }); | ||
| } | ||
|
|
||
| logger.info({ action: 'auth.key.delete', sessionId }); | ||
|
|
||
| await deleteAuthKey(sessionId); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)
Explanation
Function declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.| async function removeCreds(): Promise<any> { | ||
| try { | ||
|
|
||
| logger.warn({ action: 'redis.delete', instanceName }); | ||
|
|
||
| return await cache.delete(instanceName); | ||
| } catch { | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)
Explanation
Function declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
Math.random()
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
Math.random()
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
Math.random()
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
Math.random()
| } else { | ||
| const { host, password, port, protocol: proto, username } = proxy | ||
| protocol = (proto || 'http').replace(':', '') | ||
| const { host, password, port, protocol: proto, username } = proxy; |
Check failure
Code scanning / CodeQL
Insecure randomness High
📋 Description
Durante o processo de logout de uma instância, as chaves associadas ao estado criptográfico não estavam sendo removidas corretamente do Redis.
Dessa forma, quando uma nova conexão era estabelecida reutilizando o mesmo instanceName, o Baileys carregava chaves antigas e inválidas, incompatíveis com o novo conjunto de credenciais (creds) gerado na reconexão.
Essa inconsistência gerava o seguinte sintoma prático:
A instância autenticava com sucesso;
Contudo, ao tentar enviar mensagens, entrava em estado de bloqueio, exibindo o status “aguardando mensagem” indefinidamente.
🔗 Related Issue
Closes #(issue_number)
🧪 Type of Change
🧪 Testing
📸 Screenshots (if applicable)
✅ Checklist
📝 Additional Notes
Summary by Sourcery
Ensure cryptographic keys are properly cleaned up on instance logout by adding and invoking removeCreds methods across auth state providers and logging deletion actions.
Bug Fixes:
Enhancements: