@tiledesk/tiledesk-server 2.11.5 → 2.11.7

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 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.7
9
+ - Hotfix: solved bug on findProjectUsersAllAndAvailableWithOperatingHours_group on searching group
10
+
11
+ # 2.11.6
12
+ - Added: possibility to enable/disable groups
13
+ - Updated: delete project user endpoint to logical delete
14
+ - Updated: tybot-connector to 2.0.23
15
+ - Updated: get all namespace adding counter
16
+ - Added: attributes field in groups model
17
+
8
18
  # 2.11.5
9
19
  - Added: log in requestService
10
20
 
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
@@ -69,6 +69,7 @@ var TagSchema = require("../models/tag");
69
69
  },
70
70
  status: {
71
71
  type: String,
72
+ enum: ['active', 'disabled'],
72
73
  default: "active",
73
74
  index: true,
74
75
  required: true
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.5",
4
+ "version": "2.11.7",
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.21",
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', function (req, res) {
129
+ router.delete('/:groupid', async (req, res) => {
83
130
 
84
- winston.debug(req.body);
131
+ let id_project = req.projectid;
132
+ let group_id = req.params.groupid;
85
133
 
86
- Group.findOneAndRemove({_id: req.params.groupid}, function (err, group) {
87
- // Group.remove({ _id: req.params.groupid }, function (err, group) {
88
- if (err) {
89
- winston.error('Error removing the group ', err);
90
- return res.status(500).send({ success: false, msg: 'Error deleting object.' });
91
- }
92
- // nn funziuona perchje nn c'è id_project
93
- groupEvent.emit('group.delete', group);
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 (data.engine.type === 'serverless') {
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
- const namespaceObjArray = namespaces.map(({ _id, __v, ...keepAttrs }) => keepAttrs)
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
  }
@@ -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
- if (req.body.status!=undefined) {
304
- update.status = req.body.status;
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
- Project_user.findByIdAndRemove(req.params.project_userid, { new: false}, function (err, project_user) {
350
- if (err) {
351
- winston.error("Error gettting project_user for delete", err);
352
- return res.status(500).send({ success: false, msg: 'Error deleting object.' });
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
- winston.debug("Removed project_user", project_user);
353
+ winston.debug("Physically removed project_user", project_user);
356
354
 
357
- project_user.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, project_userPopulated){
358
- authEvent.emit('project_user.delete', {req: req, project_userPopulated: project_userPopulated});
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
- res.json(project_user);
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 = {id_project: req.projectid, role: { $in : role } };
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().
@@ -359,8 +359,7 @@ getOperators(departmentid, projectid, nobot, disableWebHookCall, context) {
359
359
  var that = this;
360
360
 
361
361
  return new Promise(function (resolve, reject) {
362
-
363
- return Group.find({ _id: department.id_group }).exec(function (err, group) {
362
+ return Group.find({ _id: department.id_group, $or: [ { enabled: true }, { enabled: { $exists: false } } ] }).exec(function (err, group) {
364
363
  if (err) {
365
364
  winston.error('D-2 GROUP -> [ FIND PROJECT USERS: ALL and AVAILABLE (with OH) ] -> ERR ', err)
366
365
  return reject(err);
@@ -603,6 +602,21 @@ getDefaultDepartment(projectid) {
603
602
  }
604
603
  }
605
604
 
605
+ /**
606
+ * Checks if the group belongs to a department of the project
607
+ * @param {String} projectId
608
+ * @param {String} groupId
609
+ * @returns {Promise<Boolean>} true if the group belongs to a department of the project, otherwise false
610
+ */
611
+ async isGroupInProjectDepartment(projectId, groupId) {
612
+ try {
613
+ const department = await Department.findOne({ id_project: projectId, id_group: groupId });
614
+ return !!department;
615
+ } catch (err) {
616
+ winston.error('Error in isGroupInProjectDepartment', err);
617
+ return false;
618
+ }
619
+ }
606
620
 
607
621
 
608
622
  }