shuttlepro-shared 1.2.68 → 1.2.70

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,145 +1,578 @@
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
+
1
375
  const { UserRole } = require("../../models/UserRole");
2
376
  const { getRedisData, setRedisData } = require("../../config/redis");
3
377
 
4
- const defaultSelect =
5
- "iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule";
378
+ // Default selection and population configurations
379
+ const DEFAULT_USER_ROLE_CONFIG = {
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
+ };
6
390
 
7
- // Cache keys
391
+ // Cache key constant
8
392
  const CACHE_KEY_ALL_MEMBERS = "userroles_all_members";
9
- const CACHE_KEY_USER_PERMISSIONS_PREFIX = "user_permissions_";
10
393
 
11
- // Comprehensive cache get method
12
- const getCachedMembers = async (filter = {}) => {
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
+
13
442
  try {
14
- let members = await getRedisData(CACHE_KEY_ALL_MEMBERS);
15
-
16
- if (!members) {
17
- // Fetch from database if not in cache
18
- members = await UserRole.find()
19
- .select("userId role userShift roleId workspaceId")
20
- .populate({
21
- path: "roleId",
22
- select: "id name userId userShift permissionId modulePermissions",
23
- populate: [{ path: "permissionId", select: "id name" }],
24
- })
25
- .populate({
26
- path: "userId",
27
- match: { isDeleted: false, suspended: false },
28
- select: "firstName lastName role email picture userShift",
29
- })
30
- .lean()
31
- .exec();
32
-
33
- // Filter out invalid members
34
- members =
35
- members?.filter((member) => member?.userId && member?.roleId) || [];
36
-
37
- // Cache the result
38
- await setRedisData(CACHE_KEY_ALL_MEMBERS, members);
443
+ // Check cache first if useCache is true
444
+ if (useCache) {
445
+ let cachedData = await getRedisData(cacheKey);
446
+
447
+ if (cachedData) {
448
+ return applyAdvancedFiltering(cachedData, filter);
449
+ }
39
450
  }
40
451
 
41
- // Apply filter in memory
42
- return members.filter((member) =>
43
- Object.entries(filter).every(([key, value]) => {
44
- // Handle nested property access and comparison
45
- const memberValue = key.includes(".")
46
- ? key.split(".").reduce((obj, prop) => obj?.[prop], member)
47
- : member[key];
452
+ // Construct base query
453
+ let query = UserRole.find(filter).select(mergedSelect.userRole);
454
+
455
+ // Apply population
456
+ populateConfig.forEach((config) => {
457
+ query = query.populate(config);
458
+ });
459
+
460
+ // Execute query
461
+ const results = lean ? await query.lean().exec() : await query.exec();
48
462
 
49
- return memberValue === value;
50
- })
463
+ // Filter out invalid entries and cache results
464
+ const validResults = results.filter(
465
+ (result) => result?.userId && result?.roleId
51
466
  );
467
+
468
+ // Cache results if useCache is true
469
+ if (useCache) {
470
+ await setRedisData(cacheKey, validResults);
471
+ }
472
+
473
+ // Apply advanced filtering
474
+ return applyAdvancedFiltering(validResults, filter);
52
475
  } catch (error) {
53
- console.error("Error fetching cached members:", error);
476
+ console.error("Error in buildUserRoleQuery:", error);
54
477
  return [];
55
478
  }
56
479
  };
57
480
 
58
- // Update the cache for all members
59
- const updateCachedMembers = async (filter = {}) => {
481
+ /**
482
+ * Apply advanced filtering with nested property support
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) => {
60
537
  try {
61
- const members = await UserRole.find(filter)
62
- .select("userId role userShift roleId")
63
- .populate({
64
- path: "roleId",
65
- select: "id name userId userShift permissionId modulePermissions",
66
- populate: [{ path: "permissionId", select: "id name" }],
67
- })
68
- .populate({
69
- path: "userId",
70
- match: { isDeleted: false, suspended: false },
71
- select: "firstName lastName role email picture userShift",
72
- })
73
- .lean()
74
- .exec();
75
-
76
- const validMembers =
77
- members?.filter((member) => member?.userId && member?.roleId) || [];
78
-
79
- await setRedisData(CACHE_KEY_ALL_MEMBERS, validMembers);
80
-
81
- return validMembers;
82
- } catch (error) {
83
- console.error("Error updating cached members:", error);
84
- return [];
538
+ const members = await getCachedMembers({ workspaceId, userId });
539
+ return members?.[0]?.roleId?.modulePermissions?.modules
540
+ ? convertPermissionsArrayToObject(
541
+ members[0].roleId.modulePermissions.modules
542
+ )
543
+ : null;
544
+ } catch (err) {
545
+ console.error("Error in getUserPermissions:", err);
546
+ return null;
85
547
  }
86
548
  };
87
549
 
88
- // Comprehensive cache update method
89
- const updateAllRelatedCaches = async (userId, workspaceId) => {
550
+ const getUserRoleWithPermissions = async (workspaceId, userId) => {
90
551
  try {
91
- // Update all members cache
92
- await updateCachedMembers();
93
-
94
- // Clear user permissions cache
95
- if (workspaceId && userId) {
96
- await clearUserPermissionsCache(workspaceId, userId);
552
+ const members = await getCachedMembers({ workspaceId, userId });
553
+ if (members?.length) {
554
+ const data = members[0];
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
+ };
97
567
  }
98
- } catch (error) {
99
- console.error("Error updating related caches:", error);
568
+ return null;
569
+ } catch (err) {
570
+ console.error("Error in getUserRoleWithPermissions:", err);
571
+ return null;
100
572
  }
101
573
  };
102
574
 
103
- // Clear user permissions cache
104
- const clearUserPermissionsCache = async (workspaceId, userId) => {
105
- const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
106
- await setRedisData(cacheKey, null, null, 0);
107
- };
108
-
109
- // Find single user role by filter
110
- const findSingleUserRoleByFilter = async (
111
- filter = {},
112
- populateOptions = {}
113
- ) => {
114
- const defaultPopulateOptions = {
115
- rolePopulate: {
116
- path: "roleId",
117
- select: "id name userId userShift permissionId modulePermissions",
118
- populate: [{ path: "permissionId", select: "id name" }],
119
- },
120
- userPopulate: {
121
- path: "userId",
122
- match: { isDeleted: false, suspended: false },
123
- select: "firstName lastName role email picture userShift",
124
- },
125
- };
126
- const mergedPopulateOptions = {
127
- rolePopulate: {
128
- ...defaultPopulateOptions.rolePopulate,
129
- ...populateOptions.rolePopulate,
130
- },
131
- userPopulate: {
132
- ...defaultPopulateOptions.userPopulate,
133
- ...populateOptions.userPopulate,
134
- },
135
- };
136
- return await UserRole.findOne(filter)
137
- .populate(mergedPopulateOptions.rolePopulate)
138
- .populate(mergedPopulateOptions.userPopulate)
139
- .lean()
140
- .exec();
141
- };
142
-
575
+ // Existing utility function
143
576
  const convertPermissionsArrayToObject = (originalArray) => {
144
577
  return originalArray?.reduce((acc, item) => {
145
578
  const { id, actions, integrationPermissions, ...extras } = item;
@@ -163,179 +596,66 @@ const convertPermissionsArrayToObject = (originalArray) => {
163
596
  }, {});
164
597
  };
165
598
 
599
+ // Existing methods (simplified)
166
600
  const createUserRole = async (data) => {
167
601
  const savedRole = await UserRole.create(data);
168
-
169
- // Update all related caches
170
- await updateAllRelatedCaches(
171
- savedRole?.userId?.toString(),
172
- savedRole?.workspaceId?.toString()
173
- );
174
-
602
+ await updateCachedMembers();
175
603
  return savedRole;
176
604
  };
177
605
 
178
- const findOneAndUpdateUserRole = async ({
179
- workspaceId,
180
- userId,
181
- userShift,
182
- role,
183
- }) => {
184
- const updatedRole = await UserRole.findOneAndUpdate(
185
- { workspaceId, userId },
186
- { $set: { userShift, role } },
187
- { new: true, upsert: false }
188
- ).exec();
189
- if (updatedRole) {
190
- await updateAllRelatedCaches(userId, workspaceId);
191
- }
192
- return updatedRole;
193
- };
194
-
195
- const findUserRole = async (filter = {}) => {
196
- return await getCachedMembers(filter);
197
- };
198
-
199
606
  const updateUserRole = async (id, data) => {
200
607
  const updatedRole = await UserRole.findByIdAndUpdate(id, data, {
201
608
  new: true,
202
609
  }).exec();
203
610
  if (updatedRole) {
204
- await updateAllRelatedCaches(updatedRole.userId, updatedRole.workspaceId);
611
+ await updateCachedMembers();
205
612
  }
206
613
  return updatedRole;
207
614
  };
208
615
 
209
- const deleteUserRoleByFilter = async (filter) => {
210
- const roleToDelete = await UserRole.findOne(filter).exec();
211
- const deletedRole = await UserRole.findOneAndDelete(filter).exec();
212
- if (deletedRole) {
213
- await updateAllRelatedCaches(
214
- roleToDelete?.userId,
215
- roleToDelete?.workspaceId
216
- );
217
- }
218
- return deletedRole;
219
- };
220
-
221
616
  const deleteUserRole = async (id) => {
222
617
  const role = await UserRole.findById(id).exec();
223
- const userId = role?.userId;
224
- const workspaceId = role?.workspaceId;
225
618
  const deletedRole = await UserRole.findByIdAndDelete(id).exec();
226
619
  if (deletedRole) {
227
- await updateAllRelatedCaches(userId, workspaceId);
620
+ await updateCachedMembers();
228
621
  }
229
622
  return deletedRole;
230
623
  };
231
624
 
232
625
  const findUserWorkspaces = async (userId) => {
233
- let userRoleWithWorkspaces = await UserRole.find({ userId: userId })
234
- .select("userId roleId workspaceId")
235
- .populate({
236
- path: "roleId",
237
- select: "id name userId userShift permissionId modulePermissions",
238
- populate: [{ path: "permissionId", select: "id name" }],
239
- })
240
- .populate({
241
- path: "workspaceId",
242
- select: defaultSelect,
243
- match: { isDeleted: false },
244
- })
245
- .lean()
246
- .exec();
247
- userRoleWithWorkspaces = userRoleWithWorkspaces
248
- ?.filter((userRole) => userRole?.workspaceId)
249
- ?.filter((userRole) => userRole?.roleId)
250
- ?.map((ur) => {
251
- return {
252
- ...ur?.workspaceId,
253
- id: ur?.workspaceId?._id?.toString(),
254
- _id: ur?.workspaceId?._id?.toString(),
255
- role: ur?.roleId?.name || "",
256
- permissions: ur?.roleId?.modulePermissions?.modules || [],
257
- };
258
- });
259
- return userRoleWithWorkspaces || [];
260
- };
261
-
262
- const getUserPermissions = async (workspaceId, userId) => {
263
- try {
264
- let members = await getCachedMembers({ workspaceId, userId });
265
- console.log(members, "members");
266
- if (members?.length) {
267
- return (
268
- convertPermissionsArrayToObject(
269
- members?.[0]?.roleId?.modulePermissions?.modules
270
- ) || null
271
- );
272
- }
273
- return null;
274
- } catch (err) {
275
- console.error("Error in getUserPermissions:", err);
276
- return null;
277
- }
278
- };
279
-
280
- const getUserRoleWithPermissions = async (workspaceId, userId) => {
281
- try {
282
- let members = await getCachedMembers({ workspaceId, userId });
283
- console.log(members, "members");
284
- if (members?.length) {
285
- let data = members?.[0];
286
- const roleWithPermissions = {
287
- ...data,
288
- roleId: data?.roleId?._id?.toString() || "",
289
- role: data?.roleId?.name || "",
290
- permissions:
291
- convertPermissionsArrayToObject(
292
- data?.roleId?.modulePermissions?.modules
293
- ) || [],
294
- parentRole: data?.roleId?.permissionId?.name || "",
295
- parentRoleId: data?.roleId?.permissionId?._id?.toString() || "",
296
- defaultModule: data?.roleId?.defaultModule || "",
297
- };
298
- return roleWithPermissions || null;
299
- }
300
- return null;
301
- } catch (err) {
302
- console.error("Error in getUserRoleWithPermissions:", err);
303
- return null;
304
- }
626
+ const userRoles = await buildUserRoleQuery({
627
+ filter: { userId },
628
+ populate: {
629
+ additional: [
630
+ {
631
+ path: "workspaceId",
632
+ select:
633
+ "iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule",
634
+ match: { isDeleted: false },
635
+ },
636
+ ],
637
+ },
638
+ });
639
+
640
+ return userRoles
641
+ .filter((userRole) => userRole.workspaceId)
642
+ .map((ur) => ({
643
+ ...ur.workspaceId,
644
+ id: ur.workspaceId?._id?.toString(),
645
+ _id: ur.workspaceId?._id?.toString(),
646
+ role: ur.roleId?.name || "",
647
+ permissions: ur.roleId?.modulePermissions?.modules || [],
648
+ }));
305
649
  };
306
650
 
307
651
  const getChannelsPermissions = async (workspaceId, userId) => {
308
- const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
309
- let cachedData = await getRedisData(cacheKey);
310
- if (cachedData && cachedData.channelsPermissions) {
311
- return cachedData.channelsPermissions;
312
- }
313
652
  try {
314
- let data = await UserRole.findOne({
315
- workspaceId: workspaceId,
316
- userId: userId,
317
- })
318
- .select("roleId userId")
319
- .populate({
320
- path: "roleId",
321
- select: "modulePermissions",
322
- })
323
- .lean()
324
- .exec();
325
- if (!data) {
326
- return [];
327
- }
328
- const channelsPermissions =
329
- convertPermissionsArrayToObject(
330
- data?.roleId?.modulePermissions?.modules
331
- )?.["conversations"]?.["integrationPermissions"] || [];
332
-
333
- // Store in cache with other permission data
334
- const permissionsData = cachedData || {};
335
- permissionsData.channelsPermissions = channelsPermissions;
336
- await setRedisData(cacheKey, permissionsData);
337
-
338
- return channelsPermissions;
653
+ const members = await getCachedMembers({ workspaceId, userId });
654
+ return members?.[0]?.roleId?.modulePermissions?.modules
655
+ ? convertPermissionsArrayToObject(
656
+ members[0].roleId.modulePermissions.modules
657
+ )?.["conversations"]?.["integrationPermissions"] || []
658
+ : [];
339
659
  } catch (err) {
340
660
  console.error("Error in getChannelsPermissions:", err);
341
661
  return [];
@@ -346,14 +666,13 @@ module.exports = {
346
666
  createUserRole,
347
667
  findUserRole,
348
668
  updateUserRole,
349
- deleteUserRoleByFilter,
350
669
  deleteUserRole,
351
670
  findUserWorkspaces,
352
671
  getUserRoleWithPermissions,
353
672
  getUserPermissions,
354
673
  getChannelsPermissions,
355
- findOneAndUpdateUserRole,
356
674
  findSingleUserRoleByFilter,
357
675
  getCachedMembers,
358
676
  updateCachedMembers,
677
+ buildUserRoleQuery, // Expose the new flexible query builder
359
678
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shuttlepro-shared",
3
- "version": "1.2.68",
3
+ "version": "1.2.70",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {