@tiledesk/tiledesk-server 2.3.27 → 2.3.29

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
@@ -1,4 +1,21 @@
1
1
 
2
+ # Untagged
3
+ - UIDGenerator class replacement for request route
4
+ - Added hasRole cache for project_user
5
+ - Added index { id_project: 1, role: 1, status: 1, createdAt: 1 } for Project_user schema
6
+ - Enabled project_user for cacheEnabler class
7
+ - Created cache test for project_user and project
8
+ - Enabled project_user cache for hasRole method
9
+ - Log fix
10
+ - add fields reply and enabled to faq model
11
+ - field answer in faq model is no longer required
12
+ - add field public to faq_kb model (IGNORA PER IL MOMENTO)
13
+ - when template is undefined the empty template is now created
14
+ - add test
15
+
16
+ # 2.3.28
17
+ - UIDGenerator renamed fix
18
+
2
19
  # 2.3.27
3
20
  - CacheUtil fix with new values
4
21
  - UIDGenerator class replacement
package/app.js CHANGED
@@ -97,6 +97,7 @@ var faq = require('./routes/faq');
97
97
  var faq_kb = require('./routes/faq_kb');
98
98
  var project = require('./routes/project');
99
99
  var project_user = require('./routes/project_user');
100
+ var project_users_test = require('./routes/project_user_test');
100
101
  var request = require('./routes/request');
101
102
  // var setting = require('./routes/setting');
102
103
  var users = require('./routes/users');
@@ -142,7 +143,9 @@ botSubscriptionNotifier.start();
142
143
 
143
144
 
144
145
  var geoService = require('./services/geoService');
145
- geoService.listen();
146
+ geoService.listen();
147
+
148
+
146
149
 
147
150
 
148
151
 
@@ -322,8 +325,8 @@ var projectSetter = function (req, res, next) {
322
325
  if (projectid) {
323
326
 
324
327
  let q = Project.findOne({_id: projectid, status: 100});
325
- if (cacheEnabler.project) {
326
- q.cache(cacheUtil.defaultTTL, "projects:id:"+projectid) //project_cache
328
+ if (cacheEnabler.project) {
329
+ q.cache(cacheUtil.longTTL, "projects:id:"+projectid) //project_cache
327
330
  winston.debug('project cache enabled');
328
331
  }
329
332
  q.exec(function(err, project){
@@ -400,6 +403,8 @@ app.use('/:projectid/', [projectIdSetter, projectSetter, IPFilter.projectIpFilte
400
403
 
401
404
  app.use('/:projectid/authtestWithRoleCheck', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken], authtestWithRoleCheck);
402
405
 
406
+ app.use('/:projectid/project_users_test', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], project_users_test);
407
+
403
408
  app.use('/:projectid/leads', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], lead);
404
409
  app.use('/:projectid/requests/:request_id/messages', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes(null, ['bot','subscription'])] , message);
405
410
 
@@ -442,6 +447,8 @@ app.use('/:projectid/project_users', project_user);
442
447
 
443
448
  // app.use('/:projectid/project_users', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], project_user);
444
449
 
450
+
451
+ //passport double check this and the next
445
452
  app.use('/:projectid/requests', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('guest', ['bot','subscription'])], userRequest);
446
453
 
447
454
  app.use('/:projectid/requests', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], request);
@@ -74,7 +74,7 @@ function populateMessageWithRequest(message, eventPrefix) {
74
74
  // request.department._id DA CORREGGERE ANCHE PER REQUEST.CREATE
75
75
  // request.department.hasBot
76
76
  // request.isOpen
77
- winston.info('message Event populate');
77
+ winston.debug('message Event populate');
78
78
  if (cacheEnabler.request) {
79
79
  q.cache(cacheUtil.defaultTTL, message.id_project+":requests:request_id:"+message.recipient) //request_cache ma con lean????attento metti a parte
80
80
  winston.debug('request cache enabled');
@@ -4,6 +4,7 @@ var Subscription = require("../models/subscription");
4
4
  var winston = require('../config/winston');
5
5
 
6
6
  var cacheUtil = require('../utils/cacheUtil');
7
+ var cacheEnabler = require("../services/cacheEnabler");
7
8
 
8
9
  class RoleChecker {
9
10
 
@@ -131,15 +132,21 @@ class RoleChecker {
131
132
 
132
133
  // JWT_HERE
133
134
  var query = { id_project: req.params.projectid, id_user: req.user._id, status: "active"};
135
+ let cache_key = req.params.projectid+":project_users:iduser:"+req.user._id
134
136
 
135
137
  if (req.user.sub && (req.user.sub=="userexternal" || req.user.sub=="guest")) {
136
138
  query = { id_project: req.params.projectid, uuid_user: req.user._id, status: "active"};
139
+ cache_key = req.params.projectid+":project_users:uuid_user:"+req.user._id
137
140
  }
138
141
  winston.debug("hasRoleOrType query " + JSON.stringify(query));
139
142
 
140
- Project_user.findOne(query)
141
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, req.params.projectid+":project_users:id:"+req.user.id)
142
- .exec(function (err, project_user) {
143
+ let q = Project_user.findOne(query);
144
+ if (cacheEnabler.project_user) {
145
+ q.cache(cacheUtil.defaultTTL, cache_key);
146
+ winston.debug("cacheEnabler.project_user enabled");
147
+
148
+ }
149
+ q.exec(function (err, project_user) {
143
150
  if (err) {
144
151
  winston.error("Error getting project_user for hasrole",err);
145
152
  return next(err);
package/models/faq.js CHANGED
@@ -39,7 +39,17 @@ var FaqSchema = new Schema({
39
39
  },
40
40
  answer: {
41
41
  type: String,
42
- required: true
42
+ //required: true
43
+ required: false
44
+ },
45
+ reply: {
46
+ type: Object,
47
+ required: false,
48
+ },
49
+ enabled: {
50
+ type: Boolean,
51
+ required: false,
52
+ default: true,
43
53
  },
44
54
  id_project: {
45
55
  type: String,
package/models/faq_kb.js CHANGED
@@ -65,6 +65,11 @@ var Faq_kbSchema = new Schema({
65
65
  createdBy: {
66
66
  type: String,
67
67
  required: true
68
+ },
69
+ public: {
70
+ type: Boolean,
71
+ required: false,
72
+ default: false
68
73
  }
69
74
  },{
70
75
  timestamps: true
package/models/message.js CHANGED
@@ -20,7 +20,7 @@ var MessageSchema = new Schema({
20
20
  senderFullname: {
21
21
  type: String,
22
22
  required: false,
23
- default: "Guest"
23
+ default: "Guest" // guest_here
24
24
  },
25
25
  recipient: {
26
26
  type: String,
@@ -111,6 +111,12 @@ Project_userSchema.virtual('isAuthenticated').get(function () {
111
111
  // Project_user.find({ id_project: projectid, id_user: { $in : group[0].members}, role: { $in : [RoleConstants.OWNER, RoleConstants.ADMIN, RoleConstants.AGENT]} })
112
112
  Project_userSchema.index({ id_project: 1, id_user:1, role: 1 });
113
113
 
114
-
114
+ // suggested by atlas
115
+ Project_userSchema.index({ id_project: 1, role: 1, status: 1, createdAt: 1 });
116
+
117
+
118
+
119
+
120
+
115
121
  module.exports = mongoose.model('project_user', Project_userSchema);;
116
122
 
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.3.27",
4
+ "version": "2.3.29",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -112,6 +112,26 @@
112
112
  winston.verbose("Updated cache for project_user.update",{err:err});
113
113
  });
114
114
 
115
+ if (project_user.id_user) {
116
+ var key = project_user.id_project+":project_users:iduser:"+project_user.id_user;
117
+ winston.verbose("Updating cache for project_user.update with key: " + key);
118
+ client.set(key, project_user, cacheUtil.defaultTTL, (err, reply) => {
119
+ winston.debug("Updated cache for project_user.update",reply);
120
+ winston.verbose("Updated cache for project_user.update",{err:err});
121
+ });
122
+ }
123
+
124
+ if (project_user.uuid_user) {
125
+ var key = project_user.id_project+":project_users:uuid_user:"+project_user.uuid_user;
126
+ winston.verbose("Updating cache for project_user.update with key: " + key);
127
+ client.set(key, project_user, cacheUtil.defaultTTL, (err, reply) => {
128
+ winston.debug("Updated cache for project_user.update",reply);
129
+ winston.verbose("Updated cache for project_user.update",{err:err});
130
+ });
131
+ }
132
+
133
+
134
+
115
135
  var role = project_user.role;
116
136
 
117
137
  var TEAMMATE_ROLES = {
@@ -563,7 +583,7 @@
563
583
 
564
584
  module.exports = function (mongoose, option) {
565
585
 
566
- if (process.env.CACHE_ENABLED == "true") {
586
+ if (process.env.CACHE_ENABLED == true || process.env.CACHE_ENABLED == "true") {
567
587
  var engine = process.env.CACHE_ENGINE;
568
588
  winston.debug("Redis engine: "+ engine);
569
589
 
@@ -176,6 +176,7 @@ router.get('/allstatus', [passport.authenticate(['basic', 'jwt'], { session: fal
176
176
  winston.debug("## GET ALL DEPTS req.project ", req.project)
177
177
 
178
178
  var query = { "id_project": req.projectid };
179
+ //secondo me qui manca un parentesi tonda per gli or
179
180
  if (req.project && req.project.profile && (req.project.profile.type === 'free' && req.project.trialExpired === true) || (req.project.profile.type === 'payment' && req.project.isActiveSubscription === false)) {
180
181
 
181
182
  query.default = true;
@@ -270,7 +271,7 @@ router.get('/', function (req, res) {
270
271
  winston.debug('GET DEPTS FILTERED FOR STATUS === 1 req.project.profile.type ', req.project.trialExpired);
271
272
  winston.debug('GET DEPTS FILTERED FOR STATUS === 1 req.project.isActiveSubscription ', req.project.isActiveSubscription);
272
273
 
273
-
274
+ //secondo me qui manca un parentesi tonda per gli or
274
275
  if (req.project && req.project.profile && (req.project.profile.type === 'free' && req.project.trialExpired === true) || (req.project.profile.type === 'payment' && req.project.isActiveSubscription === false)) {
275
276
 
276
277
  query.default = true;
package/routes/faq.js CHANGED
@@ -61,6 +61,7 @@ router.post('/uploadcsv', upload.single('uploadFile'), function (req, res, next)
61
61
  // var row = {question: element.question, answer: element.answer,
62
62
  // intent_id: element.intent_id, intent_display_name: element.intent_display_name,
63
63
  // webhook_enabled: element.webhook_enabled || false }
64
+
64
65
  var newFaq = new Faq({
65
66
  id_faq_kb: id_faq_kb,
66
67
  question: question,
@@ -114,6 +115,8 @@ router.post('/', function (req, res) {
114
115
  id_faq_kb: req.body.id_faq_kb,
115
116
  question: req.body.question,
116
117
  answer: req.body.answer,
118
+ reply: req.body.reply,
119
+ enabled: true,
117
120
  id_project: req.projectid,
118
121
  topic: req.body.topic,
119
122
  language: faq_kb.language,
@@ -123,6 +126,10 @@ router.post('/', function (req, res) {
123
126
  updatedBy: req.user.id
124
127
  });
125
128
 
129
+ if (req.body.enabled != undefined) {
130
+ newFaq.enabled = req.body.enabled;
131
+ }
132
+
126
133
  newFaq.save(function (err, savedFaq) {
127
134
  if (err) {
128
135
  if (err.code == 11000) {
@@ -177,6 +184,12 @@ router.put('/:faqid', function (req, res) {
177
184
  if (req.body.webhook_enabled!=undefined) {
178
185
  update.webhook_enabled = req.body.webhook_enabled;
179
186
  }
187
+ if (req.body.enabled!=undefined) {
188
+ update.enabled = req.body.enabled;
189
+ }
190
+ if (req.body.reply!=undefined) {
191
+ updated.reply = req.body.enabled;
192
+ }
180
193
 
181
194
 
182
195
 
@@ -308,6 +321,9 @@ router.get('/', function (req, res, next) {
308
321
 
309
322
  // query.$text = {"$search": "question"};
310
323
 
324
+ // TODO ORDER BY SCORE
325
+ // return Faq.find(query, {score: { $meta: "textScore" } })
326
+ // .sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
311
327
 
312
328
 
313
329
  return Faq.find(query).
package/routes/faqpub.js CHANGED
@@ -27,6 +27,11 @@ router.get('/', function (req, res, next) {
27
27
 
28
28
  // query.$text = {"$search": "question"};
29
29
 
30
+ // TODO ORDER BY SCORE
31
+ // return Faq.find(query, {score: { $meta: "textScore" } })
32
+ // .sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
33
+
34
+
30
35
  return Faq.find(query).
31
36
  populate({path:'faq_kb'}).//, match: { trashed: { $in: [null, false] } }}).
32
37
  exec(function (err, faq) {
package/routes/lead.js CHANGED
@@ -93,6 +93,58 @@ router.put('/:leadid', function (req, res) {
93
93
  });
94
94
  });
95
95
 
96
+
97
+
98
+ router.patch('/:leadid/attributes', function (req, res) {
99
+ var data = req.body;
100
+
101
+ // TODO use service method
102
+
103
+ Lead.findById(req.params.leadid, function (err, lead) {
104
+ if (err) {
105
+ winston.error('--- > ERROR ', err);
106
+ return res.status(500).send({ success: false, msg: 'Error updating object.' });
107
+ }
108
+
109
+ if (!lead) {
110
+ return res.status(404).send({ success: false, msg: 'Object not found.' });
111
+ }
112
+
113
+ if (!lead.attributes) {
114
+ winston.debug("empty attributes")
115
+ lead.attributes = {};
116
+ }
117
+
118
+ winston.debug(" lead attributes", lead.attributes)
119
+
120
+ Object.keys(data).forEach(function(key) {
121
+ var val = data[key];
122
+ winston.debug("data attributes "+key+" " +val)
123
+ lead.attributes[key] = val;
124
+ });
125
+
126
+ winston.debug(" lead attributes", lead.attributes)
127
+
128
+ // https://stackoverflow.com/questions/24054552/mongoose-not-saving-nested-object
129
+ lead.markModified('attributes');
130
+
131
+ //cacheinvalidation
132
+ lead.save(function (err, savedLead) {
133
+ if (err) {
134
+ winston.error("error saving lead attributes",err)
135
+ return res.status(500).send({ success: false, msg: 'Error getting object.' });
136
+ }
137
+ winston.verbose(" saved lead attributes",savedLead.toObject())
138
+ leadEvent.emit('lead.update', savedLead);
139
+
140
+ res.json(savedLead);
141
+ });
142
+ });
143
+
144
+ });
145
+
146
+
147
+
96
148
  // router.put('/:leadid', function (req, res) {
97
149
  // winston.debug(req.body);
98
150
  // var update = {};
package/routes/message.js CHANGED
@@ -48,12 +48,16 @@ async (req, res) => {
48
48
  winston.debug('req.params: ', req.params);
49
49
  winston.debug('req.params.request_id: ' + req.params.request_id);
50
50
 
51
+ if (!req.body.text && (!req.body.type || req.body.type=="text") ) {
52
+ return res.status(422).json({ errors: ["text field is required"] });
53
+ }
51
54
  const errors = validationResult(req);
52
55
  if (!errors.isEmpty()) {
53
56
  return res.status(422).json({ errors: errors.array() });
54
57
  }
55
58
 
56
-
59
+ // TODO se sei agent non puoi cambiare sender
60
+ // verificare validazione invio immagine senza caption
57
61
  var project_user = req.projectuser;
58
62
  var sender = req.body.sender;
59
63
  var fullname = req.body.senderFullname || req.user.fullName;
@@ -298,6 +302,157 @@ async (req, res) => {
298
302
 
299
303
 
300
304
 
305
+
306
+ // router.post('/multi2', async (req, res, next) => {
307
+
308
+ // if ( !req.body instanceof Array ) {
309
+ // return res.status(422).json({ errors: ["request body is not array"] });
310
+ // }
311
+ // req.url = '/';
312
+ // winston.info('--- > req.url'+req.url);
313
+
314
+ // req.method = 'POST';
315
+
316
+ // let promises = [];
317
+
318
+ // req.body.forEach(function(message,index) {
319
+ // promises.push(router.handle(req, res, next));
320
+ // });
321
+ // winston.info('--- >promises', promises);
322
+
323
+ // Promise.all(promises).then((values) => {
324
+ // console.log("finito",values);
325
+ // return res.status(200).json({ "success": true });
326
+ // }).catch((err) => {
327
+ // console.log("errore",err);
328
+ // });
329
+ // });
330
+
331
+
332
+
333
+
334
+ router.post('/multi',
335
+ async (req, res) => {
336
+
337
+ winston.debug('req.body post message', req.body);
338
+ winston.debug('req.params: ', req.params);
339
+ winston.debug('req.params.request_id: ' + req.params.request_id);
340
+
341
+ const errors = validationResult(req);
342
+ if (!errors.isEmpty()) {
343
+ return res.status(422).json({ errors: errors.array() });
344
+ }
345
+
346
+ var project_user = req.projectuser;
347
+
348
+ let q = Request.findOne({request_id: req.params.request_id, id_project: req.projectid});
349
+ // if (cacheEnabler.request) {
350
+ // q.cache(cacheUtil.defaultTTL, req.projectid+":requests:request_id:"+req.params.request_id+":simple") //request_cache
351
+ // winston.debug('request cache enabled');
352
+ // }
353
+ return q.exec(async(err, request) => {
354
+
355
+
356
+ if (err) {
357
+ winston.log({
358
+ level: 'error',
359
+ message: 'Error getting the request: '+ JSON.stringify(err) + " " + JSON.stringify(req.body) ,
360
+ label: req.projectid
361
+ });
362
+ // winston.error('Error getting the request.', err);
363
+ return res.status(500).send({success: false, msg: 'Error getting the request.', err:err});
364
+ }
365
+
366
+ if (!request) { //the request doen't exists create it
367
+ return res.status(404).send({success: false, msg: 'Request doesn\'t exist.', err:err});
368
+ } else {
369
+
370
+
371
+
372
+ winston.debug("request exists", request.toObject());
373
+
374
+
375
+ let promises = [];
376
+
377
+ let sender;
378
+ let fullname;
379
+ let email;
380
+ let text;
381
+ let attributes;
382
+ let type;
383
+ let metadata;
384
+ let language;
385
+ let channel;
386
+ let messageStatus;
387
+
388
+ req.body.forEach(function(message,index) {
389
+
390
+ sender = message.sender;
391
+ fullname = message.senderFullname || req.user.fullName;
392
+ email = message.email || req.user.email;
393
+
394
+ text = message.text;
395
+ attributes = message.attributes;
396
+ type = message.type;
397
+ metadata = message.metadata;
398
+ language = message.language;
399
+ channel = message.channel;
400
+ messageStatus = message.status || MessageConstants.CHAT_MESSAGE_STATUS.SENDING;
401
+ // create(sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language, channel_type, channel) {
402
+ let promise = messageService.create(sender || req.user._id, fullname, req.params.request_id, text,
403
+ request.id_project, null, messageStatus, attributes, type, metadata, language, undefined, channel);
404
+
405
+ promises.push(promise);
406
+ });
407
+ winston.debug('--- >promises', promises);
408
+
409
+ Promise.all(promises).then((values) => {
410
+ winston.info('Inserted multiple messages with values: ', values);
411
+ return res.status(200).json(values);
412
+ }).catch((err) => {
413
+ winston.error('Error inserting multiple messages.', err);
414
+ return res.status(500).send({success: false, msg: 'Error inserting multiple messages.', err:err});
415
+
416
+ });
417
+
418
+
419
+
420
+
421
+
422
+
423
+ }
424
+
425
+
426
+
427
+ });
428
+
429
+
430
+
431
+
432
+ });
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+ // router.patch('/:messageid', function(req, res) {
444
+
445
+ // winston.info(req.body);
446
+
447
+ // Message.findByIdAndUpdate(req.params.messageid, req.body, {new: true, upsert:true}, function(err, updatedMessage) {
448
+ // if (err) {
449
+ // return res.status(500).send({success: false, msg: 'Error updating object.'});
450
+ // }
451
+ // res.json(updatedMessage);
452
+ // });
453
+ // });
454
+
455
+
301
456
  // router.put('/:messageid', function(req, res) {
302
457
 
303
458
  // console.log(req.body);
package/routes/project.js CHANGED
@@ -451,8 +451,8 @@ Project.findByIdAndUpdate(req.params.projectid, { $pull: { bannedUsers: { "_id":
451
451
  router.get('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res) {
452
452
  winston.debug(req.body);
453
453
  let q = Project.findOne({_id: req.params.projectid, status:100});
454
- if (cacheEnabler.project) {
455
- q.cache(cacheUtil.defaultTTL, "projects:id:"+req.params.projectid) //project_cache
454
+ if (cacheEnabler.project) {
455
+ q.cache(cacheUtil.longTTL, "projects:id:"+req.params.projectid) //project_cache
456
456
  winston.debug('project cache enabled');
457
457
  }
458
458
  q.exec(function (err, project) {
@@ -0,0 +1,19 @@
1
+ var express = require('express');
2
+ var router = express.Router({mergeParams: true});
3
+
4
+ var passport = require('passport');
5
+ require('../middleware/passport')(passport);
6
+ var validtoken = require('../middleware/valid-token')
7
+ var roleChecker = require('../middleware/has-role');
8
+
9
+
10
+
11
+ router.get('/test', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res) {
12
+ // console.log("req.projectuser",req.projectuser);
13
+ res.json(req.projectuser);
14
+
15
+ });
16
+
17
+
18
+
19
+ module.exports = router;