@tiledesk/tiledesk-server 2.11.4 → 2.11.6
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 +10 -0
- package/models/group.js +8 -0
- package/models/project_user.js +1 -0
- package/package.json +2 -2
- package/routes/group.js +89 -12
- package/routes/kb.js +14 -4
- package/routes/project.js +5 -0
- package/routes/project_user.js +49 -25
- package/services/departmentService.js +16 -1
- package/services/requestService.js +1 -1
package/CHANGELOG.md
CHANGED
@@ -5,6 +5,16 @@
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
7
7
|
|
8
|
+
# 2.11.6
|
9
|
+
- Added: possibility to enable/disable groups
|
10
|
+
- Updated: delete project user endpoint to logical delete
|
11
|
+
- Updated: tybot-connector to 2.0.23
|
12
|
+
- Updated: get all namespace adding counter
|
13
|
+
- Added: attributes field in groups model
|
14
|
+
|
15
|
+
# 2.11.5
|
16
|
+
- Added: log in requestService
|
17
|
+
|
8
18
|
# 2.11.4
|
9
19
|
- Added: authentication via Keycloak
|
10
20
|
- Added: project settings fields for allowed_urls, allowed_urls_list, allow_send_emoji
|
package/models/group.js
CHANGED
@@ -18,10 +18,18 @@ var GroupSchema = new Schema({
|
|
18
18
|
index: true
|
19
19
|
// required: true
|
20
20
|
},
|
21
|
+
enabled: {
|
22
|
+
type: Boolean,
|
23
|
+
default: true,
|
24
|
+
index: true
|
25
|
+
},
|
21
26
|
trashed: {
|
22
27
|
type: Boolean,
|
23
28
|
index: true
|
24
29
|
},
|
30
|
+
attributes: {
|
31
|
+
type: Object,
|
32
|
+
},
|
25
33
|
createdBy: {
|
26
34
|
type: String,
|
27
35
|
required: true
|
package/models/project_user.js
CHANGED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@tiledesk/tiledesk-server",
|
3
3
|
"description": "The Tiledesk server module",
|
4
|
-
"version": "2.11.
|
4
|
+
"version": "2.11.6",
|
5
5
|
"scripts": {
|
6
6
|
"start": "node ./bin/www",
|
7
7
|
"pretest": "mongodb-runner start",
|
@@ -49,7 +49,7 @@
|
|
49
49
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
50
50
|
"@tiledesk/tiledesk-sms-connector": "^0.1.11",
|
51
51
|
"@tiledesk/tiledesk-telegram-connector": "^0.1.14",
|
52
|
-
"@tiledesk/tiledesk-tybot-connector": "^2.0.
|
52
|
+
"@tiledesk/tiledesk-tybot-connector": "^2.0.23",
|
53
53
|
"@tiledesk/tiledesk-voice-twilio-connector": "^0.1.22",
|
54
54
|
"@tiledesk/tiledesk-vxml-connector": "^0.1.76",
|
55
55
|
"@tiledesk/tiledesk-whatsapp-connector": "^0.1.84",
|
package/routes/group.js
CHANGED
@@ -3,6 +3,7 @@ var router = express.Router();
|
|
3
3
|
var Group = require("../models/group");
|
4
4
|
var groupEvent = require("../event/groupEvent");
|
5
5
|
var winston = require('../config/winston');
|
6
|
+
const departmentService = require('../services/departmentService');
|
6
7
|
|
7
8
|
|
8
9
|
|
@@ -44,6 +45,9 @@ router.put('/:groupid', function (req, res) {
|
|
44
45
|
if (req.body.trashed!=undefined) {
|
45
46
|
update.trashed = req.body.trashed;
|
46
47
|
}
|
48
|
+
if (req.body.attributes!=undefined) {
|
49
|
+
update.attributes = req.body.attributes;
|
50
|
+
}
|
47
51
|
|
48
52
|
|
49
53
|
Group.findByIdAndUpdate(req.params.groupid, update, { new: true, upsert: true }, function (err, updatedGroup) {
|
@@ -57,6 +61,49 @@ router.put('/:groupid', function (req, res) {
|
|
57
61
|
});
|
58
62
|
});
|
59
63
|
|
64
|
+
router.put('/enable/:groupid', async (req, res) => {
|
65
|
+
|
66
|
+
let group_id = req.params.groupid;
|
67
|
+
|
68
|
+
Group.findByIdAndUpdate(group_id, { enabled: true }, { new: true, upsert: true }, (err, updatedGroup) => {
|
69
|
+
if (err) {
|
70
|
+
winston.error("Error enabling the group: ", err);
|
71
|
+
return res.status(500).send({ success: false, error: "Error enabling group" })
|
72
|
+
}
|
73
|
+
|
74
|
+
groupEvent.emit('group.update', updatedGroup);
|
75
|
+
res.status(200).send(updatedGroup);
|
76
|
+
})
|
77
|
+
|
78
|
+
})
|
79
|
+
|
80
|
+
router.put('/disable/:groupid', async (req, res) => {
|
81
|
+
|
82
|
+
let id_project = req.projectid;
|
83
|
+
let group_id = req.params.groupid;
|
84
|
+
|
85
|
+
const isInDepartment = await departmentService.isGroupInProjectDepartment(id_project, group_id).catch((err) => {
|
86
|
+
winston.error("Error checking if group belongs to the department: ", err);
|
87
|
+
return res.status(500).send({ success: false, error: "Unable to verify group-department association due to an error" })
|
88
|
+
})
|
89
|
+
|
90
|
+
if (isInDepartment) {
|
91
|
+
winston.verbose("The group " + group_id + " belongs to a department and cannot be disabled");
|
92
|
+
return res.status(403).send({ success: false, error: "Unable to disabled a group associated with a department" })
|
93
|
+
}
|
94
|
+
|
95
|
+
Group.findByIdAndUpdate(group_id, { enabled: false }, { new: true, upsert: true }, (err, updatedGroup) => {
|
96
|
+
if (err) {
|
97
|
+
winston.error("Error disabling the group: ", err);
|
98
|
+
return res.status(500).send({ success: false, error: "Error disabling group" })
|
99
|
+
}
|
100
|
+
|
101
|
+
groupEvent.emit('group.update', updatedGroup);
|
102
|
+
res.status(200).send(updatedGroup);
|
103
|
+
})
|
104
|
+
|
105
|
+
})
|
106
|
+
|
60
107
|
// router.put('/:groupid', function (req, res) {
|
61
108
|
|
62
109
|
// winston.debug(req.body);
|
@@ -79,21 +126,51 @@ router.put('/:groupid', function (req, res) {
|
|
79
126
|
// });
|
80
127
|
// });
|
81
128
|
|
82
|
-
router.delete('/:groupid',
|
129
|
+
router.delete('/:groupid', async (req, res) => {
|
83
130
|
|
84
|
-
|
131
|
+
let id_project = req.projectid;
|
132
|
+
let group_id = req.params.groupid;
|
85
133
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
134
|
+
const isInDepartment = await departmentService.isGroupInProjectDepartment(id_project, group_id).catch((err) => {
|
135
|
+
winston.error("Error checking if group belongs to the department: ", err);
|
136
|
+
return res.status(500).send({ success: false, error: "Unable to verify group-department association due to an error" })
|
137
|
+
})
|
138
|
+
|
139
|
+
if (isInDepartment) {
|
140
|
+
winston.verbose("The group " + group_id + " belongs to a department and cannot be deleted");
|
141
|
+
return res.status(403).send({ success: false, error: "Unable to delete a group associated with a department" })
|
142
|
+
}
|
143
|
+
|
144
|
+
if (req.query.force === "true") {
|
145
|
+
|
146
|
+
Group.findByIdAndRemove(group_id, function (err, group) {
|
147
|
+
if (err) {
|
148
|
+
winston.error('Error removing the group ', err);
|
149
|
+
return res.status(500).send({ success: false, msg: 'Error deleting group' });
|
150
|
+
}
|
151
|
+
winston.debug("Physically removed group", group);
|
152
|
+
// nn funziuona perchje nn c'è id_project
|
153
|
+
groupEvent.emit('group.delete', group);
|
154
|
+
res.status(200).send(group);
|
155
|
+
});
|
156
|
+
|
157
|
+
} else {
|
158
|
+
|
159
|
+
Group.findByIdAndUpdate(group_id, { enabled: false, trashed: true }, { new: true }, function (err, group) {
|
160
|
+
if (err) {
|
161
|
+
winston.error('Error removing the group ', err);
|
162
|
+
return res.status(500).send({ success: false, msg: 'Error deleting group' });
|
163
|
+
}
|
164
|
+
|
165
|
+
winston.debug("Group logical deleted", group);
|
166
|
+
|
167
|
+
groupEvent.emit('group.update', group);
|
168
|
+
|
169
|
+
res.status(200).send({ success: true, message: "Group successfully deleted"})
|
170
|
+
}
|
171
|
+
);
|
172
|
+
}
|
94
173
|
|
95
|
-
res.json(group);
|
96
|
-
});
|
97
174
|
});
|
98
175
|
|
99
176
|
|
package/routes/kb.js
CHANGED
@@ -321,9 +321,8 @@ router.post('/qa', async (req, res) => {
|
|
321
321
|
|
322
322
|
let ns = namespaces.find(n => n.id === data.namespace);
|
323
323
|
data.engine = ns.engine || default_engine;
|
324
|
-
data.hybrid = ns.hybrid;
|
325
324
|
|
326
|
-
if (
|
325
|
+
if (ns.hybrid === true) {
|
327
326
|
data.search_type = 'hybrid';
|
328
327
|
}
|
329
328
|
|
@@ -463,7 +462,7 @@ router.get('/namespace/all', async (req, res) => {
|
|
463
462
|
|
464
463
|
let project_id = req.projectid;
|
465
464
|
|
466
|
-
Namespace.find({ id_project: project_id }).lean().exec((err, namespaces) => {
|
465
|
+
Namespace.find({ id_project: project_id }).lean().exec( async (err, namespaces) => {
|
467
466
|
|
468
467
|
if (err) {
|
469
468
|
winston.error("find namespaces error: ", err);
|
@@ -500,7 +499,18 @@ router.get('/namespace/all', async (req, res) => {
|
|
500
499
|
|
501
500
|
} else {
|
502
501
|
|
503
|
-
|
502
|
+
let namespaceObjArray = [];
|
503
|
+
if (req.query.count) {
|
504
|
+
namespaceObjArray = await Promise.all(
|
505
|
+
namespaces.map(async ({ _id, __v, ...keepAttrs }) => {
|
506
|
+
const count = await KB.countDocuments({ id_project: keepAttrs.id_project, namespace: keepAttrs.id });
|
507
|
+
return { ...keepAttrs, count };
|
508
|
+
})
|
509
|
+
);
|
510
|
+
} else {
|
511
|
+
namespaceObjArray = namespaces.map(({ _id, __v, ...keepAttrs }) => keepAttrs)
|
512
|
+
}
|
513
|
+
|
504
514
|
winston.debug("namespaceObjArray: ", namespaceObjArray);
|
505
515
|
return res.status(200).send(namespaceObjArray);
|
506
516
|
}
|
package/routes/project.js
CHANGED
@@ -1059,6 +1059,11 @@ router.get('/:projectid/users/availables', async (req, res) => {
|
|
1059
1059
|
return res.status(404).send({ success: false, error: "Group " + group_id + " not found" })
|
1060
1060
|
}
|
1061
1061
|
|
1062
|
+
if (group.enabled === false) {
|
1063
|
+
winston.error("(Users Availables) group disabled")
|
1064
|
+
return res.status(403).send({ success: false, error: "Group " + group_id + " is currently disabled" })
|
1065
|
+
}
|
1066
|
+
|
1062
1067
|
query.id_user = { $in: group.members.map(id => mongoose.Types.ObjectId(id) )}
|
1063
1068
|
}
|
1064
1069
|
}
|
package/routes/project_user.js
CHANGED
@@ -248,23 +248,18 @@ router.put('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
|
|
248
248
|
update.tags = req.body.tags;
|
249
249
|
}
|
250
250
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
251
|
Project_user.findByIdAndUpdate(req.projectuser.id, update, { new: true, upsert: true }, function (err, updatedProject_user) {
|
255
252
|
if (err) {
|
256
253
|
winston.error("Error gettting project_user for update", err);
|
257
254
|
return res.status(500).send({ success: false, msg: 'Error updating object.' });
|
258
255
|
}
|
259
|
-
updatedProject_user.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, updatedProject_userPopulated){
|
260
|
-
|
261
|
-
var pu = updatedProject_userPopulated.toJSON();
|
262
|
-
pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat);
|
263
|
-
|
264
|
-
authEvent.emit('project_user.update', {updatedProject_userPopulated:pu, req: req});
|
265
|
-
});
|
266
256
|
|
267
|
-
|
257
|
+
updatedProject_user.populate({ path:'id_user', select: { 'firstname': 1, 'lastname': 1 }}, function (err, updatedProject_userPopulated) {
|
258
|
+
var pu = updatedProject_userPopulated.toJSON();
|
259
|
+
pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat);
|
260
|
+
authEvent.emit('project_user.update', {updatedProject_userPopulated:pu, req: req});
|
261
|
+
});
|
262
|
+
|
268
263
|
res.json(updatedProject_user);
|
269
264
|
});
|
270
265
|
});
|
@@ -300,8 +295,9 @@ router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
|
|
300
295
|
update.attributes = req.body.attributes;
|
301
296
|
}
|
302
297
|
|
303
|
-
|
304
|
-
|
298
|
+
const allowedStatuses = ['active', 'disabled'];
|
299
|
+
if (req.body.status !== undefined && allowedStatuses.includes(req.body.status)) {
|
300
|
+
update.status = req.body.status;
|
305
301
|
}
|
306
302
|
|
307
303
|
if (req.body["settings.email.notification.conversation.assigned.toyou"]!=undefined) {
|
@@ -345,21 +341,45 @@ router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
|
|
345
341
|
router.delete('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) {
|
346
342
|
|
347
343
|
winston.debug(req.body);
|
344
|
+
|
345
|
+
if (req.query.force === "true") {
|
348
346
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
347
|
+
Project_user.findByIdAndRemove(req.params.project_userid, { new: false }, function (err, project_user) {
|
348
|
+
if (err) {
|
349
|
+
winston.error("Error gettting project_user for delete", err);
|
350
|
+
return res.status(500).send({ success: false, msg: 'Error deleting object.' });
|
351
|
+
}
|
354
352
|
|
355
|
-
|
353
|
+
winston.debug("Physically removed project_user", project_user);
|
356
354
|
|
357
|
-
|
358
|
-
|
355
|
+
if (project_user) {
|
356
|
+
project_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, project_userPopulated) {
|
357
|
+
authEvent.emit('project_user.delete', { req: req, project_userPopulated: project_userPopulated });
|
358
|
+
});
|
359
|
+
}
|
360
|
+
|
361
|
+
res.json(project_user);
|
359
362
|
});
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
+
} else {
|
364
|
+
|
365
|
+
Project_user.findByIdAndUpdate(req.params.project_userid, { status: "disabled", user_available: false }, { new: true }, function (err, project_user) {
|
366
|
+
if (err) {
|
367
|
+
winston.error("Error gettting project_user for logical delete", err);
|
368
|
+
return res.status(500).send({ success: false, msg: 'Error disabling object.' });
|
369
|
+
}
|
370
|
+
|
371
|
+
winston.debug("Logically disabled project_user", project_user);
|
372
|
+
|
373
|
+
if (project_user) {
|
374
|
+
project_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, project_userPopulated) {
|
375
|
+
authEvent.emit('project_user.delete', { req: req, project_userPopulated: project_userPopulated });
|
376
|
+
});
|
377
|
+
}
|
378
|
+
|
379
|
+
res.json(project_user);
|
380
|
+
}
|
381
|
+
);
|
382
|
+
}
|
363
383
|
});
|
364
384
|
|
365
385
|
router.get('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res) {
|
@@ -498,7 +518,7 @@ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
|
|
498
518
|
}
|
499
519
|
winston.debug("role", role);
|
500
520
|
|
501
|
-
var query =
|
521
|
+
var query = { id_project: req.projectid, role: { $in : role } }; //, status: 'active'
|
502
522
|
|
503
523
|
if (req.query.presencestatus) {
|
504
524
|
query["presence.status"] = req.query.presencestatus;
|
@@ -506,6 +526,10 @@ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
|
|
506
526
|
|
507
527
|
winston.debug("query", query);
|
508
528
|
|
529
|
+
if (req.query.status) {
|
530
|
+
query["status"] = req.query.status;
|
531
|
+
}
|
532
|
+
|
509
533
|
Project_user.find(query).
|
510
534
|
populate('id_user').
|
511
535
|
// lean().
|
@@ -360,7 +360,7 @@ getOperators(departmentid, projectid, nobot, disableWebHookCall, context) {
|
|
360
360
|
|
361
361
|
return new Promise(function (resolve, reject) {
|
362
362
|
|
363
|
-
return Group.find({ _id: department.id_group }).exec(function (err, group) {
|
363
|
+
return Group.find({ _id: department.id_group, enabled: true }).exec(function (err, group) {
|
364
364
|
if (err) {
|
365
365
|
winston.error('D-2 GROUP -> [ FIND PROJECT USERS: ALL and AVAILABLE (with OH) ] -> ERR ', err)
|
366
366
|
return reject(err);
|
@@ -603,6 +603,21 @@ getDefaultDepartment(projectid) {
|
|
603
603
|
}
|
604
604
|
}
|
605
605
|
|
606
|
+
/**
|
607
|
+
* Checks if the group belongs to a department of the project
|
608
|
+
* @param {String} projectId
|
609
|
+
* @param {String} groupId
|
610
|
+
* @returns {Promise<Boolean>} true if the group belongs to a department of the project, otherwise false
|
611
|
+
*/
|
612
|
+
async isGroupInProjectDepartment(projectId, groupId) {
|
613
|
+
try {
|
614
|
+
const department = await Department.findOne({ id_project: projectId, id_group: groupId });
|
615
|
+
return !!department;
|
616
|
+
} catch (err) {
|
617
|
+
winston.error('Error in isGroupInProjectDepartment', err);
|
618
|
+
return false;
|
619
|
+
}
|
620
|
+
}
|
606
621
|
|
607
622
|
|
608
623
|
}
|
@@ -1757,7 +1757,7 @@ class RequestService {
|
|
1757
1757
|
|
1758
1758
|
|
1759
1759
|
if (err) {
|
1760
|
-
winston.error("Error getting closing request ", err);
|
1760
|
+
winston.error("Error getting closing request with request_id: " + request_id, err);
|
1761
1761
|
return reject(err);
|
1762
1762
|
}
|
1763
1763
|
if (!request) {
|