shuttlepro-shared 1.2.70 → 1.2.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,578 +1,178 @@
|
|
|
1
|
-
// const { UserRole } = require("../../models/UserRole");
|
|
2
|
-
// const { getRedisData, setRedisData } = require("../../config/redis");
|
|
3
|
-
|
|
4
|
-
// const defaultSelect =
|
|
5
|
-
// "iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule";
|
|
6
|
-
|
|
7
|
-
// // Cache keys
|
|
8
|
-
// const CACHE_KEY_ALL_MEMBERS = "userroles_all_members";
|
|
9
|
-
|
|
10
|
-
// const getCachedMembers = async (filter = {}) => {
|
|
11
|
-
// try {
|
|
12
|
-
// let members = await getRedisData(CACHE_KEY_ALL_MEMBERS);
|
|
13
|
-
|
|
14
|
-
// if (!members) {
|
|
15
|
-
// members = await UserRole.find()
|
|
16
|
-
// .select("userId role userShift roleId workspaceId")
|
|
17
|
-
// .populate({
|
|
18
|
-
// path: "roleId",
|
|
19
|
-
// select: "id name userId userShift permissionId modulePermissions",
|
|
20
|
-
// populate: [{ path: "permissionId", select: "id name" }],
|
|
21
|
-
// })
|
|
22
|
-
// .populate({
|
|
23
|
-
// path: "userId",
|
|
24
|
-
// match: { isDeleted: false, suspended: false },
|
|
25
|
-
// select: "firstName lastName role email picture userShift _id",
|
|
26
|
-
// })
|
|
27
|
-
// .lean()
|
|
28
|
-
// .exec();
|
|
29
|
-
|
|
30
|
-
// members = members?.filter((m) => m?.userId && m?.roleId) || [];
|
|
31
|
-
// await setRedisData(CACHE_KEY_ALL_MEMBERS, members);
|
|
32
|
-
// }
|
|
33
|
-
|
|
34
|
-
// const userIdFilter = filter.userId
|
|
35
|
-
// ? new Set(
|
|
36
|
-
// Array.isArray(filter.userId)
|
|
37
|
-
// ? filter.userId.map((id) => id.toString())
|
|
38
|
-
// : [filter.userId.toString()]
|
|
39
|
-
// )
|
|
40
|
-
// : null;
|
|
41
|
-
|
|
42
|
-
// const roleIdFilter = filter.roleId
|
|
43
|
-
// ? Array.isArray(filter.roleId)
|
|
44
|
-
// ? new Set(filter.roleId.map((id) => id.toString()))
|
|
45
|
-
// : typeof filter.roleId === "object"
|
|
46
|
-
// ? filter.roleId
|
|
47
|
-
// : new Set([filter.roleId.toString()])
|
|
48
|
-
// : null;
|
|
49
|
-
|
|
50
|
-
// return members.filter((member) => {
|
|
51
|
-
// // Optimize userId filter
|
|
52
|
-
// if (userIdFilter && !userIdFilter.has(member.userId?._id?.toString())) {
|
|
53
|
-
// return false;
|
|
54
|
-
// }
|
|
55
|
-
|
|
56
|
-
// // Optimize roleId filter
|
|
57
|
-
// if (roleIdFilter) {
|
|
58
|
-
// if (roleIdFilter instanceof Set) {
|
|
59
|
-
// const roleIdStr =
|
|
60
|
-
// member.roleId?._id?.toString() ?? member.roleId?.id?.toString();
|
|
61
|
-
// if (!roleIdFilter.has(roleIdStr)) return false;
|
|
62
|
-
// } else if (typeof roleIdFilter === "object") {
|
|
63
|
-
// for (const [key, value] of Object.entries(roleIdFilter)) {
|
|
64
|
-
// const roleVal = key.includes(".")
|
|
65
|
-
// ? key.split(".").reduce((obj, k) => obj?.[k], member.roleId)
|
|
66
|
-
// : member.roleId?.[key];
|
|
67
|
-
// if (Array.isArray(value)) {
|
|
68
|
-
// if (!value.includes(roleVal)) return false;
|
|
69
|
-
// } else if (roleVal !== value) {
|
|
70
|
-
// return false;
|
|
71
|
-
// }
|
|
72
|
-
// }
|
|
73
|
-
// }
|
|
74
|
-
// }
|
|
75
|
-
|
|
76
|
-
// // General filters
|
|
77
|
-
// for (const [key, value] of Object.entries(filter)) {
|
|
78
|
-
// if (key === "userId" || key === "roleId") continue;
|
|
79
|
-
|
|
80
|
-
// const memberValue = key.includes(".")
|
|
81
|
-
// ? key.split(".").reduce((obj, prop) => obj?.[prop], member)
|
|
82
|
-
// : member[key];
|
|
83
|
-
|
|
84
|
-
// if (Array.isArray(value)) {
|
|
85
|
-
// if (!value.includes(memberValue)) return false;
|
|
86
|
-
// } else if (typeof value === "object" && value !== null) {
|
|
87
|
-
// for (const [subKey, subVal] of Object.entries(value)) {
|
|
88
|
-
// if (memberValue?.[subKey] !== subVal) return false;
|
|
89
|
-
// }
|
|
90
|
-
// } else {
|
|
91
|
-
// if (memberValue !== value) return false;
|
|
92
|
-
// }
|
|
93
|
-
// }
|
|
94
|
-
|
|
95
|
-
// return true;
|
|
96
|
-
// });
|
|
97
|
-
// } catch (error) {
|
|
98
|
-
// console.error("Error fetching cached members:", error);
|
|
99
|
-
// return [];
|
|
100
|
-
// }
|
|
101
|
-
// };
|
|
102
|
-
|
|
103
|
-
// // Update the cache for all members
|
|
104
|
-
// const updateCachedMembers = async (filter = {}) => {
|
|
105
|
-
// try {
|
|
106
|
-
// const members = await UserRole.find(filter)
|
|
107
|
-
// .select("userId role userShift roleId")
|
|
108
|
-
// .populate({
|
|
109
|
-
// path: "roleId",
|
|
110
|
-
// select: "id name userId userShift permissionId modulePermissions",
|
|
111
|
-
// populate: [{ path: "permissionId", select: "id name" }],
|
|
112
|
-
// })
|
|
113
|
-
// .populate({
|
|
114
|
-
// path: "userId",
|
|
115
|
-
// match: { isDeleted: false, suspended: false },
|
|
116
|
-
// select: "firstName lastName role email picture userShift",
|
|
117
|
-
// })
|
|
118
|
-
// .lean()
|
|
119
|
-
// .exec();
|
|
120
|
-
|
|
121
|
-
// const validMembers =
|
|
122
|
-
// members?.filter((member) => member?.userId && member?.roleId) || [];
|
|
123
|
-
|
|
124
|
-
// await setRedisData(CACHE_KEY_ALL_MEMBERS, validMembers);
|
|
125
|
-
|
|
126
|
-
// return validMembers;
|
|
127
|
-
// } catch (error) {
|
|
128
|
-
// console.error("Error updating cached members:", error);
|
|
129
|
-
// return [];
|
|
130
|
-
// }
|
|
131
|
-
// };
|
|
132
|
-
|
|
133
|
-
// // Comprehensive cache update method
|
|
134
|
-
// const updateAllRelatedCaches = async (userId, workspaceId) => {
|
|
135
|
-
// try {
|
|
136
|
-
// await updateCachedMembers();
|
|
137
|
-
// } catch (error) {
|
|
138
|
-
// console.error("Error updating related caches:", error);
|
|
139
|
-
// }
|
|
140
|
-
// };
|
|
141
|
-
|
|
142
|
-
// // Find single user role by filter
|
|
143
|
-
// const findSingleUserRoleByFilter = async (
|
|
144
|
-
// filter = {},
|
|
145
|
-
// populateOptions = {}
|
|
146
|
-
// ) => {
|
|
147
|
-
// const defaultPopulateOptions = {
|
|
148
|
-
// rolePopulate: {
|
|
149
|
-
// path: "roleId",
|
|
150
|
-
// select: "id name userId userShift permissionId modulePermissions",
|
|
151
|
-
// populate: [{ path: "permissionId", select: "id name" }],
|
|
152
|
-
// },
|
|
153
|
-
// userPopulate: {
|
|
154
|
-
// path: "userId",
|
|
155
|
-
// match: { isDeleted: false, suspended: false },
|
|
156
|
-
// select: "firstName lastName role email picture userShift",
|
|
157
|
-
// },
|
|
158
|
-
// };
|
|
159
|
-
// const mergedPopulateOptions = {
|
|
160
|
-
// rolePopulate: {
|
|
161
|
-
// ...defaultPopulateOptions.rolePopulate,
|
|
162
|
-
// ...populateOptions.rolePopulate,
|
|
163
|
-
// },
|
|
164
|
-
// userPopulate: {
|
|
165
|
-
// ...defaultPopulateOptions.userPopulate,
|
|
166
|
-
// ...populateOptions.userPopulate,
|
|
167
|
-
// },
|
|
168
|
-
// };
|
|
169
|
-
// return await UserRole.findOne(filter)
|
|
170
|
-
// .populate(mergedPopulateOptions.rolePopulate)
|
|
171
|
-
// .populate(mergedPopulateOptions.userPopulate)
|
|
172
|
-
// .lean()
|
|
173
|
-
// .exec();
|
|
174
|
-
// };
|
|
175
|
-
|
|
176
|
-
// const convertPermissionsArrayToObject = (originalArray) => {
|
|
177
|
-
// return originalArray?.reduce((acc, item) => {
|
|
178
|
-
// const { id, actions, integrationPermissions, ...extras } = item;
|
|
179
|
-
// const formattedExtras = {};
|
|
180
|
-
// if (extras.deletable !== undefined) {
|
|
181
|
-
// formattedExtras.deletable = extras.deletable;
|
|
182
|
-
// }
|
|
183
|
-
// if (extras.createUpdateable !== undefined) {
|
|
184
|
-
// formattedExtras.createUpdateable = extras.createUpdateable;
|
|
185
|
-
// }
|
|
186
|
-
// acc[id] = {
|
|
187
|
-
// actions: Object.keys(actions).filter((action) => actions[action]),
|
|
188
|
-
// ...formattedExtras,
|
|
189
|
-
// ...(integrationPermissions && {
|
|
190
|
-
// integrationPermissions: Object.entries(integrationPermissions)
|
|
191
|
-
// .filter(([_, allowed]) => allowed)
|
|
192
|
-
// .map(([key]) => key),
|
|
193
|
-
// }),
|
|
194
|
-
// };
|
|
195
|
-
// return acc;
|
|
196
|
-
// }, {});
|
|
197
|
-
// };
|
|
198
|
-
|
|
199
|
-
// const createUserRole = async (data) => {
|
|
200
|
-
// const savedRole = await UserRole.create(data);
|
|
201
|
-
|
|
202
|
-
// // Update all related caches
|
|
203
|
-
// await updateAllRelatedCaches(
|
|
204
|
-
// savedRole?.userId?.toString(),
|
|
205
|
-
// savedRole?.workspaceId?.toString()
|
|
206
|
-
// );
|
|
207
|
-
|
|
208
|
-
// return savedRole;
|
|
209
|
-
// };
|
|
210
|
-
|
|
211
|
-
// const findOneAndUpdateUserRole = async ({
|
|
212
|
-
// workspaceId,
|
|
213
|
-
// userId,
|
|
214
|
-
// userShift,
|
|
215
|
-
// role,
|
|
216
|
-
// }) => {
|
|
217
|
-
// const updatedRole = await UserRole.findOneAndUpdate(
|
|
218
|
-
// { workspaceId, userId },
|
|
219
|
-
// { $set: { userShift, role } },
|
|
220
|
-
// { new: true, upsert: false }
|
|
221
|
-
// ).exec();
|
|
222
|
-
// if (updatedRole) {
|
|
223
|
-
// await updateAllRelatedCaches(userId, workspaceId);
|
|
224
|
-
// }
|
|
225
|
-
// return updatedRole;
|
|
226
|
-
// };
|
|
227
|
-
|
|
228
|
-
// const findUserRole = async (filter = {}) => {
|
|
229
|
-
// return await getCachedMembers(filter);
|
|
230
|
-
// };
|
|
231
|
-
|
|
232
|
-
// const updateUserRole = async (id, data) => {
|
|
233
|
-
// const updatedRole = await UserRole.findByIdAndUpdate(id, data, {
|
|
234
|
-
// new: true,
|
|
235
|
-
// }).exec();
|
|
236
|
-
// if (updatedRole) {
|
|
237
|
-
// await updateAllRelatedCaches(updatedRole.userId, updatedRole.workspaceId);
|
|
238
|
-
// }
|
|
239
|
-
// return updatedRole;
|
|
240
|
-
// };
|
|
241
|
-
|
|
242
|
-
// const deleteUserRoleByFilter = async (filter) => {
|
|
243
|
-
// const roleToDelete = await UserRole.findOne(filter).exec();
|
|
244
|
-
// const deletedRole = await UserRole.findOneAndDelete(filter).exec();
|
|
245
|
-
// if (deletedRole) {
|
|
246
|
-
// await updateAllRelatedCaches(
|
|
247
|
-
// roleToDelete?.userId,
|
|
248
|
-
// roleToDelete?.workspaceId
|
|
249
|
-
// );
|
|
250
|
-
// }
|
|
251
|
-
// return deletedRole;
|
|
252
|
-
// };
|
|
253
|
-
|
|
254
|
-
// const deleteUserRole = async (id) => {
|
|
255
|
-
// const role = await UserRole.findById(id).exec();
|
|
256
|
-
// const userId = role?.userId;
|
|
257
|
-
// const workspaceId = role?.workspaceId;
|
|
258
|
-
// const deletedRole = await UserRole.findByIdAndDelete(id).exec();
|
|
259
|
-
// if (deletedRole) {
|
|
260
|
-
// await updateAllRelatedCaches(userId, workspaceId);
|
|
261
|
-
// }
|
|
262
|
-
// return deletedRole;
|
|
263
|
-
// };
|
|
264
|
-
|
|
265
|
-
// const findUserWorkspaces = async (userId) => {
|
|
266
|
-
// let userRoleWithWorkspaces = await UserRole.find({ userId: userId })
|
|
267
|
-
// .select("userId roleId workspaceId")
|
|
268
|
-
// .populate({
|
|
269
|
-
// path: "roleId",
|
|
270
|
-
// select: "id name userId userShift permissionId modulePermissions",
|
|
271
|
-
// populate: [{ path: "permissionId", select: "id name" }],
|
|
272
|
-
// })
|
|
273
|
-
// .populate({
|
|
274
|
-
// path: "workspaceId",
|
|
275
|
-
// select: defaultSelect,
|
|
276
|
-
// match: { isDeleted: false },
|
|
277
|
-
// })
|
|
278
|
-
// .lean()
|
|
279
|
-
// .exec();
|
|
280
|
-
// userRoleWithWorkspaces = userRoleWithWorkspaces
|
|
281
|
-
// ?.filter((userRole) => userRole?.workspaceId)
|
|
282
|
-
// ?.filter((userRole) => userRole?.roleId)
|
|
283
|
-
// ?.map((ur) => {
|
|
284
|
-
// return {
|
|
285
|
-
// ...ur?.workspaceId,
|
|
286
|
-
// id: ur?.workspaceId?._id?.toString(),
|
|
287
|
-
// _id: ur?.workspaceId?._id?.toString(),
|
|
288
|
-
// role: ur?.roleId?.name || "",
|
|
289
|
-
// permissions: ur?.roleId?.modulePermissions?.modules || [],
|
|
290
|
-
// };
|
|
291
|
-
// });
|
|
292
|
-
// return userRoleWithWorkspaces || [];
|
|
293
|
-
// };
|
|
294
|
-
|
|
295
|
-
// const getUserPermissions = async (workspaceId, userId) => {
|
|
296
|
-
// try {
|
|
297
|
-
// let members = await getCachedMembers({ workspaceId, userId });
|
|
298
|
-
// console.log(members, "members");
|
|
299
|
-
// if (members?.length) {
|
|
300
|
-
// return (
|
|
301
|
-
// convertPermissionsArrayToObject(
|
|
302
|
-
// members?.[0]?.roleId?.modulePermissions?.modules
|
|
303
|
-
// ) || null
|
|
304
|
-
// );
|
|
305
|
-
// }
|
|
306
|
-
// return null;
|
|
307
|
-
// } catch (err) {
|
|
308
|
-
// console.error("Error in getUserPermissions:", err);
|
|
309
|
-
// return null;
|
|
310
|
-
// }
|
|
311
|
-
// };
|
|
312
|
-
|
|
313
|
-
// const getUserRoleWithPermissions = async (workspaceId, userId) => {
|
|
314
|
-
// try {
|
|
315
|
-
// let members = await getCachedMembers({ workspaceId, userId });
|
|
316
|
-
// console.log(members, "members");
|
|
317
|
-
// if (members?.length) {
|
|
318
|
-
// let data = members?.[0];
|
|
319
|
-
// const roleWithPermissions = {
|
|
320
|
-
// ...data,
|
|
321
|
-
// roleId: data?.roleId?._id?.toString() || "",
|
|
322
|
-
// role: data?.roleId?.name || "",
|
|
323
|
-
// permissions:
|
|
324
|
-
// convertPermissionsArrayToObject(
|
|
325
|
-
// data?.roleId?.modulePermissions?.modules
|
|
326
|
-
// ) || [],
|
|
327
|
-
// parentRole: data?.roleId?.permissionId?.name || "",
|
|
328
|
-
// parentRoleId: data?.roleId?.permissionId?._id?.toString() || "",
|
|
329
|
-
// defaultModule: data?.roleId?.defaultModule || "",
|
|
330
|
-
// };
|
|
331
|
-
// return roleWithPermissions || null;
|
|
332
|
-
// }
|
|
333
|
-
// return null;
|
|
334
|
-
// } catch (err) {
|
|
335
|
-
// console.error("Error in getUserRoleWithPermissions:", err);
|
|
336
|
-
// return null;
|
|
337
|
-
// }
|
|
338
|
-
// };
|
|
339
|
-
|
|
340
|
-
// const getChannelsPermissions = async (workspaceId, userId) => {
|
|
341
|
-
// try {
|
|
342
|
-
// let members = await getCachedMembers({ workspaceId, userId });
|
|
343
|
-
// console.log(members, "members");
|
|
344
|
-
// if (members?.length) {
|
|
345
|
-
// let data = members?.[0];
|
|
346
|
-
// return (
|
|
347
|
-
// convertPermissionsArrayToObject(
|
|
348
|
-
// data?.roleId?.modulePermissions?.modules
|
|
349
|
-
// )?.["conversations"]?.["integrationPermissions"] || []
|
|
350
|
-
// );
|
|
351
|
-
// }
|
|
352
|
-
// return [];
|
|
353
|
-
// } catch (err) {
|
|
354
|
-
// console.error("Error in getChannelsPermissions:", err);
|
|
355
|
-
// return [];
|
|
356
|
-
// }
|
|
357
|
-
// };
|
|
358
|
-
|
|
359
|
-
// module.exports = {
|
|
360
|
-
// createUserRole,
|
|
361
|
-
// findUserRole,
|
|
362
|
-
// updateUserRole,
|
|
363
|
-
// deleteUserRoleByFilter,
|
|
364
|
-
// deleteUserRole,
|
|
365
|
-
// findUserWorkspaces,
|
|
366
|
-
// getUserRoleWithPermissions,
|
|
367
|
-
// getUserPermissions,
|
|
368
|
-
// getChannelsPermissions,
|
|
369
|
-
// findOneAndUpdateUserRole,
|
|
370
|
-
// findSingleUserRoleByFilter,
|
|
371
|
-
// getCachedMembers,
|
|
372
|
-
// updateCachedMembers,
|
|
373
|
-
// };
|
|
374
|
-
|
|
375
1
|
const { UserRole } = require("../../models/UserRole");
|
|
376
2
|
const { getRedisData, setRedisData } = require("../../config/redis");
|
|
377
3
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
select: {
|
|
381
|
-
userRole: "userId role userShift roleId workspaceId",
|
|
382
|
-
role: "id name userId userShift permissionId modulePermissions",
|
|
383
|
-
permission: "id name",
|
|
384
|
-
user: "firstName lastName role email picture userShift _id",
|
|
385
|
-
},
|
|
386
|
-
match: {
|
|
387
|
-
user: { isDeleted: false, suspended: false },
|
|
388
|
-
},
|
|
389
|
-
};
|
|
4
|
+
const defaultSelect =
|
|
5
|
+
"iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule";
|
|
390
6
|
|
|
391
|
-
// Cache
|
|
7
|
+
// Cache keys
|
|
392
8
|
const CACHE_KEY_ALL_MEMBERS = "userroles_all_members";
|
|
393
9
|
|
|
394
|
-
|
|
395
|
-
* Construct a flexible query builder for UserRole with advanced filtering and population
|
|
396
|
-
* @param {Object} options - Query configuration options
|
|
397
|
-
* @returns {Promise} Mongoose query result
|
|
398
|
-
*/
|
|
399
|
-
const buildUserRoleQuery = async (options = {}) => {
|
|
400
|
-
const {
|
|
401
|
-
filter = {},
|
|
402
|
-
select = {},
|
|
403
|
-
populate = {},
|
|
404
|
-
cacheKey = CACHE_KEY_ALL_MEMBERS,
|
|
405
|
-
useCache = true,
|
|
406
|
-
lean = true,
|
|
407
|
-
} = options;
|
|
408
|
-
|
|
409
|
-
// Merge default configurations with provided options
|
|
410
|
-
const mergedSelect = {
|
|
411
|
-
userRole: select.userRole || DEFAULT_USER_ROLE_CONFIG.select.userRole,
|
|
412
|
-
role: select.role || DEFAULT_USER_ROLE_CONFIG.select.role,
|
|
413
|
-
permission: select.permission || DEFAULT_USER_ROLE_CONFIG.select.permission,
|
|
414
|
-
user: select.user || DEFAULT_USER_ROLE_CONFIG.select.user,
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
const mergedMatch = {
|
|
418
|
-
user: {
|
|
419
|
-
...DEFAULT_USER_ROLE_CONFIG.match.user,
|
|
420
|
-
...(select.userMatch || {}),
|
|
421
|
-
},
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
// Populate configuration with fallback defaults
|
|
425
|
-
const populateConfig = [
|
|
426
|
-
{
|
|
427
|
-
path: "roleId",
|
|
428
|
-
select: mergedSelect.role,
|
|
429
|
-
populate: {
|
|
430
|
-
path: "permissionId",
|
|
431
|
-
select: mergedSelect.permission,
|
|
432
|
-
},
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
path: "userId",
|
|
436
|
-
match: mergedMatch.user,
|
|
437
|
-
select: mergedSelect.user,
|
|
438
|
-
},
|
|
439
|
-
...(populate.additional || []),
|
|
440
|
-
];
|
|
441
|
-
|
|
10
|
+
const getCachedMembers = async (filter = {}) => {
|
|
442
11
|
try {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
12
|
+
let members = await getRedisData(CACHE_KEY_ALL_MEMBERS);
|
|
13
|
+
|
|
14
|
+
if (!members) {
|
|
15
|
+
members = await UserRole.find()
|
|
16
|
+
.select("userId role userShift roleId workspaceId")
|
|
17
|
+
.populate({
|
|
18
|
+
path: "roleId",
|
|
19
|
+
select: "id name userId userShift permissionId modulePermissions",
|
|
20
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
21
|
+
})
|
|
22
|
+
.populate({
|
|
23
|
+
path: "userId",
|
|
24
|
+
match: { isDeleted: false, suspended: false },
|
|
25
|
+
select: "firstName lastName role email picture userShift _id",
|
|
26
|
+
})
|
|
27
|
+
.lean()
|
|
28
|
+
.exec();
|
|
29
|
+
|
|
30
|
+
members = members?.filter((m) => m?.userId && m?.roleId) || [];
|
|
31
|
+
await setRedisData(CACHE_KEY_ALL_MEMBERS, members);
|
|
450
32
|
}
|
|
451
33
|
|
|
452
|
-
|
|
453
|
-
|
|
34
|
+
const userIdFilter = filter.userId
|
|
35
|
+
? new Set(
|
|
36
|
+
Array.isArray(filter.userId)
|
|
37
|
+
? filter.userId.map((id) => id.toString())
|
|
38
|
+
: [filter.userId.toString()]
|
|
39
|
+
)
|
|
40
|
+
: null;
|
|
454
41
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
42
|
+
const roleIdFilter = filter.roleId
|
|
43
|
+
? Array.isArray(filter.roleId)
|
|
44
|
+
? new Set(filter.roleId.map((id) => id.toString()))
|
|
45
|
+
: typeof filter.roleId === "object"
|
|
46
|
+
? filter.roleId
|
|
47
|
+
: new Set([filter.roleId.toString()])
|
|
48
|
+
: null;
|
|
459
49
|
|
|
460
|
-
|
|
461
|
-
|
|
50
|
+
return members.filter((member) => {
|
|
51
|
+
// Optimize userId filter
|
|
52
|
+
if (userIdFilter && !userIdFilter.has(member.userId?._id?.toString())) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
462
55
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
56
|
+
// Optimize roleId filter
|
|
57
|
+
if (roleIdFilter) {
|
|
58
|
+
if (roleIdFilter instanceof Set) {
|
|
59
|
+
const roleIdStr =
|
|
60
|
+
member.roleId?._id?.toString() ?? member.roleId?.id?.toString();
|
|
61
|
+
if (!roleIdFilter.has(roleIdStr)) return false;
|
|
62
|
+
} else if (typeof roleIdFilter === "object") {
|
|
63
|
+
for (const [key, value] of Object.entries(roleIdFilter)) {
|
|
64
|
+
const roleVal = key.includes(".")
|
|
65
|
+
? key.split(".").reduce((obj, k) => obj?.[k], member.roleId)
|
|
66
|
+
: member.roleId?.[key];
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
if (!value.includes(roleVal)) return false;
|
|
69
|
+
} else if (roleVal !== value) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
467
75
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
76
|
+
// General filters
|
|
77
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
78
|
+
if (key === "userId" || key === "roleId") continue;
|
|
79
|
+
|
|
80
|
+
const memberValue = key.includes(".")
|
|
81
|
+
? key.split(".").reduce((obj, prop) => obj?.[prop], member)
|
|
82
|
+
: member[key];
|
|
83
|
+
|
|
84
|
+
if (Array.isArray(value)) {
|
|
85
|
+
if (!value.includes(memberValue)) return false;
|
|
86
|
+
} else if (typeof value === "object" && value !== null) {
|
|
87
|
+
for (const [subKey, subVal] of Object.entries(value)) {
|
|
88
|
+
if (memberValue?.[subKey] !== subVal) return false;
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
if (memberValue !== value) return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
472
94
|
|
|
473
|
-
|
|
474
|
-
|
|
95
|
+
return true;
|
|
96
|
+
});
|
|
475
97
|
} catch (error) {
|
|
476
|
-
console.error("Error
|
|
98
|
+
console.error("Error fetching cached members:", error);
|
|
477
99
|
return [];
|
|
478
100
|
}
|
|
479
101
|
};
|
|
480
102
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
* @param {Array} data - Data to filter
|
|
484
|
-
* @param {Object} filter - Filter conditions
|
|
485
|
-
* @returns {Array} Filtered results
|
|
486
|
-
*/
|
|
487
|
-
const applyAdvancedFiltering = (data, filter = {}) => {
|
|
488
|
-
if (!data || data.length === 0) return [];
|
|
489
|
-
|
|
490
|
-
return data.filter((item) => {
|
|
491
|
-
for (const [key, value] of Object.entries(filter)) {
|
|
492
|
-
// Skip special filtering keys
|
|
493
|
-
if (key === "userId" || key === "roleId") continue;
|
|
494
|
-
|
|
495
|
-
// Handle nested property access
|
|
496
|
-
const itemValue = key.includes(".")
|
|
497
|
-
? key.split(".").reduce((obj, prop) => obj?.[prop], item)
|
|
498
|
-
: item[key];
|
|
499
|
-
|
|
500
|
-
// Complex filtering logic
|
|
501
|
-
if (Array.isArray(value)) {
|
|
502
|
-
if (!value.includes(itemValue)) return false;
|
|
503
|
-
} else if (typeof value === "object" && value !== null) {
|
|
504
|
-
for (const [subKey, subVal] of Object.entries(value)) {
|
|
505
|
-
if (itemValue?.[subKey] !== subVal) return false;
|
|
506
|
-
}
|
|
507
|
-
} else {
|
|
508
|
-
if (itemValue !== value) return false;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
return true;
|
|
512
|
-
});
|
|
513
|
-
};
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* Wrapper functions using the new query builder
|
|
517
|
-
*/
|
|
518
|
-
const getCachedMembers = async (filter = {}) => buildUserRoleQuery({ filter });
|
|
519
|
-
|
|
520
|
-
const findUserRole = async (filter = {}) => buildUserRoleQuery({ filter });
|
|
521
|
-
|
|
522
|
-
const updateCachedMembers = async (filter = {}) =>
|
|
523
|
-
buildUserRoleQuery({
|
|
524
|
-
filter,
|
|
525
|
-
cacheKey: CACHE_KEY_ALL_MEMBERS,
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
const findSingleUserRoleByFilter = async (filter = {}, options = {}) => {
|
|
529
|
-
const results = await buildUserRoleQuery({
|
|
530
|
-
filter,
|
|
531
|
-
...options,
|
|
532
|
-
});
|
|
533
|
-
return results[0] || null;
|
|
534
|
-
};
|
|
535
|
-
|
|
536
|
-
const getUserPermissions = async (workspaceId, userId) => {
|
|
103
|
+
// Update the cache for all members
|
|
104
|
+
const updateCachedMembers = async (filter = {}) => {
|
|
537
105
|
try {
|
|
538
|
-
const members = await
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
106
|
+
const members = await UserRole.find(filter)
|
|
107
|
+
.select("userId role userShift roleId")
|
|
108
|
+
.populate({
|
|
109
|
+
path: "roleId",
|
|
110
|
+
select: "id name userId userShift permissionId modulePermissions",
|
|
111
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
112
|
+
})
|
|
113
|
+
.populate({
|
|
114
|
+
path: "userId",
|
|
115
|
+
match: { isDeleted: false, suspended: false },
|
|
116
|
+
select: "firstName lastName role email picture userShift",
|
|
117
|
+
})
|
|
118
|
+
.lean()
|
|
119
|
+
.exec();
|
|
120
|
+
|
|
121
|
+
const validMembers =
|
|
122
|
+
members?.filter((member) => member?.userId && member?.roleId) || [];
|
|
123
|
+
|
|
124
|
+
await setRedisData(CACHE_KEY_ALL_MEMBERS, validMembers);
|
|
125
|
+
|
|
126
|
+
return validMembers;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error("Error updating cached members:", error);
|
|
129
|
+
return [];
|
|
547
130
|
}
|
|
548
131
|
};
|
|
549
132
|
|
|
550
|
-
|
|
133
|
+
// Comprehensive cache update method
|
|
134
|
+
const updateAllRelatedCaches = async (userId, workspaceId) => {
|
|
551
135
|
try {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
return {
|
|
556
|
-
...data,
|
|
557
|
-
roleId: data?.roleId?._id?.toString() || "",
|
|
558
|
-
role: data?.roleId?.name || "",
|
|
559
|
-
permissions:
|
|
560
|
-
convertPermissionsArrayToObject(
|
|
561
|
-
data?.roleId?.modulePermissions?.modules
|
|
562
|
-
) || [],
|
|
563
|
-
parentRole: data?.roleId?.permissionId?.name || "",
|
|
564
|
-
parentRoleId: data?.roleId?.permissionId?._id?.toString() || "",
|
|
565
|
-
defaultModule: data?.roleId?.defaultModule || "",
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
return null;
|
|
569
|
-
} catch (err) {
|
|
570
|
-
console.error("Error in getUserRoleWithPermissions:", err);
|
|
571
|
-
return null;
|
|
136
|
+
await updateCachedMembers();
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error("Error updating related caches:", error);
|
|
572
139
|
}
|
|
573
140
|
};
|
|
574
141
|
|
|
575
|
-
//
|
|
142
|
+
// Find single user role by filter
|
|
143
|
+
const findSingleUserRoleByFilter = async (
|
|
144
|
+
filter = {},
|
|
145
|
+
populateOptions = {}
|
|
146
|
+
) => {
|
|
147
|
+
const defaultPopulateOptions = {
|
|
148
|
+
rolePopulate: {
|
|
149
|
+
path: "roleId",
|
|
150
|
+
select: "id name userId userShift permissionId modulePermissions",
|
|
151
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
152
|
+
},
|
|
153
|
+
userPopulate: {
|
|
154
|
+
path: "userId",
|
|
155
|
+
match: { isDeleted: false, suspended: false },
|
|
156
|
+
select: "firstName lastName role email picture userShift",
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const mergedPopulateOptions = {
|
|
160
|
+
rolePopulate: {
|
|
161
|
+
...defaultPopulateOptions.rolePopulate,
|
|
162
|
+
...populateOptions.rolePopulate,
|
|
163
|
+
},
|
|
164
|
+
userPopulate: {
|
|
165
|
+
...defaultPopulateOptions.userPopulate,
|
|
166
|
+
...populateOptions.userPopulate,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
return await UserRole.findOne(filter)
|
|
170
|
+
.populate(mergedPopulateOptions.rolePopulate)
|
|
171
|
+
.populate(mergedPopulateOptions.userPopulate)
|
|
172
|
+
.lean()
|
|
173
|
+
.exec();
|
|
174
|
+
};
|
|
175
|
+
|
|
576
176
|
const convertPermissionsArrayToObject = (originalArray) => {
|
|
577
177
|
return originalArray?.reduce((acc, item) => {
|
|
578
178
|
const { id, actions, integrationPermissions, ...extras } = item;
|
|
@@ -596,66 +196,160 @@ const convertPermissionsArrayToObject = (originalArray) => {
|
|
|
596
196
|
}, {});
|
|
597
197
|
};
|
|
598
198
|
|
|
599
|
-
// Existing methods (simplified)
|
|
600
199
|
const createUserRole = async (data) => {
|
|
601
200
|
const savedRole = await UserRole.create(data);
|
|
602
|
-
|
|
201
|
+
|
|
202
|
+
// Update all related caches
|
|
203
|
+
await updateAllRelatedCaches(
|
|
204
|
+
savedRole?.userId?.toString(),
|
|
205
|
+
savedRole?.workspaceId?.toString()
|
|
206
|
+
);
|
|
207
|
+
|
|
603
208
|
return savedRole;
|
|
604
209
|
};
|
|
605
210
|
|
|
211
|
+
const findOneAndUpdateUserRole = async ({
|
|
212
|
+
workspaceId,
|
|
213
|
+
userId,
|
|
214
|
+
userShift,
|
|
215
|
+
role,
|
|
216
|
+
}) => {
|
|
217
|
+
const updatedRole = await UserRole.findOneAndUpdate(
|
|
218
|
+
{ workspaceId, userId },
|
|
219
|
+
{ $set: { userShift, role } },
|
|
220
|
+
{ new: true, upsert: false }
|
|
221
|
+
).exec();
|
|
222
|
+
if (updatedRole) {
|
|
223
|
+
await updateAllRelatedCaches(userId, workspaceId);
|
|
224
|
+
}
|
|
225
|
+
return updatedRole;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const findUserRole = async (filter = {}) => {
|
|
229
|
+
return await getCachedMembers(filter);
|
|
230
|
+
};
|
|
231
|
+
|
|
606
232
|
const updateUserRole = async (id, data) => {
|
|
607
233
|
const updatedRole = await UserRole.findByIdAndUpdate(id, data, {
|
|
608
234
|
new: true,
|
|
609
235
|
}).exec();
|
|
610
236
|
if (updatedRole) {
|
|
611
|
-
await
|
|
237
|
+
await updateAllRelatedCaches(updatedRole.userId, updatedRole.workspaceId);
|
|
612
238
|
}
|
|
613
239
|
return updatedRole;
|
|
614
240
|
};
|
|
615
241
|
|
|
242
|
+
const deleteUserRoleByFilter = async (filter) => {
|
|
243
|
+
const roleToDelete = await UserRole.findOne(filter).exec();
|
|
244
|
+
const deletedRole = await UserRole.findOneAndDelete(filter).exec();
|
|
245
|
+
if (deletedRole) {
|
|
246
|
+
await updateAllRelatedCaches(
|
|
247
|
+
roleToDelete?.userId,
|
|
248
|
+
roleToDelete?.workspaceId
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
return deletedRole;
|
|
252
|
+
};
|
|
253
|
+
|
|
616
254
|
const deleteUserRole = async (id) => {
|
|
617
255
|
const role = await UserRole.findById(id).exec();
|
|
256
|
+
const userId = role?.userId;
|
|
257
|
+
const workspaceId = role?.workspaceId;
|
|
618
258
|
const deletedRole = await UserRole.findByIdAndDelete(id).exec();
|
|
619
259
|
if (deletedRole) {
|
|
620
|
-
await
|
|
260
|
+
await updateAllRelatedCaches(userId, workspaceId);
|
|
621
261
|
}
|
|
622
262
|
return deletedRole;
|
|
623
263
|
};
|
|
624
264
|
|
|
625
265
|
const findUserWorkspaces = async (userId) => {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
populate
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
266
|
+
let userRoleWithWorkspaces = await UserRole.find({ userId: userId })
|
|
267
|
+
.select("userId roleId workspaceId")
|
|
268
|
+
.populate({
|
|
269
|
+
path: "roleId",
|
|
270
|
+
select: "id name userId userShift permissionId modulePermissions",
|
|
271
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
272
|
+
})
|
|
273
|
+
.populate({
|
|
274
|
+
path: "workspaceId",
|
|
275
|
+
select: defaultSelect,
|
|
276
|
+
match: { isDeleted: false },
|
|
277
|
+
})
|
|
278
|
+
.lean()
|
|
279
|
+
.exec();
|
|
280
|
+
userRoleWithWorkspaces = userRoleWithWorkspaces
|
|
281
|
+
?.filter((userRole) => userRole?.workspaceId)
|
|
282
|
+
?.filter((userRole) => userRole?.roleId)
|
|
283
|
+
?.map((ur) => {
|
|
284
|
+
return {
|
|
285
|
+
...ur?.workspaceId,
|
|
286
|
+
id: ur?.workspaceId?._id?.toString(),
|
|
287
|
+
_id: ur?.workspaceId?._id?.toString(),
|
|
288
|
+
role: ur?.roleId?.name || "",
|
|
289
|
+
permissions: ur?.roleId?.modulePermissions?.modules || [],
|
|
290
|
+
};
|
|
291
|
+
});
|
|
292
|
+
return userRoleWithWorkspaces || [];
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const getUserPermissions = async (workspaceId, userId) => {
|
|
296
|
+
try {
|
|
297
|
+
let members = await getCachedMembers({ workspaceId, userId });
|
|
298
|
+
console.log(members, "members");
|
|
299
|
+
if (members?.length) {
|
|
300
|
+
return (
|
|
301
|
+
convertPermissionsArrayToObject(
|
|
302
|
+
members?.[0]?.roleId?.modulePermissions?.modules
|
|
303
|
+
) || null
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
return null;
|
|
307
|
+
} catch (err) {
|
|
308
|
+
console.error("Error in getUserPermissions:", err);
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const getUserRoleWithPermissions = async (workspaceId, userId) => {
|
|
314
|
+
try {
|
|
315
|
+
let members = await getCachedMembers({ workspaceId, userId });
|
|
316
|
+
console.log(members, "members");
|
|
317
|
+
if (members?.length) {
|
|
318
|
+
let data = members?.[0];
|
|
319
|
+
const roleWithPermissions = {
|
|
320
|
+
...data,
|
|
321
|
+
roleId: data?.roleId?._id?.toString() || "",
|
|
322
|
+
role: data?.roleId?.name || "",
|
|
323
|
+
permissions:
|
|
324
|
+
convertPermissionsArrayToObject(
|
|
325
|
+
data?.roleId?.modulePermissions?.modules
|
|
326
|
+
) || [],
|
|
327
|
+
parentRole: data?.roleId?.permissionId?.name || "",
|
|
328
|
+
parentRoleId: data?.roleId?.permissionId?._id?.toString() || "",
|
|
329
|
+
defaultModule: data?.roleId?.defaultModule || "",
|
|
330
|
+
};
|
|
331
|
+
return roleWithPermissions || null;
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
} catch (err) {
|
|
335
|
+
console.error("Error in getUserRoleWithPermissions:", err);
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
649
338
|
};
|
|
650
339
|
|
|
651
340
|
const getChannelsPermissions = async (workspaceId, userId) => {
|
|
652
341
|
try {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
342
|
+
let members = await getCachedMembers({ workspaceId, userId });
|
|
343
|
+
console.log(members, "members");
|
|
344
|
+
if (members?.length) {
|
|
345
|
+
let data = members?.[0];
|
|
346
|
+
return (
|
|
347
|
+
convertPermissionsArrayToObject(
|
|
348
|
+
data?.roleId?.modulePermissions?.modules
|
|
657
349
|
)?.["conversations"]?.["integrationPermissions"] || []
|
|
658
|
-
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return [];
|
|
659
353
|
} catch (err) {
|
|
660
354
|
console.error("Error in getChannelsPermissions:", err);
|
|
661
355
|
return [];
|
|
@@ -666,13 +360,14 @@ module.exports = {
|
|
|
666
360
|
createUserRole,
|
|
667
361
|
findUserRole,
|
|
668
362
|
updateUserRole,
|
|
363
|
+
deleteUserRoleByFilter,
|
|
669
364
|
deleteUserRole,
|
|
670
365
|
findUserWorkspaces,
|
|
671
366
|
getUserRoleWithPermissions,
|
|
672
367
|
getUserPermissions,
|
|
673
368
|
getChannelsPermissions,
|
|
369
|
+
findOneAndUpdateUserRole,
|
|
674
370
|
findSingleUserRoleByFilter,
|
|
675
371
|
getCachedMembers,
|
|
676
372
|
updateCachedMembers,
|
|
677
|
-
buildUserRoleQuery, // Expose the new flexible query builder
|
|
678
373
|
};
|