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
|
|
13
|
-
const
|
|
12
|
+
// Comprehensive cache get method
|
|
13
|
+
const getCachedMembers = async (filter = {}) => {
|
|
14
14
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
54
|
+
console.error("Error fetching cached members:", error);
|
|
55
|
+
return [];
|
|
29
56
|
}
|
|
30
57
|
};
|
|
31
58
|
|
|
32
|
-
//
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
85
|
-
const
|
|
86
|
-
const cacheKey =
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
};
|