From 7b4d9fea4191a0e37ebe6fa30e64ccf770feef64 Mon Sep 17 00:00:00 2001 From: Christian Wahle <59534030+bratelefant@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:46:32 +0100 Subject: [PATCH] add getUserIdsInRole and getUserIdsInRoleAsync methods with tests --- packages/roles/definitions.d.ts | 25 +++++++++++++++++++++++++ packages/roles/roles_client.js | 21 +++++++++++++++++++++ packages/roles/roles_common_async.js | 23 +++++++++++++++++++++++ packages/roles/tests/serverAsync.js | 16 ++++++++++++++++ 4 files changed, 85 insertions(+) diff --git a/packages/roles/definitions.d.ts b/packages/roles/definitions.d.ts index c15c8c9652..be5ba9ffaa 100644 --- a/packages/roles/definitions.d.ts +++ b/packages/roles/definitions.d.ts @@ -359,6 +359,31 @@ export declare namespace Roles { queryOptions?: QueryOptions ): Promise>; + /** + * Retrieve all userIds who are in target role. + * + * Options: + * + * @method getUserIdsInRole + * @param {Array|String} roles Name of role or an array of roles. If array, users + * returned will have at least one of the roles + * specified but need not have _all_ roles. + * Roles do not have to exist. + * @param {Object|String} options Options: + * - `scope`: name of the scope to restrict roles to; user's global + * roles will also be checked + * - `anyScope`: if set, role can be in any scope (`scope` option is ignored) + * - `onlyScoped`: if set, only roles in the specified scope are returned + */ + function getUserIdsInRole( + roles: string | string[], + options?: string | { scope?: string; anyScope?: boolean; onlyScoped?: boolean } + ): string[] + function getUserIdsInRoleAsync( + roles: string | string[], + options?: string | { scope?: string; anyScope?: boolean; onlyScoped?: boolean } + ): Promise; + /** * Remove users from assigned roles. * diff --git a/packages/roles/roles_client.js b/packages/roles/roles_client.js index e0ec9a7fd8..95b5fdffbb 100644 --- a/packages/roles/roles_client.js +++ b/packages/roles/roles_client.js @@ -809,6 +809,27 @@ Object.assign(Roles, { return Meteor.users.find({ _id: { $in: ids } }, ((options && options.queryOptions) || queryOptions) || {}) }, + /** + * Retrieve all user IDs who are in target role. + * + * @method getUserIdsInRole + * @param {Array|String} roles Name of role or an array of roles. If array, users + * returned will have at least one of the roles + * specified but need not have _all_ roles. + * Roles do not have to exist. + * @param {Object|String} [options] Options: + * - `scope`: name of the scope to restrict roles to; user's global + * roles will also be checked + * - `anyScope`: if set, role can be in any scope (`scope` option is ignored) + * * @return {Array} Array of user IDs in roles. + * @static + */ + getUserIdsInRole: function (roles, options) { + const ids = Roles.getUserAssignmentsForRole(roles, options).fetch().map(a => a.user._id) + + return ids + }, + /** * Retrieve all assignments of a user which are for the target role. * diff --git a/packages/roles/roles_common_async.js b/packages/roles/roles_common_async.js index dbd46d5b71..a4f95af825 100644 --- a/packages/roles/roles_common_async.js +++ b/packages/roles/roles_common_async.js @@ -1062,6 +1062,29 @@ Object.assign(Roles, { ) }, + /** + * Retrieve all userIds who are in target role. + * + * Options: + * + * @method getUserIdsInRoleAsync + * @param {Array|String} roles Name of role or an array of roles. If array, users + * returned will have at least one of the roles + * specified but need not have _all_ roles. + * Roles do not have to exist. + * @param {Object|String} [options] Options: + * - `scope`: name of the scope to restrict roles to; user's global + * roles will also be checked + * - `anyScope`: if set, role can be in any scope (`scope` option is ignored) + * @return {Promise} Array of user IDs in roles. + * @static + */ + getUserIdsInRoleAsync: async function (roles, options) { + const cursor = Roles.getUserAssignmentsForRole(roles, options) + + return (await cursor.fetchAsync()).map((a) => a.user._id) + }, + /** * @summary Retrieve all assignments of a user which are for the target role. * @memberof Roles diff --git a/packages/roles/tests/serverAsync.js b/packages/roles/tests/serverAsync.js index 1e844550fc..197b587c37 100644 --- a/packages/roles/tests/serverAsync.js +++ b/packages/roles/tests/serverAsync.js @@ -1518,6 +1518,22 @@ Tinytest.addAsync("roles -can get all users in role", async function (test) { sameMembers(test, actual, expected); }); +Tinytest.addAsync("roles - can get all userIds in role", async function (test) { + await clearData(); + + await Roles.createRoleAsync('admin'); + await Roles.createRoleAsync('user'); + await Roles.createRoleAsync('editor'); + + const ids = ['foo', 'bar', 'baz']; + await Roles.addUsersToRolesAsync([ids[0], ids[1]], ['admin', 'user']); + await Roles.addUsersToRolesAsync([ids[1], ids[2]], ['editor']); + + const expected = [ids[0], ids[1]]; + const userIds = await Roles.getUserIdsInRoleAsync('admin'); + sameMembers(test, userIds, expected); +}); + Tinytest.addAsync( "roles -can get all users in role by scope", async function (test) {