Skip to content

Conversation

@ricardogarim
Copy link
Contributor

@ricardogarim ricardogarim commented Dec 7, 2025

Proposed changes

As described in SUP-839, SAML role assignment fails when the SAML_Custom_Default_default_user_role setting is configured using a role name instead of a role ID. If administrators set this value to a role name (e.g., "custom-admin"), SAML authentication returns "Invalid role [error-invalid-role]". This issue does not occur with default roles like "user" or "admin" because their role IDs match their names. However, it fails for custom roles where the role ID differs from the role name.

Solution

Added convertRoleNamesToIds() helper in SAML.ts that converts role names to IDs using Roles.findInIdsOrNames().

Issue(s)

Steps to test or reproduce

  1. Keycloak configured as SAML IdP - follow RC SAML Keycloak docs
  2. Create a custom role in RocketChat (Administration > Permissions > New Role) with the name custom-admin
  3. Configure SAML settings in Administration > Settings > SAML:
    • In the General tab > Behavior section, set SAML_Default_User_Role = custom-admin
    • Do NOT enable role attribute sync in the Premium tab
  4. Attempt SAML login with a new user
    • Expected result: User is created successfully and assigned the "custom-admin" role
    • Previous behavior: Login fails with "Invalid role [error-invalid-role]"

Further comments

Full investigation notes and technical details have been documented in the task SUP-839.

Summary by CodeRabbit

  • Bug Fixes
    • SAML authentication now accepts role names in the default user role setting (SAML_Custom_Default_default_user_role) instead of requiring role IDs.
    • Users created or updated via SAML now reliably receive the intended roles when role names are provided, preventing incorrect role assignment and login issues.

✏️ Tip: You can customize this high-level summary in your review settings.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Dec 7, 2025

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 Dec 7, 2025

🦋 Changeset detected

Latest commit: 978d54d

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

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

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

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 7, 2025

Walkthrough

Adds a changeset entry and fixes SAML role mapping by converting provided role names to role IDs before creating or updating users, ensuring role resolution occurs prior to inserting or updating user documents. (48 words)

Changes

Cohort / File(s) Change Summary
Changeset documentation
.changeset/metal-moose-travel.md
Added a patch-release changeset for @rocket.chat/meteor documenting a fix for SAML default user role handling when a role name (not an ID) is provided.
SAML role resolution and user flow
apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts
Added convertRoleNamesToIds() helper; imported IRole and Roles; use Roles.findInIdsOrNames to resolve role names/IDs to IDs; apply resolved role IDs for both new user creation (Accounts.insertUserDoc with skipNewUserRolesSetting: true) and existing user updates.
Manifest / package metadata
package.json
Mentioned in manifest analyzer (no public/export changes).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus areas:
    • convertRoleNamesToIds() validation, partial-match logging and thrown error paths
    • Correct use of Roles.findInIdsOrNames and behavior when roles are missing
    • Interaction between Accounts.insertUserDoc(..., skipNewUserRolesSetting: true) and subsequent role assignment
    • Consistency of role assignment between new user insertion and existing user updates

Suggested labels

stat: ready to merge, stat: QA assured

Poem

🐇 I hopped through SAML's meadow bright,
Names turned to IDs in moonlit night,
I nudged the roles and set them right,
Users now land where they belong —
A tiny hop, a joyful song. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: making role validation/assignment accept role names or IDs, which directly addresses the SAML role mapping issue.
Linked Issues check ✅ Passed The code changes fully implement the fix for SUP-839 by adding convertRoleNamesToIds() helper that resolves role names to IDs before validation/assignment, enabling SAML configuration with role names.
Out of Scope Changes check ✅ Passed All changes are focused on fixing the SAML role mapping issue: updates to SAML.ts imports, helper function implementation, and role resolution logic are directly scoped to addressing SUP-839.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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 fix/saml-default-role

📜 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 6a1491d and 9222e4f.

📒 Files selected for processing (2)
  • .changeset/metal-moose-travel.md (1 hunks)
  • apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (4 hunks)
🧰 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/meteor-accounts-saml/server/lib/SAML.ts
🧠 Learnings (5)
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

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

Applied to files:

  • apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: 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/meteor-accounts-saml/server/lib/SAML.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/meteor-accounts-saml/server/lib/SAML.ts
🧬 Code graph analysis (1)
apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (1)
apps/meteor/app/authentication/server/startup/index.js (1)
  • roles (306-306)
🔇 Additional comments (4)
.changeset/metal-moose-travel.md (1)

1-5: Verify the setting name in the changeset description.

The changeset mentions SAML_Custom_Default_default_user_role, but the PR objectives reference SAML_Default_User_Role. Ensure the setting name in the description is accurate and matches what users will see in their configuration.

apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (3)

146-147: LGTM! Role name resolution for new users looks correct.

The logic correctly falls back to defaultUserRole when no roles are provided in the SAML assertion, then converts names/IDs to validated IDs before user creation.


32-44: Confirm that partial role resolution behavior is intentional.

The function logs a warning but continues when some roles aren't found, throwing only when all roles fail. This allows user creation/update with a subset of configured roles.

If an admin configures defaultUserRole = "user,invalid-role", the user will be created with only the "user" role, and the misconfiguration surfaces only as a server log warning. This differs from other role validation in the codebase which typically throws on invalid roles.

Verify whether this graceful-degradation approach aligns with your security model, or if stricter validation (failing on any missing role) would be preferable.


218-219: The code at lines 218-219 is correct. The roles field used in Users.updateOne() matches the IUser interface definition (roles: IRole['_id'][]). The globalRoles parameter in user creation (line 152) is a Meteor Accounts API parameter, not a document field—it's separate from the roles field used in direct document updates.


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.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 7, 2025

📦 Docker Image Size Report

📈 Changes

Service Current Baseline Change Percent
sum of all images 1.2GiB 1.2GiB +12MiB
rocketchat 360MiB 349MiB +12MiB
omnichannel-transcript-service 132MiB 132MiB -878B
queue-worker-service 132MiB 132MiB -179B
ddp-streamer-service 126MiB 126MiB +240B
account-service 113MiB 113MiB -446B
stream-hub-service 111MiB 111MiB -72B
authorization-service 111MiB 111MiB -390B
presence-service 111MiB 111MiB -428B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/15 22:28", "11/16 01:28", "11/17 23:50", "11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 02:21", "12/09 11:17 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "queue-worker-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
  line "rocketchat" [0.36, 0.36, 0.35, 0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.35]
  line "stream-hub-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
Loading

Statistics (last 16 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.2GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 1.2GiB
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-37713
  • Baseline: develop
  • Timestamp: 2025-12-09 11:17:51 UTC
  • Historical data points: 16

Updated: Tue, 09 Dec 2025 11:17:52 GMT

@codecov
Copy link

codecov bot commented Dec 7, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.80%. Comparing base (53547cc) to head (978d54d).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37713      +/-   ##
===========================================
- Coverage    67.89%   67.80%   -0.09%     
===========================================
  Files         3450     3450              
  Lines       113968   113968              
  Branches     20955    20955              
===========================================
- Hits         77373    77271     -102     
- Misses       34472    34578     +106     
+ Partials      2123     2119       -4     
Flag Coverage Δ
e2e 57.32% <ø> (-0.03%) ⬇️
e2e-api 42.15% <ø> (-0.98%) ⬇️

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.

@ricardogarim ricardogarim marked this pull request as ready for review December 8, 2025 11:32
@ricardogarim ricardogarim requested a review from a team as a code owner December 8, 2025 11:32
@ricardogarim ricardogarim added this to the 7.14.0 milestone Dec 8, 2025
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/server/lib/roles/addUserRoles.ts (1)

18-29: Validation occurs before array normalization.

The call to validateRoleList(roles) at line 18 happens before the array normalization at lines 26-29. If a non-array value is somehow passed (despite the type signature), validateRoleList returns true early for non-arrays, effectively bypassing validation before the value is wrapped in an array.

Consider moving the validation after normalization:

+	if (!Array.isArray(roles)) {
+		roles = [roles];
+		process.env.NODE_ENV === 'development' && console.warn('[WARN] RolesRaw.addUserRoles: roles should be an array');
+	}
+
 	if (!(await validateRoleList(roles))) {
 		throw new MeteorError('error-invalid-role', 'Invalid role');
 	}
 
 	if (process.env.NODE_ENV === 'development' && (scope === 'Users' || scope === 'Subscriptions')) {
 		throw new Error('Roles.addUserRoles method received a role scope instead of a scope value.');
 	}
-
-	if (!Array.isArray(roles)) {
-		roles = [roles];
-		process.env.NODE_ENV === 'development' && console.warn('[WARN] RolesRaw.addUserRoles: roles should be an array');
-	}
📜 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 d0be8ad and 158b5df.

📒 Files selected for processing (4)
  • .changeset/metal-moose-travel.md (1 hunks)
  • apps/meteor/server/lib/roles/addUserRoles.ts (2 hunks)
  • apps/meteor/server/lib/roles/removeUserFromRoles.ts (2 hunks)
  • apps/meteor/server/lib/roles/validateRoleList.ts (1 hunks)
🧰 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/server/lib/roles/validateRoleList.ts
  • apps/meteor/server/lib/roles/removeUserFromRoles.ts
  • apps/meteor/server/lib/roles/addUserRoles.ts
🧠 Learnings (3)
📓 Common learnings
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.
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.
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

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

Applied to files:

  • apps/meteor/server/lib/roles/removeUserFromRoles.ts
  • apps/meteor/server/lib/roles/addUserRoles.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 (4)
.changeset/metal-moose-travel.md (1)

1-5: LGTM!

The changeset accurately describes the fix and correctly categorizes it as a patch release.

apps/meteor/server/lib/roles/validateRoleList.ts (1)

4-18: LGTM!

The validation logic correctly handles both role IDs and role names by querying with findInIdsOrNames and checking matches against both _id and name fields. The early return for empty arrays is appropriate since an empty role list is valid.

apps/meteor/server/lib/roles/removeUserFromRoles.ts (1)

31-45: LGTM!

The role lookup correctly uses findOneByIdOrName to support both IDs and names, and appropriately uses role._id for the actual database operations. This ensures consistency in the stored data regardless of how the role was specified.

apps/meteor/server/lib/roles/addUserRoles.ts (1)

31-48: LGTM!

The role lookup correctly uses findOneByIdOrName to resolve roles by either ID or name, and consistently uses role._id for the actual database operations. The graceful handling of missing roles (warn and continue) allows processing of other valid roles in the list.

Copy link
Contributor

@pierre-lehnen-rc pierre-lehnen-rc left a comment

Choose a reason for hiding this comment

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

Roles must always be identified by their ID, and so those functions (addUserRoles, removeUserFromRoles and validateRoleList) are not meant to support role names. Instead of modifying them, you should make sure that no role names are passed to them by converting any potential name to an ID before those functions get called.

Ideally even the setting itself should accept only role IDs as values, but that would require some new UI component to select roles and get their ID (which is not feasible for a simple fix), so converting the name to an ID before using it is the next best approach.

@ricardogarim ricardogarim force-pushed the fix/saml-default-role branch from 158b5df to 6dd88c9 Compare December 8, 2025 17:06
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 (1)
apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (1)

32-40: Solid implementation of role name/ID resolution.

The validation via length comparison is reasonable. One minor improvement: the error message could identify which specific roles failed to match for easier debugging.

 const convertRoleNamesToIds = async (roleNamesOrIds: string[]): Promise<IRole['_id'][]> => {
 	const roles = await Roles.findInIdsOrNames(roleNamesOrIds).toArray();
 
 	if (roles.length !== roleNamesOrIds.length) {
-		throw new Error(`Failed to convert role names to ids: ${roleNamesOrIds.join(', ')}`);
+		const foundIds = new Set(roles.flatMap((r) => [r._id, r.name]));
+		const notFound = roleNamesOrIds.filter((r) => !foundIds.has(r));
+		throw new Error(`Failed to find roles: ${notFound.join(', ')}`);
 	}
 
 	return roles.map((role) => role._id);
 };
📜 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 158b5df and 6dd88c9.

📒 Files selected for processing (2)
  • .changeset/metal-moose-travel.md (1 hunks)
  • apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/metal-moose-travel.md
🧰 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/meteor-accounts-saml/server/lib/SAML.ts
🧠 Learnings (1)
📚 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/meteor-accounts-saml/server/lib/SAML.ts
🧬 Code graph analysis (1)
apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (1)
apps/meteor/app/authentication/server/startup/index.js (2)
  • roles (306-306)
  • Accounts (282-282)
⏰ 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 (2)
apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts (2)

177-178: LGTM!

Using skipNewUserRolesSetting: true correctly ensures the pre-resolved role IDs in globalRoles are used directly without modification.


213-215: LGTM!

Correctly uses the pre-converted role IDs for existing user updates, ensuring consistency with new user creation.

@ricardogarim ricardogarim force-pushed the fix/saml-default-role branch from 6a1491d to 9222e4f Compare December 8, 2025 17:47
@ricardogarim
Copy link
Contributor Author

ricardogarim commented Dec 8, 2025

Just one note: when the default flow is triggered, both SAML_Custom_Default_default_user_role and Accounts_Registration_AuthenticationServices_Default_Roles end up being applied. In the test using a custom role custom-admin, the user receives both custom-admin and the default user role (from the second setting).

Since this behavior isn’t directly tied to the scope of this task, I’m flagging it so the team can decide whether it should be handled as a separate fix.

@ricardogarim ricardogarim added the stat: QA assured Means it has been tested and approved by a company insider label Dec 9, 2025
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Dec 9, 2025
@kodiakhq kodiakhq bot merged commit a2b2e26 into develop Dec 9, 2025
48 checks passed
@kodiakhq kodiakhq bot deleted the fix/saml-default-role branch December 9, 2025 11:43
@pierre-lehnen-rc pierre-lehnen-rc changed the title fix: make validateRoleList to check by role name or id fix: Default SAML User Role setting not working with role names Dec 9, 2025
@dougfabris dougfabris modified the milestones: 7.14.0, 8.0.0 Jan 19, 2026
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants