Skip to content

fix(e2ee): re-fetch subscription inside the write in toggleRoomE2EE - #7554

Open
OtavioStasiak wants to merge 3 commits into
developfrom
fix.refetch-room-inside-the-write-in-toggleroome2e
Open

fix(e2ee): re-fetch subscription inside the write in toggleRoomE2EE#7554
OtavioStasiak wants to merge 3 commits into
developfrom
fix.refetch-room-inside-the-write-in-toggleroome2e

Conversation

@OtavioStasiak

@OtavioStasiak OtavioStasiak commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

toggleRoomE2EE fetched the subscription record once, before showing the confirm Alert, and then reused that same instance for all three of its writes: the optimistic update, the Cancel revert, and the revert after a failed saveRoomSettings.

The last two happen after the record has crossed user input (the Alert can stay open indefinitely) and a network round trip. If a subscription stream event updates the row in that window, the captured instance is stale, WatermelonDB rejects record.update(), and the revert is silently swallowed by the surrounding catch — leaving the switch showing an encrypted state the server never agreed to.

Each update path now re-fetches the subscription with getSubscriptionByRoomId(rid) inside its own db.write callback and updates the fresh record, bailing out if the row no longer exists. optimisticUpdate takes a rid instead of a record; toggleRoomE2EE(rid) and all of its callers are unchanged.

Added toggleRoomE2EE.test.ts, which mocks database.active with a store that reproduces WatermelonDB's staleness check (a handle remembers the version it was fetched at and throws record has pending changes if another writer bumped it). It covers a concurrent write landing while the Alert is open, one landing during the failing save request, and the happy path. Both concurrency tests fail against the previous code.

Issue(s)

https://rocketchat.atlassian.net/browse/NATIVE-1468

How to test or reproduce

  • Open a room where you can toggle E2E encryption (Room Actions → Encrypted, or the E2EE Toggle Room screen) and tap the switch — the switch flips
    immediately and the confirm Alert appears.
  • With the Alert still open, have the room's subscription updated from elsewhere (change a room setting from another client/admin, or receive a
    message in the room) so a stream event writes to that subscription row.
  • Tap Cancel. The switch must go back to its original value. Before this fix it stayed on the optimistic value, because the revert wrote to a record
    fetched before the Alert opened.
  • Repeat, but tap the confirm button (Enable/Disable) while offline or with the server unreachable so saveRoomSettings fails, again with a stream
    update landing during the request. The switch must revert.
  • Confirm the happy path is untouched: toggle, confirm, and the room stays encrypted/decrypted as chosen after a reload.
  • Unit tests: TZ=UTC pnpm test app/lib/encryption/helpers/toggleRoomE2EE.test.ts

Screenshots

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • Improvement (non-breaking change which improves a current function)
  • New feature (non-breaking change which adds functionality)
  • Documentation update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA
  • Lint and unit tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works (if applicable)
  • I have added necessary documentation (if applicable)
  • Any dependent changes have been merged and published in downstream modules

Further comments

Summary by CodeRabbit

  • Bug Fixes
    • Improved room encryption toggling to keep the displayed setting accurate when changes are cancelled, dismissed, or fail to save.
    • Added safeguards for concurrent updates and rooms that are no longer available.
    • Prevented encryption settings from becoming inconsistent after interrupted or unsuccessful changes.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0688662e-310c-48a8-90dd-e970bc86e25d

📥 Commits

Reviewing files that changed from the base of the PR and between df991f7 and 671dba9.

📒 Files selected for processing (2)
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/lib/encryption/helpers/toggleRoomE2EE.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts

Walkthrough

The room encryption toggle reloads the current subscription during optimistic updates and rollbacks. Tests cover concurrent writes, cancellation, alert dismissal, failed persistence, and successful persistence.

Changes

Room encryption toggle

Layer / File(s) Summary
Reload subscriptions during toggle updates
app/lib/encryption/helpers/toggleRoomE2EE.ts
optimisticUpdate accepts a room ID, reloads the current subscription inside the database write, and skips updates for missing rooms. Update and rollback paths pass the room ID. Alert dismissal rolls back the optimistic value.
Validate concurrent rollback and success paths
app/lib/encryption/helpers/toggleRoomE2EE.test.ts
Tests simulate stale records and concurrent writes. Cancellation, alert dismissal, and failed saves restore the previous state without update errors. Successful saves retain the new value and send the expected payload.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: type: bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: re-fetching the subscription inside the database write for toggleRoomE2EE.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • NATIVE-1468: Request failed with status code 401

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/lib/encryption/helpers/toggleRoomE2EE.ts`:
- Line 10: In app/lib/encryption/helpers/toggleRoomE2EE.ts at optimisticUpdate,
add an explicit Promise<void> return annotation. In
app/lib/encryption/helpers/toggleRoomE2EE.test.ts lines 39-70, add explicit void
or Promise<void> annotations to the fixture helpers as appropriate and define a
named interface for the createStore return object, using it as that helper’s
return type.
- Line 56: The alert configuration in toggleRoomE2EE must treat Android
outside-dismissal as cancellation: add an onDismiss handler that restores the
previous encryption value via optimisticUpdate, while preserving existing
cancellation behavior. Update app/lib/encryption/helpers/toggleRoomE2EE.test.ts
lines 92-104 to cover the outside-dismissal path and verify the rollback.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e91218a-0f54-4c40-9de6-e9ecfcbc33e1

📥 Commits

Reviewing files that changed from the base of the PR and between 140a44e and df991f7.

📒 Files selected for processing (2)
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: ESLint and Test / run-eslint-and-test
  • GitHub Check: E2E Shard Preflight
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use descriptive names for functions, variables, and classes that clearly convey their purpose
Write comments that explain the 'why' behind code decisions, not the 'what'
Keep functions small and focused on a single responsibility
Use const by default, let when reassignment is needed, and avoid var
Prefer async/await over .then() chains for handling asynchronous operations
Use explicit error handling with try/catch blocks for async operations
Avoid deeply nested code; refactor complex logic into helper functions

Files:

  • app/lib/encryption/helpers/toggleRoomE2EE.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for type safety; add explicit type annotations to function parameters and return types
Prefer interfaces over type aliases for defining object shapes in TypeScript
Use enums for sets of related constants rather than magic strings or numbers

Files:

  • app/lib/encryption/helpers/toggleRoomE2EE.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{js,jsx,ts,tsx}: Format JavaScript and TypeScript code with Oxfmt using the repository configuration: tabs, single quotes, 130-character width, no trailing commas, omitted arrow-function parentheses where possible, and same-line brackets.
Follow Oxlint rules configured in .oxlintrc.json, including the import, React, Jest, TypeScript, and React Native plugins.

Files:

  • app/lib/encryption/helpers/toggleRoomE2EE.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
🧠 Learnings (2)
📚 Learning: 2026-04-30T17:07:51.020Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7274
File: app/lib/services/voip/MediaCallEvents.ts:0-0
Timestamp: 2026-04-30T17:07:51.020Z
Learning: In this Rocket.Chat React Native codebase, the ESLint rule `no-void: error` is enforced. When you see a promise returned from an async call that is not awaited (a “floating promise”), do not silence it with the `void somePromise()` pattern. Instead, handle the promise explicitly by attaching `.catch(...)` (or otherwise awaiting/handling the error) so unhandled-rejection risks are addressed in a way that satisfies the existing ESLint configuration.

Applied to files:

  • app/lib/encryption/helpers/toggleRoomE2EE.ts
  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
📚 Learning: 2026-06-25T18:37:25.526Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7434
File: app/views/ScreenLockConfigView.test.tsx:16-22
Timestamp: 2026-06-25T18:37:25.526Z
Learning: In Rocket.Chat ReactNative tests that mock selectors for `useAppSelector`, don’t require the mocked selector input to be typed as `IApplicationState` when the fixture only includes a partial Redux state slice (e.g., only `server` and `settings`). Requiring the full `IApplicationState` type in that scenario forces unsafe `as IApplicationState` casts and undermines type-safety. For these narrowly scoped selector-mock fixtures, use a less strict type (e.g., `any`) to keep the mock focused on the slice under test.

Applied to files:

  • app/lib/encryption/helpers/toggleRoomE2EE.test.ts
🔇 Additional comments (1)
app/lib/encryption/helpers/toggleRoomE2EE.ts (1)

45-45: LGTM!

Also applies to: 76-76

Comment thread app/lib/encryption/helpers/toggleRoomE2EE.ts Outdated
Comment thread app/lib/encryption/helpers/toggleRoomE2EE.ts

// Instantly feedback to the user
await db.write(async () => {
// Fetch the room again: a stream event may have updated the record while the alert was open or while the request was in flight

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants