Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/fix-missing-protected-roles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/models': patch
'@rocket.chat/meteor': patch
---

Fix custom roles not being found when `protected` is missing. Closes #40798.
4 changes: 2 additions & 2 deletions packages/models/src/models/Roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@ export class RolesRaw extends BaseRaw<IRole> implements IRolesModel {

findCustomRoles(options?: FindOptions<IRole>): FindCursor<IRole> {
const query: Filter<IRole> = {
protected: false,
protected: { $ne: true },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Don't classify unmarked default roles as custom

On upgraded workspaces where default roles were created before protected existed, those roles can still be missing the field: startup runs createOrUpdateProtectedRoleAsync, but its existing-role path only calls Roles.updateById(...) and never writes protected: true. This predicate therefore makes built-in roles like admin, moderator, and user match findCustomRoles/countCustomRoles, so Apps-Engine custom-role reads and custom-role statistics include protected default roles instead of only real custom roles. The fix should distinguish known protected roles or migrate/default their protected flag, rather than treating every missing value as custom.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for pointing this out. My intention was to include custom roles where the protected field is missing, since the previous query only matched roles with protected: false.

However, I see the issue with legacy workspaces where built-in roles such as admin, moderator, and user may also be missing the protected field. In those cases, using protected: { $ne: true } would incorrectly classify those default roles as custom roles.

I'll revisit the approach and look into a solution that correctly handles legacy protected roles, either by ensuring their protected flag is properly set through a migration or by explicitly distinguishing them from custom roles.

};

return this.find(query, options || {});
}

countCustomRoles(options?: CountDocumentsOptions): Promise<number> {
const query: Filter<IRole> = {
protected: false,
protected: { $ne: true },
};

return this.countDocuments(query, options || {});
Expand Down