shuttlepro-shared 1.2.43 → 1.2.45
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.
- package/common/repositories/descriptionTemplates.repository.js +0 -25
- package/common/repositories/index.js +2 -0
- package/common/repositories/role.repository.js +329 -0
- package/common/repositories/userRole.repository.js +313 -6
- package/common/repositories/workspace.repository.js +49 -2
- package/config/redis.js +1 -0
- package/models/UserRole.js +0 -106
- package/package.json +1 -1
|
@@ -79,30 +79,6 @@ const findTemplateByFilter = async (
|
|
|
79
79
|
) || null
|
|
80
80
|
);
|
|
81
81
|
};
|
|
82
|
-
const findAllTemplateByFilter = async (
|
|
83
|
-
filter,
|
|
84
|
-
bodyFilter = {},
|
|
85
|
-
workspaceId = null
|
|
86
|
-
) => {
|
|
87
|
-
const allTemplates = await getCachedAllDescriptionTemplates();
|
|
88
|
-
|
|
89
|
-
// Filter by workspaceId if provided
|
|
90
|
-
let filteredTemplates = workspaceId
|
|
91
|
-
? allTemplates.filter((desc) => desc.workspaceId === workspaceId)
|
|
92
|
-
: allTemplates;
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
filteredTemplates.filter(
|
|
96
|
-
(item) =>
|
|
97
|
-
// Check direct properties of item
|
|
98
|
-
Object.entries(filter).every(([key, value]) => item[key] === value) &&
|
|
99
|
-
// If bodyFilter is provided, check inside item.body
|
|
100
|
-
Object.entries(bodyFilter).every(
|
|
101
|
-
([key, value]) => item.body?.[key] === value
|
|
102
|
-
)
|
|
103
|
-
) || null
|
|
104
|
-
);
|
|
105
|
-
};
|
|
106
82
|
const createOrUpdateTemplate = async (filter, data) => {
|
|
107
83
|
const template = await DescriptionTemplate.findOneAndUpdate(filter, data, {
|
|
108
84
|
upsert: true,
|
|
@@ -225,5 +201,4 @@ module.exports = {
|
|
|
225
201
|
findTemplateById,
|
|
226
202
|
deleteTemplatesByFilter,
|
|
227
203
|
insertManyTemplates,
|
|
228
|
-
findAllTemplateByFilter,
|
|
229
204
|
};
|
|
@@ -9,6 +9,7 @@ const settingRepository = require("./settings.repository");
|
|
|
9
9
|
const socialMediaSettingRepository = require("./socialMediaSetting.repository");
|
|
10
10
|
const notificationSettingRepository = require("./notificationSetting.repository");
|
|
11
11
|
const chatMemberRepository = require("./chatMember.repository");
|
|
12
|
+
const roleRepository = require("./role.repository");
|
|
12
13
|
|
|
13
14
|
exports.module = {
|
|
14
15
|
workspaceRepository,
|
|
@@ -22,4 +23,5 @@ exports.module = {
|
|
|
22
23
|
socialMediaSettingRepository,
|
|
23
24
|
notificationSettingRepository,
|
|
24
25
|
chatMemberRepository,
|
|
26
|
+
roleRepository,
|
|
25
27
|
};
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
const Role = require("../../models/Role");
|
|
2
|
+
const { utils } = require("shuttlepro-utils");
|
|
3
|
+
const { getRedisData, setRedisData } = require("../config/redis");
|
|
4
|
+
|
|
5
|
+
const CACHE_KEY_ALL = "roles_all";
|
|
6
|
+
const CACHE_KEY_DEFAULT = "roles_default";
|
|
7
|
+
|
|
8
|
+
const getCachedRoles = async () => {
|
|
9
|
+
let roles = await getRedisData(CACHE_KEY_ALL);
|
|
10
|
+
if (!roles) {
|
|
11
|
+
roles = await Role.find().populate("permissionId").lean().exec();
|
|
12
|
+
await setRedisData(CACHE_KEY_ALL, roles);
|
|
13
|
+
} else {
|
|
14
|
+
roles = roles;
|
|
15
|
+
}
|
|
16
|
+
return roles;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const updateCachedRoles = async () => {
|
|
20
|
+
const roles = await Role.find().populate("permissionId").lean().exec();
|
|
21
|
+
await setRedisData(CACHE_KEY_ALL, roles);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const getCachedDefaultRoles = async () => {
|
|
25
|
+
let defaultRoles = await getRedisData(CACHE_KEY_DEFAULT);
|
|
26
|
+
if (!defaultRoles) {
|
|
27
|
+
const data = await Role.find({ name: { $ne: "super" }, workspaceId: null })
|
|
28
|
+
.select("name")
|
|
29
|
+
.sort({ _id: -1 })
|
|
30
|
+
.lean()
|
|
31
|
+
.exec();
|
|
32
|
+
|
|
33
|
+
defaultRoles = data.map((d) => {
|
|
34
|
+
return {
|
|
35
|
+
id: d?._id,
|
|
36
|
+
name: utils.capitalize(d?.name),
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await setRedisData(CACHE_KEY_DEFAULT, defaultRoles);
|
|
41
|
+
}
|
|
42
|
+
return defaultRoles;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const updateCachedDefaultRoles = async () => {
|
|
46
|
+
const data = await Role.find({ name: { $ne: "super" }, workspaceId: null })
|
|
47
|
+
.select("name")
|
|
48
|
+
.sort({ _id: -1 })
|
|
49
|
+
.lean()
|
|
50
|
+
.exec();
|
|
51
|
+
|
|
52
|
+
const defaultRoles = data.map((d) => {
|
|
53
|
+
return {
|
|
54
|
+
id: d?._id,
|
|
55
|
+
name: utils.capitalize(d?.name),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await setRedisData(CACHE_KEY_DEFAULT, defaultRoles);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const createRole = async (roleData) => {
|
|
63
|
+
const newRole = await Role.create(roleData);
|
|
64
|
+
const createdRole = await Role.findById(newRole._id)
|
|
65
|
+
.populate("permissionId")
|
|
66
|
+
.lean()
|
|
67
|
+
.exec();
|
|
68
|
+
await updateCachedRoles();
|
|
69
|
+
return createdRole;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const findRoleById = async (id) => {
|
|
73
|
+
const roles = await getCachedRoles();
|
|
74
|
+
const role = roles.find((r) => r._id.toString() === id) || null;
|
|
75
|
+
|
|
76
|
+
if (role) return role;
|
|
77
|
+
|
|
78
|
+
// If not found in cache, query directly
|
|
79
|
+
return await Role.findById(id).populate("permissionId").lean().exec();
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const findSingleRole = async (filter) => {
|
|
83
|
+
const roles = await getCachedRoles();
|
|
84
|
+
const role =
|
|
85
|
+
roles.find((r) =>
|
|
86
|
+
Object.entries(filter).every(([key, value]) => r[key] === value)
|
|
87
|
+
) || null;
|
|
88
|
+
|
|
89
|
+
if (role) return role;
|
|
90
|
+
|
|
91
|
+
// If not found in cache, query directly
|
|
92
|
+
return await Role.findOne(filter).populate("permissionId").lean().exec();
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const findRolesByPagination = async (body) => {
|
|
96
|
+
let { page, limit, workspaceId, query, status } = body;
|
|
97
|
+
|
|
98
|
+
page = parseInt(page, 10) || 1;
|
|
99
|
+
limit = parseInt(limit, 10) || 10;
|
|
100
|
+
|
|
101
|
+
const skip = (page - 1) * limit;
|
|
102
|
+
|
|
103
|
+
let obj = { workspaceId };
|
|
104
|
+
if (query) {
|
|
105
|
+
obj.name = { $regex: query, $options: "i" };
|
|
106
|
+
}
|
|
107
|
+
if (status) {
|
|
108
|
+
obj.status = status;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const totalRoles = await Role.countDocuments(obj);
|
|
112
|
+
const totalPages = Math.ceil(totalRoles / limit);
|
|
113
|
+
|
|
114
|
+
const roles = await Role.find(obj)
|
|
115
|
+
.sort({ _id: -1 })
|
|
116
|
+
.skip(skip)
|
|
117
|
+
.limit(limit)
|
|
118
|
+
.populate("permissionId")
|
|
119
|
+
.lean()
|
|
120
|
+
.exec();
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
totalPages,
|
|
124
|
+
currentPage: page,
|
|
125
|
+
roles,
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const findRoles = async (workspaceId) => {
|
|
130
|
+
const roles = await getCachedRoles();
|
|
131
|
+
return roles.filter((r) => r.workspaceId === workspaceId);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const findDefaultRoles = async () => {
|
|
135
|
+
return await getCachedDefaultRoles();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const updateRoleById = async (id, updateData) => {
|
|
139
|
+
const updateQuery = {
|
|
140
|
+
...updateData,
|
|
141
|
+
...(Array.isArray(updateData.logs) && {
|
|
142
|
+
$push: { logs: { $each: updateData.logs } },
|
|
143
|
+
}),
|
|
144
|
+
};
|
|
145
|
+
delete updateQuery.logs;
|
|
146
|
+
|
|
147
|
+
const updatedRole = await Role.findByIdAndUpdate(id, updateQuery, {
|
|
148
|
+
new: true,
|
|
149
|
+
})
|
|
150
|
+
.populate("permissionId")
|
|
151
|
+
.lean()
|
|
152
|
+
.exec();
|
|
153
|
+
|
|
154
|
+
if (updatedRole) {
|
|
155
|
+
await updateCachedRoles();
|
|
156
|
+
// Update default roles cache if needed
|
|
157
|
+
if (!updatedRole.workspaceId) {
|
|
158
|
+
await updateCachedDefaultRoles();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return updatedRole;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const updateRoleByFilter = async (filter, updateData) => {
|
|
166
|
+
const updatedRole = await Role.findOneAndUpdate(filter, updateData, {
|
|
167
|
+
new: true,
|
|
168
|
+
})
|
|
169
|
+
.populate("permissionId")
|
|
170
|
+
.lean()
|
|
171
|
+
.exec();
|
|
172
|
+
|
|
173
|
+
if (updatedRole) {
|
|
174
|
+
await updateCachedRoles();
|
|
175
|
+
// Update default roles cache if needed
|
|
176
|
+
if (!updatedRole.workspaceId) {
|
|
177
|
+
await updateCachedDefaultRoles();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return updatedRole;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const updateRolesByFilter = async (filter, updateData) => {
|
|
185
|
+
const result = await Role.updateMany(filter, updateData, { new: true });
|
|
186
|
+
|
|
187
|
+
if (result.matchedCount > 0) {
|
|
188
|
+
await updateCachedRoles();
|
|
189
|
+
|
|
190
|
+
// Check if we need to update default roles cache
|
|
191
|
+
if (!filter.workspaceId || filter.workspaceId === null) {
|
|
192
|
+
await updateCachedDefaultRoles();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return result;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const addLogToRole = async (id, logData) => {
|
|
200
|
+
const updatedRole = await Role.findByIdAndUpdate(
|
|
201
|
+
id,
|
|
202
|
+
{ $push: { logs: logData } },
|
|
203
|
+
{ new: true }
|
|
204
|
+
)
|
|
205
|
+
.populate("permissionId")
|
|
206
|
+
.lean()
|
|
207
|
+
.exec();
|
|
208
|
+
|
|
209
|
+
if (updatedRole) {
|
|
210
|
+
await updateCachedRoles();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return updatedRole;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const clearRoleLogs = async (id) => {
|
|
217
|
+
const updatedRole = await Role.findByIdAndUpdate(
|
|
218
|
+
id,
|
|
219
|
+
{ $set: { logs: [] } },
|
|
220
|
+
{ new: true }
|
|
221
|
+
)
|
|
222
|
+
.populate("permissionId")
|
|
223
|
+
.lean()
|
|
224
|
+
.exec();
|
|
225
|
+
|
|
226
|
+
if (updatedRole) {
|
|
227
|
+
await updateCachedRoles();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return updatedRole;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const addPermissionToRole = async (id, permission) => {
|
|
234
|
+
const updatedRole = await Role.findByIdAndUpdate(
|
|
235
|
+
id,
|
|
236
|
+
{ $push: { permissions: permission } },
|
|
237
|
+
{ new: true }
|
|
238
|
+
)
|
|
239
|
+
.populate("permissionId")
|
|
240
|
+
.lean()
|
|
241
|
+
.exec();
|
|
242
|
+
|
|
243
|
+
if (updatedRole) {
|
|
244
|
+
await updateCachedRoles();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return updatedRole;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const removePermissionFromRole = async (id, permission) => {
|
|
251
|
+
const updatedRole = await Role.findByIdAndUpdate(
|
|
252
|
+
id,
|
|
253
|
+
{ $pull: { permissions: permission } },
|
|
254
|
+
{ new: true }
|
|
255
|
+
)
|
|
256
|
+
.populate("permissionId")
|
|
257
|
+
.lean()
|
|
258
|
+
.exec();
|
|
259
|
+
|
|
260
|
+
if (updatedRole) {
|
|
261
|
+
await updateCachedRoles();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return updatedRole;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const deleteRoleById = async (id) => {
|
|
268
|
+
const deletedRole = await Role.findByIdAndDelete(id).lean().exec();
|
|
269
|
+
|
|
270
|
+
if (deletedRole) {
|
|
271
|
+
await updateCachedRoles();
|
|
272
|
+
// Update default roles cache if needed
|
|
273
|
+
if (!deletedRole.workspaceId) {
|
|
274
|
+
await updateCachedDefaultRoles();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return deletedRole;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const deleteSingleRole = async (filter) => {
|
|
282
|
+
const deletedRole = await Role.findOneAndDelete(filter).lean().exec();
|
|
283
|
+
|
|
284
|
+
if (deletedRole) {
|
|
285
|
+
await updateCachedRoles();
|
|
286
|
+
// Update default roles cache if needed
|
|
287
|
+
if (!deletedRole.workspaceId) {
|
|
288
|
+
await updateCachedDefaultRoles();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return deletedRole;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const deleteManyRoles = async (filter) => {
|
|
296
|
+
// Check if we need to update default roles cache
|
|
297
|
+
const includesDefaultRoles =
|
|
298
|
+
!filter.workspaceId || filter.workspaceId === null;
|
|
299
|
+
|
|
300
|
+
const result = await Role.deleteMany(filter);
|
|
301
|
+
|
|
302
|
+
if (result.deletedCount > 0) {
|
|
303
|
+
await updateCachedRoles();
|
|
304
|
+
if (includesDefaultRoles) {
|
|
305
|
+
await updateCachedDefaultRoles();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return result;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
module.exports = {
|
|
313
|
+
createRole,
|
|
314
|
+
findRoleById,
|
|
315
|
+
findSingleRole,
|
|
316
|
+
findRoles,
|
|
317
|
+
updateRoleById,
|
|
318
|
+
updateRoleByFilter,
|
|
319
|
+
updateRolesByFilter,
|
|
320
|
+
addLogToRole,
|
|
321
|
+
clearRoleLogs,
|
|
322
|
+
addPermissionToRole,
|
|
323
|
+
removePermissionFromRole,
|
|
324
|
+
deleteRoleById,
|
|
325
|
+
deleteSingleRole,
|
|
326
|
+
deleteManyRoles,
|
|
327
|
+
findRolesByPagination,
|
|
328
|
+
findDefaultRoles,
|
|
329
|
+
};
|
|
@@ -1,12 +1,68 @@
|
|
|
1
1
|
const { UserRole } = require("../../models/UserRole");
|
|
2
|
+
const { getRedisData, setRedisData } = require("../../config/redis");
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
+
const CACHE_KEY_USER_WORKSPACE_PREFIX = "userrole_workspace_";
|
|
10
|
+
const CACHE_KEY_USER_PERMISSIONS_PREFIX = "user_permissions_";
|
|
11
|
+
|
|
12
|
+
// Clear user workspace cache
|
|
13
|
+
const clearUserWorkspaceCache = async (userId) => {
|
|
14
|
+
await setRedisData(
|
|
15
|
+
`${CACHE_KEY_USER_WORKSPACE_PREFIX}${userId}`,
|
|
16
|
+
null,
|
|
17
|
+
null,
|
|
18
|
+
0
|
|
19
|
+
);
|
|
7
20
|
};
|
|
8
21
|
|
|
9
|
-
|
|
22
|
+
// Clear user permissions cache
|
|
23
|
+
const clearUserPermissionsCache = async (workspaceId, userId) => {
|
|
24
|
+
const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
|
|
25
|
+
await setRedisData(cacheKey, null, null, 0);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Get cached members
|
|
29
|
+
const getCachedMembers = async (filter = {}) => {
|
|
30
|
+
const cacheKey =
|
|
31
|
+
Object.keys(filter).length > 0
|
|
32
|
+
? `${CACHE_KEY_ALL_MEMBERS}_${JSON.stringify(filter)}`
|
|
33
|
+
: CACHE_KEY_ALL_MEMBERS;
|
|
34
|
+
|
|
35
|
+
let members = await getRedisData(cacheKey);
|
|
36
|
+
|
|
37
|
+
if (!members) {
|
|
38
|
+
members = await UserRole.find(filter)
|
|
39
|
+
.select("userId role userShift roleId")
|
|
40
|
+
.populate({
|
|
41
|
+
path: "roleId",
|
|
42
|
+
select: "id name userId userShift permissionId modulePermissions",
|
|
43
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
44
|
+
})
|
|
45
|
+
.populate({
|
|
46
|
+
path: "userId",
|
|
47
|
+
match: { isDeleted: false, suspended: false },
|
|
48
|
+
select: "firstName lastName role email picture userShift",
|
|
49
|
+
})
|
|
50
|
+
.lean()
|
|
51
|
+
.exec();
|
|
52
|
+
|
|
53
|
+
await setRedisData(cacheKey, members, null, 0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return members;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Update the cache for all members
|
|
60
|
+
const updateCachedMembers = async (filter = {}) => {
|
|
61
|
+
const cacheKey =
|
|
62
|
+
Object.keys(filter).length > 0
|
|
63
|
+
? `${CACHE_KEY_ALL_MEMBERS}_${JSON.stringify(filter)}`
|
|
64
|
+
: CACHE_KEY_ALL_MEMBERS;
|
|
65
|
+
|
|
10
66
|
const members = await UserRole.find(filter)
|
|
11
67
|
.select("userId role userShift roleId")
|
|
12
68
|
.populate({
|
|
@@ -18,28 +74,279 @@ const findUserRole = async (filter = {}) => {
|
|
|
18
74
|
path: "userId",
|
|
19
75
|
match: { isDeleted: false, suspended: false },
|
|
20
76
|
select: "firstName lastName role email picture userShift",
|
|
21
|
-
})
|
|
77
|
+
})
|
|
78
|
+
.lean()
|
|
79
|
+
.exec();
|
|
22
80
|
|
|
81
|
+
await setRedisData(cacheKey, members, null, 0);
|
|
23
82
|
return members;
|
|
24
83
|
};
|
|
25
84
|
|
|
85
|
+
const createUserRole = async (data) => {
|
|
86
|
+
const newRole = new UserRole(data);
|
|
87
|
+
const savedRole = await newRole.save();
|
|
88
|
+
|
|
89
|
+
// Update cache
|
|
90
|
+
await updateCachedMembers();
|
|
91
|
+
if (data.userId) {
|
|
92
|
+
await clearUserWorkspaceCache(data.userId);
|
|
93
|
+
// Clear permissions cache if workspaceId exists
|
|
94
|
+
if (data.workspaceId) {
|
|
95
|
+
await clearUserPermissionsCache(data.workspaceId, data.userId);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return savedRole;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const findUserRole = async (filter = {}) => {
|
|
103
|
+
return await getCachedMembers(filter);
|
|
104
|
+
};
|
|
105
|
+
|
|
26
106
|
const updateUserRole = async (id, data) => {
|
|
27
107
|
const updatedRole = await UserRole.findByIdAndUpdate(id, data, {
|
|
28
108
|
new: true,
|
|
29
109
|
}).exec();
|
|
30
110
|
|
|
111
|
+
if (updatedRole) {
|
|
112
|
+
await updateCachedMembers();
|
|
113
|
+
if (updatedRole.userId) {
|
|
114
|
+
await clearUserWorkspaceCache(updatedRole.userId);
|
|
115
|
+
// Clear permissions cache if workspaceId exists
|
|
116
|
+
if (updatedRole.workspaceId) {
|
|
117
|
+
await clearUserPermissionsCache(
|
|
118
|
+
updatedRole.workspaceId,
|
|
119
|
+
updatedRole.userId
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
31
125
|
return updatedRole;
|
|
32
126
|
};
|
|
33
127
|
|
|
34
128
|
const deleteUserRole = async (id) => {
|
|
129
|
+
const role = await UserRole.findById(id).exec();
|
|
130
|
+
const userId = role?.userId;
|
|
131
|
+
const workspaceId = role?.workspaceId;
|
|
132
|
+
|
|
35
133
|
const deletedRole = await UserRole.findByIdAndDelete(id).exec();
|
|
36
134
|
|
|
135
|
+
if (deletedRole) {
|
|
136
|
+
await updateCachedMembers();
|
|
137
|
+
if (userId) {
|
|
138
|
+
await clearUserWorkspaceCache(userId);
|
|
139
|
+
// Clear permissions cache if workspaceId exists
|
|
140
|
+
if (workspaceId) {
|
|
141
|
+
await clearUserPermissionsCache(workspaceId, userId);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
37
146
|
return deletedRole;
|
|
38
147
|
};
|
|
39
148
|
|
|
149
|
+
const findUserWorkspaces = async (userId) => {
|
|
150
|
+
const cacheKey = `${CACHE_KEY_USER_WORKSPACE_PREFIX}${userId}`;
|
|
151
|
+
let userRoleWithWorkspaces = await getRedisData(cacheKey);
|
|
152
|
+
if (!userRoleWithWorkspaces) {
|
|
153
|
+
userRoleWithWorkspaces = await UserRole.find({
|
|
154
|
+
userId: userId,
|
|
155
|
+
})
|
|
156
|
+
.select("userId roleId workspaceId")
|
|
157
|
+
.populate({
|
|
158
|
+
path: "roleId",
|
|
159
|
+
select: "id name userId userShift permissionId modulePermissions",
|
|
160
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
161
|
+
})
|
|
162
|
+
.populate({
|
|
163
|
+
path: "workspaceId",
|
|
164
|
+
select: defaultSelect,
|
|
165
|
+
match: { isDeleted: false },
|
|
166
|
+
})
|
|
167
|
+
.lean()
|
|
168
|
+
.exec();
|
|
169
|
+
userRoleWithWorkspaces = userRoleWithWorkspaces.map((ur) => {
|
|
170
|
+
return {
|
|
171
|
+
...ur?.workspaceId,
|
|
172
|
+
id: ur?.workspaceId?._id?.toString(),
|
|
173
|
+
_id: ur?.workspaceId?._id?.toString(),
|
|
174
|
+
role: ur?.roleId?.name || "",
|
|
175
|
+
permissions: ur?.roleId?.modulePermissions?.modules || [],
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
if (userRoleWithWorkspaces) {
|
|
179
|
+
await setRedisData(cacheKey, userRoleWithWorkspaces, null, 0);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return userRoleWithWorkspaces;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const convertPermissionsArrayToObject = (originalArray) => {
|
|
186
|
+
return originalArray?.reduce((acc, item) => {
|
|
187
|
+
const { id, actions, integrationPermissions, ...extras } = item;
|
|
188
|
+
const formattedExtras = {};
|
|
189
|
+
if (extras.deletable !== undefined) {
|
|
190
|
+
formattedExtras.deletable = extras.deletable;
|
|
191
|
+
}
|
|
192
|
+
if (extras.createUpdateable !== undefined) {
|
|
193
|
+
formattedExtras.createUpdateable = extras.createUpdateable;
|
|
194
|
+
}
|
|
195
|
+
acc[id] = {
|
|
196
|
+
actions: Object.keys(actions).filter((action) => actions[action]),
|
|
197
|
+
...formattedExtras,
|
|
198
|
+
...(integrationPermissions && {
|
|
199
|
+
integrationPermissions: Object.entries(integrationPermissions)
|
|
200
|
+
.filter(([_, allowed]) => allowed)
|
|
201
|
+
.map(([key]) => key),
|
|
202
|
+
}),
|
|
203
|
+
};
|
|
204
|
+
return acc;
|
|
205
|
+
}, {});
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const getUserRoleWithPermissions = async (workspaceId, userId) => {
|
|
209
|
+
const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
|
|
210
|
+
let cachedData = await getRedisData(cacheKey);
|
|
211
|
+
|
|
212
|
+
if (cachedData && cachedData.roleWithPermissions) {
|
|
213
|
+
return cachedData.roleWithPermissions;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
let data = await UserRole.findOne({
|
|
218
|
+
workspaceId: workspaceId,
|
|
219
|
+
userId: userId,
|
|
220
|
+
})
|
|
221
|
+
.populate({
|
|
222
|
+
path: "roleId",
|
|
223
|
+
select:
|
|
224
|
+
"id name userId userShift permissionId modulePermissions defaultModule",
|
|
225
|
+
populate: [{ path: "permissionId", select: "id name" }],
|
|
226
|
+
})
|
|
227
|
+
.lean()
|
|
228
|
+
.exec();
|
|
229
|
+
|
|
230
|
+
if (!data) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const roleWithPermissions = {
|
|
235
|
+
...data,
|
|
236
|
+
roleId: data?.roleId?._id?.toString() || "",
|
|
237
|
+
role: data?.roleId?.name || "",
|
|
238
|
+
permissions:
|
|
239
|
+
convertPermissionsArrayToObject(
|
|
240
|
+
data?.roleId?.modulePermissions?.modules
|
|
241
|
+
) || [],
|
|
242
|
+
parentRole: data?.roleId?.permissionId?.name || "",
|
|
243
|
+
parentRoleId: data?.roleId?.permissionId?._id?.toString() || "",
|
|
244
|
+
defaultModule: data?.roleId?.defaultModule || "",
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// Store in cache with other permission data
|
|
248
|
+
const permissionsData = cachedData || {};
|
|
249
|
+
permissionsData.roleWithPermissions = roleWithPermissions;
|
|
250
|
+
await setRedisData(cacheKey, permissionsData, null, 0);
|
|
251
|
+
|
|
252
|
+
return roleWithPermissions;
|
|
253
|
+
} catch (err) {
|
|
254
|
+
console.error("Error in getUserRoleWithPermissions:", err);
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const getUserPermissions = async (workspaceId, userId) => {
|
|
260
|
+
const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
|
|
261
|
+
let cachedData = await getRedisData(cacheKey);
|
|
262
|
+
|
|
263
|
+
if (cachedData && cachedData.permissions) {
|
|
264
|
+
return cachedData.permissions;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
let data = await UserRole.findOne({
|
|
269
|
+
workspaceId: workspaceId,
|
|
270
|
+
userId: userId,
|
|
271
|
+
})
|
|
272
|
+
.select("roleId userId")
|
|
273
|
+
.populate({
|
|
274
|
+
path: "roleId",
|
|
275
|
+
select: "modulePermissions",
|
|
276
|
+
})
|
|
277
|
+
.lean()
|
|
278
|
+
.exec();
|
|
279
|
+
|
|
280
|
+
if (!data) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const permissions =
|
|
285
|
+
convertPermissionsArrayToObject(
|
|
286
|
+
data?.roleId?.modulePermissions?.modules
|
|
287
|
+
) || null;
|
|
288
|
+
|
|
289
|
+
// Store in cache with other permission data
|
|
290
|
+
const permissionsData = cachedData || {};
|
|
291
|
+
permissionsData.permissions = permissions;
|
|
292
|
+
await setRedisData(cacheKey, permissionsData, null, 0);
|
|
293
|
+
|
|
294
|
+
return permissions;
|
|
295
|
+
} catch (err) {
|
|
296
|
+
console.error("Error in getUserPermissions:", err);
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const getChannelsPermissions = async (workspaceId, userId) => {
|
|
302
|
+
const cacheKey = `${CACHE_KEY_USER_PERMISSIONS_PREFIX}${workspaceId}_${userId}`;
|
|
303
|
+
let cachedData = await getRedisData(cacheKey);
|
|
304
|
+
|
|
305
|
+
if (cachedData && cachedData.channelsPermissions) {
|
|
306
|
+
return cachedData.channelsPermissions;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
try {
|
|
310
|
+
let data = await UserRole.findOne({
|
|
311
|
+
workspaceId: workspaceId,
|
|
312
|
+
userId: userId,
|
|
313
|
+
})
|
|
314
|
+
.select("roleId userId")
|
|
315
|
+
.populate({
|
|
316
|
+
path: "roleId",
|
|
317
|
+
select: "modulePermissions",
|
|
318
|
+
})
|
|
319
|
+
.lean()
|
|
320
|
+
.exec();
|
|
321
|
+
|
|
322
|
+
if (!data) {
|
|
323
|
+
return [];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const channelsPermissions =
|
|
327
|
+
convertPermissionsArrayToObject(
|
|
328
|
+
data?.roleId?.modulePermissions?.modules
|
|
329
|
+
)?.["conversations"]?.["integrationPermissions"] || [];
|
|
330
|
+
|
|
331
|
+
// Store in cache with other permission data
|
|
332
|
+
const permissionsData = cachedData || {};
|
|
333
|
+
permissionsData.channelsPermissions = channelsPermissions;
|
|
334
|
+
await setRedisData(cacheKey, permissionsData, null, 0);
|
|
335
|
+
|
|
336
|
+
return channelsPermissions;
|
|
337
|
+
} catch (err) {
|
|
338
|
+
console.error("Error in getChannelsPermissions:", err);
|
|
339
|
+
return [];
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
40
343
|
module.exports = {
|
|
41
344
|
createUserRole,
|
|
42
345
|
findUserRole,
|
|
43
346
|
updateUserRole,
|
|
44
347
|
deleteUserRole,
|
|
348
|
+
findUserWorkspaces,
|
|
349
|
+
getUserRoleWithPermissions,
|
|
350
|
+
getUserPermissions,
|
|
351
|
+
getChannelsPermissions,
|
|
45
352
|
};
|
|
@@ -28,7 +28,8 @@ const createWorkspace = async (data) => {
|
|
|
28
28
|
|
|
29
29
|
const findWorkspaceById = async (id, select = []) => {
|
|
30
30
|
const workspaces = await getCachedWorkspaces();
|
|
31
|
-
const workspace =
|
|
31
|
+
const workspace =
|
|
32
|
+
workspaces.find((ws) => ws._id.toString() === id && !ws?.isDeleted) || null;
|
|
32
33
|
if (workspace && select.length > 0) {
|
|
33
34
|
return select.reduce((result, field) => {
|
|
34
35
|
if (workspace[field] !== undefined) {
|
|
@@ -49,6 +50,16 @@ const findWorkspace = async (filter) => {
|
|
|
49
50
|
);
|
|
50
51
|
};
|
|
51
52
|
|
|
53
|
+
const findSingleWorkspace = async (filter) => {
|
|
54
|
+
const cachedWorkspaces = await getCachedWorkspaces();
|
|
55
|
+
const cachedWorkspace = cachedWorkspaces.find((ws) =>
|
|
56
|
+
Object.entries(filter).every(([key, value]) => ws[key] === value)
|
|
57
|
+
);
|
|
58
|
+
if (cachedWorkspace) return cachedWorkspace;
|
|
59
|
+
const workspace = await Workspace.findOne(filter).lean().exec();
|
|
60
|
+
return workspace;
|
|
61
|
+
};
|
|
62
|
+
|
|
52
63
|
const findWorkspaceByIdAndQueueTracking = async (id) => {
|
|
53
64
|
const workspaces = await getCachedWorkspaces();
|
|
54
65
|
return (
|
|
@@ -75,6 +86,38 @@ const updateWorkspace = async (id, data) => {
|
|
|
75
86
|
return updatedWorkspace;
|
|
76
87
|
};
|
|
77
88
|
|
|
89
|
+
const updateOneWorkspace = async (filter, update, options = {}) => {
|
|
90
|
+
const result = await Workspace.updateOne(filter, update, options).exec();
|
|
91
|
+
if (result.matchedCount > 0) {
|
|
92
|
+
await updateCachedWorkspaces();
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const updateManyWorkspaces = async (filter, update, options = {}) => {
|
|
98
|
+
const result = await Workspace.updateMany(filter, update, options).exec();
|
|
99
|
+
if (result.matchedCount > 0) {
|
|
100
|
+
await updateCachedWorkspaces();
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const findOneAndUpdateWorkspace = async (
|
|
106
|
+
filter,
|
|
107
|
+
update,
|
|
108
|
+
options = { new: true }
|
|
109
|
+
) => {
|
|
110
|
+
const updatedWorkspace = await Workspace.findOneAndUpdate(
|
|
111
|
+
filter,
|
|
112
|
+
update,
|
|
113
|
+
options
|
|
114
|
+
).exec();
|
|
115
|
+
if (updatedWorkspace) {
|
|
116
|
+
await updateCachedWorkspaces();
|
|
117
|
+
}
|
|
118
|
+
return updatedWorkspace;
|
|
119
|
+
};
|
|
120
|
+
|
|
78
121
|
const deleteWorkspace = async (id) => {
|
|
79
122
|
const deletedWorkspace = await Workspace.findByIdAndDelete(id).exec();
|
|
80
123
|
if (deletedWorkspace) {
|
|
@@ -85,10 +128,14 @@ const deleteWorkspace = async (id) => {
|
|
|
85
128
|
|
|
86
129
|
module.exports = {
|
|
87
130
|
createWorkspace,
|
|
88
|
-
findWorkspaceById,
|
|
89
131
|
findWorkspace,
|
|
132
|
+
findSingleWorkspace,
|
|
133
|
+
findWorkspaceById,
|
|
90
134
|
findWorkspaceByIdAndQueueTracking,
|
|
91
135
|
findAllWorkspaces,
|
|
136
|
+
findOneAndUpdateWorkspace,
|
|
92
137
|
updateWorkspace,
|
|
138
|
+
updateOneWorkspace,
|
|
139
|
+
updateManyWorkspaces,
|
|
93
140
|
deleteWorkspace,
|
|
94
141
|
};
|
package/config/redis.js
CHANGED
package/models/UserRole.js
CHANGED
|
@@ -52,112 +52,6 @@ const userRoleSchema = new Schema(
|
|
|
52
52
|
|
|
53
53
|
const UserRole = mongoose.model("UserRole", userRoleSchema);
|
|
54
54
|
|
|
55
|
-
const convertPermissionsArrayToObject = (originalArray) => {
|
|
56
|
-
return originalArray?.reduce((acc, item) => {
|
|
57
|
-
const { id, actions, integrationPermissions, ...extras } = item;
|
|
58
|
-
const formattedExtras = {};
|
|
59
|
-
if (extras.deletable !== undefined) {
|
|
60
|
-
formattedExtras.deletable = extras.deletable;
|
|
61
|
-
}
|
|
62
|
-
if (extras.createUpdateable !== undefined) {
|
|
63
|
-
formattedExtras.createUpdateable = extras.createUpdateable;
|
|
64
|
-
}
|
|
65
|
-
acc[id] = {
|
|
66
|
-
actions: Object.keys(actions).filter((action) => actions[action]),
|
|
67
|
-
...formattedExtras,
|
|
68
|
-
...(integrationPermissions && {
|
|
69
|
-
integrationPermissions: Object.entries(integrationPermissions)
|
|
70
|
-
.filter(([_, allowed]) => allowed)
|
|
71
|
-
.map(([key]) => key),
|
|
72
|
-
}),
|
|
73
|
-
};
|
|
74
|
-
return acc;
|
|
75
|
-
}, {});
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const getUserRoleWithPermissions = async (workspaceId, userId) => {
|
|
79
|
-
try {
|
|
80
|
-
let data = await UserRole.findOne({
|
|
81
|
-
workspaceId: workspaceId,
|
|
82
|
-
userId: userId,
|
|
83
|
-
})
|
|
84
|
-
.populate({
|
|
85
|
-
path: "roleId",
|
|
86
|
-
select:
|
|
87
|
-
"id name userId userShift permissionId modulePermissions defaultModule",
|
|
88
|
-
populate: [{ path: "permissionId", select: "id name" }],
|
|
89
|
-
})
|
|
90
|
-
.lean()
|
|
91
|
-
.exec();
|
|
92
|
-
return {
|
|
93
|
-
...data,
|
|
94
|
-
roleId: data?.roleId?._id?.toString() || "",
|
|
95
|
-
role: data?.roleId?.name || "",
|
|
96
|
-
permissions:
|
|
97
|
-
convertPermissionsArrayToObject(
|
|
98
|
-
data?.roleId?.modulePermissions?.modules
|
|
99
|
-
) || [],
|
|
100
|
-
parentRole: data?.roleId?.permissionId?.name || "",
|
|
101
|
-
parentRoleId: data?.roleId?.permissionId?._id?.toString() || "",
|
|
102
|
-
defaultModule: data?.roleId?.defaultModule || "",
|
|
103
|
-
};
|
|
104
|
-
} catch (err) {
|
|
105
|
-
console.error("Error in getUserRole:", err);
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const getUserPermissions = async (workspaceId, userId) => {
|
|
111
|
-
try {
|
|
112
|
-
let data = await UserRole.findOne({
|
|
113
|
-
workspaceId: workspaceId,
|
|
114
|
-
userId: userId,
|
|
115
|
-
})
|
|
116
|
-
.select("roleId userId")
|
|
117
|
-
.populate({
|
|
118
|
-
path: "roleId",
|
|
119
|
-
select: "modulePermissions",
|
|
120
|
-
})
|
|
121
|
-
.lean()
|
|
122
|
-
.exec();
|
|
123
|
-
return (
|
|
124
|
-
convertPermissionsArrayToObject(
|
|
125
|
-
data?.roleId?.modulePermissions?.modules
|
|
126
|
-
) || null
|
|
127
|
-
);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
console.error("Error in getUserRole:", err);
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const getChannelsPermissions = async (workspaceId, userId) => {
|
|
135
|
-
try {
|
|
136
|
-
let data = await UserRole.findOne({
|
|
137
|
-
workspaceId: workspaceId,
|
|
138
|
-
userId: userId,
|
|
139
|
-
})
|
|
140
|
-
.select("roleId userId")
|
|
141
|
-
.populate({
|
|
142
|
-
path: "roleId",
|
|
143
|
-
select: "modulePermissions",
|
|
144
|
-
})
|
|
145
|
-
.lean()
|
|
146
|
-
.exec();
|
|
147
|
-
return (
|
|
148
|
-
convertPermissionsArrayToObject(
|
|
149
|
-
data?.roleId?.modulePermissions?.modules
|
|
150
|
-
)?.["conversations"]?.["integrationPermissions"] || []
|
|
151
|
-
);
|
|
152
|
-
} catch (err) {
|
|
153
|
-
console.error("Error in getUserRole:", err);
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
55
|
module.exports = {
|
|
159
56
|
UserRole,
|
|
160
|
-
getChannelsPermissions,
|
|
161
|
-
getUserPermissions,
|
|
162
|
-
getUserRoleWithPermissions,
|
|
163
57
|
};
|