Skip to content

fix: require unban before using inviting link #40087

Merged
ggazzo merged 5 commits intodevelopfrom
fix/test-reinvite-banned-user-requires-unban
Apr 8, 2026
Merged

fix: require unban before using inviting link #40087
ggazzo merged 5 commits intodevelopfrom
fix/test-reinvite-banned-user-requires-unban

Conversation

@ggazzo
Copy link
Copy Markdown
Member

@ggazzo ggazzo commented Apr 8, 2026

Summary

Fixes the 4 CE + 4 EE API test failures on develop.

Test plan

  • CI passes on develop (the 8 failing tests should now pass)

Summary by CodeRabbit

  • Bug Fixes

    • Invite/token flows now block banned users from using invites or tokens and return an error until unbanned.
  • Tests

    • Added end-to-end tests for invite-token behavior for banned vs. unbanned users.
    • Removed an outdated reinvite-after-ban test scenario.
  • Documentation

    • Clarified join/invite/re-entry behavior and enforcement for banned users across entry points.

Task: FEDCORE-61

The test from #40061 assumed `groups.invite` would automatically unban
and re-add a user, but the current flow requires an explicit
`rooms.unbanUser` call first. Aligns the test with the actual behavior
introduced in #39840.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ggazzo ggazzo requested a review from a team as a code owner April 8, 2026 16:43
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Apr 8, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 8, 2026

⚠️ No Changeset found

Latest commit: 5b885be

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Added a server-side ban check to invite-token consumption, removed an outdated reinvite-after-ban e2e test, and added e2e tests asserting useInviteToken returns error-user-is-banned until an explicit unban is performed.

Changes

Cohort / File(s) Summary
Invite token server logic
apps/meteor/app/invites/server/functions/useInviteToken.ts
Retrieve the user's subscription for the target room and throw Meteor.Error('error-user-is-banned') when isBannedSubscription is true before updating invite usage or user token.
Invites end-to-end tests
apps/meteor/tests/end-to-end/api/invites.ts
Added tests for POST /useInviteToken validating banned users receive 400 error-user-is-banned, then succeed after rooms.unbanUser.
Rooms end-to-end tests (removed)
apps/meteor/tests/end-to-end/api/rooms.ts
Deleted test that assumed re-inviting a banned user would implicitly unban and restore membership while preserving other subscriptions.
Docs: ban behavior
docs/features/ban-user.md
Rewrote re-entry behavior to require explicit unban before join/invite/re-entry and documented enforcement points (addUsersToRoom, useInviteToken, Room.join/canAccessRoom, federation handleInvite).

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client
participant Server
participant DB
Client->>Server: POST /useInviteToken (token)
Server->>DB: find subscription for user & room
DB-->>Server: subscription (may be BANNED)
alt subscription indicates banned
Server-->>Client: 400 error-user-is-banned
else not banned
Server->>DB: increment invite usage / set user invite token
DB-->>Server: success
Server-->>Client: 200 with room object
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • FEDCORE-61 — Matches this change: enforces explicit unban before re-inviting/using an invite for a banned user and updates tests to expect error-user-is-banned.
🚥 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 'fix: require unban before using inviting link' accurately reflects the main change: enforcing that banned users must be explicitly unbanned before using invite links or being re-invited.
Linked Issues check ✅ Passed The PR successfully addresses all objectives from FEDCORE-61: updates tests to reflect explicit unban requirement, asserts error-user-is-banned on banned user re-invite attempts, verifies unban followed by successful re-invite, and adds explicit room-ban check in useInviteToken implementation.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing the ban-and-reinvite flow: test updates, useInviteToken implementation fix, and documentation updates. No unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@ggazzo ggazzo changed the title fix(test): require unban before re-inviting banned user test: require unban before re-inviting banned user Apr 8, 2026
@ggazzo ggazzo added this to the 8.4.0 milestone Apr 8, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.53%. Comparing base (3340757) to head (5b885be).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #40087      +/-   ##
===========================================
+ Coverage    70.52%   70.53%   +0.01%     
===========================================
  Files         3273     3273              
  Lines       116717   116880     +163     
  Branches     21018    21101      +83     
