@tiledesk/tiledesk-server 2.3.27 → 2.3.29

Sign up to get free protection for your applications and to get access to all the features.
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;