shuttlepro-shared 1.2.64 → 1.2.66

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,61 +1,65 @@
1
1
  const { UserRole } = require("../../models/UserRole");
2
2
  const { getRedisData, setRedisData } = require("../../config/redis");
3
+ const mongoose = require("mongoose");
3
4
 
4
5
  const defaultSelect =
5
6
  "iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule";
6
7
 
7
8
  // Cache keys
8
9
  const CACHE_KEY_ALL_MEMBERS = "userroles_all_members";
9
- const CACHE_KEY_USER_WORKSPACE_PREFIX = "userrole_workspace_";
10
10
  const CACHE_KEY_USER_PERMISSIONS_PREFIX = "user_permissions_";
11
11
 
12
- // Comprehensive cache update method
13
- const updateAllRelatedCaches = async (userId, workspaceId) => {
12
+ // Comprehensive cache get method
13
+ const getCachedMembers = async (filter = {}) => {
14
14
  try {
15
- // Update all members cache
16
- await updateCachedMembers();
17
-
18
- // Clear user workspace cache
19
- if (userId) {
20
- await clearUserWorkspaceCache(userId);
15
+ let members = await getRedisData(CACHE_KEY_ALL_MEMBERS);
16
+
17
+ if (!members) {
18
+ // Fetch from database if not in cache
19
+ members = await UserRole.find()
20
+ .select("userId role userShift roleId workspaceId")
21
+ .populate({
22
+ path: "roleId",
23
+ select: "id name userId userShift permissionId modulePermissions",
24
+ populate: [{ path: "permissionId", select: "id name" }],
25
+ })
26
+ .populate({
27
+ path: "userId",
28
+ match: { isDeleted: false, suspended: false },
29
+ select: "firstName lastName role email picture userShift",
30
+ })
31
+ .lean()
32
+ .exec();
33
+
34
+ // Filter out invalid members
35
+ members =
36
+ members?.filter((member) => member?.userId && member?.roleId) || [];
37
+
38
+ // Cache the result
39
+ await setRedisData(CACHE_KEY_ALL_MEMBERS, members);
21
40
  }
22
41
 
23
- // Clear user permissions cache
24
- if (workspaceId && userId) {
25
- await clearUserPermissionsCache(workspaceId, userId);
26
- }
42
+ // Apply filter in memory
43
+ return members.filter((member) =>
44
+ Object.entries(filter).every(([key, value]) => {
45
+ // Handle nested property access and comparison
46
+ const memberValue = key.includes(".")
47
+ ? key.split(".").reduce((obj, prop) => obj?.[prop], member)
48
+ : member[key];
49
+
50
+ return memberValue === value;
51
+ })
52
+ );
27
53
  } catch (error) {
28
- console.error("Error updating related caches:", error);
54
+ console.error("Error fetching cached members:", error);
55
+ return [];
29
56
  }
30
57
  };
31
58
 
32
- // Clear user workspace cache
33
- const clearUserWorkspaceCache = async (userId) => {
34
- await setRedisData(
35
- `${CACHE_KEY_USER_WORKSPACE_PREFIX}${userId}`,
36
- null,
37
- null,
38
- 0
39
- );
40
- };
41
-
42
- // Clear user permissions cache
43
- const clearUserPermissionsCache = async (workspaceId, userId) => {
44
- const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
45
- await setRedisData(cacheKey, null, null, 0);
46
- };
47
-
48
- // Get cached members
49
- const getCachedMembers = async (filter = {}) => {
50
- const cacheKey =
51
- Object.keys(filter).length > 0
52
- ? `${CACHE_KEY_ALL_MEMBERS}_${JSON.stringify(filter)}`
53
- : CACHE_KEY_ALL_MEMBERS;
54
-
55
- let members = await getRedisData(cacheKey);
56
-
57
- if (!members) {
58
- members = await UserRole.find(filter)
59
+ // Update the cache for all members
60
+ const updateCachedMembers = async (filter = {}) => {
61
+ try {
62
+ const members = await UserRole.find(filter)
59
63
  .select("userId role userShift roleId")
60
64
  .populate({
61
65
  path: "roleId",
@@ -70,46 +74,94 @@ const getCachedMembers = async (filter = {}) => {
70
74
  .lean()
71
75
  .exec();
72
76
 
73
- await setRedisData(
74
- cacheKey,
75
- members?.filter((member) => member?.userId && member?.roleId),
76
- null,
77
- 0
78
- );
77
+ const validMembers =
78
+ members?.filter((member) => member?.userId && member?.roleId) || [];
79
+
80
+ await setRedisData(CACHE_KEY_ALL_MEMBERS, validMembers);
81
+
82
+ return validMembers;
83
+ } catch (error) {
84
+ console.error("Error updating cached members:", error);
85
+ return [];
79
86
  }
87
+ };
80
88
 
81
- return members;
89
+ // Comprehensive cache update method
90
+ const updateAllRelatedCaches = async (userId, workspaceId) => {
91
+ try {
92
+ // Update all members cache
93
+ await updateCachedMembers();
94
+
95
+ // Clear user permissions cache
96
+ if (workspaceId && userId) {
97
+ await clearUserPermissionsCache(workspaceId, userId);
98
+ }
99
+ } catch (error) {
100
+ console.error("Error updating related caches:", error);
101
+ }
82
102
  };
83
103
 
84
- // Update the cache for all members
85
- const updateCachedMembers = async (filter = {}) => {
86
- const cacheKey =
87
- Object.keys(filter).length > 0
88
- ? `${CACHE_KEY_ALL_MEMBERS}_${JSON.stringify(filter)}`
89
- : CACHE_KEY_ALL_MEMBERS;
104
+ // Clear user permissions cache
105
+ const clearUserPermissionsCache = async (workspaceId, userId) => {
106
+ const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
107
+ await setRedisData(cacheKey, null, null, 0);
108
+ };
90
109
 
91
- const members = await UserRole.find(filter)
92
- .select("userId role userShift roleId")
93
- .populate({
110
+ // Find single user role by filter
111
+ const findSingleUserRoleByFilter = async (
112
+ filter = {},
113
+ populateOptions = {}
114
+ ) => {
115
+ const defaultPopulateOptions = {
116
+ rolePopulate: {
94
117
  path: "roleId",
95
118
  select: "id name userId userShift permissionId modulePermissions",
96
119
  populate: [{ path: "permissionId", select: "id name" }],
97
- })
98
- .populate({
120
+ },
121
+ userPopulate: {
99
122
  path: "userId",
100
123
  match: { isDeleted: false, suspended: false },
101
124
  select: "firstName lastName role email picture userShift",
102
- })
125
+ },
126
+ };
127
+ const mergedPopulateOptions = {
128
+ rolePopulate: {
129
+ ...defaultPopulateOptions.rolePopulate,
130
+ ...populateOptions.rolePopulate,
131
+ },
132
+ userPopulate: {
133
+ ...defaultPopulateOptions.userPopulate,
134
+ ...populateOptions.userPopulate,
135
+ },
136
+ };
137
+ return await UserRole.findOne(filter)
138
+ .populate(mergedPopulateOptions.rolePopulate)
139
+ .populate(mergedPopulateOptions.userPopulate)
103
140
  .lean()
104
141
  .exec();
142
+ };
105
143
 
106
- await setRedisData(
107
- cacheKey,
108
- members?.filter((member) => member?.userId && member?.roleId),
109
- null,
110
- 0
111
- );
112
- return members;
144
+ const convertPermissionsArrayToObject = (originalArray) => {
145
+ return originalArray?.reduce((acc, item) => {
146
+ const { id, actions, integrationPermissions, ...extras } = item;
147
+ const formattedExtras = {};
148
+ if (extras.deletable !== undefined) {
149
+ formattedExtras.deletable = extras.deletable;
150
+ }
151
+ if (extras.createUpdateable !== undefined) {
152
+ formattedExtras.createUpdateable = extras.createUpdateable;
153
+ }
154
+ acc[id] = {
155
+ actions: Object.keys(actions).filter((action) => actions[action]),
156
+ ...formattedExtras,
157
+ ...(integrationPermissions && {
158
+ integrationPermissions: Object.entries(integrationPermissions)
159
+ .filter(([_, allowed]) => allowed)
160
+ .map(([key]) => key),
161
+ }),
162
+ };
163
+ return acc;
164
+ }, {});
113
165
  };
114
166
 
115
167
  const createUserRole = async (data) => {
@@ -124,6 +176,23 @@ const createUserRole = async (data) => {
124
176
  return savedRole;
125
177
  };
126
178
 
179
+ const findOneAndUpdateUserRole = async ({
180
+ workspaceId,
181
+ userId,
182
+ userShift,
183
+ role,
184
+ }) => {
185
+ const updatedRole = await UserRole.findOneAndUpdate(
186
+ { workspaceId, userId },
187
+ { $set: { userShift, role } },
188
+ { new: true, upsert: false }
189
+ ).exec();
190
+ if (updatedRole) {
191
+ await updateAllRelatedCaches(userId, workspaceId);
192
+ }
193
+ return updatedRole;
194
+ };
195
+
127
196
  const findUserRole = async (filter = {}) => {
128
197
  return await getCachedMembers(filter);
129
198
  };
@@ -132,29 +201,21 @@ const updateUserRole = async (id, data) => {
132
201
  const updatedRole = await UserRole.findByIdAndUpdate(id, data, {
133
202
  new: true,
134
203
  }).exec();
135
-
136
204
  if (updatedRole) {
137
- // Update all related caches
138
205
  await updateAllRelatedCaches(updatedRole.userId, updatedRole.workspaceId);
139
206
  }
140
-
141
207
  return updatedRole;
142
208
  };
143
209
 
144
210
  const deleteUserRoleByFilter = async (filter) => {
145
- // Find the role before deleting to get userId and workspaceId
146
211
  const roleToDelete = await UserRole.findOne(filter).exec();
147
-
148
212
  const deletedRole = await UserRole.findOneAndDelete(filter).exec();
149
-
150
213
  if (deletedRole) {
151
- // Update all related caches
152
214
  await updateAllRelatedCaches(
153
215
  roleToDelete?.userId,
154
216
  roleToDelete?.workspaceId
155
217
  );
156
218
  }
157
-
158
219
  return deletedRole;
159
220
  };
160
221
 
@@ -162,76 +223,40 @@ const deleteUserRole = async (id) => {
162
223
  const role = await UserRole.findById(id).exec();
163
224
  const userId = role?.userId;
164
225
  const workspaceId = role?.workspaceId;
165
-
166
226
  const deletedRole = await UserRole.findByIdAndDelete(id).exec();
167
-
168
227
  if (deletedRole) {
169
- // Update all related caches
170
228
  await updateAllRelatedCaches(userId, workspaceId);
171
229
  }
172
-
173
230
  return deletedRole;
174
231
  };
175
232
 
176
233
  const findUserWorkspaces = async (userId) => {
177
- const cacheKey = `${CACHE_KEY_USER_WORKSPACE_PREFIX}${userId}`;
178
- let userRoleWithWorkspaces = await getRedisData(cacheKey);
179
- if (!userRoleWithWorkspaces) {
180
- userRoleWithWorkspaces = await UserRole.find({
181
- userId: userId,
234
+ return await UserRole.find({ userId: userId })
235
+ .select("userId roleId workspaceId")
236
+ .populate({
237
+ path: "roleId",
238
+ select: "id name userId userShift permissionId modulePermissions",
239
+ populate: [{ path: "permissionId", select: "id name" }],
182
240
  })
183
- .select("userId roleId workspaceId")
184
- .populate({
185
- path: "roleId",
186
- select: "id name userId userShift permissionId modulePermissions",
187
- populate: [{ path: "permissionId", select: "id name" }],
188
- })
189
- .populate({
190
- path: "workspaceId",
191
- select: defaultSelect,
192
- match: { isDeleted: false },
193
- })
194
- .lean()
195
- .exec();
196
- userRoleWithWorkspaces = userRoleWithWorkspaces
197
- ?.filter((userRole) => userRole?.workspaceId)
198
- ?.map((ur) => {
199
- return {
200
- ...ur?.workspaceId,
201
- id: ur?.workspaceId?._id?.toString(),
202
- _id: ur?.workspaceId?._id?.toString(),
203
- role: ur?.roleId?.name || "",
204
- permissions: ur?.roleId?.modulePermissions?.modules || [],
205
- };
206
- });
207
- if (userRoleWithWorkspaces) {
208
- await setRedisData(cacheKey, userRoleWithWorkspaces, null, 0);
209
- }
210
- }
211
- return userRoleWithWorkspaces;
212
- };
213
-
214
- const convertPermissionsArrayToObject = (originalArray) => {
215
- return originalArray?.reduce((acc, item) => {
216
- const { id, actions, integrationPermissions, ...extras } = item;
217
- const formattedExtras = {};
218
- if (extras.deletable !== undefined) {
219
- formattedExtras.deletable = extras.deletable;
220
- }
221
- if (extras.createUpdateable !== undefined) {
222
- formattedExtras.createUpdateable = extras.createUpdateable;
223
- }
224
- acc[id] = {
225
- actions: Object.keys(actions).filter((action) => actions[action]),
226
- ...formattedExtras,
227
- ...(integrationPermissions && {
228
- integrationPermissions: Object.entries(integrationPermissions)
229
- .filter(([_, allowed]) => allowed)
230
- .map(([key]) => key),
231
- }),
232
- };
233
- return acc;
234
- }, {});
241
+ .populate({
242
+ path: "workspaceId",
243
+ select: defaultSelect,
244
+ match: { isDeleted: false },
245
+ })
246
+ .lean()
247
+ .exec();
248
+ userRoleWithWorkspaces = userRoleWithWorkspaces
249
+ ?.filter((userRole) => userRole?.workspaceId)
250
+ ?.filter((userRole) => userRole?.roleId)
251
+ ?.map((ur) => {
252
+ return {
253
+ ...ur?.workspaceId,
254
+ id: ur?.workspaceId?._id?.toString(),
255
+ _id: ur?.workspaceId?._id?.toString(),
256
+ role: ur?.roleId?.name || "",
257
+ permissions: ur?.roleId?.modulePermissions?.modules || [],
258
+ };
259
+ });
235
260
  };
236
261
 
237
262
  const getUserRoleWithPermissions = async (workspaceId, userId) => {
@@ -276,7 +301,7 @@ const getUserRoleWithPermissions = async (workspaceId, userId) => {
276
301
  // Store in cache with other permission data
277
302
  const permissionsData = cachedData || {};
278
303
  permissionsData.roleWithPermissions = roleWithPermissions;
279
- await setRedisData(cacheKey, permissionsData, null, 0);
304
+ await setRedisData(cacheKey, permissionsData);
280
305
 
281
306
  return roleWithPermissions;
282
307
  } catch (err) {
@@ -318,7 +343,7 @@ const getUserPermissions = async (workspaceId, userId) => {
318
343
  // Store in cache with other permission data
319
344
  const permissionsData = cachedData || {};
320
345
  permissionsData.permissions = permissions;
321
- await setRedisData(cacheKey, permissionsData, null, 0);
346
+ await setRedisData(cacheKey, permissionsData);
322
347
 
323
348
  return permissions;
324
349
  } catch (err) {
@@ -330,11 +355,9 @@ const getUserPermissions = async (workspaceId, userId) => {
330
355
  const getChannelsPermissions = async (workspaceId, userId) => {
331
356
  const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
332
357
  let cachedData = await getRedisData(cacheKey);
333
-
334
358
  if (cachedData && cachedData.channelsPermissions) {
335
359
  return cachedData.channelsPermissions;
336
360
  }
337
-
338
361
  try {
339
362
  let data = await UserRole.findOne({
340
363
  workspaceId: workspaceId,
@@ -347,11 +370,9 @@ const getChannelsPermissions = async (workspaceId, userId) => {
347
370
  })
348
371
  .lean()
349
372
  .exec();
350
-
351
373
  if (!data) {
352
374
  return [];
353
375
  }
354
-
355
376
  const channelsPermissions =
356
377
  convertPermissionsArrayToObject(
357
378
  data?.roleId?.modulePermissions?.modules
@@ -360,7 +381,7 @@ const getChannelsPermissions = async (workspaceId, userId) => {
360
381
  // Store in cache with other permission data
361
382
  const permissionsData = cachedData || {};
362
383
  permissionsData.channelsPermissions = channelsPermissions;
363
- await setRedisData(cacheKey, permissionsData, null, 0);
384
+ await setRedisData(cacheKey, permissionsData);
364
385
 
365
386
  return channelsPermissions;
366
387
  } catch (err) {
@@ -369,26 +390,6 @@ const getChannelsPermissions = async (workspaceId, userId) => {
369
390
  }
370
391
  };
371
392
 
372
- const findOneAndUpdateUserRole = async ({
373
- workspaceId,
374
- userId,
375
- userShift,
376
- role,
377
- }) => {
378
- const updatedRole = await UserRole.findOneAndUpdate(
379
- { workspaceId, userId },
380
- { $set: { userShift, role } },
381
- { new: true, upsert: false }
382
- ).exec();
383
-
384
- if (updatedRole) {
385
- // Update all related caches
386
- await updateAllRelatedCaches(userId, workspaceId);
387
- }
388
-
389
- return updatedRole;
390
- };
391
-
392
393
  module.exports = {
393
394
  createUserRole,
394
395
  findUserRole,
@@ -400,4 +401,7 @@ module.exports = {
400
401
  getUserPermissions,
401
402
  getChannelsPermissions,
402
403
  findOneAndUpdateUserRole,
404
+ findSingleUserRoleByFilter,
405
+ getCachedMembers,
406
+ updateCachedMembers,
403
407
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shuttlepro-shared",
3
- "version": "1.2.64",
3
+ "version": "1.2.66",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {