* chore: update scheduled messages author association to nullable and adjust related specs
* chore: update sender handling for WhatsApp messages and add external sender name
- Linear::CallbacksController: Replace broken
`described_class.new`mocking with proper `GlobalConfigService` stubbing
and real JWT token generation. The old pattern doesn't work in request
specs since Rails instantiates controllers internally.
- User associations: Remove `.class_name('Conversation')` assertion that
fails intermittently due to enterprise `prepend_mod_with` timing in
parallel tests. The class_name is already enforced by Rails at runtime -
if wrong, the app would crash immediately. No need to explicitly test
for this
Fixes
https://linear.app/chatwoot/issue/CW-6138/debug-linear-and-user-spec-failures-in-ci
## Linear:
- https://github.com/chatwoot/chatwoot/issues/486
## Description
This PR implements Multi-Factor Authentication (MFA) support for user
accounts, enhancing security by requiring a second form of verification
during login. The feature adds TOTP (Time-based One-Time Password)
authentication with QR code generation and backup codes for account
recovery.
## Type of change
- [ ] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
- Added comprehensive RSpec tests for MFA controller functionality
- Tested MFA setup flow with QR code generation
- Verified OTP validation and backup code generation
- Tested login flow with MFA enabled/disabled
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
The system determines a user’s active account by checking the
`active_at` field in the `account_users` table and selecting the most
recently active account:
```ruby
def active_account_user
account_users.order(active_at: :desc)&.first
end
```
This works fine when all accounts have a valid active_at timestamp.
**Problem**
When a user is added to a new account, the `active_at` value is NULL
(because the account has never been explicitly activated). Ordering by
active_at DESC produces inconsistent results across databases, since
handling of NULL values differs (sometimes treated as high, sometimes
low).
As a result:
- Mobile apps (critical impact): `/profile` returns the wrong account.
The UI keeps showing the old account even after switching, and
restarting does not fix it.
- Web app (accidentally works): Appears correct because the active
account is inferred from the browser URL, but the backend API is still
wrong.
**Root Cause**
- The ordering logic did not account for NULL `active_at`.
- New accounts without active_at sometimes get incorrectly prioritized
as the “active” account.
**Solution**
Explicitly ensure that accounts with NULL active_at are sorted after
accounts with real timestamps by using NULLS LAST:
```ruby
def active_account_user
account_users.order(Arel.sql('active_at DESC NULLS LAST, id DESC'))&.first
end
```
- Accounts with actual `active_at` values will always be prioritized.
- New accounts (with NULL active_at) will be placed at the bottom until
the user explicitly activates them.
- Adding id DESC as a secondary ordering ensures consistent tie-breaking
when multiple accounts have the same `active_at`.
* feat: add customizable signature position and separator options
* fix: correct default value note for signatureSeparator and ensure reactivity
* fix: correct watcher boolean conversion and add immediate ui_settings updates
- Fix watchers to convert string props to boolean values for reactive refs
- Add immediate event handlers for switch changes to update ui_settings in real-time
- Ensure proper synchronization between switch states and user.ui_settings
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* fix: split signature content and ui_settings updates to resolve persistence bug
- Use updateUISettings store action for signature_position and signature_separator
- Keep updateProfile for message_signature content only
- Fixes FormData serialization issue that corrupted nested ui_settings object
- Add diagnostic logging to verify data flow
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* clean: remove diagnostic console logging from updateSignature method
- Remove temporary console.log statements added for verification
- Keep core implementation that splits signature content and ui_settings updates
- Keep console.error for proper error handling with eslint-disable comment
- Implementation now ready for production use
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* fix: updateUISettings call in updateSignature method
* chore: move signature application to send-time and add button highlighting (#79)
* fix: move signature application from editor manipulation to send-time
- Remove addSignature/removeSignature/toggleSignatureInEditor from WootWriter
- Remove signature logic from draft handling and canned response insertion
- Apply signatures only in getMessagePayload during message sending
- Add button highlighting for signature toggle when activated
- Prevents signature duplication and persistence in editor content
- Fixes signature position toggle bug
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* fix: escape signature separator to prevent markdown setext heading interpretation
- Escape '--' separator as '\--' in appendSignature to prevent H2 heading creation
- Update removeSignature to handle escaped separators correctly
- Fixes signature separator being rendered as markdown instead of plain text
- Refactor nested ternary to fix ESLint error
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* fix: prevent signature separator markdown interpretation in message processing
- Add fix_signature_separator_markdown method to escape '--' separators
- Update ensure_processed_message_content to fix separators before saving
- Prevents signature separators from being interpreted as setext headings
- Ensures correct message display in channels and email notifications
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* fix: update separator format to use \n--\n instead of escaping
- Change separator delimiter from '\--' to '\n--\n' format
- Update removeSignature function to handle new separator format correctly
- Simplify message processing since separators are already properly formatted
- Ensures consistent separator handling across frontend and backend
Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>
* fix: update signature delimiter format to include extra new lines
* chore: remove comment about signature application logic
* refactor: remove unused method and comments related to signature separator markdown processing
* chore: simplify slash command detection by using updatedMessage directly
* refactor: remove signature logic from draft message handling
* refactor: simplify body empty check by removing signature manipulation logic
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cayo@fazer.ai <cayoproliveira@gmail.com>
* refactor: extract signature settings logic into a separate method
* fix: handle nil ui_settings in signature position and separator methods
* fix: update return value of findSignatureInBody to include position information
* fix: update signature handling in findSignatureInBody and related methods
* fix: adjust delimiter length handling in removeSignature function
* test: add cases for appending, removing, and replacing signatures with various separators
* test: add cases for signature position and separator handling
* test: add cases for updating signature position and separator in ui_settings
* fix: correct typo in comment for findSignatureInBody function
* refactor: simplify translation function calls in MessageSignature component
* chore: refactoring
* chore: refactor
* feat: switch -> select
* chore: refactor and undo changes
* chore: refactor and undo changes
* chore: refactor
* fix: remove old select component usage
* chore: remove useless style
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
This PR addresses several items listed in our rubocop_todo by implementing the necessary corrections and enhancements. As a result, we are now able to remove the rubocop_todo file entirely, streamlining our codebase and ensuring adherence to our coding standards.
fixes: https://linear.app/chatwoot/issue/CW-1806/chore-rubocop-audit
fixes: #3853
- Introduced DISABLE_GRAVATAR Global Config, which will stop chatwoot from making API requests to gravatar
- Cleaned up avatar-related logic and centralized it into the avatarable concern
- Added specs for the missing cases
- Added migration for existing installations to move the avatar to attachment, rather than making the API that results in 404.
Users can change their email from profile settings. They will be logged out immediately. Users can log in again with the updated email without verifying the same. This is a security problem.
So this change enforce the user to reconfirm the email after changing it. Users can log in with the updated email only after the confirmation.
Fixes: https://huntr.dev/bounties/7afd04b4-232e-4907-8a3c-acf8bd4b5b22/
Addresses: #402
- migrations to split roles and other attributes from users table
- make changes in code to accommodate this change
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
* Add `invited_by` foreign key to User
Allows for a User to be tied to the user who invited them
* Include `current_user` in new agent initialization parameters
* Add `shoulda-matchers` for testing associations
* Add Inviter information and associated account to welcome email
* Only show inviter info if applicable
* Update conversation spec for FFaker compatibility