Thanks to visit codestin.com
Credit goes to github.com

Skip to content

chore: Enforce username over users inside endpoint context#39266

Merged
ggazzo merged 12 commits intodevelopfrom
chore/username-api
Mar 3, 2026
Merged

chore: Enforce username over users inside endpoint context#39266
ggazzo merged 12 commits intodevelopfrom
chore/username-api

Conversation

@ggazzo
Copy link
Member

@ggazzo ggazzo commented Mar 3, 2026

It's crucial to enforce a stricter typing for the user object, particularly around the username field. Initially, the username was optional to accommodate user registration flows that don't require a username. However, within the core application logic, users without a username should not perform critical actions (like sending messages, inviting others, etc.). Thus, this stricter typing ensures we catch these cases at compile time. By propagating this type safety across the codebase, we reduce repetitive runtime checks, streamlining development and increasing confidence in user actions.

This pull request introduces improvements to API authentication handling, specifically around user objects and username requirements. The main change is the addition of a new option, userWithoutUsername, which allows certain API routes to accept users without a username property. This enables more flexible authentication scenarios, such as login routes or anonymous access, while ensuring stricter type safety and runtime validation elsewhere. Several type definitions and runtime checks are updated to reflect this change, and usages of this.user.username! are made safer throughout the codebase.

Authentication and User Handling Improvements:

  • Added a new userWithoutUsername option to API route definitions, allowing some routes to accept users without a username property. This is used, for example, in the login route. [1] [2] [3]
  • Updated TypeScript type definitions (ActionThis, TypedThis) to conditionally require the username property on the user object based on the userWithoutUsername option. [1] [2]
  • Added a runtime type guard and check in ApiClass.ts to ensure that, unless userWithoutUsername is set, authenticated users must have a username. Unauthorized requests without a username now throw an error. [1] [2]

Codebase Safety and Consistency:

  • Replaced unsafe usages of this.user.username! with safer accesses to this.user.username in all API route implementations, ensuring compatibility with the new type definitions. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

Minor Code Quality Improvements:

  • Simplified type casts and method usages in ApiClass.ts for better readability and maintainability. [1] [2] [3]

Proposed changes (including videos or screenshots)

Issue(s)

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • New Features

    • Login and selected routes can now accept users who don’t have a username.
  • Improvements

    • Authenticated routes require a username by default unless explicitly opted out.
    • Audit and analytics records now handle missing usernames without forcing a value.
  • Bug Fixes

    • After changing your username, the app reloads to ensure updated profile data is applied.

Task: ARCH-2024

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Mar 3, 2026

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Mar 3, 2026

⚠️ No Changeset found

Latest commit: 86e63ed

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
Contributor

coderabbitai bot commented Mar 3, 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

Adds a userWithoutUsername route option and conditional typings; enforces at runtime that authenticated users must have a username unless the option is set; removes non-null assertions for this.user.username across API handlers; simplifies internal type casts and uses direct method symbols.

Changes

Cohort / File(s) Summary
Core API framework
apps/meteor/app/api/server/definition.ts, apps/meteor/app/api/server/ApiClass.ts
Add userWithoutUsername?: boolean to route options; update conditional ActionThis/TypedThis typings to require username unless exempt; add runtime guard rejecting authenticated users without username unless userWithoutUsername is true; remove unnecessary casts.
Route registrations
apps/meteor/app/api/server/v1/misc.ts, apps/meteor/app/api/server/v1/users.ts
Mark specific routes with userWithoutUsername: true (e.g., me, method.call routes, users.updateOwnBasicInfo, users.getUsernameSuggestion) to allow users without username.
Username usage / audits
apps/meteor/app/api/server/v1/assets.ts, apps/meteor/app/api/server/v1/settings.ts, apps/meteor/app/api/server/v1/videoConference.ts, apps/meteor/app/livechat/.../appearance.ts, apps/meteor/app/livechat/server/api/v1/integration.ts, apps/meteor/ee/server/api/licenses.ts
Remove non-null assertions (this.user.username!, this.user.type!) and pass this.user.username/this.user.type directly to audit and downstream calls, permitting undefined where previously asserted non-null.
Client UI
apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx
After successful username registration, invalidate users.info cache and trigger a full page reload.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Router as "API Router"
    participant ApiClass as "ApiClass (auth)"
    participant Action as "Route Action"
    participant AuditDB as "Audit/DB"

    Client->>Router: HTTP request
    Router->>ApiClass: dispatch request
    ApiClass->>ApiClass: authenticate user
    alt authRequired && not userWithoutUsername
        ApiClass->>ApiClass: ensure user.username present
        ApiClass-->>Client: 401 Unauthorized (if missing)
    end
    ApiClass->>Action: invoke action (this.user may lack username)
    Action->>AuditDB: updateAuditedByUser(username: this.user.username)
    Action-->>Client: success response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

type: chore

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes a minor out-of-scope addition: RegisterUsername.tsx adds a full page reload on successful username update, which is not mentioned in the linked issue requirements and goes beyond the core objective of username enforcement. Review and justify the page reload addition in RegisterUsername.tsx or move it to a separate PR if unrelated to username enforcement in endpoint context.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Enforce username over users inside endpoint context' clearly and specifically describes the main change of the PR: implementing username enforcement with the new userWithoutUsername option for API endpoint authentication.
Linked Issues check ✅ Passed The code changes comprehensively implement all objectives: new userWithoutUsername option added [misc.ts, users.ts, definition.ts], TypeScript types updated to conditionally require username [definition.ts], runtime validation in ApiClass.ts enforces username unless option set, and unsafe non-null assertions replaced with safe accesses across route implementations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 force-pushed the chore/username-api branch from af3651b to 7d48050 Compare March 3, 2026 01:44
@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.89%. Comparing base (b7ff7b2) to head (86e63ed).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #39266      +/-   ##
===========================================
+ Coverage    70.85%   70.89%   +0.03%     
===========================================
  Files         3208     3208              
  Lines       113431   113432       +1     
  Branches     20542    20549       +7     
===========================================
+ Hits         80376    80421      +45     
+ Misses       31004    30961      -43     
+ Partials      2051     2050       -1     
Flag Coverage Δ
e2e 60.36% <100.00%> (+<0.01%) ⬆️
e2e-api 48.81% <ø> (+1.04%) ⬆️
unit 71.58% <ø> (+0.01%) ⬆️

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.

@ggazzo ggazzo added this to the 8.3.0 milestone Mar 3, 2026
@ggazzo ggazzo marked this pull request as ready for review March 3, 2026 14:44
@ggazzo ggazzo requested review from a team as code owners March 3, 2026 14:44
@coderabbitai coderabbitai bot added type: feature Pull requests that introduces new feature area: authentication labels Mar 3, 2026
Copy link
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/app/api/server/ApiClass.ts (1)

829-857: Runtime username enforcement looks correct.

The type guard and check ensure authenticated users have a username unless the route explicitly opts out via userWithoutUsername. This aligns well with the updated type definitions.

Minor observation: the isUserWithUsername type guard is defined inside the action handler, meaning it's recreated on each request. Consider hoisting it to module scope for a minor efficiency gain.

,

♻️ Optional: Hoist type guard to module scope
+const isUserWithUsername = (user: IUser | null): user is Omit<IUser, 'username'> & Required<Pick<IUser, 'username'>> => {
+	return user !== null && typeof user === 'object' && 'username' in user && user.username !== undefined;
+};
+
 export class APIClass<TBasePath extends string = '', TOperations extends Record<string, unknown> = Record<string, never>> {

Then remove the inline definition at lines 830-832.

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

In `@apps/meteor/app/api/server/ApiClass.ts` around lines 829 - 857, The inline
type guard isUserWithUsername (user: IUser | null): user is Omit<IUser,
'username'> & Required<Pick<IUser, 'username'>>) should be hoisted to module
scope to avoid recreating it per request; move its declaration out of the action
handler into the top-level of the module, export or keep it private as needed,
then remove the inline definition inside the handler and keep the existing
runtime check (if (user && !options.userWithoutUsername &&
!isUserWithUsername(user)) ...) unchanged so it uses the hoisted helper.
🤖 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/api/server/ApiClass.ts`:
- Around line 829-857: The inline type guard isUserWithUsername (user: IUser |
null): user is Omit<IUser, 'username'> & Required<Pick<IUser, 'username'>>)
should be hoisted to module scope to avoid recreating it per request; move its
declaration out of the action handler into the top-level of the module, export
or keep it private as needed, then remove the inline definition inside the
handler and keep the existing runtime check (if (user &&
!options.userWithoutUsername && !isUserWithUsername(user)) ...) unchanged so it
uses the hoisted helper.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c23512 and 757dee4.

📒 Files selected for processing (10)
  • apps/meteor/app/api/server/ApiClass.ts
  • apps/meteor/app/api/server/definition.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/api/server/v1/settings.ts
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/api/server/v1/videoConference.ts
  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/ee/server/api/licenses.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). (10)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: cubic · AI code reviewer
🧰 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/api/server/v1/settings.ts
  • apps/meteor/ee/server/api/licenses.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/app/api/server/v1/videoConference.ts
  • apps/meteor/app/api/server/definition.ts
  • apps/meteor/app/api/server/ApiClass.ts
🧠 Learnings (19)
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.

Applied to files:

  • apps/meteor/app/api/server/v1/settings.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/api/server/v1/settings.ts
  • apps/meteor/ee/server/api/licenses.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/app/api/server/v1/videoConference.ts
  • apps/meteor/app/api/server/definition.ts
📚 Learning: 2025-11-07T14:50:33.544Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37423
File: packages/i18n/src/locales/en.i18n.json:18-18
Timestamp: 2025-11-07T14:50:33.544Z
Learning: Rocket.Chat settings: in apps/meteor/ee/server/settings/abac.ts, the Abac_Cache_Decision_Time_Seconds setting uses invalidValue: 0 as the fallback when ABAC is unlicensed. With a valid license, admins can still set the value to 0 to intentionally disable the ABAC decision cache.

Applied to files:

  • apps/meteor/app/api/server/v1/settings.ts
  • apps/meteor/ee/server/api/licenses.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/settings.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/api/server/v1/videoConference.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/settings.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/api/server/v1/videoConference.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/api/server/v1/settings.ts
  • apps/meteor/ee/server/api/licenses.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/app/api/server/v1/videoConference.ts
  • apps/meteor/app/api/server/definition.ts
  • apps/meteor/app/api/server/ApiClass.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/api/server/v1/settings.ts
  • apps/meteor/ee/server/api/licenses.ts
  • apps/meteor/app/api/server/v1/assets.ts
  • apps/meteor/app/api/server/v1/users.ts
  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/app/api/server/v1/videoConference.ts
  • apps/meteor/app/api/server/definition.ts
  • apps/meteor/app/api/server/ApiClass.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/api/server/v1/assets.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
📚 Learning: 2026-03-03T11:11:45.505Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 39230
File: apps/meteor/app/api/server/v1/chat.ts:214-222
Timestamp: 2026-03-03T11:11:45.505Z
Learning: In apps/meteor/server/lib/moderation/reportMessage.ts, the reportMessage function validates that description is not empty or whitespace-only with `if (!description.trim())`. When migrating the chat.reportMessage endpoint to OpenAPI, adding minLength validation to the schema preserves this existing behavior.

Applied to files:

  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/livechat/server/api/v1/integration.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/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/app/api/server/ApiClass.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.

Applied to files:

  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
  • apps/meteor/app/api/server/v1/videoConference.ts
📚 Learning: 2026-02-24T19:36:55.089Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').

Applied to files:

  • apps/meteor/app/livechat/imports/server/rest/appearance.ts
  • apps/meteor/app/livechat/server/api/v1/integration.ts
📚 Learning: 2026-01-26T18:26:01.279Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38227
File: apps/meteor/app/api/server/router.ts:44-49
Timestamp: 2026-01-26T18:26:01.279Z
Learning: In apps/meteor/app/api/server/router.ts, when retrieving bodyParams and queryParams from the Hono context via c.get(), do not add defensive defaults (e.g., ?? {}). The code should fail fast if these parameters are missing, as endpoint handlers expect them to be present and breaking here helps surface parsing problems rather than hiding them.

Applied to files:

  • apps/meteor/app/api/server/v1/misc.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: The im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). Constructing slug-like identifiers like `user2${Users.userE2EE.data.username}` doesn't work for this endpoint.

Applied to files:

  • apps/meteor/app/api/server/v1/videoConference.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: In Rocket.Chat test files, the im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). It does not accept slug-like constructions such as concatenating usernames together.

Applied to files:

  • apps/meteor/app/api/server/v1/videoConference.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/api/server/v1/videoConference.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/api/server/v1/videoConference.ts
📚 Learning: 2025-09-15T06:21:00.139Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 36868
File: apps/meteor/app/apps/server/bridges/serverEndpoints.ts:35-48
Timestamp: 2025-09-15T06:21:00.139Z
Learning: In ServerEndpointsBridge.ts, the permission model distinguishes between token pass-through and true impersonation: `server-endpoints.call` is required for all endpoint access, while `server-endpoints.impersonate` is only required when `info.user.id` is provided without `info.user.token` (lines 48-53), meaning the bridge needs to mint a token. When both user ID and token are provided, it's considered legitimate credential usage, not impersonation.

Applied to files:

  • apps/meteor/app/api/server/definition.ts
📚 Learning: 2025-09-15T13:10:30.049Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 36868
File: packages/http-router/src/Router.ts:416-425
Timestamp: 2025-09-15T13:10:30.049Z
Learning: In packages/http-router/src/Router.ts, the dispatch() method's use of replaceAll('//', '/') on the full path is acceptable because URL normalization and query string handling is performed by the caller function before dispatch() is invoked.

Applied to files:

  • apps/meteor/app/api/server/ApiClass.ts
🧬 Code graph analysis (1)
apps/meteor/app/api/server/v1/videoConference.ts (1)
apps/meteor/app/authorization/server/functions/canSendMessage.ts (1)
  • canSendMessageAsync (54-66)
🔇 Additional comments (20)
apps/meteor/ee/server/api/licenses.ts (1)

59-64: LGTM!

Removing the non-null assertion is safe here. Since this route has authRequired: true without userWithoutUsername, the runtime check in ApiClass.ts guarantees username is present before this code executes.

apps/meteor/app/api/server/definition.ts (3)

113-113: LGTM!

The userWithoutUsername option is correctly added to both union arms of SharedOptions, ensuring it's available regardless of which branch of the type is used.

Also applies to: 132-132


218-234: LGTM!

The conditional typing for user in ActionThis correctly handles all authentication scenarios:

  • authRequired: true → user is non-optional with username conditional on userWithoutUsername
  • authOrAnonRequired: true → user is optional with same username conditional
  • Default → user is optional with same conditional

321-327: LGTM!

The TypedThis user typing mirrors the ActionThis pattern, maintaining consistency across both typing utilities.

apps/meteor/app/api/server/ApiClass.ts (3)

279-279: LGTM!

The explicit cast to SuccessResult<T> was redundant since the object literal already satisfies the type.


1085-1087: LGTM!

The login route correctly sets userWithoutUsername: true since users may authenticate before having a username configured (e.g., during initial login flows or OAuth scenarios).


802-803: LGTM!

Simplifying the action assignment and router registration by removing unnecessary intermediate casting improves readability.

Also applies to: 965-965

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

213-218: LGTM!

Removing the non-null assertion is safe. The route requires authentication and doesn't opt into userWithoutUsername, so the runtime enforcement guarantees username is present.

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

31-35: LGTM!

Removing the non-null assertions is safe. For username, the runtime check guarantees its presence. For type, the canSendMessageAsync function accepts IUser['type'] which already accounts for its optionality.

apps/meteor/app/livechat/imports/server/rest/appearance.ts (1)

98-103: LGTM!

Removing the non-null assertion is safe here. The route's authRequired: true without userWithoutUsername ensures username presence at runtime.

apps/meteor/app/api/server/v1/assets.ts (2)

40-45: LGTM!

Safe removal of non-null assertion due to runtime username enforcement.


77-82: LGTM!

Same as above - runtime enforcement guarantees username presence.

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

112-117: LGTM!

The removal of the || '' fallback is safe. Since this route has authRequired: true without userWithoutUsername, the runtime now guarantees username presence, making the fallback unnecessary.


143-152: LGTM!

Adding userWithoutUsername: true is appropriate for users.updateOwnBasicInfo since users may be setting their username for the first time through this endpoint.


924-934: LGTM!

Adding userWithoutUsername: true to users.getUsernameSuggestion is correct - this endpoint's primary use case is for users who don't yet have a username and need a suggestion.

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

54-59: Audit actor handling is correctly aligned with the new route typing.

Line 56 now uses this.user.username directly, which is appropriate here since this route remains authRequired: true without userWithoutUsername.

apps/meteor/app/api/server/v1/misc.ts (4)

172-175: me route option update is consistent with username-optional auth flows.

Line 174 correctly opts this authenticated endpoint into userWithoutUsername.


472-476: method.call/:method now explicitly supports authenticated users without usernames.

Line 475 is a good fit for this endpoint’s auth model and current handler usage.


535-539: method.callAnon/:method option change is safely applied.

Line 538 keeps this route aligned with the new username-optional context handling.


668-673: Audit payload updates are correct without non-null assertions.

Lines 670 and 690 now rely on route/user context typing directly, which is cleaner and still consistent with authenticated enforcement on this endpoint.

Also applies to: 688-693

Copy link
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 10 files

@ggazzo ggazzo added type: chore and removed area: authentication type: feature Pull requests that introduces new feature labels Mar 3, 2026
@ggazzo
Copy link
Member Author

ggazzo commented Mar 3, 2026

/jira ARCH-2021

Copy link
Contributor

Copilot AI commented Mar 3, 2026

@ggazzo I've opened a new pull request, #39292, to work on those changes. Once the pull request is ready, I'll request review from you.

…finition (#39292)

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: ggazzo <[email protected]>
@pierre-lehnen-rc pierre-lehnen-rc requested a review from a team as a code owner March 3, 2026 17:49
Copy link
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 `@apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx`:
- Around line 76-77: In RegisterUsername.tsx remove the inline implementation
comment immediately preceding the call to location.reload() and leave the
location.reload() call unchanged; locate the comment near the
registration/onLogin retry logic in the RegisterUsername component and delete
that single-line comment so only the existing location.reload() remains.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8af5b98 and 727bcd6.

📒 Files selected for processing (1)
  • apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx
📜 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: 📦 Build Packages
  • GitHub Check: cubic · AI code reviewer
  • 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/client/views/root/MainLayout/RegisterUsername.tsx

Comment on lines +76 to +77
// Reload to redo any onLogin request that may have failed without an username
location.reload();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove inline implementation comment on Line 76; keep the reload call.

The inline comment at Line 76 violates the repository rule for TS/TSX implementation code. You can keep location.reload() at Line 77 and drop the comment.

Suggested diff
-			// Reload to redo any onLogin request that may have failed without an username
 			location.reload();

As per coding guidelines, **/*.{ts,tsx,js}: "Avoid code comments in the implementation".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Reload to redo any onLogin request that may have failed without an username
location.reload();
location.reload();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/views/root/MainLayout/RegisterUsername.tsx` around lines
76 - 77, In RegisterUsername.tsx remove the inline implementation comment
immediately preceding the call to location.reload() and leave the
location.reload() call unchanged; locate the comment near the
registration/onLogin retry logic in the RegisterUsername component and delete
that single-line comment so only the existing location.reload() remains.

Copy link
Contributor

Copilot AI commented Mar 3, 2026

@ggazzo I've opened a new pull request, #39303, to work on those changes. Once the pull request is ready, I'll request review from you.

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: ggazzo <[email protected]>
Copy link
Contributor

Copilot AI commented Mar 3, 2026

@ggazzo I've opened a new pull request, #39306, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/meteor/app/api/server/ApiClass.ts (1)

806-812: ⚠️ Potential issue | 🟠 Major

Use merged endpoint options for the username bypass check.

_options contains the effective route/method options, but Line 855 checks options.userWithoutUsername. This can incorrectly block legacy addRoute endpoints that set userWithoutUsername in the method config.

Suggested fix
-						if (user && !options.userWithoutUsername && !isUserWithUsername(user)) {
+						if (user && !_options.userWithoutUsername && !isUserWithUsername(user)) {
 							throw new Meteor.Error('error-unauthorized', 'Users must have a username');
 						}

Also applies to: 855-857

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

In `@apps/meteor/app/api/server/ApiClass.ts` around lines 806 - 812, The route
username-bypass check is reading the original method config
(`options.userWithoutUsername`) instead of the merged effective options in
`_options`, so legacy endpoints that set `userWithoutUsername` in method-level
config can be mis-blocked; update the check(s) that reference
`options.userWithoutUsername` (around the username bypass logic) to use
`_options.userWithoutUsername` (and any other places that read `options.*` after
merging `extraOptions` from `operations[method]`) so the code uses the merged
endpoint options when deciding whether to bypass username enforcement.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/meteor/app/api/server/ApiClass.ts`:
- Around line 806-812: The route username-bypass check is reading the original
method config (`options.userWithoutUsername`) instead of the merged effective
options in `_options`, so legacy endpoints that set `userWithoutUsername` in
method-level config can be mis-blocked; update the check(s) that reference
`options.userWithoutUsername` (around the username bypass logic) to use
`_options.userWithoutUsername` (and any other places that read `options.*` after
merging `extraOptions` from `operations[method]`) so the code uses the merged
endpoint options when deciding whether to bypass username enforcement.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 727bcd6 and 82b0a4c.

📒 Files selected for processing (1)
  • apps/meteor/app/api/server/ApiClass.ts
📜 Review details
🧰 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/api/server/ApiClass.ts
🧠 Learnings (7)
📚 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/api/server/ApiClass.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/api/server/ApiClass.ts
📚 Learning: 2026-03-03T11:11:45.505Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 39230
File: apps/meteor/app/api/server/v1/chat.ts:214-222
Timestamp: 2026-03-03T11:11:45.505Z
Learning: In apps/meteor/server/lib/moderation/reportMessage.ts, the reportMessage function validates that description is not empty or whitespace-only with `if (!description.trim())`. When migrating the chat.reportMessage endpoint to OpenAPI, adding minLength validation to the schema preserves this existing behavior.

Applied to files:

  • apps/meteor/app/api/server/ApiClass.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/api/server/ApiClass.ts
📚 Learning: 2025-09-15T13:10:30.049Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 36868
File: packages/http-router/src/Router.ts:416-425
Timestamp: 2025-09-15T13:10:30.049Z
Learning: In packages/http-router/src/Router.ts, the dispatch() method's use of replaceAll('//', '/') on the full path is acceptable because URL normalization and query string handling is performed by the caller function before dispatch() is invoked.

Applied to files:

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

1085-1088: Login opt-out is correctly scoped.

Allowing userWithoutUsername: true on the login route is a good targeted exception and aligns with the new auth flow requirement.

Copy link
Contributor

Copilot AI commented Mar 3, 2026

@ggazzo I've opened a new pull request, #39307, to work on those changes. Once the pull request is ready, I'll request review from you.

… endpoint context type (#39306)

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: ggazzo <[email protected]>
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Mar 3, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Mar 3, 2026
@dionisio-bot dionisio-bot bot enabled auto-merge March 3, 2026 20:54
@ggazzo ggazzo disabled auto-merge March 3, 2026 20:54
@ggazzo ggazzo merged commit ea73f1c into develop Mar 3, 2026
86 of 89 checks passed
@ggazzo ggazzo deleted the chore/username-api branch March 3, 2026 20:55
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 stat: ready to merge PR tested and approved waiting for merge type: chore

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants