@tiledesk/tiledesk-server 2.10.15 → 2.10.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/app.js +2 -1
  3. package/models/request.js +8 -0
  4. package/package.json +4 -3
  5. package/pubmodules/activities/test/activityRoute.js +6 -2
  6. package/pubmodules/events/test/eventRoute.js +7 -3
  7. package/pubmodules/pubModulesManager.js +24 -0
  8. package/pubmodules/voice-twilio/index.js +6 -0
  9. package/pubmodules/voice-twilio/listener.js +59 -0
  10. package/routes/campaigns.js +1 -1
  11. package/routes/files.js +6 -4
  12. package/routes/images.js +0 -2
  13. package/routes/kb.js +7 -1
  14. package/routes/users.js +2 -2
  15. package/services/fileGridFsService.js +12 -10
  16. package/services/requestService.js +2 -1
  17. package/test/app-test.js +36 -1
  18. package/test/authentication.js +662 -796
  19. package/test/authenticationJwt.js +213 -315
  20. package/test/authorization.js +53 -72
  21. package/test/campaignsRoute.js +42 -47
  22. package/test/cannedRoute.js +30 -16
  23. package/test/departmentService.js +222 -274
  24. package/test/example.json +31 -1
  25. package/test/faqRoute.js +713 -622
  26. package/test/faqService.js +124 -159
  27. package/test/faqkbRoute.js +128 -100
  28. package/test/fileRoute.js +50 -46
  29. package/test/imageRoute.js +263 -254
  30. package/test/jwtRoute.js +128 -153
  31. package/test/kbRoute.js +40 -17
  32. package/test/kbsettingsRoute.js +78 -54
  33. package/test/keysRoute.js +6 -7
  34. package/test/labelRoute.js +591 -696
  35. package/test/labelService.js +40 -47
  36. package/test/leadService.js +100 -115
  37. package/test/logsRoute.js +13 -7
  38. package/test/messageRootRoute.js +112 -102
  39. package/test/messageRoute.js +1171 -1419
  40. package/test/messageService.js +41 -43
  41. package/test/openaiRoute.js +5 -1
  42. package/test/projectRoute.js +23 -4
  43. package/test/projectService.js +3 -1
  44. package/test/quoteManager.js +36 -13
  45. package/test/requestRoute.js +103 -72
  46. package/test/requestService.js +51 -51
  47. package/test/userRoute.js +37 -8
  48. package/test/userService.js +34 -31
  49. package/utils/promiseUtil.js +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
+ # 2.10.17
9
+ - changed bodyParser.urlencoded extended to TRUE
10
+ - updated tybot-connector to 0.2.130
11
+ - added twilio voice module
12
+ - updated messenger-connectorto 0.1.22
13
+
14
+ # 2.10.16 - abort
15
+ - changed bodyParser.urlencoded extended to TRUE
16
+ - updated tybot-connector to 0.2.130
17
+ - added twilio voice module
18
+ - updated messenger-connectorto 0.1.22
19
+
8
20
  # 2.10.15
9
21
  - Readded event on fully_abandoned request
10
22
 
package/app.js CHANGED
@@ -280,6 +280,7 @@ if (process.env.ENABLE_ALTERNATIVE_CORS_MIDDLEWARE === "true") {
280
280
 
281
281
  // https://stackoverflow.com/questions/18710225/node-js-get-raw-request-body-using-express
282
282
 
283
+
283
284
  const JSON_BODY_LIMIT = process.env.JSON_BODY_LIMIT || '500KB';
284
285
  winston.debug("JSON_BODY_LIMIT : " + JSON_BODY_LIMIT);
285
286
 
@@ -293,7 +294,7 @@ app.use(bodyParser.json({limit: JSON_BODY_LIMIT,
293
294
  }
294
295
  }));
295
296
 
296
- app.use(bodyParser.urlencoded({limit: JSON_BODY_LIMIT, extended: false }));
297
+ app.use(bodyParser.urlencoded({limit: JSON_BODY_LIMIT, extended: true }));
297
298
 
298
299
  app.use(cookieParser());
299
300
  app.use(express.static(path.join(__dirname, 'public')));
package/models/request.js CHANGED
@@ -492,6 +492,14 @@ RequestSchema.index({ id_project: 1, createdAt: 1, preflight: 1});
492
492
  //suggested by atlas profiler. Used by auto closing requests
493
493
  RequestSchema.index({ hasBot: 1, status: 1, createdAt: 1});
494
494
 
495
+ // Evaluate following indexes
496
+ RequestSchema.index({ "channel.name": 1, id_project: 1, preflight: 1, "snapshot.requester.uuid_user": 1, createdAt: - 1, status: 1 })
497
+ RequestSchema.index({ id_project: 1, preflight: 1, "snapshot.agents.id_user": 1, updatedAt: -1, draft: 1, status: 1 })
498
+ RequestSchema.index({ id_project: 1, participants: 1, preflight: 1, updatedAt: -1, draft: 1, status: 1 })
499
+ RequestSchema.index({ id_project: 1, preflight: 1, updatedAt: -1, draft: 1, status: 1 })
500
+ RequestSchema.index({ id_project: 1, preflight: 1, "snapshot.requester.uuid_user": 1, createdAt: -1, status: 1 })
501
+ RequestSchema.index({ department: 1, id_project: 1, participants: 1, preflight: 1, createdAt: -1, status: 1 })
502
+
495
503
 
496
504
  // cannot index parallel arrays [agents] [participants] {"driv
497
505
  // RequestSchema.index({ id_project: 1, status: 1, preflight:1, participants:1, "agents.id_user":1, updatedAt: -1 }); //NN LO APPLICA
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.10.15",
4
+ "version": "2.10.17",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -44,15 +44,16 @@
44
44
  "@tiledesk/tiledesk-dialogflow-connector": "^1.8.4",
45
45
  "@tiledesk/tiledesk-json-rules-engine": "^4.0.3",
46
46
  "@tiledesk/tiledesk-kaleyra-proxy": "^0.1.7",
47
- "@tiledesk/tiledesk-messenger-connector": "^0.1.21",
47
+ "@tiledesk/tiledesk-messenger-connector": "^0.1.22",
48
48
  "@tiledesk/tiledesk-rasa-connector": "^1.0.10",
49
49
  "@tiledesk/tiledesk-telegram-connector": "^0.1.14",
50
50
  "@tiledesk/tiledesk-train-jobworker": "^0.0.11",
51
- "@tiledesk/tiledesk-tybot-connector": "^0.2.127",
51
+ "@tiledesk/tiledesk-tybot-connector": "^0.2.130",
52
52
  "@tiledesk/tiledesk-whatsapp-connector": "^0.1.73",
53
53
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.8",
54
54
  "@tiledesk/tiledesk-sms-connector": "^0.1.10",
55
55
  "@tiledesk/tiledesk-vxml-connector": "^0.1.49",
56
+ "@tiledesk/tiledesk-voice-twilio-connector": "^0.1.7",
56
57
  "amqplib": "^0.5.5",
57
58
  "app-root-path": "^3.0.0",
58
59
  "bcrypt-nodejs": "0.0.3",
@@ -12,6 +12,8 @@ let server = require('../../../app');
12
12
  let should = chai.should();
13
13
  var winston = require('../../../config/winston');
14
14
 
15
+ let log = false;
16
+
15
17
  // chai.config.includeStack = true;
16
18
 
17
19
  var expect = chai.expect;
@@ -56,8 +58,10 @@ describe('ActivityRoute', () => {
56
58
  .get('/'+ savedProject._id + '/activities')
57
59
  .auth(email, pwd)
58
60
  .end((err, res) => {
59
- //console.log("res", res);
60
- console.log("res.body", res.body);
61
+
62
+ if (err) { console.error("err: ", err); }
63
+ if (log) { console.log("res.body", res.body); }
64
+
61
65
  res.should.have.status(200);
62
66
  res.body.activities.should.be.a('array');
63
67
  expect(res.body.count).to.equal(1);
@@ -13,6 +13,8 @@ let chaiHttp = require('chai-http');
13
13
  let server = require('../../../app');
14
14
  let should = chai.should();
15
15
 
16
+ let log = false;
17
+
16
18
  // chai.config.includeStack = true;
17
19
 
18
20
  var expect = chai.expect;
@@ -40,8 +42,10 @@ describe('EventRoute', () => {
40
42
  .auth(email, pwd)
41
43
  .send({"name":"event1", attributes: {"attr1":"val1"}})
42
44
  .end((err, res) => {
43
- //console.log("res", res);
44
- console.log("res.body", res.body);
45
+
46
+ if (err) { console.error("err: ", err); }
47
+ if (log) { console.log("res.body", res.body); }
48
+
45
49
  res.should.have.status(200);
46
50
  res.body.should.be.a('object');
47
51
  expect(res.body.name).to.equal("event1");
@@ -50,7 +54,7 @@ describe('EventRoute', () => {
50
54
  Project_user.findOne({ id_user: savedUser.id, status: "active"} )
51
55
  .populate('events')
52
56
  .exec(function (err, project_user) {
53
- console.log("project_user", project_user.toJSON());
57
+ if (log) { console.log("project_user", project_user.toJSON()); }
54
58
  expect(project_user.events.length).to.equal(1);
55
59
  done();
56
60
  });
@@ -39,6 +39,9 @@ class PubModulesManager {
39
39
  this.voice = undefined;
40
40
  this.voiceRoute = undefined;
41
41
 
42
+ this.voiceTwilio = undefined;
43
+ this.voiceTwilioRoute = undefined;
44
+
42
45
  this.mqttTest = undefined;
43
46
  this.mqttTestRoute = undefined;
44
47
 
@@ -105,6 +108,10 @@ class PubModulesManager {
105
108
  app.use('/modules/voice', this.voiceRoute);
106
109
  winston.info("PubModulesManager voiceRoute controller loaded");
107
110
  }
111
+ if (this.voiceTwilioRoute) {
112
+ app.use('/modules/voice-twilio', this.voiceTwilioRoute);
113
+ winston.info("PubModulesManager voiceTwilioRoute controller loaded");
114
+ }
108
115
  if (this.mqttTestRoute) {
109
116
  app.use('/modules/mqttTest', this.mqttTestRoute);
110
117
  winston.info("PubModulesManager mqttTestRoute controller loaded");
@@ -364,6 +371,23 @@ class PubModulesManager {
364
371
  }
365
372
  }
366
373
 
374
+ try {
375
+ this.voiceTwilio = require('./voice-twilio');
376
+ winston.info("this.voiceTwilio: " + this.voiceTwilio);
377
+ this.voiceTwilio.listener.listen(config);
378
+
379
+ this.voiceTwilioRoute = this.voice.voiceTwilioRoute;
380
+
381
+ winston.info("PubModulesManager initialized apps (voiceTwilio).")
382
+ } catch(err) {
383
+ console.log("\n Unable to start voiceTwilio connector: ", err);
384
+ if (err.code == 'MODULE_NOT_FOUND') {
385
+ winston.info("PubModulesManager init apps module not found ");
386
+ } else {
387
+ winston.info("PubModulesManager error initializing init apps module", err);
388
+ }
389
+ }
390
+
367
391
  try {
368
392
  this.sms = require('./sms');
369
393
  winston.info("this.sms: " + this.sms);
@@ -0,0 +1,6 @@
1
+ const listener = require("./listener");
2
+
3
+ const twilio_voice = require('@tiledesk/tiledesk-voice-twilio-connector');
4
+ const twilioVoiceRoute = twilio_voice.router;
5
+
6
+ module.exports = { listener: listener, twilioVoiceRoute: twilioVoiceRoute }
@@ -0,0 +1,59 @@
1
+ const voice_twilio = require('@tiledesk/tiledesk-voice-twilio-connector');
2
+ let winston = require('../../config/winston');
3
+ let configGlobal = require('../../config/global');
4
+ const mongoose = require('mongoose');
5
+
6
+ const apiUrl = process.env.API_URL || configGlobal.apiUrl;
7
+ winston.info("TwilioVoice apiUrl: " + apiUrl);
8
+
9
+ const dbConnection = mongoose.connection;
10
+
11
+ class Listener {
12
+
13
+ listen(config) {
14
+
15
+ winston.info("TwilioVoice Listener listen");
16
+ if (config.databaseUri) {
17
+ winston.debug("TwilioVoice config databaseUri: " + config.databaseUri);
18
+ }
19
+
20
+ var port = process.env.CACHE_REDIS_PORT || 6379;
21
+ winston.debug("Redis port: "+ port);
22
+
23
+ var host = process.env.CACHE_REDIS_HOST || "127.0.0.1"
24
+ winston.debug("Redis host: "+ host);
25
+
26
+ var password = process.env.CACHE_REDIS_PASSWORD;
27
+ winston.debug("Redis password: "+ password);
28
+
29
+ let brand_name = null;
30
+ if (process.env.BRAND_NAME) {
31
+ brand_name = process.env.BRAND_NAME
32
+ }
33
+
34
+ let log = process.env.VOICE_TWILIO_LOG || false
35
+ winston.debug("Voice log: "+ log);
36
+
37
+ voice_twilio.startApp({
38
+ MONGODB_URI: config.databaseUri,
39
+ dbconnection: dbConnection,
40
+ API_URL: apiUrl,
41
+ BASE_URL: apiUrl + "/modules/twilio-voice",
42
+ REDIS_HOST: host,
43
+ REDIS_PORT: port,
44
+ REDIS_PASSWORD: password,
45
+ BRAND_NAME: brand_name,
46
+ log: log
47
+ }, (err) => {
48
+ if (!err) {
49
+ winston.info("Tiledesk Twilio Voice Connector proxy server succesfully started.");
50
+ } else {
51
+ winston.info("unable to start Tiledesk Twilio Voice Connector. " + err);
52
+ }
53
+ })
54
+ }
55
+ }
56
+
57
+ let listener = new Listener();
58
+
59
+ module.exports = listener;
@@ -325,7 +325,7 @@ router.post('/direct', async function (req, res) {
325
325
  channel_type: MessageConstants.CHANNEL_TYPE.DIRECT,
326
326
  channel: req.body.channel
327
327
  };
328
-
328
+
329
329
  winston.info("message before", message);
330
330
 
331
331
  jobManager.publish(
package/routes/files.js CHANGED
@@ -30,11 +30,13 @@ curl -u andrea.leo@f21.it:123456 \
30
30
  */
31
31
 
32
32
  router.post('/users', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken], upload.single('file'), (req, res, next) => {
33
+
34
+ console.log("asdasd")
33
35
  winston.info("files/users")
34
- return res.status(201).json({
35
- message: 'File uploded successfully',
36
- filename: req.file.filename
37
- });
36
+ return res.status(201).json({
37
+ message: 'File uploded successfully',
38
+ filename: req.file.filename
39
+ });
38
40
 
39
41
  });
40
42
 
package/routes/images.js CHANGED
@@ -211,7 +211,6 @@ uploadAvatar.single('file'), async (req, res, next) => {
211
211
  winston.error("Error finding project user: ", err);
212
212
  return res.status(500).send({ success: false, error: "Unable to find project user for user " + userid + "in project " + id_project });
213
213
  })
214
-
215
214
  if (!puser) {
216
215
  winston.warn("User" + userid + "don't belongs the project " + id_project);
217
216
  return res.status(401).send({ success: false, error: "You don't belong the chatbot's project" })
@@ -225,7 +224,6 @@ uploadAvatar.single('file'), async (req, res, next) => {
225
224
  entity_id = bot_id;
226
225
  }
227
226
 
228
-
229
227
  var destinationFolder = 'uploads/users/' + entity_id + "/images/";
230
228
  winston.debug("destinationFolder:"+destinationFolder);
231
229
 
package/routes/kb.js CHANGED
@@ -514,6 +514,10 @@ router.get('/namespace/:id/chunks/:content_id', async (req, res) => {
514
514
  let engine = ns.engine || default_engine;
515
515
  delete engine._id;
516
516
 
517
+ if (process.env.NODE_ENV === 'test') {
518
+ return res.status(200).send({ success: true, message: "Get chunks skipped in test environment"});
519
+ }
520
+
517
521
  openaiService.getContentChunks(namespace_id, content_id, engine).then((resp) => {
518
522
  let chunks = resp.data;
519
523
  winston.debug("chunks for content " + content_id);
@@ -1119,7 +1123,9 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
1119
1123
  });
1120
1124
  winston.verbose("resources to be sent to worker: ", resources);
1121
1125
 
1122
- scheduleScrape(resources);
1126
+ if (!process.env.NODE_ENV) {
1127
+ scheduleScrape(resources);
1128
+ }
1123
1129
  res.status(200).send(result);
1124
1130
 
1125
1131
  }).catch((err) => {
package/routes/users.js CHANGED
@@ -215,11 +215,11 @@ router.post('/loginemail', function (req, res) {
215
215
  let namespace_id = req.body.namespace_id;
216
216
 
217
217
  if (!project_id) {
218
- res.status(500).send({ success: false, error: "missing 'id_project' field" });
218
+ return res.status(500).send({ success: false, error: "missing 'id_project' field" });
219
219
  }
220
220
 
221
221
  if (!chatbot_id && !namespace_id) {
222
- res.status(500).send({ success: false, error: "missing 'bot_id' or 'namespace_id' field" });
222
+ return res.status(500).send({ success: false, error: "missing 'bot_id' or 'namespace_id' field" });
223
223
  }
224
224
 
225
225
  User.findById(user_id, (err, user) => {
@@ -20,6 +20,9 @@ class FileGridFsService extends FileService {
20
20
  // DB
21
21
  this.mongoURI = process.env.DATABASE_URI || process.env.MONGODB_URI || config.database;
22
22
 
23
+ if (process.env.NODE_ENV === 'test') {
24
+ this.mongoURI = config.databasetest;
25
+ }
23
26
 
24
27
  // // connection
25
28
  this.conn = mongoose.createConnection(this.mongoURI, {
@@ -133,8 +136,8 @@ class FileGridFsService extends FileService {
133
136
  }
134
137
 
135
138
  getStorage(folderName) {
136
- const storageMongo = new GridFsStorage({
137
- url : this.mongoURI,
139
+ const storageMongo = new GridFsStorage({
140
+ url: this.mongoURI,
138
141
  options: { useNewUrlParser: true, useUnifiedTopology: true },
139
142
  file: (req, file) => {
140
143
  var folder = uuidv4();
@@ -154,32 +157,31 @@ class FileGridFsService extends FileService {
154
157
  // console.log("XXX file",file)
155
158
 
156
159
  // if (req.body.folder) {
157
-
160
+
158
161
  // folder = req.body.folder;
159
162
  // }
160
163
 
161
164
  var subfolder = "/public";
162
165
  if (req.user && req.user.id) {
163
- subfolder = "/users/"+req.user.id;
166
+ subfolder = "/users/" + req.user.id;
164
167
  }
165
- const path = 'uploads'+ subfolder + "/" + folderName + "/" + folder ;
168
+ const path = 'uploads' + subfolder + "/" + folderName + "/" + folder;
166
169
  req.folder = folder;
167
-
168
170
  // const match = ["image/png", "image/jpeg"];
169
-
171
+
170
172
  // if (match.indexOf(file.mimetype) === -1) {
171
173
  // const filename = `${Date.now()}-${file.originalname}`;
172
174
  // return filename;
173
175
  // }
174
-
176
+
175
177
  return {
176
178
  bucketName: folderName,
177
179
  filename: `${path}/${file.originalname}`
178
180
  };
179
181
  }
180
- });
182
+ });
181
183
 
182
- return storageMongo;
184
+ return storageMongo;
183
185
  }
184
186
 
185
187
 
@@ -774,6 +774,7 @@ class RequestService {
774
774
  })
775
775
  }
776
776
 
777
+ // DEPRECATED
777
778
  async _create(request) {
778
779
 
779
780
  var startDate = new Date();
@@ -1072,7 +1073,7 @@ class RequestService {
1072
1073
 
1073
1074
  }
1074
1075
 
1075
-
1076
+ // DEPRECATED
1076
1077
  async __create(request) {
1077
1078
 
1078
1079
  var startDate = new Date();
package/test/app-test.js CHANGED
@@ -1,4 +1,5 @@
1
1
  process.env.NODE_ENV = 'test';
2
+ process.env.LOG_LEVEL = 'critical'
2
3
 
3
4
  let chai = require('chai');
4
5
  let chaiHttp = require('chai-http');
@@ -18,7 +19,7 @@ describe('Root Test', () => {
18
19
 
19
20
  /**
20
21
  * Try to perform a request with an invalid id project.
21
- * A fake id or non existent mongo id (like user id) is passed.
22
+ * A fake id is passed.
22
23
  * This test must respond with status 400 and with an error.
23
24
  */
24
25
  it("Wrong request url", (done) => {
@@ -31,6 +32,39 @@ describe('Root Test', () => {
31
32
 
32
33
  let fake_id_project = "fake1234"
33
34
 
35
+ chai.request(server)
36
+ //.get('/' + savedUser._id + '/faq_kb')
37
+ .get('/' + fake_id_project + '/faq_kb')
38
+ .auth(email, pwd)
39
+ .end((err, res) => {
40
+ if (err) { console.error("err: ", err); }
41
+ if (log) { console.log("res.body", res.body); }
42
+
43
+ res.should.have.status(400);
44
+ assert.notEqual(res.body.error, null);
45
+ expect(res.body.error).to.equal("Invalid project id: " + fake_id_project)
46
+ done();
47
+ })
48
+ })
49
+ })
50
+ }).timeout(5000)
51
+
52
+ /**
53
+ * Try to perform a request with an invalid id project.
54
+ * A non existent mongo id (like user id) is passed.
55
+ * This test must respond with status 400 and with an error.
56
+ */
57
+ it("Wrong request url", (done) => {
58
+
59
+ var email = "test-signup-" + Date.now() + "@email.com";
60
+ var pwd = "pwd";
61
+
62
+ userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
63
+ projectService.create("test-root-project", savedUser._id).then((savedProject) => {
64
+
65
+ // A real valid mongo id without a corresponding project
66
+ let fake_id_project = savedUser._id;
67
+
34
68
  chai.request(server)
35
69
  //.get('/' + savedUser._id + '/faq_kb')
36
70
  .get('/' + fake_id_project + '/faq_kb')
@@ -47,4 +81,5 @@ describe('Root Test', () => {
47
81
  })
48
82
  })
49
83
  }).timeout(5000)
84
+
50
85
  })