Skip to content

feat: email filtering in users.info and users.list endpoints#39989

Open
nazabucciarelli wants to merge 12 commits intodevelopfrom
feat/email-filter-user-endpoints
Open

feat: email filtering in users.info and users.list endpoints#39989
nazabucciarelli wants to merge 12 commits intodevelopfrom
feat/email-filter-user-endpoints

Conversation

@nazabucciarelli
Copy link
Copy Markdown
Contributor

@nazabucciarelli nazabucciarelli commented Mar 30, 2026

Proposed changes (including videos or screenshots)

  • users.info
    • UsersInfoParamsGet.ts validation schema was extended so that email is accepted as query parameter.
    • getFullUserData.ts was modified to support email lookup only if the user is looking for their own info or if the user view-full-other-user-info permission they would be able to look for other users by email.
  • users.list
    • UsersListParamsGET.ts was brought from this open PR, with the additional email property.
    • Implemented case-insensitive matching ($regex + $options: 'i') to align with database collation and users.info behavior.
    • The new email filter is intentionally injected into the nonEmptyQuery object rather than creating a separate database query. This is done to maintain backward compatibility with the legacy query parameter. By merging them, both explicit parameters and legacy queries can work together seamlessly until the legacy query parameter is officially removed.
  • Added tests covering cases where users.info and users.list are queried with email.
  • Removed obsolete test for the name query parameter on /api/v1/users.list. Manually verified that the endpoint completely ignores this parameter. Passing complex objects or regex operators (e.g., ?name[$regex]=...) returns the exact same full array as an empty request. Dropping this test removes dead code and prevents future confusion.

Issue(s)

CORE-1994 [Feature Request]: Add Email filter to users.info and users.list endpoints

Steps to test or reproduce

Using an API client and having two users: one with the view-full-other-user-info permission and the other one without it. We have to get the X-Auth-Token and X-User-Id values for each one and set them on the Headers section.

  • For users.info: Try fetching info of any user if the requester has the view-full-other-user-info permission, or if the requester doesn't, then try to fetch their own info (same email), and they shouldn't be able to fetch others data.
    Example URL:http://localhost:3000/api/v1/users.info?email=email@example.com
  • For users.list: In this case, only the user with the view-full-other-user-info is able to fetch by email and they must be able to see the emails property from each user in the response payload. Users without the permission, shouldn't be able to fetch by email (unauthorized) but they can call users.list without any query parameter, with the exception that the emails property isn't shown to them.
    Example URL: http://localhost:3000/api/v1/users.list?email=test@rocket.chat

Further comments

Summary by CodeRabbit

  • New Features

    • Add email-based search to user listing and user info endpoints so users can be queried by email (enforced by permission checks).
  • Tests

    • Add end-to-end tests for email-based user queries covering success, not-found, and permission-denied scenarios.

@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Mar 30, 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 Mar 30, 2026

🦋 Changeset detected

Latest commit: 415958c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/rest-typings Minor
@rocket.chat/meteor Minor
@rocket.chat/api-client Patch
@rocket.chat/core-services Patch
@rocket.chat/ddp-client Patch
@rocket.chat/http-router Patch
@rocket.chat/models Patch
@rocket.chat/ui-contexts Major
@rocket.chat/web-ui-registration Major
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/abac Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/livechat Patch
@rocket.chat/mock-providers Patch
@rocket.chat/cron Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/server-fetch Patch
@rocket.chat/ui-client Major
@rocket.chat/media-calls Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/fuselage-ui-kit Major
@rocket.chat/gazzodown Major
@rocket.chat/ui-avatar Major
@rocket.chat/ui-video-conf Major
@rocket.chat/ui-voip Major
@rocket.chat/core-typings Minor
@rocket.chat/apps Patch
@rocket.chat/model-typings Patch
@rocket.chat/license Patch
@rocket.chat/pdf-worker Patch

Not sure what this means? Click here to learn what changesets are.

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

@nazabucciarelli nazabucciarelli added this to the 8.4.0 milestone Mar 30, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

Walkthrough

Adds email-based lookup to users.info and email filtering to users.list; extends server full-user lookup to accept email searches and enforces permission gating; updates REST typings and exports; adds end-to-end tests and a changeset documenting package bumps.

Changes

Cohort / File(s) Summary
API Route Extensions
apps/meteor/app/api/server/v1/users.ts
users.info accepts email discriminator and calls the extended lookup; users.list uses isUsersListParamsGET, computes canViewFullOtherUserInfo once, enforces permission for email queries, and adds case-insensitive exact-match regex on emails.address.
User Lookup Function
apps/meteor/app/lib/server/functions/getFullUserData.ts
Renamed exported function to include OrEmail, added searchType: 'email', include emails in projections, treat matching caller email as "myself", route queries to findOneByEmailAddress, and deny email/importId searches when caller lacks view-full-other-user-info.
REST Type Definitions & Exports
packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts, packages/rest-typings/src/v1/users/UsersListParamsGET.ts, packages/rest-typings/src/index.ts
Added { email: string } discriminator to UsersInfoParamsGet; added UsersListParamsGET type, JSON schema, and isUsersListParamsGET validator; re-exported UsersListParamsGET at package root.
Tests
apps/meteor/tests/end-to-end/api/users.ts
Extended fixtures with emails; added end-to-end tests for users.info and users.list email scenarios (success, non-existent email, permission denial) and added permission setup/teardown.
Changeset
.changeset/soft-rats-behave.md
Recorded minor version bumps for @rocket.chat/rest-typings and @rocket.chat/meteor, noting the email-based user search additions.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant APIRoute as API Route (users.info / users.list)
    participant PermSys as Permission System
    participant UserLookup as User Lookup Function
    participant DB as Database

    rect rgba(100,150,200,0.5)
    note over Client,DB: Email-based user query flow
    Client->>APIRoute: GET /users.info?email=user@example.com
    APIRoute->>PermSys: check view-full-other-user-info
    alt permission granted
        PermSys-->>APIRoute: allowed
        APIRoute->>UserLookup: getFullUserDataBy...OrEmail(requesterId, 'user@example.com', 'email')
        UserLookup->>PermSys: check view-full-other-user-info (for email/importId)
        PermSys-->>UserLookup: allowed
        UserLookup->>DB: findOneByEmailAddress('user@example.com')
        DB-->>UserLookup: user record (includes emails)
        UserLookup-->>APIRoute: full user data
        APIRoute-->>Client: 200 + user
    else permission denied
        PermSys-->>APIRoute: denied
        APIRoute-->>Client: 400/403 (User not found / unauthorized)
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: adding email filtering capability to the users.info and users.list endpoints.
Linked Issues check ✅ Passed The PR fully addresses CORE-1994 requirements: email-based lookup in users.info, email filtering in users.list, permission gating via view-full-other-user-info, and comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the CORE-1994 objectives. Minor refactoring (like permission reuse in users.list) and test cleanup (removing obsolete test) are reasonable supporting changes.

✏️ 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.

@nazabucciarelli nazabucciarelli changed the title Feat/email filter user endpoints feat: email filtering in user.info and user.list endpoints Mar 30, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.53%. Comparing base (31d3419) to head (415958c).
⚠️ Report is 9 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #39989      +/-   ##
===========================================
+ Coverage    70.50%   70.53%   +0.02%     
===========================================
  Files         3267     3270       +3     
  Lines       116717   116766      +49     
  Branches     21069    21057      -12     
===========================================
+ Hits         82297    82364      +67     
+ Misses       32358    32346      -12     
+ Partials      2062     2056       -6     
Flag Coverage Δ
e2e 60.46% <ø> (-0.12%) ⬇️
e2e-api 49.04% <ø> (+0.98%) ⬆️
unit 70.96% <ø> (+0.06%) ⬆️

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.

@nazabucciarelli
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai bot added the type: feature Pull requests that introduces new feature label Mar 31, 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/meteor/app/lib/server/functions/getFullUserData.ts (1)

94-95: Remove inline implementation comment in this function.

This comment should be dropped to keep implementation code comment-free.

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/app/lib/server/functions/getFullUserData.ts` around lines 94 -
95, Remove the inline implementation comment inside getFullUserData by deleting
the comment line that precedes the permission check; keep the conditional as-is:
if ((searchType === 'importId' && !canViewAllInfo) || (searchType === 'email' &&
!canViewAllInfo)) { ... } so the logic using searchType and canViewAllInfo
remains unchanged and no implementation comments remain in the function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/api/server/v1/users.ts`:
- Around line 510-515: The email filter in users.list currently sets
nonEmptyQuery['emails.address'] to an exact string match of
this.queryParams.email which is case-sensitive; change it to perform a
case-insensitive full-string match by assigning a MongoDB regex (anchored with
^...$ and option 'i') to nonEmptyQuery['emails.address'], and ensure you escape
the user-supplied this.queryParams.email (add or reuse an
escapeRegExp/escapeRegex helper) to avoid regex injection; keep the existing
permission check (canViewFullOtherUserInfo) intact.

In `@apps/meteor/app/lib/server/functions/getFullUserData.ts`:
- Around line 91-96: In getFullUserData, the self-detection check that sets
"myself" (which currently compares the raw searchValue to caller.emails via
caller.emails?.some(...)) must apply the same normalization used for email
lookups before evaluating permission gating; normalize searchValue (trim +
toLowerCase) and compare against each caller.emails address normalized the same
way so that "myself" is true for case/spacing variants, then evaluate
canViewAllInfo and the subsequent permission early-return using that normalized
self-detection.

---

Nitpick comments:
In `@apps/meteor/app/lib/server/functions/getFullUserData.ts`:
- Around line 94-95: Remove the inline implementation comment inside
getFullUserData by deleting the comment line that precedes the permission check;
keep the conditional as-is: if ((searchType === 'importId' && !canViewAllInfo)
|| (searchType === 'email' && !canViewAllInfo)) { ... } so the logic using
searchType and canViewAllInfo remains unchanged and no implementation comments
remain in the function.
🪄 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: 567fa3cd-4993-4e11-a70b-21733d498066

📥 Commits

Reviewing files that changed from the base of the PR and between 4235cd9 and d67a345.

📒 Files selected for processing (7)
  • .changeset/soft-rats-behave.md
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/lib/server/functions/getFullUserData.ts
  • apps/meteor/tests/end-to-end/api/users.ts
  • packages/rest-typings/src/index.ts
  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.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). (4)
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 🔎 Code Check / Code Lint
  • 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:

  • packages/rest-typings/src/index.ts
  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • apps/meteor/app/api/server/v1/users.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
  • apps/meteor/app/lib/server/functions/getFullUserData.ts
  • apps/meteor/tests/end-to-end/api/users.ts
🧠 Learnings (26)
📓 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.
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38974
File: apps/meteor/app/api/server/v1/im.ts:220-221
Timestamp: 2026-02-24T19:09:09.561Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs for apps/meteor/app/api/server/v1 endpoints, maintainers prefer to avoid any logic changes; style-only cleanups (like removing inline comments) may be deferred to follow-ups to keep scope tight.
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39647
File: apps/meteor/app/api/server/v1/users.ts:710-757
Timestamp: 2026-03-15T14:31:28.969Z
Learning: In RocketChat/Rocket.Chat, the `UserCreateParamsPOST` type in `apps/meteor/app/api/server/v1/users.ts` (migrated from `packages/rest-typings/src/v1/users/UserCreateParamsPOST.ts`) intentionally has `fields: string` (non-optional) and `settings?: IUserSettings` without a corresponding AJV schema entry. This is a pre-existing divergence carried over verbatim from the original rest-typings source (PR `#39647`). Do not flag this type/schema misalignment during the OpenAPI migration review — it is tracked as a separate follow-up fix.
📚 Learning: 2026-03-16T21:50:42.118Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: .changeset/migrate-users-register-openapi.md:3-3
Timestamp: 2026-03-16T21:50:42.118Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs, removing endpoint types and validators from `rocket.chat/rest-typings` (e.g., `UserRegisterParamsPOST`, `/v1/users.register` entry) is the *required* migration pattern per RocketChat/Rocket.Chat-Open-API#150 Rule 7 ("No More rest-typings or Manual Typings"). The endpoint type is re-exposed via a module augmentation `.d.ts` file in the consuming package (e.g., `packages/web-ui-registration/src/users-register.d.ts`). This is NOT a breaking change — the correct changeset bump for `rocket.chat/rest-typings` in this scenario is `minor`, not `major`. Do not flag this as a breaking change during OpenAPI migration reviews.

Applied to files:

  • packages/rest-typings/src/index.ts
  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • apps/meteor/app/api/server/v1/users.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
📚 Learning: 2026-03-15T14:31:28.969Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39647
File: apps/meteor/app/api/server/v1/users.ts:710-757
Timestamp: 2026-03-15T14:31:28.969Z
Learning: In RocketChat/Rocket.Chat, the `UserCreateParamsPOST` type in `apps/meteor/app/api/server/v1/users.ts` (migrated from `packages/rest-typings/src/v1/users/UserCreateParamsPOST.ts`) intentionally has `fields: string` (non-optional) and `settings?: IUserSettings` without a corresponding AJV schema entry. This is a pre-existing divergence carried over verbatim from the original rest-typings source (PR `#39647`). Do not flag this type/schema misalignment during the OpenAPI migration review — it is tracked as a separate follow-up fix.

Applied to files:

  • packages/rest-typings/src/index.ts
  • .changeset/soft-rats-behave.md
  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
  • apps/meteor/app/lib/server/functions/getFullUserData.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:

  • packages/rest-typings/src/index.ts
  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • apps/meteor/app/api/server/v1/users.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
  • apps/meteor/app/lib/server/functions/getFullUserData.ts
  • apps/meteor/tests/end-to-end/api/users.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:

  • packages/rest-typings/src/index.ts
  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • apps/meteor/app/api/server/v1/users.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
  • apps/meteor/app/lib/server/functions/getFullUserData.ts
  • apps/meteor/tests/end-to-end/api/users.ts
📚 Learning: 2026-03-16T21:50:37.589Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: .changeset/migrate-users-register-openapi.md:3-3
Timestamp: 2026-03-16T21:50:37.589Z
Learning: For changes related to OpenAPI migrations in Rocket.Chat/OpenAPI, when removing endpoint types and validators from rocket.chat/rest-typings (e.g., UserRegisterParamsPOST, /v1/users.register) document this as a minor changeset (not breaking) per RocketChat/Rocket.Chat-Open-API#150 Rule 7. Note that the endpoint type is re-exposed via a module augmentation .d.ts in the consuming package (e.g., packages/web-ui-registration/src/users-register.d.ts). In reviews, ensure the changeset clearly states: this is a non-breaking change, the major version should not be bumped, and the changeset reflects a minor version bump. Do not treat this as a breaking change during OpenAPI migrations.

Applied to files:

  • .changeset/soft-rats-behave.md
📚 Learning: 2026-02-24T19:09:09.561Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38974
File: apps/meteor/app/api/server/v1/im.ts:220-221
Timestamp: 2026-02-24T19:09:09.561Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs for apps/meteor/app/api/server/v1 endpoints, maintainers prefer to avoid any logic changes; style-only cleanups (like removing inline comments) may be deferred to follow-ups to keep scope tight.

Applied to files:

  • .changeset/soft-rats-behave.md
📚 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:

  • .changeset/soft-rats-behave.md
📚 Learning: 2026-02-24T19:05:56.710Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 0
File: :0-0
Timestamp: 2026-02-24T19:05:56.710Z
Learning: Rocket.Chat repo context: When a workspace manifest on develop already pins a dependency version (e.g., packages/web-ui-registration → "rocket.chat/ui-contexts": "27.0.1"), a lockfile change in a feature PR that upgrades only that dependency’s resolution is considered a manifest-driven sync and can be kept, preferably as a small "chore: sync yarn.lock with manifests" commit.

Applied to files:

  • .changeset/soft-rats-behave.md
📚 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:

  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
  • apps/meteor/tests/end-to-end/api/users.ts
📚 Learning: 2026-03-16T23:33:15.721Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: apps/meteor/app/api/server/v1/users.ts:862-869
Timestamp: 2026-03-16T23:33:15.721Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs (e.g., PR `#39676` for users.register in apps/meteor/app/api/server/v1/users.ts), calls to `this.parseJsonQuery()` inside migrated handlers are intentionally preserved without adding a corresponding `query` AJV schema to the route options. Adding query-param schemas for the `fields`/`sort`/`query` parameters consumed by `parseJsonQuery()` is a separate cross-cutting concern shared by many endpoints (e.g., users.create, users.update, users.list) and is explicitly out of scope for individual endpoint migration PRs. Do not flag the absence of a `query` schema for `parseJsonQuery()` usage as a violation of OpenAPI/AJV contract during migration reviews.

Applied to files:

  • packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts
  • packages/rest-typings/src/v1/users/UsersListParamsGET.ts
📚 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/api/server/v1/users.ts
  • apps/meteor/tests/end-to-end/api/users.ts
📚 Learning: 2026-03-15T14:31:25.380Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39647
File: apps/meteor/app/api/server/v1/users.ts:710-757
Timestamp: 2026-03-15T14:31:25.380Z
Learning: Do not flag this type/schema misalignment in the OpenAPI/migration review for apps/meteor/app/api/server/v1/users.ts. The UserCreateParamsPOST type intentionally uses non-optional fields: fields: string and settings?: IUserSettings without an AJV schema entry, carried over from the original rest-typings (PR `#39647`). Treat this as a known pre-existing divergence and document it as a separate follow-up fix; do not block or mark it as a review issue during the migration.

Applied to files:

  • apps/meteor/app/api/server/v1/users.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/app/api/server/v1/users.ts
📚 Learning: 2026-02-23T17:53:06.802Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:06.802Z
Learning: During PR reviews that touch endpoint files under apps/meteor/app/api/server/v1, enforce strict scope: if a PR targets a specific endpoint (e.g., rooms.favorite), do not propose changes to unrelated endpoints (e.g., rooms.invite) unless maintainers explicitly request them. Focus feedback on the touched endpoint's behavior, API surface, and related tests; avoid broad cross-endpoint changes in the same PR unless requested.

Applied to files:

  • apps/meteor/app/api/server/v1/users.ts
📚 Learning: 2026-02-24T19:09:01.522Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38974
File: apps/meteor/app/api/server/v1/im.ts:220-221
Timestamp: 2026-02-24T19:09:01.522Z
Learning: In Rocket.Chat OpenAPI migration PRs for endpoints under apps/meteor/app/api/server/v1, avoid introducing logic changes. Only perform scope-tight changes that preserve behavior; style-only cleanups (e.g., removing inline comments) may be deferred to follow-ups to keep the migration PR focused.

Applied to files:

  • apps/meteor/app/api/server/v1/users.ts
📚 Learning: 2026-03-16T23:33:11.443Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: apps/meteor/app/api/server/v1/users.ts:862-869
Timestamp: 2026-03-16T23:33:11.443Z
Learning: In rockets OpenAPI/AJV migration reviews for RocketChat/Rocket.Chat, when reviewing migrations that involve apps/meteor/app/api/server/v1/users.ts, do not require or flag a missing query AJV schema for the fields consumed by parseJsonQuery() (i.e., fields, sort, query) as part of this endpoint's migration PR. The addition of global query-param schemas for parseJsonQuery() usage is a cross-cutting concern and out of scope for individual endpoint migrations. Only flag violations related to the specific scope of the migration, not the absence of a query schema for parseJsonQuery() in this file.

Applied to files:

  • apps/meteor/app/api/server/v1/users.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/app/lib/server/functions/getFullUserData.ts
  • apps/meteor/tests/end-to-end/api/users.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/users.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/users.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/users.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/users.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/users.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/users.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/users.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/users.ts
🔇 Additional comments (8)
packages/rest-typings/src/v1/users/UsersListParamsGET.ts (1)

4-23: Schema and runtime validator are well-scoped for the new email filter.

The UsersListParamsGET type and UsersListParamsGetSchema stay aligned and correctly constrain the allowed query surface for users.list.

packages/rest-typings/src/index.ts (1)

241-241: Root re-export is correct.

Line 241 properly exposes UsersListParamsGET from the package entrypoint, matching how this package is consumed elsewhere.

.changeset/soft-rats-behave.md (1)

1-6: Changeset classification looks appropriate.

The documented scope is additive and the minor bumps are consistent with the endpoint feature addition.

apps/meteor/app/api/server/v1/users.ts (1)

436-447: users.info email discriminator wiring is clean.

Line 436 through Line 447 correctly extends search dispatch and routes through the unified lookup function.

packages/rest-typings/src/v1/users/UsersInfoParamsGet.ts (1)

3-77: Email discriminator extension is correctly implemented.

The new type union member and matching AJV anyOf branch are consistent and keep the contract explicit.

apps/meteor/tests/end-to-end/api/users.ts (3)

15-15: Fixture/import updates are appropriate for email-based assertions.

Line 15 and Line 185 through Line 200 correctly prepare test data and permission utilities required by the new scenarios.

Also applies to: 185-200


1171-1250: /users.info email coverage is solid.

This block adds the key success, not-found, and permission-gated cases and restores permission state afterwards.


1613-1671: /users.list email filter tests cover the critical matrix.

The new cases validate single-match, empty-result, and forbidden access behavior with proper permission cleanup.

@RocketChat RocketChat deleted a comment from coderabbitai bot Mar 31, 2026
@nazabucciarelli nazabucciarelli marked this pull request as ready for review March 31, 2026 20:09
@nazabucciarelli nazabucciarelli requested review from a team as code owners March 31, 2026 20:09
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 7 files

Comment on lines +515 to +519
const escapedEmail = escapeRegExp(this.queryParams.email as string);
nonEmptyQuery['emails.address'] = {
$regex: `^${escapedEmail}$`,
$options: 'i',
};
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.

The PR description mentions using $regex + $options: 'i' to align with users.info behavior. However, users.info actually uses findOneByEmailAddress internally, which uses MongoDB collation:

// In Users.findOneByEmailAddress()
{ collation: { locale: 'en', strength: 2 } }

The current users.list implementation uses regex instead:

nonEmptyQuery['emails.address'] = {
    $regex: `^${escapedEmail}$`,
    $options: 'i',
};

To truly align with users.info, consider using collation in the aggregation:

nonEmptyQuery['emails.address'] = (this.queryParams.email as string).trim();

// And add collation to aggregate()
.aggregate([...], { collation: { locale: 'en', strength: 2 } })

Benefits:

  • Consistent behavior with users.info
  • Better index utilization for large deployments
  • Built-in trimming (already done in findOneByEmailAddress)

@nazabucciarelli nazabucciarelli changed the title feat: email filtering in user.info and user.list endpoints feat: email filtering in users.info and users.list endpoints Apr 1, 2026
…hat/Rocket.Chat into feat/email-filter-user-endpoints
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 (2)
apps/meteor/app/lib/server/functions/getFullUserData.ts (2)

101-102: Drop the inline comment and fold the guard.

The condition is readable on its own, and collapsing the duplicated !canViewAllInfo check removes the need for implementation prose here.

🧹 Proposed cleanup
-	// Only search for importId/email if the user has permission to view them
-	if ((searchType === 'importId' && !canViewAllInfo) || (searchType === 'email' && !canViewAllInfo)) {
+	if (!canViewAllInfo && (searchType === 'importId' || searchType === 'email')) {
 		return null;
 	}
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/app/lib/server/functions/getFullUserData.ts` around lines 101 -
102, Remove the inline comment and simplify the guard in getFullUserData by
folding the duplicated !canViewAllInfo check; replace the current condition that
tests (searchType === 'importId' && !canViewAllInfo) || (searchType === 'email'
&& !canViewAllInfo) with a single combined guard that first checks
!canViewAllInfo and then whether searchType is 'importId' or 'email' (i.e.,
!canViewAllInfo && (searchType === 'importId' || searchType === 'email')),
leaving the surrounding logic in the same function unchanged.

78-82: Tighten the helper signature to the supported search discriminant.

type: string and opts: any throw away the compiler guarantees already established at Line 87. If a future caller passes an unsupported discriminator, this helper silently falls back to findOneByIdOrUsername. Reuse a shared union and a typed options parameter so the dispatch stays exhaustive.

♻️ Proposed refactor
+type UserSearchType = 'id' | 'username' | 'importId' | 'email';
+
-const findTargetUser = (type: string, value: string, opts: any) => {
-	if (type === 'importId') return Users.findOneByImportId(value, opts);
-	if (type === 'email') return Users.findOneByEmailAddress(value, opts);
-	return Users.findOneByIdOrUsername(value, opts);
-};
+const findTargetUser = (
+	type: UserSearchType,
+	value: string,
+	opts: Parameters<typeof Users.findOneByEmailAddress>[1],
+) => {
+	switch (type) {
+		case 'importId':
+			return Users.findOneByImportId(value, opts);
+		case 'email':
+			return Users.findOneByEmailAddress(value, opts);
+		case 'id':
+		case 'username':
+			return Users.findOneByIdOrUsername(value, opts);
+	}
+};
 
 export async function getFullUserDataByIdOrUsernameOrImportIdOrEmail(
 	userId: string,
 	searchValue: string,
-	searchType: 'id' | 'username' | 'importId' | 'email',
+	searchType: UserSearchType,
 ): Promise<IUser | null> {

Also applies to: 84-87, 115-115

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

In `@apps/meteor/app/lib/server/functions/getFullUserData.ts` around lines 78 -
82, The helper findTargetUser currently accepts loose types (type: string, opts:
any) which loses compiler guarantees and allows unsupported discriminants;
change its signature to use the shared union type used elsewhere for the search
discriminant (e.g., 'importId' | 'email' | the existing shared union type name)
and a properly typed options parameter (reuse the same Options/FindOptions type
used by Users.findOneByImportId/findOneByEmailAddress/findOneByIdOrUsername).
Keep the switch/exhaustive dispatch across the three branches
(Users.findOneByImportId, Users.findOneByEmailAddress,
Users.findOneByIdOrUsername) so the compiler will error on unsupported
discriminants, and update the other similar helpers/uses (the other occurrences
mentioned) to use the same typed signature.
🤖 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/app/lib/server/functions/getFullUserData.ts`:
- Around line 101-102: Remove the inline comment and simplify the guard in
getFullUserData by folding the duplicated !canViewAllInfo check; replace the
current condition that tests (searchType === 'importId' && !canViewAllInfo) ||
(searchType === 'email' && !canViewAllInfo) with a single combined guard that
first checks !canViewAllInfo and then whether searchType is 'importId' or
'email' (i.e., !canViewAllInfo && (searchType === 'importId' || searchType ===
'email')), leaving the surrounding logic in the same function unchanged.
- Around line 78-82: The helper findTargetUser currently accepts loose types
(type: string, opts: any) which loses compiler guarantees and allows unsupported
discriminants; change its signature to use the shared union type used elsewhere
for the search discriminant (e.g., 'importId' | 'email' | the existing shared
union type name) and a properly typed options parameter (reuse the same
Options/FindOptions type used by
Users.findOneByImportId/findOneByEmailAddress/findOneByIdOrUsername). Keep the
switch/exhaustive dispatch across the three branches (Users.findOneByImportId,
Users.findOneByEmailAddress, Users.findOneByIdOrUsername) so the compiler will
error on unsupported discriminants, and update the other similar helpers/uses
(the other occurrences mentioned) to use the same typed signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2507f484-0e64-4ab3-80e8-248ebf47f2fe

📥 Commits

Reviewing files that changed from the base of the PR and between fa72905 and 415958c.

📒 Files selected for processing (1)
  • apps/meteor/app/lib/server/functions/getFullUserData.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). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • 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/lib/server/functions/getFullUserData.ts
🧠 Learnings (22)
📓 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.
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
📚 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/app/lib/server/functions/getFullUserData.ts
📚 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/lib/server/functions/getFullUserData.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/lib/server/functions/getFullUserData.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/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-03-15T14:31:28.969Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39647
File: apps/meteor/app/api/server/v1/users.ts:710-757
Timestamp: 2026-03-15T14:31:28.969Z
Learning: In RocketChat/Rocket.Chat, the `UserCreateParamsPOST` type in `apps/meteor/app/api/server/v1/users.ts` (migrated from `packages/rest-typings/src/v1/users/UserCreateParamsPOST.ts`) intentionally has `fields: string` (non-optional) and `settings?: IUserSettings` without a corresponding AJV schema entry. This is a pre-existing divergence carried over verbatim from the original rest-typings source (PR `#39647`). Do not flag this type/schema misalignment during the OpenAPI migration review — it is tracked as a separate follow-up fix.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-03-18T22:07:19.687Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38357
File: apps/meteor/app/apps/server/converters/departments.ts:59-70
Timestamp: 2026-03-18T22:07:19.687Z
Learning: In `apps/meteor/app/apps/server/converters/departments.ts`, the `convertAppDepartment` method uses non-null assertions (`!`) on `department.name`, `department.email`, and `department.offlineMessageChannelName` when constructing `newDepartment: ILivechatDepartment`. These fields are optional on `IAppsDepartment`, but the App framework flow guarantees their presence at the call site. Do not flag these non-null assertions as unsafe during code review.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-03-20T13:51:23.302Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 39553
File: apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:179-181
Timestamp: 2026-03-20T13:51:23.302Z
Learning: In `apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts`, the truthiness guards `...(integration.avatar && { avatar })`, `...(integration.emoji && { emoji })`, `...(integration.alias && { alias })`, and `...(integration.script && { script })` in the `$set` payload of `updateIncomingIntegration` are intentional. Empty-string values for these fields should NOT overwrite the stored value — only truthy values are persisted. Do not flag these as bugs preventing explicit clears.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.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/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-02-23T17:53:18.785Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-02-24T19:09:09.561Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38974
File: apps/meteor/app/api/server/v1/im.ts:220-221
Timestamp: 2026-02-24T19:09:09.561Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs for apps/meteor/app/api/server/v1 endpoints, maintainers prefer to avoid any logic changes; style-only cleanups (like removing inline comments) may be deferred to follow-ups to keep scope tight.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2025-10-16T21:09:51.816Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/keychain.ts:148-156
Timestamp: 2025-10-16T21:09:51.816Z
Learning: In the RocketChat/Rocket.Chat repository, only platforms with native crypto.randomUUID() support are targeted, so fallback implementations for crypto.randomUUID() are not required in E2EE or cryptographic code.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-03-06T18:10:23.330Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 39397
File: packages/gazzodown/src/code/CodeBlock.spec.tsx:47-68
Timestamp: 2026-03-06T18:10:23.330Z
Learning: In the RocketChat/Rocket.Chat `packages/gazzodown` package and more broadly, the HTML `<code>` element has an implicit ARIA role of `code` per WAI-ARIA 1.3, and `testing-library/dom` / jsdom supports it. Therefore, `screen.getByRole('code')` / `screen.findByRole('code')` correctly locates `<code>` elements without needing an explicit `role="code"` attribute. Do NOT flag `findByRole('code')` as invalid in future reviews.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-03-10T08:13:52.153Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 39414
File: apps/meteor/app/api/server/v1/rooms.ts:1241-1297
Timestamp: 2026-03-10T08:13:52.153Z
Learning: In the RocketChat/Rocket.Chat OpenAPI migration PRs for endpoints under apps/meteor/app/api/server/v1/rooms.ts, the pattern `ajv.compile<void>({...})` is intentionally used for the 200 response schema even when the endpoint returns `{ success: true }`. This is an established convention across all migrated endpoints (rooms.leave, rooms.favorite, rooms.delete, rooms.muteUser, rooms.unmuteUser). Do not flag this as a type mismatch during reviews of these migration PRs.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.ts
📚 Learning: 2026-03-16T23:33:15.721Z
Learnt from: amitb0ra
Repo: RocketChat/Rocket.Chat PR: 39676
File: apps/meteor/app/api/server/v1/users.ts:862-869
Timestamp: 2026-03-16T23:33:15.721Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs (e.g., PR `#39676` for users.register in apps/meteor/app/api/server/v1/users.ts), calls to `this.parseJsonQuery()` inside migrated handlers are intentionally preserved without adding a corresponding `query` AJV schema to the route options. Adding query-param schemas for the `fields`/`sort`/`query` parameters consumed by `parseJsonQuery()` is a separate cross-cutting concern shared by many endpoints (e.g., users.create, users.update, users.list) and is explicitly out of scope for individual endpoint migration PRs. Do not flag the absence of a `query` schema for `parseJsonQuery()` usage as a violation of OpenAPI/AJV contract during migration reviews.

Applied to files:

  • apps/meteor/app/lib/server/functions/getFullUserData.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/app/lib/server/functions/getFullUserData.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/lib/server/functions/getFullUserData.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/lib/server/functions/getFullUserData.ts
🔇 Additional comments (1)
apps/meteor/app/lib/server/functions/getFullUserData.ts (1)

89-99: Email self-lookup handling looks correct.

Normalizing the caller addresses before the permission decision keeps self lookups aligned with the case-insensitive email lookup path and avoids false denials on casing or surrounding whitespace.

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

Labels

type: feature Pull requests that introduces new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants