Skip to content

Conversation

@KevLehman
Copy link
Member

@KevLehman KevLehman commented Oct 29, 2025

Proposed changes (including videos or screenshots)

Issue(s)

https://rocketchat.atlassian.net/browse/ABAC-25

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • New Features

    • ABAC enforcement added to invite/add flows to block users who don't meet room attribute requirements.
  • Bug Fixes

    • Improved invite error handling with clearer, detailed messages for ABAC-related failures.
  • Tests

    • New end-to-end and unit tests covering ABAC invite/add behavior, mismatches, and recovery flows.
  • Chores

    • ABAC checks integrated into startup and a pre-join validation step added to invite/add processing.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Oct 29, 2025

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

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Oct 29, 2025

⚠️ No Changeset found

Latest commit: 54897f8

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 Oct 29, 2025

Walkthrough

Adds a CE no-op hook beforeAddUserToRoom, invokes it from single and bulk add flows, introduces an EE patch enforcing ABAC via Abac.checkUsernamesMatchAttributes, implements that Abac API method and interface, tightens invite command error handling, and adds unit and e2e tests covering ABAC invite/add behavior.

Changes

Cohort / File(s) Summary
Hook infra (CE)
apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts, apps/meteor/app/lib/server/functions/addUserToRoom.ts
Add CE hook beforeAddUserToRoom(usernames, room, actor?) (async no-op). addUserToRoom now computes inviterUser, calls a small patch helper then beforeAddUserToRoom.run(...); error handling preserved.
Bulk add entry
apps/meteor/server/methods/addAllUserToRoom.ts
Invoke beforeAddUserToRoom with all usernames and the room before creating subscriptions.
EE ABAC hook & loader
apps/meteor/ee/server/hooks/abac/beforeAddUserToRoom.ts, apps/meteor/ee/server/hooks/abac/index.ts, apps/meteor/ee/server/configuration/abac.ts
EE patch wraps the CE hook: filters valid usernames, checks license/setting/room type/attributes, then calls Abac.checkUsernamesMatchAttributes; index.ts imports the patch and abac.ts dynamically imports hooks at startup.
ABAC service & types
ee/packages/abac/src/index.ts, packages/core-services/src/types/IAbacService.ts
Add AbacService.checkUsernamesMatchAttributes(usernames, attributes): Promise<void> and declare it on IAbacService; implementation queries non-compliant usernames and throws MeteorError with details listing offending usernames.
Invite command error handling
apps/meteor/slashcommands-invite/server/server.ts
Replace catch ({ error }) with catch (e: unknown) and add guards for MeteorError and string-error objects; handle and broadcast ephemeral/i18n messages including serialized details.
Tests (unit & e2e)
ee/packages/abac/src/index.spec.ts, apps/meteor/tests/end-to-end/api/abac.ts
Unit tests expand mocks and add tests for checkUsernamesMatchAttributes and helpers; e2e tests exercise invite/add flows for ABAC-enabled vs non-ABAC rooms, covering blocking/unblocking scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AddFlow as addUserToRoom / addAllUserToRoom
    participant HookCE as beforeAddUserToRoom (CE)
    participant EEpatch as EE.beforeAddUserToRoom (patch)
    participant AbacSvc as AbacService
    participant RoomOps as Room Operations

    Client->>AddFlow: request to add user(s)
    AddFlow->>HookCE: invoke (usernames, room, inviter)

    alt EE patch loaded
        HookCE->>EEpatch: run prev() and await
        EEpatch->>AbacSvc: checkUsernamesMatchAttributes(usernames, room.abacAttributes)
        alt non-compliant found
            AbacSvc-->>EEpatch: throw MeteorError (details: [usernames])
            EEpatch-->>HookCE: propagate error
            HookCE-->>AddFlow: error
            AddFlow-->>Client: reject with message
        else all comply
            AbacSvc-->>EEpatch: resolve
            EEpatch-->>HookCE: resolve
        end
    else CE/no-op
        HookCE-->>AddFlow: resolve
    end

    AddFlow->>RoomOps: proceed to add members/subscriptions
    RoomOps-->>Client: success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay special attention to:
    • ABAC query construction and thrown MeteorError shape (error code, message, details array).
    • Correct propagation and usage of inviterUser and username arrays across addUserToRoom, addAllUserToRoom, and the EE patch.
    • Invite command error branching and ephemeral message formatting/serialization.
    • New tests' mocks/coverage, e2e setup/teardown reliability and flakiness.

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • tassoevan
  • ggazzo

Poem

🐇 I hopped through hooks to count each name,
asked ABAC kindly to guard the frame,
patched the flow and ran the test,
filtered users, did my best,
carrots checked — now open or tame. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Linked Issues check ❓ Inconclusive The pull request substantially implements the ABAC-25 requirements by: (1) creating a new beforeAddUserToRoom hook to validate ABAC attributes [beforeAddUserToRoom.ts], (2) adding the checkUsernamesMatchAttributes method to enforce ABAC rules [index.ts, IAbacService.ts], (3) integrating ABAC checks into addUserToRoom and addAllUserToRoom methods, (4) adding ABAC validation in the invite command, and (5) including end-to-end tests. However, coverage is partial: the PR addresses room.invite, room.addAll, and slash commands but does not demonstrably address all listed mechanisms (join codes, team auto-join, LDAP/AD sync, imports, Apps-Engine flows, or pre-join hooks like IPreRoomUserJoined), leaving some acceptance criteria unmet. Verify that the implementation covers all identified user-add mechanisms listed in ABAC-25 (join codes, team auto-join, LDAP/AD sync, imports, Apps-Engine flows, and pre-join hooks). If additional mechanisms require ABAC enforcement, create follow-up issues or extend this PR to address them comprehensively.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Update add/join methods to use abac rules' directly aligns with the primary objective of the pull request, which is to integrate ABAC enforcement into mechanisms that add or join users to private rooms. The title is concise, specific, and accurately represents the main change being implemented.
Out of Scope Changes check ✅ Passed All changes in the pull request are directly related to ABAC enforcement for add/join operations. The modifications include: new ABAC validation hooks, integration into addUserToRoom and addAllUserToRoom, error handling in the invite command, test coverage, and necessary type/interface updates. No unrelated refactoring, cleanup, or feature additions are present outside the scope of ABAC-25.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/join-prevent-obj

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 83a372f and 54897f8.

📒 Files selected for processing (1)
  • ee/packages/abac/src/index.spec.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • ee/packages/abac/src/index.spec.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:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-10-06T20:30:45.540Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/storage/storage.ts:101-122
Timestamp: 2025-10-06T20:30:45.540Z
Learning: In `packages/apps-engine/tests/test-data/storage/storage.ts`, the stub methods (updatePartialAndReturnDocument, updateStatus, updateSetting, updateAppInfo, updateMarketplaceInfo) intentionally throw "Method not implemented." Tests using these methods must stub them using `SpyOn` from the test library rather than relying on actual implementations.

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (test, page, expect) consistently

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements

Applied to files:

  • ee/packages/abac/src/index.spec.ts
⏰ 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 comments (1)
ee/packages/abac/src/index.spec.ts (1)

830-945: Comprehensive ABAC compliance coverage

Nice job exercising both the early-return branches and the failure path with the real MeteorError, and the cursor mock mirrors the production .map().toArray() pipeline so these tests lock the contract in place.


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.

@codecov
Copy link

codecov bot commented Oct 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.43%. Comparing base (3f5c8d4) to head (54897f8).
⚠️ Report is 1 commits behind head on feat/abac.

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##           feat/abac   #37339      +/-   ##
=============================================
+ Coverage      70.39%   70.43%   +0.03%     
=============================================
  Files           3050     3050              
  Lines         105153   105163      +10     
  Branches       18588    18596       +8     
=============================================
+ Hits           74022    74068      +46     
+ Misses         29174    29141      -33     
+ Partials        1957     1954       -3     
Flag Coverage Δ
e2e 57.45% <ø> (+0.04%) ⬆️
unit 72.07% <100.00%> (+0.03%) ⬆️

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

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

@KevLehman KevLehman marked this pull request as ready for review October 29, 2025 19:49
@KevLehman KevLehman requested a review from a team as a code owner October 29, 2025 19: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: 4

🧹 Nitpick comments (1)
ee/packages/abac/src/index.spec.ts (1)

823-884: Consider adding a test case for non-existent usernames.

The current tests cover compliant and non-compliant users, but don't test the scenario where a provided username doesn't exist in the database at all. This would help verify the expected behavior when invalid usernames are passed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 81c197b and 0400906.

📒 Files selected for processing (11)
  • apps/meteor/app/lib/server/functions/addUserToRoom.ts (2 hunks)
  • apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (1 hunks)
  • apps/meteor/app/slashcommands-invite/server/server.ts (1 hunks)
  • apps/meteor/ee/server/configuration/abac.ts (1 hunks)
  • apps/meteor/ee/server/hooks/abac/beforeAddUserToRoom.ts (1 hunks)
  • apps/meteor/ee/server/hooks/abac/index.ts (1 hunks)
  • apps/meteor/server/methods/addAllUserToRoom.ts (2 hunks)
  • apps/meteor/tests/end-to-end/api/abac.ts (1 hunks)
  • ee/packages/abac/src/index.spec.ts (3 hunks)
  • ee/packages/abac/src/index.ts (1 hunks)
  • packages/core-services/src/types/IAbacService.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing

Applied to files:

  • apps/meteor/app/slashcommands-invite/server/server.ts
📚 Learning: 2025-10-24T17:32:05.348Z
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.

Applied to files:

  • packages/core-services/src/types/IAbacService.ts
  • apps/meteor/ee/server/hooks/abac/beforeAddUserToRoom.ts
  • ee/packages/abac/src/index.ts
  • apps/meteor/tests/end-to-end/api/abac.ts
📚 Learning: 2025-10-27T14:38:46.994Z
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.

Applied to files:

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

Applied to files:

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

Applied to files:

  • apps/meteor/server/methods/addAllUserToRoom.ts
  • apps/meteor/ee/server/hooks/abac/index.ts
  • ee/packages/abac/src/index.ts
  • apps/meteor/app/lib/server/functions/addUserToRoom.ts
  • apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
PR: RocketChat/Rocket.Chat#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/server/methods/addAllUserToRoom.ts
  • apps/meteor/ee/server/hooks/abac/index.ts
  • apps/meteor/app/lib/server/functions/addUserToRoom.ts
  • apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • ee/packages/abac/src/index.spec.ts
  • apps/meteor/tests/end-to-end/api/abac.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases

Applied to files:

  • ee/packages/abac/src/index.spec.ts
  • apps/meteor/tests/end-to-end/api/abac.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • ee/packages/abac/src/index.spec.ts
  • apps/meteor/tests/end-to-end/api/abac.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (test, page, expect) consistently

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
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/abac.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use test.beforeAll() and test.afterAll() for setup and teardown

Applied to files:

  • apps/meteor/tests/end-to-end/api/abac.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
PR: RocketChat/Rocket.Chat#37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/lib/server/functions/addUserToRoom.ts
  • apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts
🧬 Code graph analysis (7)
packages/core-services/src/types/IAbacService.ts (1)
packages/core-typings/src/IAbacAttribute.ts (1)
  • IAbacAttributeDefinition (3-14)
apps/meteor/server/methods/addAllUserToRoom.ts (1)
apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (1)
  • beforeAddUserToRoom (4-6)
apps/meteor/ee/server/hooks/abac/beforeAddUserToRoom.ts (2)
apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (1)
  • beforeAddUserToRoom (4-6)
packages/core-services/src/index.ts (2)
  • License (164-164)
  • Abac (202-202)
ee/packages/abac/src/index.ts (1)
packages/core-typings/src/IAbacAttribute.ts (1)
  • IAbacAttributeDefinition (3-14)
apps/meteor/tests/end-to-end/api/abac.ts (3)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (22-98)
apps/meteor/tests/data/api-data.ts (2)
  • request (10-10)
  • credentials (39-42)
apps/meteor/tests/e2e/utils/create-target-channel.ts (1)
  • deleteRoom (48-50)
apps/meteor/app/lib/server/functions/addUserToRoom.ts (2)
apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (1)
  • beforeAddUserToRoom (4-6)
apps/meteor/lib/callbacks/beforeAddUserToRoom.ts (1)
  • beforeAddUserToRoom (5-5)
apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (2)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-255)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (22-98)
⏰ 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). (21)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 7.0 [legacy watchers] (5/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 7.0 [legacy watchers] (4/5) - Alpine (Official)
  • GitHub Check: 🔨 Test API (CE) / MongoDB 7.0 (1/1) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 5.0 (3/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 7.0 [legacy watchers] (2/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 7.0 [legacy watchers] (1/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 7.0 [legacy watchers] (3/5) - Alpine (Official)
  • GitHub Check: 🔨 Test API (CE) / MongoDB 5.0 (1/1) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 7.0 (1/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 5.0 (4/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 7.0 (2/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 7.0 (4/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 7.0 (3/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 5.0 (2/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 5.0 (2/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 5.0 (1/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 5.0 (3/4) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 5.0 (5/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 5.0 (1/5) - Alpine (Official)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 5.0 (4/5) - Alpine (Official)
  • GitHub Check: 🔨 Test API (EE) / MongoDB 5.0 (1/1) - Alpine (Official)
🔇 Additional comments (14)
apps/meteor/app/slashcommands-invite/server/server.ts (1)

76-84: Good approach to support both Error instances and legacy error objects.

The dual-path error handling maintains backward compatibility while supporting new Error instances that may be thrown by ABAC validation hooks. However, the Error instance handling has critical implementation issues (see next comment).

apps/meteor/ee/server/hooks/abac/index.ts (1)

1-1: LGTM!

The side-effect import pattern ensures the ABAC hook module is loaded and registered at initialization time, enabling ABAC validation for user additions.

apps/meteor/ee/server/configuration/abac.ts (1)

10-11: LGTM!

The dynamic import of ABAC hooks is properly sequenced after settings and permissions setup, ensuring the hooks are only loaded when the ABAC license is active.

apps/meteor/server/methods/addAllUserToRoom.ts (2)

9-9: LGTM!

The import enables pre-join ABAC validation for bulk user additions.


54-57: Pass the actor parameter to beforeAddUserToRoom and consider safer null handling.

The function receives userId as a parameter but omits it when calling beforeAddUserToRoom. The hook signature expects an actor parameter (line 4 of apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts shows _actor?: IUser), and the ABAC hook patches it to accept and forward this parameter. This should be:

await beforeAddUserToRoom(
	users.map((u) => u.username!),
	room,
	{ _id: userId } as IUser,
);

Additionally, while no undefined usernames were found empirically, the non-null assertion is defensive. Consider optional chaining or filtering falsy values instead: .filter((u) => u.username).map((u) => u.username).

⛔ Skipped due to learnings
Learnt from: Dnouv
PR: RocketChat/Rocket.Chat#37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).
Learnt from: Dnouv
PR: RocketChat/Rocket.Chat#37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.
Learnt from: Dnouv
PR: RocketChat/Rocket.Chat#37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
Learnt from: ricardogarim
PR: RocketChat/Rocket.Chat#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.
Learnt from: ricardogarim
PR: RocketChat/Rocket.Chat#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.
apps/meteor/app/lib/server/functions/addUserToRoom.ts (1)

15-15: LGTM!

The alias import distinguishes the patch-based hook from the callback-based hook, supporting the migration strategy.

apps/meteor/tests/end-to-end/api/abac.ts (1)

1415-1485: LGTM! Comprehensive test coverage for ABAC-based room access.

The test suite effectively validates:

  • Successful invites when user attributes match room requirements
  • Blocked invites when user lacks required attributes
  • Restored access after room attributes are removed

The test structure follows established patterns with proper setup and cleanup.

packages/core-services/src/types/IAbacService.ts (1)

20-20: LGTM!

The new method signature is clear and follows the interface pattern. The Promise<void> return type appropriately indicates that validation failures will be communicated via thrown errors.

apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (1)

1-6: LGTM!

The patchable hook provides a clean extension point for Enterprise Edition ABAC validation while remaining a no-op in Community Edition. The signature properly accommodates batch user validation with an optional actor parameter.

ee/packages/abac/src/index.spec.ts (2)

17-17: Mock setup looks good.

The Users.find mock is properly wired and consistent with existing mock patterns in this test file.

Also applies to: 41-43


885-937: Well-structured tests for the query builder.

The tests thoroughly verify that buildNonCompliantConditions constructs the correct MongoDB query structure for finding non-compliant users.

ee/packages/abac/src/index.ts (3)

432-443: Query construction logic is correct.

The MongoDB query structure properly identifies users who lack the required ABAC attributes using the $not + $elemMatch + $all pattern.


469-474: Address the TODO comment about error structure.

The comment questions whether returning non-compliant usernames via an error's details field is the right approach. This design decision should be resolved before merging.

Current implementation attaches details to a generic Error object, which works but isn't type-safe. Consider:

  1. Creating a custom error class with a typed details property
  2. Removing the TODO if you're confident in the current approach
  3. Logging details separately and using a generic error message

Which approach aligns with the project's error handling patterns?


445-480: Verify handling of non-existent usernames.

The current implementation queries for non-compliant users who exist in the database. If a username in the provided list doesn't exist at all, it won't be returned by the query and won't be flagged as non-compliant.

Is this the intended behavior? Should the method assume that callers have already validated that all usernames exist, or should it explicitly check for non-existent users?

If validation is the caller's responsibility, consider adding a JSDoc comment to document this assumption.

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

🧹 Nitpick comments (2)
apps/meteor/app/slashcommands-invite/server/server.ts (2)

88-91: Avoid empty backticks when details is invalid.

When e.details exists but isn't an array, line 88 sets details to an empty string, resulting in the i18n message receiving details: `\`\ ``. This renders as empty backticks in the UI.

Apply this diff to omit the details parameter entirely when invalid:

 				if (isErrorWithDetails(e)) {
-					const details = Array.isArray(e.details) ? e.details.join(', ') : '';
+					const details = e.details.join(', ');

 					void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
-						msg: i18n.t(e.message, { lng: settings.get('Language') || 'en', details: `\`${details}\`` }),
+						msg: i18n.t(e.message, { 
+							lng: settings.get('Language') || 'en', 
+							...(details && { details: `\`${details}\`` })
+						}),
 					});
 					return;
 				}

Note: If you apply the fix from the previous comment to strengthen isErrorWithDetails, the Array.isArray check at line 88 becomes redundant and can be removed as shown above.


86-112: Add fallback handling for unexpected error shapes.

If an error doesn't match either type guard, it's silently swallowed with no feedback to the user. This can create confusion when some invites fail without explanation.

Apply this diff to add a generic fallback:

 					if (isStringError(e)) {
 						const { error } = e;
 						if (error === 'error-federated-users-in-non-federated-rooms') {
 							void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
 								msg: i18n.t('You_cannot_add_external_users_to_non_federated_room', { lng: settings.get('Language') || 'en' }),
 							});
 						} else if (error === 'cant-invite-for-direct-room') {
 							void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
 								msg: i18n.t('Cannot_invite_users_to_direct_rooms', { lng: settings.get('Language') || 'en' }),
 							});
 						} else {
 							void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
 								msg: i18n.t(error, { lng: settings.get('Language') || 'en' }),
 							});
 						}
+					} else {
+						// Fallback for unexpected error shapes
+						void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
+							msg: i18n.t('Error_inviting_user', { 
+								lng: settings.get('Language') || 'en',
+								username: user.username || 'unknown'
+							}),
+						});
 					}
 				}
 			}),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 92f8b31 and 9fb3e96.

📒 Files selected for processing (1)
  • apps/meteor/app/slashcommands-invite/server/server.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing

Applied to files:

  • apps/meteor/app/slashcommands-invite/server/server.ts
⏰ 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

@KevLehman KevLehman requested a review from tassoevan October 29, 2025 20:52
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: 0

🧹 Nitpick comments (1)
apps/meteor/app/slashcommands-invite/server/server.ts (1)

13-19: Tighten the type guards to match their contracts.

isErrorWithDetails narrows to details: string[], but it currently only checks that details is an array. That lets arbitrary payloads through, breaks the guarantee these helpers promise, and forces the downstream Array.isArray recheck. Please require every entry to be a string. Likewise, add an explicit object check in isStringError before reading .error so the guard can’t succeed on primitives by accident. With stronger guards you can rely on the narrowing inside the catch block without additional defensive checks.

-function isErrorWithDetails(error: unknown): error is Error & { details: string[] } {
-	return error instanceof Error && Array.isArray((error as any).details);
-}
-
-function isStringError(error: unknown): error is { error: string } {
-	return typeof (error as any)?.error === 'string';
-}
+function isErrorWithDetails(error: unknown): error is Error & { details: string[] } {
+	if (!(error instanceof Error)) {
+		return false;
+	}
+	const { details } = error as { details?: unknown };
+	return Array.isArray(details) && details.every((detail) => typeof detail === 'string');
+}
+
+function isStringError(error: unknown): error is { error: string } {
+	return typeof error === 'object' && error !== null && typeof (error as any).error === 'string';
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9fb3e96 and d453c8b.

📒 Files selected for processing (1)
  • apps/meteor/app/slashcommands-invite/server/server.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.
⏰ 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

@KevLehman KevLehman force-pushed the feat/join-prevent-obj branch from d453c8b to b5d08f3 Compare October 30, 2025 16:26
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

♻️ Duplicate comments (1)
apps/meteor/app/slashcommands-invite/server/server.ts (1)

13-15: Strengthen type guard to validate array element types.

The type guard claims details: string[] but only checks Array.isArray(details) without verifying that elements are strings. This mismatch forces the defensive Array.isArray check at line 88, undermining the type guard's purpose.

Apply this diff to properly validate string array elements:

 function isErrorWithDetails(error: unknown): error is Error & { details: string[] } {
-	return error instanceof Error && Array.isArray((error as any).details);
+	return error instanceof Error && Array.isArray((error as any).details) && (error as any).details.every((d: unknown) => typeof d === 'string');
 }

This ensures the type predicate accurately reflects runtime validation, eliminating the need for redundant checks downstream.

🧹 Nitpick comments (1)
ee/packages/abac/src/index.ts (1)

445-475: Consider a custom Error class for structured error details.

The validation logic is correct and efficiently queries for non-compliant users. However, attaching a details property directly to a standard Error instance (line 467) is informal and loses type safety.

For better maintainability, consider creating a custom Error class:

class AbacValidationError extends Error {
  constructor(message: string, public readonly details: string[]) {
    super(message);
    this.name = 'AbacValidationError';
  }
}

Then replace lines 466-468 with:

-const err = new Error('error-usernames-not-matching-abac-attributes');
-(err as any).details = Array.from(nonCompliantSet);
-throw err;
+throw new AbacValidationError('error-usernames-not-matching-abac-attributes', Array.from(nonCompliantSet));

This provides compile-time type safety for consumers who need to access the non-compliant usernames.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d453c8b and b5d08f3.

📒 Files selected for processing (11)
  • apps/meteor/app/lib/server/functions/addUserToRoom.ts (2 hunks)
  • apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts (1 hunks)
  • apps/meteor/app/slashcommands-invite/server/server.ts (2 hunks)
  • apps/meteor/ee/server/configuration/abac.ts (1 hunks)
  • apps/meteor/ee/server/hooks/abac/beforeAddUserToRoom.ts (1 hunks)
  • apps/meteor/ee/server/hooks/abac/index.ts (1 hunks)
  • apps/meteor/server/methods/addAllUserToRoom.ts (2 hunks)
  • apps/meteor/tests/end-to-end/api/abac.ts (1 hunks)
  • ee/packages/abac/src/index.spec.ts (3 hunks)
  • ee/packages/abac/src/index.ts (1 hunks)
  • packages/core-services/src/types/IAbacService.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/meteor/ee/server/hooks/abac/index.ts
  • apps/meteor/ee/server/hooks/abac/beforeAddUserToRoom.ts
  • apps/meteor/server/methods/addAllUserToRoom.ts
  • apps/meteor/app/lib/server/lib/beforeAddUserToRoom.ts
  • apps/meteor/app/lib/server/functions/addUserToRoom.ts
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.
📚 Learning: 2025-10-24T17:32:05.348Z
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37299
File: apps/meteor/ee/server/lib/ldap/Manager.ts:438-454
Timestamp: 2025-10-24T17:32:05.348Z
Learning: In Rocket.Chat, ABAC attributes can only be set on private rooms and teams (type 'p'), not on public rooms (type 'c'). Therefore, when checking for ABAC-protected rooms/teams during LDAP sync or similar operations, it's sufficient to query only private rooms using methods like `findPrivateRoomsByIdsWithAbacAttributes`.

Applied to files:

  • packages/core-services/src/types/IAbacService.ts
  • apps/meteor/tests/end-to-end/api/abac.ts
  • ee/packages/abac/src/index.ts
📚 Learning: 2025-10-27T14:38:46.994Z
Learnt from: KevLehman
PR: RocketChat/Rocket.Chat#37303
File: apps/meteor/tests/end-to-end/api/abac.ts:1125-1137
Timestamp: 2025-10-27T14:38:46.994Z
Learning: In Rocket.Chat ABAC feature, when ABAC is disabled globally (ABAC_Enabled setting is false), room-level ABAC attributes are not evaluated when changing room types. This means converting a private room to public will succeed even if the room has ABAC attributes, as long as the global ABAC setting is disabled.

Applied to files:

  • packages/core-services/src/types/IAbacService.ts
  • apps/meteor/ee/server/configuration/abac.ts
  • apps/meteor/tests/end-to-end/api/abac.ts
  • ee/packages/abac/src/index.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing

Applied to files:

  • apps/meteor/app/slashcommands-invite/server/server.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • apps/meteor/tests/end-to-end/api/abac.ts
  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases

Applied to files:

  • apps/meteor/tests/end-to-end/api/abac.ts
  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
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/abac.ts
  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
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/abac.ts
  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
PR: RocketChat/Rocket.Chat#37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

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

Applied to files:

  • ee/packages/abac/src/index.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (test, page, expect) consistently

Applied to files:

  • ee/packages/abac/src/index.spec.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements

Applied to files:

  • ee/packages/abac/src/index.spec.ts
🧬 Code graph analysis (3)
packages/core-services/src/types/IAbacService.ts (1)
packages/core-typings/src/IAbacAttribute.ts (1)
  • IAbacAttributeDefinition (3-14)
apps/meteor/tests/end-to-end/api/abac.ts (3)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (22-98)
apps/meteor/tests/data/api-data.ts (2)
  • request (10-10)
  • credentials (39-42)
apps/meteor/tests/e2e/utils/create-target-channel.ts (1)
  • deleteRoom (48-50)
ee/packages/abac/src/index.ts (1)
packages/core-typings/src/IAbacAttribute.ts (1)
  • IAbacAttributeDefinition (3-14)
⏰ 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 comments (7)
apps/meteor/app/slashcommands-invite/server/server.ts (1)

96-111: Error handling logic is sound.

The multi-branch error handling correctly distinguishes between specific known errors and generic cases. The logic allows Promise.all to continue processing other users even when one invitation fails.

Note: Line 108 shares the same i18n key validation concern as line 91 (using error directly without checking if it's a valid translation key), though it's less critical here since these error values typically originate from controlled system code.

apps/meteor/ee/server/configuration/abac.ts (1)

10-11: LGTM!

The dynamic import of ABAC hooks is correctly placed after core setup (settings and permissions) completes, ensuring proper initialization order.

packages/core-services/src/types/IAbacService.ts (1)

20-20: LGTM!

The new method signature is clear and appropriate for username-attribute validation. The Promise<void> return type correctly signals that validation errors are communicated via exceptions.

apps/meteor/tests/end-to-end/api/abac.ts (1)

1415-1485: LGTM!

The test suite comprehensively validates ABAC enforcement during invitation workflows. The test cases correctly cover:

  • Baseline: invitation to non-ABAC room succeeds
  • ABAC enforcement: invitation fails when user lacks required attributes
  • Attribute removal: invitation succeeds after room loses ABAC requirements

The use of direct DB manipulation (line 1430) is appropriately documented and necessary to avoid triggering ABAC removal during test setup.

ee/packages/abac/src/index.spec.ts (3)

17-17: LGTM!

The Users.find mock is correctly integrated into the existing mock factory and returns a cursor-like object that matches the MongoDB Node driver API.

Also applies to: 41-43


823-884: LGTM!

The test suite comprehensively covers the checkUsernamesMatchAttributes method:

  • Edge cases (empty inputs) correctly skip queries
  • Compliant scenario validates the exact MongoDB query structure
  • Non-compliant scenario verifies both the error message and the structured details array

The detailed query structure assertion at lines 850-867 is valuable for preventing regressions in the validation logic.


885-937: LGTM!

The tests for buildNonCompliantConditions thoroughly validate the MongoDB query fragment construction, including:

  • Empty input handling
  • Correct nesting structure ($not > $elemMatch)
  • Use of $all operator for "must have all values" semantics
  • Order preservation for multiple attributes

These tests ensure the ABAC query logic remains correct as the codebase evolves.

@KevLehman KevLehman requested a review from tassoevan October 31, 2025 14:47
@tassoevan tassoevan merged commit d9c7701 into feat/abac Nov 4, 2025
85 of 87 checks passed
@tassoevan tassoevan deleted the feat/join-prevent-obj branch November 4, 2025 19:26
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants