1
- import type { IUser , IRole } from '@rocket.chat/core-typings' ;
2
- import { Subscriptions } from '@rocket.chat/models' ;
1
+ import { type IUser , type IRole , ROOM_ROLE_PRIORITY_MAP } from '@rocket.chat/core-typings' ;
2
+ import { Subscriptions , Users } from '@rocket.chat/models' ;
3
3
import { escapeRegExp } from '@rocket.chat/string-helpers' ;
4
4
import type { Document , FilterOperators } from 'mongodb' ;
5
5
@@ -12,7 +12,6 @@ type FindUsersParam = {
12
12
limit ?: number ;
13
13
filter ?: string ;
14
14
sort ?: Record < string , any > ;
15
- rolesInOrder ?: IRole [ '_id' ] [ ] ;
16
15
exceptions ?: string [ ] ;
17
16
extraQuery ?: Document [ ] ;
18
17
} ;
@@ -28,135 +27,101 @@ export async function findUsersOfRoomOrderedByRole({
28
27
limit = 0 ,
29
28
filter = '' ,
30
29
sort,
31
- rolesInOrder = [ ] ,
32
30
exceptions = [ ] ,
33
31
extraQuery = [ ] ,
34
32
} : FindUsersParam ) : Promise < { members : UserWithRoleData [ ] ; total : number } > {
35
33
const searchFields = settings . get < string > ( 'Accounts_SearchFields' ) . trim ( ) . split ( ',' ) ;
36
34
const termRegex = new RegExp ( escapeRegExp ( filter ) , 'i' ) ;
37
35
const orStmt = filter && searchFields . length ? searchFields . map ( ( field ) => ( { [ field . trim ( ) ] : termRegex } ) ) : [ ] ;
38
36
39
- const useRealName = settings . get ( 'UI_Use_Real_Name' ) ;
40
- const defaultSort = useRealName ? { name : 1 } : { username : 1 } ;
37
+ const { rolePriority : rolePrioritySort , ...rest } = sort || { } ;
41
38
42
39
const sortCriteria = {
43
- rolePriority : 1 ,
40
+ rolePriority : rolePrioritySort ?? 1 ,
44
41
statusConnection : - 1 ,
45
- ...( sort || defaultSort ) ,
42
+ ...( Object . keys ( rest ) . length > 0
43
+ ? rest
44
+ : {
45
+ ...( settings . get ( 'UI_Use_Real_Name' ) ? { name : 1 } : { username : 1 } ) ,
46
+ } ) ,
46
47
} ;
47
48
48
- const userLookupPipeline : Document [ ] = [
49
- {
50
- $match : {
51
- $and : [
52
- {
53
- $expr : { $eq : [ '$_id' , '$$userId' ] } ,
54
- active : true ,
55
- username : {
56
- $exists : true ,
57
- ...( exceptions . length > 0 && { $nin : exceptions } ) ,
58
- } ,
59
- ...( status && { status } ) ,
60
- ...( filter && orStmt . length > 0 && { $or : orStmt } ) ,
61
- } ,
62
- ...extraQuery ,
63
- ] ,
64
- } ,
65
- } ,
66
- ] ;
67
-
68
- const defaultPriority = rolesInOrder . length + 1 ;
69
-
70
- const branches = rolesInOrder . map ( ( role , index ) => ( {
71
- case : { $eq : [ '$$this' , role ] } ,
72
- then : index + 1 ,
73
- } ) ) ;
74
-
75
- const filteredPipeline : Document [ ] = [
76
- {
77
- $lookup : {
78
- from : 'users' ,
79
- let : { userId : '$u._id' } ,
80
- pipeline : userLookupPipeline ,
81
- as : 'userDetails' ,
49
+ const matchUserFilter = {
50
+ $and : [
51
+ {
52
+ __rooms : rid ,
53
+ active : true ,
54
+ username : {
55
+ $exists : true ,
56
+ ...( exceptions . length > 0 && { $nin : exceptions } ) ,
57
+ } ,
58
+ ...( status && { status } ) ,
59
+ ...( filter && orStmt . length > 0 && { $or : orStmt } ) ,
82
60
} ,
83
- } ,
84
- { $unwind : '$userDetails' } ,
85
- ] ;
61
+ ... extraQuery ,
62
+ ] ,
63
+ } ;
86
64
87
- const membersResult = Subscriptions . col . aggregate (
65
+ const membersResult = Users . col . aggregate (
88
66
[
89
- { $match : { rid } } ,
90
- ...filteredPipeline ,
91
67
{
92
- $addFields : {
93
- primaryRole : {
94
- $reduce : {
95
- input : '$roles' ,
96
- initialValue : { role : null , priority : defaultPriority } ,
97
- in : {
98
- $let : {
99
- vars : {
100
- currentPriority : {
101
- $switch : {
102
- branches,
103
- default : defaultPriority ,
104
- } ,
105
- } ,
106
- } ,
107
- in : {
108
- $cond : [
109
- {
110
- $and : [ { $in : [ '$$this' , rolesInOrder ] } , { $lt : [ '$$currentPriority' , '$$value.priority' ] } ] ,
111
- } ,
112
- { role : '$$this' , priority : '$$currentPriority' } ,
113
- '$$value' ,
114
- ] ,
115
- } ,
68
+ $match : matchUserFilter ,
69
+ } ,
70
+ {
71
+ $project : {
72
+ _id : 1 ,
73
+ name : 1 ,
74
+ username : 1 ,
75
+ nickname : 1 ,
76
+ status : 1 ,
77
+ avatarETag : 1 ,
78
+ _updatedAt : 1 ,
79
+ federated : 1 ,
80
+ rolePriority : {
81
+ $ifNull : [ `$roomRolePriorities.${ rid } ` , ROOM_ROLE_PRIORITY_MAP . default ] ,
82
+ } ,
83
+ } ,
84
+ } ,
85
+ { $sort : sortCriteria } ,
86
+ ...( skip > 0 ? [ { $skip : skip } ] : [ ] ) ,
87
+ ...( limit > 0 ? [ { $limit : limit } ] : [ ] ) ,
88
+ {
89
+ $lookup : {
90
+ from : Subscriptions . getCollectionName ( ) ,
91
+ as : 'subscription' ,
92
+ let : { userId : '$_id' , roomId : rid } ,
93
+ pipeline : [
94
+ {
95
+ $match : {
96
+ $expr : {
97
+ $and : [ { $eq : [ '$rid' , '$$roomId' ] } , { $eq : [ '$u._id' , '$$userId' ] } ] ,
116
98
} ,
117
99
} ,
118
100
} ,
119
- } ,
101
+ { $project : { roles : 1 } } ,
102
+ ] ,
120
103
} ,
121
104
} ,
122
105
{
123
106
$addFields : {
124
- rolePriority : { $ifNull : [ '$primaryRole.priority ' , defaultPriority ] } ,
107
+ roles : { $arrayElemAt : [ '$subscription.roles ' , 0 ] } ,
125
108
} ,
126
109
} ,
127
110
{
128
111
$project : {
129
- _id : '$userDetails._id' ,
130
- rid : 1 ,
131
- roles : 1 ,
132
- primaryRole : '$primaryRole.role' ,
133
- rolePriority : 1 ,
134
- username : '$userDetails.username' ,
135
- name : '$userDetails.name' ,
136
- nickname : '$userDetails.nickname' ,
137
- status : '$userDetails.status' ,
138
- avatarETag : '$userDetails.avatarETag' ,
139
- _updatedAt : '$userDetails._updatedAt' ,
140
- federated : '$userDetails.federated' ,
141
- statusConnection : '$userDetails.statusConnection' ,
112
+ subscription : 0 ,
142
113
} ,
143
114
} ,
144
- { $sort : sortCriteria } ,
145
- ...( skip > 0 ? [ { $skip : skip } ] : [ ] ) ,
146
- ...( limit > 0 ? [ { $limit : limit } ] : [ ] ) ,
147
115
] ,
148
116
{
149
117
allowDiskUse : true ,
150
118
} ,
151
119
) ;
152
120
153
- const totalResult = Subscriptions . col . aggregate ( [ { $match : { rid } } , ...filteredPipeline , { $count : 'total' } ] , { allowDiskUse : true } ) ;
154
-
155
- const [ members , [ { totalCount } ] ] = await Promise . all ( [ membersResult . toArray ( ) , totalResult . toArray ( ) ] ) ;
121
+ const [ members , totalCount ] = await Promise . all ( [ membersResult . toArray ( ) , Users . countDocuments ( matchUserFilter ) ] ) ;
156
122
157
123
return {
158
124
members : members . map ( ( member : any ) => {
159
- delete member . primaryRole ;
160
125
delete member . rolePriority ;
161
126
return member ;
162
127
} ) ,
0 commit comments