@tiledesk/tiledesk-server 2.17.4 → 2.18.1
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/CHANGELOG.md +4 -3
- package/app.js +2 -0
- package/channels/chat21/chat21WebHook.js +6 -1
- package/event/authEvent.js +16 -0
- package/event/projectUserEvent.js +39 -0
- package/event/roleEvent.js +9 -0
- package/middleware/has-role.js +160 -121
- package/middleware/passport.js +180 -179
- package/migrations/1757601159298-project_user_role_type.js +45 -0
- package/models/department.js +3 -0
- package/models/groupMemberSchama.js +19 -0
- package/models/kb_setting.js +6 -2
- package/models/permissionConstants.js +19 -0
- package/models/project_user.js +86 -8
- package/models/request.js +1 -0
- package/models/role.js +31 -0
- package/models/roleConstants.js +2 -0
- package/package.json +1 -1
- package/pubmodules/analytics/analytics.js +2 -2
- package/pubmodules/cache/mongoose-cachegoose-fn.js +37 -0
- package/pubmodules/canned/cannedResponseRoute.js +34 -6
- package/pubmodules/routing-queue/listener.js +7 -1
- package/pubmodules/trigger/rulesTrigger.js +1 -6
- package/routes/auth.js +3 -1
- package/routes/department.js +7 -1
- package/routes/message.js +4 -1
- package/routes/project.js +41 -3
- package/routes/project_user.js +62 -11
- package/routes/request.js +32 -30
- package/routes/roles.js +151 -0
- package/routes/unanswered.js +1 -1
- package/routes/widget.js +3 -1
- package/services/cacheEnabler.js +5 -8
- package/services/departmentService.js +39 -11
- package/services/emailService.js +2 -2
- package/services/pendingInvitationService.js +2 -0
- package/services/projectService.js +3 -1
- package/services/projectUserService.js +67 -4
- package/services/subscriptionNotifierQueued.js +8 -0
- package/services/updateRequestSnapshotQueued.js +0 -3
- package/test/departmentService.js +5 -0
- package/test/messageRoute.js +7 -4
- package/test/projectUserRoute.js +116 -0
- package/test/requestService.js +7 -3
- package/test-int/bot.js +3 -2
- package/websocket/webSocketServer.js +273 -225
- package/routes/auth_newjwt.js +0 -648
package/CHANGELOG.md
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
|
7
7
|
|
|
8
|
-
# 2.
|
|
9
|
-
-
|
|
8
|
+
# 2.18.1
|
|
9
|
+
- Added permissions logic
|
|
10
|
+
- Added custom roles support
|
|
10
11
|
|
|
11
12
|
# 2.17.4
|
|
12
|
-
-
|
|
13
|
+
- Refactor error handling and code structure in webhook.js
|
|
13
14
|
|
|
14
15
|
# 2.17.3
|
|
15
16
|
- Added missing import path on kb route
|
package/app.js
CHANGED
|
@@ -149,6 +149,7 @@ var property = require('./routes/property');
|
|
|
149
149
|
var segment = require('./routes/segment');
|
|
150
150
|
var webhook = require('./routes/webhook');
|
|
151
151
|
var webhooks = require('./routes/webhooks');
|
|
152
|
+
var roles = require('./routes/roles');
|
|
152
153
|
var copilot = require('./routes/copilot');
|
|
153
154
|
var mcp = require('./routes/mcp');
|
|
154
155
|
|
|
@@ -648,6 +649,7 @@ app.use('/:projectid/logs', [passport.authenticate(['basic', 'jwt'], { session:
|
|
|
648
649
|
|
|
649
650
|
app.use('/:projectid/webhooks', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], webhooks);
|
|
650
651
|
app.use('/:projectid/copilot', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], copilot);
|
|
652
|
+
app.use('/:projectid/roles', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], roles);
|
|
651
653
|
|
|
652
654
|
app.use('/:projectid/files', filesp);
|
|
653
655
|
|
|
@@ -307,7 +307,12 @@ router.post('/', function (req, res) {
|
|
|
307
307
|
// TODO se stato = 50 e scrive visitatotre sposto a stato 100 poi queuue lo smista
|
|
308
308
|
|
|
309
309
|
// TOOD update also request attributes and sourcePage
|
|
310
|
-
|
|
310
|
+
if (message.sender !== 'system') {
|
|
311
|
+
Request.findOneAndUpdate({request_id: request.request_id, id_project: request.id_project}, { "attributes.last_message": savedMessage}).catch((err) => {
|
|
312
|
+
winston.error("Create message - saving last message in request error: ", err);
|
|
313
|
+
})
|
|
314
|
+
}
|
|
315
|
+
|
|
311
316
|
// return requestService.incrementMessagesCountByRequestId(request.request_id, request.id_project).then(function(savedRequest) {
|
|
312
317
|
// winston.debug("savedRequest.participants.indexOf(message.sender)", savedRequest.participants.indexOf(message.sender));
|
|
313
318
|
winston.debug("before updateWaitingTimeByRequestId*******",request.participants, message.sender);
|
package/event/authEvent.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const EventEmitter = require('events');
|
|
2
|
+
var RoleConstants = require("../models/roleConstants");
|
|
2
3
|
|
|
3
4
|
class AuthEvent extends EventEmitter {
|
|
4
5
|
constructor() {
|
|
@@ -9,6 +10,21 @@ class AuthEvent extends EventEmitter {
|
|
|
9
10
|
|
|
10
11
|
const authEvent = new AuthEvent();
|
|
11
12
|
|
|
13
|
+
var projectuserUpdateKey = 'project_user.update';
|
|
14
|
+
if (process.env.QUEUE_ENABLED === "true") {
|
|
15
|
+
projectuserUpdateKey = 'project_user.update.queue';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
authEvent.on(projectuserUpdateKey, function(event) {
|
|
19
|
+
if (event.updatedProject_userPopulated) {
|
|
20
|
+
var pu = event.updatedProject_userPopulated;
|
|
21
|
+
if (pu.roleType === RoleConstants.TYPE_AGENTS) {
|
|
22
|
+
authEvent.emit("project_user.update.agent", event);
|
|
23
|
+
} else {
|
|
24
|
+
authEvent.emit("project_user.update.user", event);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
12
28
|
|
|
13
29
|
//listen for sigin and signup event
|
|
14
30
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const EventEmitter = require('events');
|
|
2
|
+
const winston = require('../config/winston');
|
|
3
|
+
const Group = require("../models/group");
|
|
4
|
+
|
|
5
|
+
class ProjectUserEvent extends EventEmitter {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.registerListeners();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
registerListeners() {
|
|
12
|
+
|
|
13
|
+
this.on('project_user.deleted', async (pu) => {
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
winston.debug('[project_user.deleted] Event catched:', pu);
|
|
17
|
+
|
|
18
|
+
const id_project = pu.id_project;
|
|
19
|
+
let id_user = pu.id_user.toString();
|
|
20
|
+
if (typeof id_user === 'object' && id_user._id) {
|
|
21
|
+
id_user = id_user._id.toString();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const result = await Group.updateMany({ id_project: id_project }, { $pull: { members: id_user }});
|
|
25
|
+
winston.verbose(`Event project_user.deleted: User ${id_user} removed from ${result?.nModified} groups.`)
|
|
26
|
+
|
|
27
|
+
} catch (err) {
|
|
28
|
+
winston.verbose(`Event project_user.deleted: Error removing user ${id_user} from groups: `, err);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Istanza singleton
|
|
37
|
+
const puEvent = new ProjectUserEvent();
|
|
38
|
+
|
|
39
|
+
module.exports = puEvent;
|
package/middleware/has-role.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
var Project_user = require("../models/project_user");
|
|
2
1
|
var Faq_kb = require("../models/faq_kb");
|
|
3
2
|
var Subscription = require("../models/subscription");
|
|
4
3
|
var winston = require('../config/winston');
|
|
5
4
|
|
|
6
|
-
var
|
|
7
|
-
var cacheEnabler = require("../services/cacheEnabler");
|
|
8
|
-
|
|
5
|
+
var projectUserService = require("../services/projectUserService");
|
|
9
6
|
class RoleChecker {
|
|
10
7
|
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
constructor() {
|
|
11
|
+
winston.debug("RoleChecker");
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
this.ROLES = {
|
|
16
14
|
"guest": ["guest"],
|
|
17
15
|
"user": ["guest","user"],
|
|
18
16
|
"teammate": ["guest","user","teammate"],
|
|
@@ -20,7 +18,7 @@ class RoleChecker {
|
|
|
20
18
|
"supervisor": ["guest","user","teammate","agent","supervisor"],
|
|
21
19
|
"admin": ["guest","user","teammate","agent", "supervisor", "admin"],
|
|
22
20
|
"owner": ["guest","user","teammate","agent", "supervisor", "admin", "owner"],
|
|
23
|
-
|
|
21
|
+
}
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
isType(type) {
|
|
@@ -87,18 +85,90 @@ class RoleChecker {
|
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
|
|
88
|
+
hasPermission(permission) {
|
|
89
|
+
var that = this;
|
|
90
|
+
return async(req, res, next) => {
|
|
91
|
+
if (!req.params.projectid && !req.projectid) {
|
|
92
|
+
return res.status(400).send({success: false, msg: 'req.params.projectid is not defined.'});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let projectid = req.params.projectid || req.projectid;
|
|
96
|
+
|
|
97
|
+
var project_user = req.projectuser;
|
|
98
|
+
winston.debug("hasPermission project_user hasPermission", project_user);
|
|
99
|
+
|
|
100
|
+
if (!project_user) {
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
project_user = await projectUserService.getWithPermissions(req.user._id, projectid, req.user.sub);
|
|
104
|
+
} catch(err) {
|
|
105
|
+
winston.error("Error getting project_user for hasrole",err);
|
|
106
|
+
return next(err);
|
|
107
|
+
}
|
|
108
|
+
winston.debug("project_user: ", JSON.stringify(project_user));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (project_user) {
|
|
112
|
+
|
|
113
|
+
req.projectuser = project_user;
|
|
114
|
+
winston.debug("hasPermission req.projectuser", req.projectuser);
|
|
115
|
+
|
|
116
|
+
var permissions = project_user._doc.rolePermissions;
|
|
117
|
+
|
|
118
|
+
winston.debug("hasPermission permissions", permissions);
|
|
119
|
+
|
|
120
|
+
winston.debug("hasPermission permission: "+ permission);
|
|
121
|
+
|
|
122
|
+
if (permission==undefined) {
|
|
123
|
+
winston.debug("permission is empty go next");
|
|
124
|
+
return next();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (permissions!=undefined && permissions.length>0) {
|
|
128
|
+
if (permissions.includes(permission)) {
|
|
129
|
+
next();
|
|
130
|
+
}else {
|
|
131
|
+
res.status(403).send({success: false, msg: 'you dont have the required permission.'});
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
res.status(403).send({success: false, msg: 'you dont have the required permission. Is is empty'});
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Updated by Johnny - 29mar2024 - START
|
|
140
|
+
*/
|
|
141
|
+
// console.log("req.user: ", req.user);
|
|
142
|
+
if (req.user.email === process.env.ADMIN_EMAIL) {
|
|
143
|
+
req.user.attributes = { isSuperadmin: true };
|
|
144
|
+
next();
|
|
145
|
+
} else {
|
|
146
|
+
res.status(403).send({success: false, msg: 'you dont belong to the project.'});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Updated by Johnny - 29mar2024 - END
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
}
|
|
90
159
|
|
|
91
160
|
|
|
92
161
|
hasRole(role) {
|
|
93
162
|
return this.hasRoleOrTypes(role);
|
|
94
163
|
}
|
|
95
164
|
|
|
96
|
-
hasRoleOrTypes(role, types) {
|
|
97
|
-
|
|
165
|
+
hasRoleOrTypes(role, types, permission) {
|
|
166
|
+
// console.log("hasRoleOrTypes",role,types);
|
|
167
|
+
|
|
98
168
|
var that = this;
|
|
99
169
|
|
|
100
170
|
// winston.debug("HasRole");
|
|
101
|
-
return
|
|
171
|
+
return async(req, res, next) => {
|
|
102
172
|
|
|
103
173
|
// winston.debug("req.originalUrl" + req.originalUrl);
|
|
104
174
|
// winston.debug("req.params" + JSON.stringify(req.params));
|
|
@@ -111,7 +181,7 @@ class RoleChecker {
|
|
|
111
181
|
|
|
112
182
|
let projectid = req.params.projectid || req.projectid;
|
|
113
183
|
|
|
114
|
-
|
|
184
|
+
// winston.info("req.user._id: " + req.user._id);
|
|
115
185
|
|
|
116
186
|
// winston.info("req.projectuser: " + req.projectuser);
|
|
117
187
|
//winston.debug("req.user", req.user);
|
|
@@ -135,138 +205,107 @@ class RoleChecker {
|
|
|
135
205
|
// res.status(403).send({success: false, msg: 'req.user._id not defined.'});
|
|
136
206
|
// }
|
|
137
207
|
winston.debug("hasRoleOrType req.user._id " +req.user._id);
|
|
138
|
-
// project_user_qui_importante
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
208
|
+
// project_user_qui_importante
|
|
209
|
+
|
|
210
|
+
var project_user = req.projectuser;
|
|
211
|
+
winston.debug("hasRoleOrTypes project_user hasRoleOrTypes", project_user);
|
|
212
|
+
|
|
213
|
+
if (!project_user) {
|
|
214
|
+
winston.debug("load project_user");
|
|
215
|
+
try {
|
|
216
|
+
project_user = await projectUserService.getWithPermissions(req.user._id, projectid, req.user.sub);
|
|
217
|
+
} catch(err) {
|
|
218
|
+
winston.error("Error getting project_user for hasrole",err);
|
|
219
|
+
return next(err);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
winston.debug("project_user: ", JSON.stringify(project_user));
|
|
223
|
+
|
|
147
224
|
}
|
|
148
|
-
winston.debug("hasRoleOrType query " + JSON.stringify(query));
|
|
149
225
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
winston.debug("
|
|
226
|
+
if (project_user) {
|
|
227
|
+
|
|
228
|
+
req.projectuser = project_user;
|
|
229
|
+
winston.debug("hasRoleOrTypes req.projectuser", req.projectuser.toJSON());
|
|
154
230
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (err) {
|
|
158
|
-
winston.error("Error on Request path: " + req.originalUrl);
|
|
159
|
-
winston.error("Error getting project_user for hasrole",err);
|
|
160
|
-
return next(err);
|
|
161
|
-
}
|
|
162
|
-
winston.debug("project_user: ", JSON.stringify(project_user));
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (project_user) {
|
|
167
|
-
|
|
168
|
-
req.projectuser = project_user;
|
|
169
|
-
winston.debug("req.projectuser", req.projectuser);
|
|
231
|
+
var userRole = project_user.role;
|
|
232
|
+
winston.debug("userRole", userRole);
|
|
170
233
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
next();
|
|
183
|
-
}else {
|
|
184
|
-
res.status(403).send({success: false, msg: 'you dont have the required role.'});
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
} else {
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Updated by Johnny - 29mar2024 - START
|
|
191
|
-
*/
|
|
192
|
-
// console.log("req.user: ", req.user);
|
|
193
|
-
if (req.user.email === process.env.ADMIN_EMAIL) {
|
|
194
|
-
req.user.attributes = { isSuperadmin: true };
|
|
234
|
+
|
|
235
|
+
if (!role) { //????
|
|
236
|
+
next();
|
|
237
|
+
}else {
|
|
238
|
+
|
|
239
|
+
var hierarchicalRoles = that.ROLES[userRole];
|
|
240
|
+
winston.debug("hierarchicalRoles", hierarchicalRoles);
|
|
241
|
+
|
|
242
|
+
if ( hierarchicalRoles ) { //standard role
|
|
243
|
+
winston.debug("standard role: "+ userRole);
|
|
244
|
+
if (hierarchicalRoles.includes(role)) {
|
|
195
245
|
next();
|
|
196
246
|
} else {
|
|
197
|
-
res.status(403).send({success: false, msg: 'you dont
|
|
247
|
+
res.status(403).send({success: false, msg: 'you dont have the required role.'});
|
|
198
248
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
249
|
+
} else { //custom role
|
|
250
|
+
|
|
251
|
+
winston.debug("custom role: "+ userRole);
|
|
252
|
+
return that.hasPermission(permission)(req, res, next);
|
|
202
253
|
|
|
203
|
-
// if (
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
}
|
|
254
|
+
// if (permission==undefined) {
|
|
255
|
+
// winston.debug("permission is empty go next");
|
|
256
|
+
// return next();
|
|
257
|
+
// }
|
|
212
258
|
|
|
213
|
-
//
|
|
214
|
-
|
|
259
|
+
// // invece di questo codice richiama hasPermission()
|
|
260
|
+
// var permissions = project_user._doc.rolePermissions;
|
|
215
261
|
|
|
216
|
-
|
|
262
|
+
// winston.debug("hasPermission permissions", permissions);
|
|
263
|
+
|
|
264
|
+
// winston.debug("hasPermission permission: "+ permission);
|
|
217
265
|
|
|
218
|
-
|
|
219
|
-
|
|
266
|
+
// if (permissions!=undefined && permissions.length>0) {
|
|
267
|
+
// if (permissions.includes(permission)) {
|
|
268
|
+
// next();
|
|
269
|
+
// }else {
|
|
270
|
+
// res.status(403).send({success: false, msg: 'you dont have the required permission.'});
|
|
271
|
+
// }
|
|
272
|
+
// } else {
|
|
273
|
+
// res.status(403).send({success: false, msg: 'you dont have the required permission. Is is empty'});
|
|
274
|
+
// }
|
|
220
275
|
|
|
221
|
-
// JWT_HERE
|
|
222
|
-
var query = { id_project: req.params.projectid, id_user: req.user._id, status: "active"};
|
|
223
|
-
if (req.user.sub && (req.user.sub=="userexternal" || req.user.sub=="guest")) {
|
|
224
|
-
query = { id_project: req.params.projectid, uuid_user: req.user._id};
|
|
225
|
-
}
|
|
226
276
|
|
|
227
|
-
Project_user.find(query).
|
|
228
|
-
exec(function (err, project_users) {
|
|
229
|
-
if (err) {
|
|
230
|
-
winston.error(err);
|
|
231
|
-
return reject(err);
|
|
232
277
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (project_users && project_users.length>0) {
|
|
236
278
|
|
|
237
|
-
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
} else {
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Updated by Johnny - 29mar2024 - START
|
|
285
|
+
*/
|
|
286
|
+
// console.log("req.user: ", req.user);
|
|
287
|
+
if (req.user.email === process.env.ADMIN_EMAIL) {
|
|
288
|
+
req.user.attributes = { isSuperadmin: true };
|
|
289
|
+
next();
|
|
290
|
+
} else {
|
|
291
|
+
res.status(403).send({success: false, msg: 'you dont belong to the project.'});
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Updated by Johnny - 29mar2024 - END
|
|
295
|
+
*/
|
|
238
296
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (!role) {
|
|
243
|
-
resolve(project_user);
|
|
244
|
-
}else {
|
|
245
|
-
|
|
246
|
-
var hierarchicalRoles = that.ROLES[userRole];
|
|
247
|
-
// winston.debug("hierarchicalRoles", hierarchicalRoles);
|
|
248
|
-
|
|
249
|
-
if ( hierarchicalRoles.includes(role)) {
|
|
250
|
-
resolve(project_user);
|
|
251
|
-
}else {
|
|
252
|
-
reject({success: false, msg: 'you dont have the required role.'});
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
} else {
|
|
256
|
-
|
|
257
|
-
// if (req.user) equals super admin next()
|
|
258
|
-
reject({success: false, msg: 'you dont belong to the project.'});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
});
|
|
297
|
+
// if (req.user) equals super admin next()
|
|
298
|
+
//res.status(403).send({success: false, msg: 'you dont belong to the project.'});
|
|
299
|
+
}
|
|
262
300
|
|
|
263
|
-
});
|
|
264
301
|
|
|
265
|
-
|
|
266
|
-
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
267
305
|
}
|
|
268
306
|
|
|
269
307
|
|
|
308
|
+
|
|
270
309
|
var roleChecker = new RoleChecker();
|
|
271
310
|
module.exports = roleChecker;
|
|
272
311
|
|