===========================================
+ Hits         82310    82443     +133     
- Misses       32368    32378      +10     
- Partials      2039     2059      +20     
Flag Coverage Δ
e2e 60.65% <ø> (+0.08%) ⬆️
e2e-api 48.06% <ø> (-1.05%) ⬇️
unit 70.95% <ø> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

@ggazzo
Copy link
Copy Markdown
Member Author

ggazzo commented Apr 8, 2026

/jira FEDCORE-59

ggazzo and others added 3 commits April 8, 2026 13:59
Banned users could bypass the ban by using an invite link, since
`useInviteToken` called `addUserToRoom` without checking ban status.
Now checks for banned subscription before saving the invite token,
which also prevents the secondary path through `setUsername`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removes the entire "Re-inviting a banned user should preserve other
subscriptions" describe block added by #40061 and subsequently modified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds tests verifying that a banned user gets error-user-is-banned when
using an invite token, and that the invite succeeds after unbanning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ggazzo ggazzo changed the title test: require unban before re-inviting banned user fix: require unban before using inviting link Apr 8, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/meteor/tests/end-to-end/api/invites.ts (1)

209-210: Cover the username-less invite flow too.

This scenario logs the user in with bannedUser.username, so it only exercises the branch where useInviteToken can immediately proceed to room join. The new guard was added before updateInviteToken to protect the deferred setUsername path as well; please add a case with a user that has no username yet, otherwise a regression that stores the invite token before throwing would still pass this suite.

Also applies to: 233-257

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/tests/end-to-end/api/invites.ts` around lines 209 - 210, Add a
test case that covers the "username-less" invite flow: create a user with no
username (use the same createUser() path but ensure username is unset), obtain
credentials via login(bannedUser.username?) by logging in the user without a
username (use the existing bannedUser/bannedUserCredentials pattern), then
exercise useInviteToken and the deferred setUsername path so the guard added
before updateInviteToken is executed; assert that the guard throws (or prevents
storing the invite token) before updateInviteToken is called. Locate this by the
existing createUser(), login(), useInviteToken, setUsername and
updateInviteToken logic and mirror the existing test steps at lines ~233-257 to
add the username-less scenario.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/meteor/tests/end-to-end/api/invites.ts`:
- Around line 209-210: Add a test case that covers the "username-less" invite
flow: create a user with no username (use the same createUser() path but ensure
username is unset), obtain credentials via login(bannedUser.username?) by
logging in the user without a username (use the existing
bannedUser/bannedUserCredentials pattern), then exercise useInviteToken and the
deferred setUsername path so the guard added before updateInviteToken is
executed; assert that the guard throws (or prevents storing the invite token)
before updateInviteToken is called. Locate this by the existing createUser(),
login(), useInviteToken, setUsername and updateInviteToken logic and mirror the
existing test steps at lines ~233-257 to add the username-less scenario.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bd70f647-bc8f-44e4-a82a-d7e396ae67cd

📥 Commits

Reviewing files that changed from the base of the PR and between bfccc69 and 7544122.

📒 Files selected for processing (3)
  • apps/meteor/app/invites/server/functions/useInviteToken.ts
  • apps/meteor/tests/end-to-end/api/invites.ts
  • apps/meteor/tests/end-to-end/api/rooms.ts
💤 Files with no reviewable changes (1)
  • apps/meteor/tests/end-to-end/api/rooms.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 🔨 Test Storybook / Test Storybook
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 📦 Meteor Build (coverage)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
  • apps/meteor/tests/end-to-end/api/invites.ts
🧠 Learnings (24)
📓 Common learnings
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.
📚 Learning: 2026-03-09T18:39:21.178Z
Learnt from: Harxhit
Repo: RocketChat/Rocket.Chat PR: 39476
File: apps/meteor/server/methods/addAllUserToRoom.ts:0-0
Timestamp: 2026-03-09T18:39:21.178Z
Learning: In apps/meteor/server/methods/addAllUserToRoom.ts, the implementation uses a single cursor pass (Users.find(userFilter).batchSize(100)) that collects both the full user objects (collectedUsers: IUser[]) and their usernames (usernames: string[]) in one iteration. `beforeAddUserToRoom` is then called once with the full usernames batch (preserving batch-validation semantics), and the subsequent subscription/message processing loop iterates over the same stable `collectedUsers` array — no second DB query is made. This avoids any race condition between validation and processing while preserving the original batch-validation behavior.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-11T22:04:20.529Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 39545
File: apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts:59-61
Timestamp: 2026-03-11T22:04:20.529Z
Learning: In `apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts`, the `msg.u._id === uid` early-return in the `streamNewMessage` handler is intentional: the "New messages" indicator is designed to notify about messages from other users only. Self-sent messages — including those sent from a different session/device — are always skipped, by design. Do not flag this as a multi-session regression.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2026-03-14T14:58:58.834Z
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2026-03-09T21:20:12.687Z
Learnt from: pierre-lehnen-rc
Repo: RocketChat/Rocket.Chat PR: 39386
File: apps/meteor/server/services/push/tokenManagement/findDocumentToUpdate.ts:12-15
Timestamp: 2026-03-09T21:20:12.687Z
Learning: In `apps/meteor/server/services/push/tokenManagement/findDocumentToUpdate.ts`, the early return `if (data.voipToken) return null` (Lines 13-15) is intentionally correct. VoIP token updates always include an `_id`, so they are handled by the `_id` lookup block above (Lines 5-9) and never reach this guard. The guard is only a safety net for edge cases where `_id` is absent or no document was found, preventing an incorrect `token + appName` fallback match for VoIP-only payloads.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2026-03-11T16:46:55.955Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 39535
File: apps/meteor/app/apps/server/bridges/livechat.ts:249-249
Timestamp: 2026-03-11T16:46:55.955Z
Learning: In `apps/meteor/app/apps/server/bridges/livechat.ts`, `createVisitor()` intentionally does not propagate `externalIds` to `registerData`. This is by design: the method is deprecated (JSDoc: `deprecated Use createAndReturnVisitor instead. Note: This method does not support externalIds.`) to push callers toward `createAndReturnVisitor()`, which does support `externalIds`. Do not flag the missing `externalIds` field in `createVisitor()` as a bug.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2026-02-25T20:10:16.987Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38913
File: packages/ddp-client/src/legacy/types/SDKLegacy.ts:34-34
Timestamp: 2026-02-25T20:10:16.987Z
Learning: In the RocketChat/Rocket.Chat monorepo, packages/ddp-client and apps/meteor do not use TypeScript project references. Module augmentations in apps/meteor (e.g., declare module 'rocket.chat/rest-typings') are not visible when compiling packages/ddp-client in isolation, which is why legacy SDK methods that depend on OperationResult types for OpenAPI-migrated endpoints must remain commented out.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/app/invites/server/functions/useInviteToken.ts
  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-16T11:57:17.987Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 39657
File: apps/meteor/tests/end-to-end/apps/app-resolve-visitor.ts:43-45
Timestamp: 2026-03-16T11:57:17.987Z
Learning: In `apps/meteor/tests/end-to-end/apps/app-resolve-visitor.ts`, `externalIds` lookups are namespaced per `app.id`. Because `cleanupApps()` is called before each test run and a fresh app is installed (giving a new unique `app.id`), fixed `userId` strings like `'nonexistent-id'` in null-path tests are safe and cannot collide with stale visitor records from previous runs. Do not flag these as needing unique/random values.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-15T14:31:23.493Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39647
File: apps/meteor/app/api/server/v1/users.ts:891-899
Timestamp: 2026-03-15T14:31:23.493Z
Learning: In RocketChat/Rocket.Chat, `IUser.inactiveReason` in `packages/core-typings/src/IUser.ts` is typed as `'deactivated' | 'pending_approval' | 'idle_too_long'` (optional, no `null`), but the database stores `null` for newly created users. The Typia-generated `$ref: '#/components/schemas/IUser'` schema therefore correctly rejects `null` for `inactiveReason`. This causes the test "should create a new user with default roles" to fail when response validation is active (TEST_MODE). The fix is to add `| null` to `inactiveReason` in core-typings and rebuild Typia schemas in a separate PR. Do not flag this test failure as a bug introduced by the users.create OpenAPI migration (PR `#39647`). Do not suggest inlining a custom schema to work around it, as migration rules require using `$ref` when a Typia schema exists.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-12T10:26:26.697Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 39340
File: apps/meteor/app/api/server/v1/im.ts:1349-1398
Timestamp: 2026-03-12T10:26:26.697Z
Learning: In `apps/meteor/app/api/server/v1/im.ts` (PR `#39340`), the `DmEndpoints` type intentionally includes temporary stub entries for `/v1/im.kick`, `/v1/dm.kick`, `/v1/im.leave`, and `/v1/dm.leave` (using `DmKickProps` and `DmLeaveProps`) even though no route handlers exist for them yet. These stubs were added to preserve type compatibility after removing the original `DmLeaveProps` and related files. They are planned for cleanup in a follow-up PR. Do not flag these as missing implementations when reviewing this file until the follow-up is merged.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
🔇 Additional comments (1)
apps/meteor/app/invites/server/functions/useInviteToken.ts (1)

41-46: Good placement for the ban guard.

Checking the subscription before persisting the invite token closes the banned-user path without relying on the later room-join step.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
docs/features/ban-user.md (1)

62-62: Optional wording polish for formal docs tone.

At Line 62, consider “invitation” instead of “invite” for consistency with formal documentation style.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/features/ban-user.md` at line 62, Replace the informal term "invite"
with the more formal "invitation" in the sentence "When a Matrix homeserver
sends an invite for a user who is banned locally:" so update that exact phrase
to "When a Matrix homeserver sends an invitation for a user who is banned
locally:" to maintain consistent formal documentation tone.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/features/ban-user.md`:
- Line 62: Replace the informal term "invite" with the more formal "invitation"
in the sentence "When a Matrix homeserver sends an invite for a user who is
banned locally:" so update that exact phrase to "When a Matrix homeserver sends
an invitation for a user who is banned locally:" to maintain consistent formal
documentation tone.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec9d8f12-8f4e-4fe0-b656-c74c1c739837

📥 Commits

Reviewing files that changed from the base of the PR and between 7544122 and 0234e75.

📒 Files selected for processing (1)
  • docs/features/ban-user.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 📦 Meteor Build (coverage)
  • GitHub Check: CodeQL-Build
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • docs/features/ban-user.md
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • docs/features/ban-user.md
🪛 LanguageTool
docs/features/ban-user.md

[style] ~62-~62: The noun “invitation” is usually used instead of ‘invite’ in formal writing.
Context: ...ents When a Matrix homeserver sends an invite for a user who is banned locally: - `ha...

(AN_INVITE)

🔇 Additional comments (1)
docs/features/ban-user.md (1)

37-69: Accurate behavior mapping for ban enforcement across entry paths.

This update is aligned with current server behavior and the described guard points for API invite, invite token, public/private join checks, and required explicit unban flow.

Also applies to: 77-77

@ggazzo ggazzo force-pushed the fix/test-reinvite-banned-user-requires-unban branch from 0234e75 to 1a56d92 Compare April 8, 2026 17:34
Replaces the outdated "Re-entry After Unban" section (which claimed
auto-unban on invite) with a comprehensive "Join / Invite / Re-entry
Behavior" section covering all entry points: API invite, invite link,
direct join, and federation events — for both normal and federated rooms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ggazzo ggazzo force-pushed the fix/test-reinvite-banned-user-requires-unban branch from 1a56d92 to 5b885be Compare April 8, 2026 17:37
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/features/ban-user.md`:
- Around line 68-69: The documentation is inconsistent: the unban flow now
requires an explicit unban before re-entry (via POST /v1/rooms.unbanUser, /unban
`@username`, or the "Banned Users" bar) but the system-message description for the
`user-unbanned` event still says “including via re-addition.” Update the
phrasing around the `user-unbanned` system-message to remove or clarify
“including via re-addition” so it reflects the current behavior (explicit unban
required), and ensure cross-references to the Unban section and the POST
/v1/rooms.unbanUser endpoint consistently state that re-entry requires an
explicit unban.
🪄 Autofix (Beta)

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

Run ID: 58a0d573-664c-4c6c-809a-a9e690def80a

📥 Commits

Reviewing files that changed from the base of the PR and between 0234e75 and 1a56d92.

📒 Files selected for processing (2)
  • apps/meteor/tests/end-to-end/api/invites.ts
  • docs/features/ban-user.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/tests/end-to-end/api/invites.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 🔨 Test Storybook / Test Storybook
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 📦 Meteor Build (coverage)
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • docs/features/ban-user.md
📚 Learning: 2026-03-09T18:39:21.178Z
Learnt from: Harxhit
Repo: RocketChat/Rocket.Chat PR: 39476
File: apps/meteor/server/methods/addAllUserToRoom.ts:0-0
Timestamp: 2026-03-09T18:39:21.178Z
Learning: In apps/meteor/server/methods/addAllUserToRoom.ts, the implementation uses a single cursor pass (Users.find(userFilter).batchSize(100)) that collects both the full user objects (collectedUsers: IUser[]) and their usernames (usernames: string[]) in one iteration. `beforeAddUserToRoom` is then called once with the full usernames batch (preserving batch-validation semantics), and the subsequent subscription/message processing loop iterates over the same stable `collectedUsers` array — no second DB query is made. This avoids any race condition between validation and processing while preserving the original batch-validation behavior.

Applied to files:

  • docs/features/ban-user.md
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • docs/features/ban-user.md
🪛 LanguageTool
docs/features/ban-user.md

[style] ~62-~62: The noun “invitation” is usually used instead of ‘invite’ in formal writing.
Context: ...ents When a Matrix homeserver sends an invite for a user who is banned locally: - `ha...

(AN_INVITE)

🔇 Additional comments (1)
docs/features/ban-user.md (1)

37-69: Behavior documentation is clear and aligned with the new ban enforcement flow.

This section correctly captures the explicit-unban requirement across API invite, invite token, join, and federation paths, matching the intended test updates.

Also applies to: 77-77

Comment thread docs/features/ban-user.md
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
docs/features/ban-user.md (1)

68-69: ⚠️ Potential issue | 🟡 Minor

Align unban semantics across the page.

This section says re-entry requires explicit unban, but Line 91 still says user-unbanned can happen “including via re-addition,” which implies implicit unban. Please make these statements consistent.

📝 Suggested doc adjustment
-| `user-unbanned` | A user is unbanned (including via re-addition) |
+| `user-unbanned` | A user is explicitly unbanned from the room |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/features/ban-user.md` around lines 68 - 69, The doc currently
contradicts itself about whether re-adding a banned user implicitly unbans them;
make the semantics consistent by choosing one behavior and updating the wording:
either (A) keep explicit unban required—ensure the first list item ("POST
/v1/rooms.unbanUser", "/unban `@username`", "Banned Users") remains and remove or
reword the phrase "including via re-addition" from the "user-unbanned" mention
so it no longer implies implicit unban, or (B) change the first list item to
state that inviting/re-adding implicitly clears the ban and adjust the
"user-unbanned" line to match; edit the occurrences of "POST
/v1/rooms.unbanUser", "/unban `@username`", "Banned Users", and the
"user-unbanned" sentence so both places state the same unban semantics.
🧹 Nitpick comments (3)
apps/meteor/tests/end-to-end/api/invites.ts (3)

229-232: Make teardown resilient to partial setup failures.

Guard cleanup calls so teardown does not throw when setup fails before all resources are created.

🧹 Safer teardown
 		after(async () => {
-			await deleteRoom({ type: 'p', roomId: room._id });
-			await deleteUser(bannedUser);
+			if (room?._id) {
+				await deleteRoom({ type: 'p', roomId: room._id });
+			}
+			if (bannedUser) {
+				await deleteUser(bannedUser);
+			}
 		});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/tests/end-to-end/api/invites.ts` around lines 229 - 232, The
teardown currently calls deleteRoom({ type: 'p', roomId: room._id }) and
deleteUser(bannedUser) unguarded, which will throw if setup failed and room or
bannedUser weren't created; update the after hook to guard these calls by
checking that room and room._id exist before calling deleteRoom and that
bannedUser is defined (or truthy) before calling deleteUser, or wrap each
cleanup call in a try/catch to swallow errors so teardown is resilient to
partial setup failures.

216-220: Drop inline implementation comments in this test block.

These comments can be removed without losing clarity; the step names are already explicit in code structure.

As per coding guidelines "Avoid code comments in the implementation".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/tests/end-to-end/api/invites.ts` around lines 216 - 220, Remove
the inline implementation comments in the test block surrounding the group
invite and ban requests: delete the "// Add user then ban them" and "// Create
invite link for the room" comments that sit above the calls to
request.post(api('groups.invite')).set(credentials).send({ roomId: room._id,
userId: bannedUser._id }) and
request.post(api('rooms.banUser')).set(credentials).send({ roomId: room._id,
userId: bannedUser._id }); the test steps and variable names (room, bannedUser,
api('groups.invite'), api('rooms.banUser')) are already self-descriptive so
simply remove those two comment lines.

224-224: Strengthen the regression check by using a single-use token.

Using maxUses: 10 can hide accidental token consumption in the banned path. Setting it to 1 makes this test verify non-consumption more strictly.

✅ Minimal change
-				.send({ rid: room._id, days: 1, maxUses: 10 })
+				.send({ rid: room._id, days: 1, maxUses: 1 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/tests/end-to-end/api/invites.ts` at line 224, Change the invite
creation payload to request a single-use token so the regression asserts
non-consumption strictly: in the test where you call .send({ rid: room._id,
days: 1, maxUses: 10 }) update maxUses to 1 (i.e., .send({ rid: room._id, days:
1, maxUses: 1 })) and ensure any related assertions expecting token use counts
remain consistent with a single-use token.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/features/ban-user.md`:
- Around line 68-69: The doc currently contradicts itself about whether
re-adding a banned user implicitly unbans them; make the semantics consistent by
choosing one behavior and updating the wording: either (A) keep explicit unban
required—ensure the first list item ("POST /v1/rooms.unbanUser", "/unban
`@username`", "Banned Users") remains and remove or reword the phrase "including
via re-addition" from the "user-unbanned" mention so it no longer implies
implicit unban, or (B) change the first list item to state that
inviting/re-adding implicitly clears the ban and adjust the "user-unbanned" line
to match; edit the occurrences of "POST /v1/rooms.unbanUser", "/unban
`@username`", "Banned Users", and the "user-unbanned" sentence so both places
state the same unban semantics.

---

Nitpick comments:
In `@apps/meteor/tests/end-to-end/api/invites.ts`:
- Around line 229-232: The teardown currently calls deleteRoom({ type: 'p',
roomId: room._id }) and deleteUser(bannedUser) unguarded, which will throw if
setup failed and room or bannedUser weren't created; update the after hook to
guard these calls by checking that room and room._id exist before calling
deleteRoom and that bannedUser is defined (or truthy) before calling deleteUser,
or wrap each cleanup call in a try/catch to swallow errors so teardown is
resilient to partial setup failures.
- Around line 216-220: Remove the inline implementation comments in the test
block surrounding the group invite and ban requests: delete the "// Add user
then ban them" and "// Create invite link for the room" comments that sit above
the calls to request.post(api('groups.invite')).set(credentials).send({ roomId:
room._id, userId: bannedUser._id }) and
request.post(api('rooms.banUser')).set(credentials).send({ roomId: room._id,
userId: bannedUser._id }); the test steps and variable names (room, bannedUser,
api('groups.invite'), api('rooms.banUser')) are already self-descriptive so
simply remove those two comment lines.
- Line 224: Change the invite creation payload to request a single-use token so
the regression asserts non-consumption strictly: in the test where you call
.send({ rid: room._id, days: 1, maxUses: 10 }) update maxUses to 1 (i.e.,
.send({ rid: room._id, days: 1, maxUses: 1 })) and ensure any related assertions
expecting token use counts remain consistent with a single-use token.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cfce5d15-dc65-4e0e-b46b-2182964e12b9

📥 Commits

Reviewing files that changed from the base of the PR and between 1a56d92 and 5b885be.

📒 Files selected for processing (2)
  • apps/meteor/tests/end-to-end/api/invites.ts
  • docs/features/ban-user.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 🔨 Test Storybook / Test Storybook
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 📦 Meteor Build (coverage)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/end-to-end/api/invites.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.
📚 Learning: 2026-03-15T14:31:23.493Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39647
File: apps/meteor/app/api/server/v1/users.ts:891-899
Timestamp: 2026-03-15T14:31:23.493Z
Learning: In RocketChat/Rocket.Chat, `IUser.inactiveReason` in `packages/core-typings/src/IUser.ts` is typed as `'deactivated' | 'pending_approval' | 'idle_too_long'` (optional, no `null`), but the database stores `null` for newly created users. The Typia-generated `$ref: '#/components/schemas/IUser'` schema therefore correctly rejects `null` for `inactiveReason`. This causes the test "should create a new user with default roles" to fail when response validation is active (TEST_MODE). The fix is to add `| null` to `inactiveReason` in core-typings and rebuild Typia schemas in a separate PR. Do not flag this test failure as a bug introduced by the users.create OpenAPI migration (PR `#39647`). Do not suggest inlining a custom schema to work around it, as migration rules require using `$ref` when a Typia schema exists.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-16T11:57:17.987Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 39657
File: apps/meteor/tests/end-to-end/apps/app-resolve-visitor.ts:43-45
Timestamp: 2026-03-16T11:57:17.987Z
Learning: In `apps/meteor/tests/end-to-end/apps/app-resolve-visitor.ts`, `externalIds` lookups are namespaced per `app.id`. Because `cleanupApps()` is called before each test run and a fresh app is installed (giving a new unique `app.id`), fixed `userId` strings like `'nonexistent-id'` in null-path tests are safe and cannot collide with stale visitor records from previous runs. Do not flag these as needing unique/random values.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-12T10:26:26.697Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 39340
File: apps/meteor/app/api/server/v1/im.ts:1349-1398
Timestamp: 2026-03-12T10:26:26.697Z
Learning: In `apps/meteor/app/api/server/v1/im.ts` (PR `#39340`), the `DmEndpoints` type intentionally includes temporary stub entries for `/v1/im.kick`, `/v1/dm.kick`, `/v1/im.leave`, and `/v1/dm.leave` (using `DmKickProps` and `DmLeaveProps`) even though no route handlers exist for them yet. These stubs were added to preserve type compatibility after removing the original `DmLeaveProps` and related files. They are planned for cleanup in a follow-up PR. Do not flag these as missing implementations when reviewing this file until the follow-up is merged.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-14T14:58:58.834Z
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
  • docs/features/ban-user.md
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/tests/end-to-end/api/invites.ts
📚 Learning: 2026-03-11T22:04:20.529Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 39545
File: apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts:59-61
Timestamp: 2026-03-11T22:04:20.529Z
Learning: In `apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts`, the `msg.u._id === uid` early-return in the `streamNewMessage` handler is intentional: the "New messages" indicator is designed to notify about messages from other users only. Self-sent messages — including those sent from a different session/device — are always skipped, by design. Do not flag this as a multi-session regression.

Applied to files:

  • docs/features/ban-user.md
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • docs/features/ban-user.md
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • docs/features/ban-user.md
🪛 LanguageTool
docs/features/ban-user.md

[style] ~62-~62: The noun “invitation” is usually used instead of ‘invite’ in formal writing.
Context: ...ents When a Matrix homeserver sends an invite for a user who is banned locally: - `ha...

(AN_INVITE)

🔇 Additional comments (1)
apps/meteor/tests/end-to-end/api/invites.ts (1)

234-257: Good coverage of the unban-before-reinvite flow.

The new assertions correctly enforce error-user-is-banned before unban and successful token use after unban.

@ggazzo ggazzo merged commit f21ed3a into develop Apr 8, 2026
45 checks passed
@ggazzo ggazzo deleted the fix/test-reinvite-banned-user-requires-unban branch April 8, 2026 18:25
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Apr 8, 2026
@ggazzo
Copy link
Copy Markdown
Member Author

ggazzo commented Apr 8, 2026

/patch

@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Apr 8, 2026

Pull request #40092 added to Project: "Patch 8.3.1"

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

Labels

stat: QA assured Means it has been tested and approved by a company insider type: bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants