@tiledesk/tiledesk-server 2.12.0 → 2.13.1

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,8 +5,51 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
- # 2.11.0
8
+ # 2.12.1
9
+ - Bug fix: wrong endpoint for hybrid qa
10
+
11
+ # 2.12.0
12
+ - Updated: whatsapp module listener
13
+ - Updated: whatsapp-connector to 1.0.0
14
+ - Updated: tybot-connector to 2.0.26
15
+ - Updated: vxml-connector to 0.1.77
16
+
17
+ # 2.11.12 (deprecated)
18
+ - Updated: whatsapp-connector to 0.1.87
19
+
20
+ # 2.11.11 (deprecated)
21
+ - Updated: whatsapp module listener
22
+ - Updated: whatsapp-connector to 0.1.86
23
+
24
+ # 2.11.10 (deprecated)
25
+ - Updated: whatsapp module listener
26
+ - Updated: whatsapp-connector to 0.1.85
27
+ - Updated: tybot-connector to 2.0.26
28
+ - Updated: vxml-connector to 0.1.77
29
+
30
+ # 2.11.9
31
+ - Changed: oauth2 endpoints in auth route
32
+ - Updated: improved project users management (soft delete)
33
+
34
+ # 2.11.8
35
+ - Added: migration file to migrate namespace engine
36
+
37
+ # 2.11.7
38
+ - Hotfix: solved bug on findProjectUsersAllAndAvailableWithOperatingHours_group on searching group
39
+
40
+ # 2.11.6
41
+ - Added: possibility to enable/disable groups
42
+ - Updated: delete project user endpoint to logical delete
43
+ - Updated: tybot-connector to 2.0.23
44
+ - Updated: get all namespace adding counter
45
+ - Added: attributes field in groups model
46
+
47
+ # 2.11.5
48
+ - Added: log in requestService
49
+
50
+ # 2.11.4
9
51
  - Added: authentication via Keycloak
52
+ - Added: project settings fields for allowed_urls, allowed_urls_list, allow_send_emoji
10
53
 
11
54
  # 2.10.104
12
55
  - Update: standard/hybrid namespace management
package/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:16
1
+ FROM node:18-bullseye
2
2
 
3
3
  RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
4
4
 
package/Dockerfile-en CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:16
1
+ FROM node:18-bullseye
2
2
 
3
3
  RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
4
4
 
package/Dockerfile-jobs CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:16
1
+ FROM node:18-bullseye
2
2
 
3
3
  RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
4
4
 
@@ -1,4 +1,4 @@
1
- FROM node:16
1
+ FROM node:18-bullseye
2
2
 
3
3
  RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
4
4
 
package/deploy.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  git pull
2
- npm version minor
2
+ npm version patch
3
3
  version=`node -e 'console.log(require("./package.json").version)'`
4
4
  echo "version $version"
5
5
 
@@ -1,11 +1,17 @@
1
1
  var winston = require('../config/winston');
2
2
 
3
- var Recaptcha = require('express-recaptcha').RecaptchaV3
4
- var recaptcha = new Recaptcha('6Lf1khcpAAAAABMNHJfnJm43vVTxFzXM7ADqDAp5', '6Lf1khcpAAAAAG6t7LuOfl9vThGPFOOJIiAoMIhs')
3
+ var Recaptcha = require('express-recaptcha').RecaptchaV3;
5
4
 
6
- const RECAPTCHA_ENABLED = false;
5
+ const recaptcha_key = process.env.RECAPTCHA_KEY;
6
+ const recaptcha_secret = process.env.RECAPTCHA_SECRET;
7
+
8
+ winston.info("Recaptcha key: " + recaptcha_key + " and secret: " + recaptcha_secret );
9
+ let recaptcha;
10
+
11
+ let RECAPTCHA_ENABLED = false;
7
12
 
8
13
  if (process.env.RECAPTCHA_ENABLED === true || process.env.RECAPTCHA_ENABLED ==="true") {
14
+ recaptcha = new Recaptcha(recaptcha_key, recaptcha_secret);
9
15
  RECAPTCHA_ENABLED = true;
10
16
  }
11
17
 
@@ -21,7 +27,7 @@ module.exports =
21
27
  next();
22
28
  // success code
23
29
  } else {
24
- winston.error("Signup recaptcha ko");
30
+ winston.error("Signup recaptcha ko: "+ error);
25
31
  // next({status:"Signup recaptcha ko"});
26
32
  res.status(403).send({success: false, msg: 'Recaptcha error.'});
27
33
 
@@ -29,4 +35,4 @@ module.exports =
29
35
  }
30
36
  })
31
37
 
32
- }
38
+ }
@@ -0,0 +1,31 @@
1
+ var winston = require('../config/winston');
2
+ const { Namespace } = require('../models/kb_setting');
3
+
4
+ async function up () {
5
+
6
+ if (!process.env.PINECONE_INDEX || !process.env.PINECONE_TYPE) {
7
+ winston.error("Namespace engine migration STOPPED. PINECONE_TYPE or PINECONE_INDEX undefined.");
8
+ return;
9
+ }
10
+
11
+ let engine = {
12
+ name: "pinecone",
13
+ type: process.env.PINECONE_TYPE,
14
+ apikey: "",
15
+ vector_size: 1536,
16
+ index_name: process.env.PINECONE_INDEX
17
+ };
18
+
19
+ try {
20
+ const updates = await Namespace.updateMany(
21
+ { engine: { $exists: false } },
22
+ { engine: engine }
23
+ );
24
+ winston.info("Schema updated for " + updates.nModified + " namespace");
25
+ } catch (err) {
26
+ winston.error("Error updating namespaces in migration:", err);
27
+ throw err;
28
+ }
29
+ }
30
+
31
+ module.exports = { up };
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,10 +69,16 @@ 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
75
76
  },
77
+ trashed: {
78
+ type: Boolean,
79
+ default: false,
80
+ required: false
81
+ }
76
82
  }, {
77
83
  timestamps: true,
78
84
  toJSON: { virtuals: true } //used to polulate messages in toJSON// https://mongoosejs.com/docs/populate.html
@@ -115,7 +121,24 @@ Project_userSchema.virtual('isAuthenticated').get(function () {
115
121
  Project_userSchema.index({ id_project: 1, role: 1, status: 1, createdAt: 1 });
116
122
 
117
123
 
118
-
124
+ Project_userSchema.pre('findOneAndUpdate', async function(next) {
125
+ // Get the update object
126
+ const update = this.getUpdate();
127
+
128
+ // Check if 'trashed' is being set to true
129
+ if (update && (
130
+ (update.trashed === true) ||
131
+ (update.$set && update.$set.trashed === true)
132
+ )) {
133
+ // Set status to "disabled"
134
+ if (!update.$set) {
135
+ update.$set = {};
136
+ }
137
+ update.$set.status = "disabled";
138
+ this.setUpdate(update);
139
+ }
140
+ next();
141
+ });
119
142
 
120
143
 
121
144
  module.exports = mongoose.model('project_user', Project_userSchema);;
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.12.0",
4
+ "version": "2.13.1",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -49,10 +49,10 @@
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.26",
53
53
  "@tiledesk/tiledesk-voice-twilio-connector": "^0.1.22",
54
- "@tiledesk/tiledesk-vxml-connector": "^0.1.76",
55
- "@tiledesk/tiledesk-whatsapp-connector": "^0.1.84",
54
+ "@tiledesk/tiledesk-vxml-connector": "^0.1.77",
55
+ "@tiledesk/tiledesk-whatsapp-connector": "^1.0.0",
56
56
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.12",
57
57
  "amqplib": "^0.5.5",
58
58
  "app-root-path": "^3.0.0",
@@ -28,6 +28,12 @@ class Listener {
28
28
  let graph_url = process.env.META_GRAPH_URL || config.graphUrl || "https://graph.facebook.com/v14.0/"
29
29
  winston.debug("Whatsapp graph_url: "+ password);
30
30
 
31
+ let fb_app_id = process.env.FB_APP_ID;
32
+ winston.debug("Whatsapp fb_app_id: "+ fb_app_id);
33
+
34
+ let configuration_id = process.env.CONFIGURATION_ID;
35
+ winston.debug("Whatsapp configuration_id: "+ configuration_id);
36
+
31
37
  let baseFileUrl = process.env.BASE_FILE_URL || apiUrl || "http://localhost:3000"
32
38
 
33
39
  let job_topic = process.env.JOB_TOPIC_EXCHANGE;
@@ -50,6 +56,8 @@ class Listener {
50
56
  API_URL: apiUrl,
51
57
  BASE_FILE_URL: baseFileUrl,
52
58
  GRAPH_URL: graph_url,
59
+ FB_APP_ID: fb_app_id,
60
+ CONFIGURATION_ID: configuration_id,
53
61
  BASE_URL: apiUrl + "/modules/whatsapp",
54
62
  APPS_API_URL: apiUrl + "/modules/apps",
55
63
  REDIS_HOST: host,
package/routes/auth.js CHANGED
@@ -773,78 +773,73 @@ router.get("/google/callback", passport.authenticate("google", { session: false
773
773
 
774
774
 
775
775
 
776
- router.get("/oauth2", function(req,res,next){
777
- winston.debug("redirect_url: "+ req.query.redirect_url );
776
+ router.get("/oauth2", function (req, res, next) {
777
+ winston.debug("(oauth2) redirect_url: " + req.query.redirect_url);
778
778
  req.session.redirect_url = req.query.redirect_url;
779
779
 
780
- winston.debug("forced_redirect_url: "+ req.query.forced_redirect_url );
780
+ winston.debug("(oauth2) forced_redirect_url: " + req.query.forced_redirect_url);
781
781
  req.session.forced_redirect_url = req.query.forced_redirect_url;
782
782
 
783
783
  passport.authenticate(
784
784
  'oauth2'
785
- )(req,res,next);
785
+ )(req, res, next);
786
786
  });
787
787
 
788
788
  // router.get('/oauth2',
789
789
  // passport.authenticate('oauth2'));
790
790
 
791
- router.get('/oauth2/callback',
792
- passport.authenticate('oauth2', { session: false}),
793
- function(req, res) {
794
- winston.debug("'/oauth2/callback: ", req.query);
795
- winston.debug("/oauth2/callback --> req.session.redirect_url", req.session.redirect_url);
796
- winston.debug("/oauth2/callback --> req.session.forced_redirect_url", req.session.forced_redirect_url);
797
-
798
- var user = req.user;
799
- winston.debug("user", user);
800
- winston.debug("req.session.redirect_url: "+ req.session.redirect_url);
801
- var userJson = user.toObject();
791
+ router.get('/oauth2/callback', passport.authenticate('oauth2', { session: false }), function (req, res) {
792
+ winston.debug("'/oauth2/callback: ", req.query);
793
+ winston.debug("/oauth2/callback --> req.session.redirect_url", req.session.redirect_url);
794
+ winston.debug("/oauth2/callback --> req.session.forced_redirect_url", req.session.forced_redirect_url);
795
+
796
+ var user = req.user;
797
+ winston.debug("(/oauth2/callback) user", user);
798
+ winston.debug("(/oauth2/callback) req.session.redirect_url: " + req.session.redirect_url);
799
+ var userJson = user.toObject();
800
+
801
+ delete userJson.password;
802
+
803
+ var signOptions = {
804
+ issuer: 'https://tiledesk.com',
805
+ subject: 'user',
806
+ audience: 'https://tiledesk.com',
807
+ jwtid: uuidv4()
808
+
809
+ };
810
+
811
+ var alg = process.env.GLOBAL_SECRET_ALGORITHM;
812
+ if (alg) {
813
+ signOptions.algorithm = alg;
814
+ }
815
+
816
+ var token = jwt.sign(userJson, configSecret, signOptions); //priv_jwt pp_jwt
817
+
818
+ // return the information including token as JSON
819
+ // res.json(returnObject);
820
+
821
+ let dashboard_base_url = process.env.EMAIL_BASEURL || config.baseUrl;
822
+ winston.debug("(/oauth2/callback) Google Redirect dashboard_base_url: ", dashboard_base_url);
823
+
824
+ let homeurl = "/#/";
802
825
 
803
- delete userJson.password;
804
-
805
-
806
- var signOptions = {
807
- issuer: 'https://tiledesk.com',
808
- subject: 'user',
809
- audience: 'https://tiledesk.com',
810
- jwtid: uuidv4()
811
-
812
- };
813
-
814
- var alg = process.env.GLOBAL_SECRET_ALGORITHM;
815
- if (alg) {
816
- signOptions.algorithm = alg;
817
- }
818
-
819
-
820
- var token = jwt.sign(userJson, configSecret, signOptions); //priv_jwt pp_jwt
821
-
822
-
823
- // return the information including token as JSON
824
- // res.json(returnObject);
825
-
826
- let dashboard_base_url = process.env.EMAIL_BASEURL || config.baseUrl;
827
- winston.debug("Google Redirect dashboard_base_url: ", dashboard_base_url);
828
-
829
- let homeurl = "/#/";
830
-
831
- if (req.session.redirect_url) {
832
- homeurl = req.session.redirect_url;
833
- }
834
-
835
- var url = dashboard_base_url+homeurl+"?token=JWT "+token;
836
-
837
- if (req.session.forced_redirect_url) {
838
- url = req.session.forced_redirect_url+"?jwt=JWT "+token; //attention we use jwt= (ionic) instead token=(dashboard) for ionic
839
- }
840
-
841
- winston.debug("Google Redirect: "+ url);
842
-
843
- res.redirect(url);
826
+ const separator = homeurl.includes('?') ? '&' : '?';
827
+ var url = dashboard_base_url+homeurl+ separator + "token=JWT "+token;
844
828
 
829
+ if (req.session.redirect_url) {
830
+ const separator = req.session.redirect_url.includes('?') ? '&' : '?';
831
+ url = req.session.redirect_url+ separator + "token=JWT "+token;
832
+ }
845
833
 
846
-
847
- });
834
+ if (req.session.forced_redirect_url) {
835
+ const separator = req.session.forced_redirect_url.includes('?') ? '&' : '?';
836
+ url = req.session.forced_redirect_url+ separator + "jwt=JWT "+token; //attention we use jwt= (ionic) instead token=(dashboard) for ionic
837
+ }
838
+
839
+ winston.debug("(/oauth2/callback) Google Redirect: " + url);
840
+
841
+ res.redirect(url);
842
+ });
848
843
 
849
844
  router.get(
850
845
  "/keycloak",
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
  }
@@ -1528,10 +1538,12 @@ router.post('/sitemap', async (req, res) => {
1528
1538
 
1529
1539
  const sitemap = new Sitemapper({
1530
1540
  url: sitemap_url,
1531
- timeout: 15000
1541
+ timeout: 15000,
1542
+ debug: true
1532
1543
  });
1533
1544
 
1534
1545
  sitemap.fetch().then((data) => {
1546
+ // TODO - check on data.errors to catch error
1535
1547
  winston.debug("data: ", data);
1536
1548
  res.status(200).send(data);
1537
1549
  }).catch((err) => {
package/routes/project.js CHANGED
@@ -349,9 +349,6 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
349
349
  update["settings.email.notification.conversation.pooled"] = req.body["settings.email.notification.conversation.pooled"];
350
350
  }
351
351
 
352
-
353
-
354
-
355
352
  if (req.body["settings.email.templates.assignedRequest"]!=undefined) {
356
353
  update["settings.email.templates.assignedRequest"] = req.body["settings.email.templates.assignedRequest"];
357
354
  }
@@ -380,7 +377,6 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
380
377
  update["settings.email.templates.emailDirect"] = req.body["settings.email.templates.emailDirect"];
381
378
  }
382
379
 
383
-
384
380
  if (req.body["settings.email.from"]!=undefined) {
385
381
  update["settings.email.from"] = req.body["settings.email.from"];
386
382
  }
@@ -452,6 +448,18 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
452
448
  if (req.body["settings.chatbots_attributes_hidden"]!=undefined) {
453
449
  update["settings.chatbots_attributes_hidden"] = req.body["settings.chatbots_attributes_hidden"];
454
450
  }
451
+
452
+ if (req.body["settings.allow_send_emoji"]!=undefined) {
453
+ update["settings.allow_send_emoji"] = req.body["settings.allow_send_emoji"];
454
+ }
455
+
456
+ if (req.body["settings.allowed_urls"]!=undefined) {
457
+ update["settings.allowed_urls"] = req.body["settings.allowed_urls"];
458
+ }
459
+
460
+ if (req.body["settings.allowed_urls_list"]!=undefined) {
461
+ update["settings.allowed_urls_list"] = req.body["settings.allowed_urls_list"];
462
+ }
455
463
 
456
464
  if (req.body.widget!=undefined) {
457
465
  update.widget = req.body.widget;
@@ -1051,6 +1059,11 @@ router.get('/:projectid/users/availables', async (req, res) => {
1051
1059
  return res.status(404).send({ success: false, error: "Group " + group_id + " not found" })
1052
1060
  }
1053
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
+
1054
1067
  query.id_user = { $in: group.members.map(id => mongoose.Types.ObjectId(id) )}
1055
1068
  }
1056
1069
  }
@@ -12,176 +12,118 @@ var RoleConstants = require("../models/roleConstants");
12
12
  var ProjectUserUtil = require("../utils/project_userUtil");
13
13
  const uuidv4 = require('uuid/v4');
14
14
 
15
-
16
15
  var passport = require('passport');
17
16
  require('../middleware/passport')(passport);
18
17
  var validtoken = require('../middleware/valid-token')
19
18
  var roleChecker = require('../middleware/has-role');
20
19
 
21
20
 
22
-
23
- // NEW: INVITE A USER
24
21
  router.post('/invite', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) {
25
22
 
26
- winston.debug('-> INVITE USER ', req.body);
23
+ winston.debug('Invite ProjectUser body ', req.body);
27
24
 
28
- var email = req.body.email;
25
+ let id_project = req.projectid;
26
+ let email = req.body.email;
29
27
  if (email) {
30
28
  email = email.toLowerCase();
31
29
  }
32
30
 
33
- winston.debug('»»» INVITE USER EMAIL', email);
34
- winston.debug('»»» CURRENT USER ID', req.user._id);
35
- winston.debug('»»» PROJECT ID', req.projectid);
36
- // authType
37
- User.findOne({ email: email, status: 100
38
- // , authType: 'email_password'
39
- }, function (err, user) {
40
- if (err) throw err;
31
+ winston.debug('Invite ProjectUser with email ' + email + ' on project ' + req.projectid);
32
+
33
+ User.findOne({ email: email, status: 100 }, (err, user) => {
34
+
35
+ if (err) {
36
+ winston.error("Error in searching for a possible existing project user with email " + email);
37
+ return res.status(500).send({ success: false, error: "An error occurred during the invite process" });
38
+ }
41
39
 
42
40
  if (!user) {
43
- /*
44
- * *** USER NOT FOUND > SAVE EMAIL AND PROJECT ID IN PENDING INVITATION *** */
41
+ // User not registered on Tiledesk Platform -> Save email and project_id in pending invitation
45
42
  // TODO req.user.firstname is null for bot visitor
46
- return pendinginvitation.saveInPendingInvitation(req.projectid, req.project.name, email, req.body.role, req.user._id, req.user.firstname, req.user.lastname)
47
- .then(function (savedPendingInvitation) {
48
-
49
- var eventData = {req: req, savedPendingInvitation: savedPendingInvitation};
50
- winston.debug("eventData",eventData);
51
- authEvent.emit('project_user.invite.pending', eventData);
52
-
53
- return res.json({ msg: "User not found, save invite in pending ", pendingInvitation: savedPendingInvitation });
54
- })
55
- .catch(function (err) {
56
- return res.send(err);
57
- // return res.status(500).send(err);
58
- });
59
- // return res.status(404).send({ success: false, msg: 'User not found.' });
43
+ return pendinginvitation.saveInPendingInvitation(req.projectid, req.project.name, email, req.body.role, req.user._id, req.user.firstname, req.user.lastname).then(function (savedPendingInvitation) {
44
+ var eventData = { req: req, savedPendingInvitation: savedPendingInvitation };
45
+ winston.debug("eventData", eventData);
46
+ authEvent.emit('project_user.invite.pending', eventData);
47
+ return res.json({ msg: "User not found, save invite in pending ", pendingInvitation: savedPendingInvitation });
48
+ }).catch(function (err) {
49
+ return res.send(err);
50
+ });
60
51
 
61
52
  } else if (req.user.id == user._id) {
62
- winston.debug('-> -> FOUND USER ID', user._id)
63
- winston.debug('-> -> CURRENT USER ID', req.user.id);
64
- // if the current user id is = to the id of found user return an error:
65
- // (to a user is not allowed to invite oneself)
66
-
67
- winston.debug('XXX XXX FORBIDDEN')
53
+ // If the current user id is = to the id of found user return an error. To a user is not allowed to invite oneself.
54
+ winston.debug('Invite User: found user ' + user._id + ' is equal to current user ' + req.user.id + '. Is not allowed to invite oneself.')
68
55
  return res.status(403).send({ success: false, msg: 'Forbidden. It is not allowed to invite oneself', code: 4000 });
69
56
 
70
57
  } else {
71
58
 
72
- /**
73
- * *** IT IS NOT ALLOWED TO INVITE A USER WHO IS ALREADY A MEMBER OF THE PROJECT ***
74
- * FIND THE PROJECT USERS FOR THE PROJECT ID PASSED BY THE CLIENT IN THE BODY OF THE REQUEST
75
- * IF THE ID OF THE USER FOUND FOR THE EMAIL (PASSED IN THE BODY OF THE REQUEST - see above)
76
- * MATCHES ONE OF THE USER ID CONTENTS IN THE PROJECTS USER OBJECT STOP THE WORKFLOW AND RETURN AN ERROR */
77
-
78
- var role = [RoleConstants.OWNER, RoleConstants.ADMIN, RoleConstants.SUPERVISOR, RoleConstants.AGENT];
79
- winston.debug("role", role);
80
-
81
- // winston.debug("PROJECT USER ROUTES - req projectid", req.projectid);
59
+ let roles = [RoleConstants.OWNER, RoleConstants.ADMIN, RoleConstants.SUPERVISOR, RoleConstants.AGENT];
82
60
 
83
- return Project_user.find({ id_project: req.projectid, role: { $in : role }, status: "active"}, function (err, projectuser) {
84
-
85
-
86
- winston.debug('PRJCT-USERS FOUND (FILTERED FOR THE PROJECT ID) ', projectuser)
61
+ Project_user.findOne({ id_project: id_project, id_user: user._id, role: { $in: roles }}, (err, puser) => {
87
62
  if (err) {
88
- winston.error("Error gettting project_user for invite", err);
89
- return res.status(500).send(err);
63
+ winston.error("Error inviting an already existing user: ", err);
64
+ return res.status(500).send({ success: false, msg: "An error occurred on inviting user " + email + " on project " + id_project })
90
65
  }
91
66
 
92
- if (!projectuser) {
93
- // winston.debug('*** PRJCT-USER NOT FOUND ***')
94
- return res.status(404).send({ success: false, msg: 'Project user not found.' });
67
+ if (!roles.includes(req.body.role)) {
68
+ return res.status(400).send({ success: false, msg: 'Invalid role specified: ' + req.body.role });
95
69
  }
70
+
71
+ let user_available = typeof req.body.user_available === 'boolean' ? req.body.user_available : true
96
72
 
97
- if (projectuser) {
98
- try {
99
- projectuser.forEach(p_user => {
100
- if (p_user) {
101
- // winston.debug('»»»» FOUND USER ID: ', user._id, ' TYPE OF ', typeof (user._id))
102
- // winston.debug('»»»» PRJCT USER > USER ID: ', p_user.id_user, ' TYPE OF ', typeof (p_user.id_user));
103
- var projectUserId = p_user.id_user.toString();
104
- var foundUserId = user._id.toString()
105
-
106
- winston.debug('»»»» FOUND USER ID: ', foundUserId, ' TYPE OF ', typeof (foundUserId))
107
- winston.debug('»»»» PRJCT USER > USER ID: ', projectUserId, ' TYPE OF ', typeof (projectUserId));
108
-
109
- // var n = projectuser.includes('5ae6c62c61c7d54bf119ac73');
110
- // winston.debug('USER IS ALREADY A MEMBER OF THE PROJECT ', n)
111
- if (projectUserId == foundUserId) {
112
- // if ('5ae6c62c61c7d54bf119ac73' == '5ae6c62c61c7d54bf119ac73') {
113
-
114
- winston.debug('»»»» THE PRJCT-USER ID ', p_user.id_user, ' MATCHES THE FOUND USER-ID', user._id)
115
- winston.warn("User " + projectUserId+ " is already a member of the project: " + req.projectid)
116
-
117
- // cannot use continue or break inside a JavaScript Array.prototype.forEach loop. However, there are other options:
118
- throw new Error('User is already a member'); // break
119
- // return res.status(403).send({ success: false, msg: 'Forbidden. User is already a member' });
120
- }
121
- }
122
- });
123
- }
124
- catch (e) {
125
- winston.error('»»» ERROR ', e)
73
+ if (puser) {
74
+ if (puser.trashed !== true) {
75
+ winston.warn("Trying to invite an already project member user")
126
76
  return res.status(403).send({ success: false, msg: 'Forbidden. User is already a member', code: 4001 });
127
77
  }
128
78
 
129
- winston.debug('NO ERROR, SO CREATE AND SAVE A NEW PROJECT USER ')
130
-
131
- var user_available = true;
132
- if (req.body.user_available!=undefined) {
133
- user_available = req.body.user_available;
134
- }
135
- var newProject_user = new Project_user({
136
- // _id: new mongoose.Types.ObjectId(),
137
- id_project: req.projectid,
138
- id_user: user._id,
139
- role: req.body.role,
140
- user_available: user_available,
141
- createdBy: req.user.id,
142
- updatedBy: req.user.id
143
- });
144
-
145
- return newProject_user.save(function (err, savedProject_user) {
79
+ Project_user.findByIdAndUpdate(puser._id, { role: req.body.role, user_available: user_available, trashed: false, status: 'active' }, { new: true}, (err, updatedPuser) => {
146
80
  if (err) {
147
- winston.error('--- > ERROR ', err)
148
- return res.status(500).send({ success: false, msg: 'Error saving object.' });
81
+ winston.error("Error update existing project user before inviting it ", err)
82
+ return res.status(500).send({ success: false, msg: "An error occurred on inviting user " + email + " on project " + id_project })
149
83
  }
150
84
 
85
+ emailService.sendYouHaveBeenInvited(email, req.user.firstname, req.user.lastname, req.project.name, id_project, user.firstname, user.lastname, req.body.role)
86
+
87
+ updatedPuser.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, updatedPuserPopulated){
88
+ var pu = updatedPuserPopulated.toJSON();
89
+ pu.isBusy = ProjectUserUtil.isBusy(savedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat);
90
+ var eventData = {req:req, updatedPuserPopulated: pu};
91
+ winston.debug("eventData",eventData);
92
+ authEvent.emit('project_user.invite', eventData);
93
+ });
151
94
 
95
+ return res.status(200).send(updatedPuser);
96
+ })
152
97
 
153
- winston.debug('INVITED USER (IS THE USER FOUND BY EMAIL) ', user);
154
- winston.debug('EMAIL of THE INVITED USER ', email);
155
- winston.debug('ROLE of THE INVITED USER ', req.body.role);
156
- winston.debug('PROJECT NAME ', req.body.role);
157
- winston.debug('LOGGED USER ID ', req.user.id);
158
- winston.debug('LOGGED USER NAME ', req.user.firstname);
159
- winston.debug('LOGGED USER NAME ', req.user.lastname);
98
+ } else {
160
99
 
100
+ let newProject_user = new Project_user({
101
+ id_project: id_project,
102
+ id_user: user._id,
103
+ role: req.body.role,
104
+ user_available: user_available,
105
+ createdBy: req.user.id,
106
+ updatedBy: req.user.id
107
+ })
161
108
 
162
- var invitedUserFirstname = user.firstname
163
- var invitedUserLastname = user.lastname
109
+ newProject_user.save((err, savedProject_user) => {
110
+ if (err) {
111
+ winston.error("Error saving new project user: ", err)
112
+ return res.status(500).send({ success: false, msg: "An error occurred on inviting user " + email + " on project " + id_project })
113
+ }
164
114
 
165
- emailService.sendYouHaveBeenInvited(email, req.user.firstname, req.user.lastname, req.project.name, req.projectid, invitedUserFirstname, invitedUserLastname, req.body.role)
166
-
167
- // try {
168
- //test it
169
- savedProject_user.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, savedProject_userPopulated){
170
- var pu = savedProject_userPopulated.toJSON();
171
- pu.isBusy = ProjectUserUtil.isBusy(savedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat);
172
-
173
-
174
- var eventData = {req:req, savedProject_userPopulated: pu};
175
- winston.debug("eventData",eventData);
176
- authEvent.emit('project_user.invite', eventData);
177
- });
178
- // } catch(e) {winston.error('Error emitting activity');}
179
-
180
- return res.json(savedProject_user);
115
+ emailService.sendYouHaveBeenInvited(email, req.user.firstname, req.user.lastname, req.project.name, id_project, user.firstname, user.lastname, req.body.role)
181
116
 
182
-
183
- });
117
+ savedProject_user.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, savedProject_userPopulated){
118
+ var pu = savedProject_userPopulated.toJSON();
119
+ pu.isBusy = ProjectUserUtil.isBusy(savedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat);
120
+ var eventData = {req:req, savedProject_userPopulated: pu};
121
+ winston.debug("eventData",eventData);
122
+ authEvent.emit('project_user.invite', eventData);
123
+ });
184
124
 
125
+ return res.status(200).send(savedProject_user);
126
+ })
185
127
  }
186
128
  })
187
129
  }
@@ -248,28 +190,22 @@ router.put('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
248
190
  update.tags = req.body.tags;
249
191
  }
250
192
 
251
-
252
-
253
-
254
193
  Project_user.findByIdAndUpdate(req.projectuser.id, update, { new: true, upsert: true }, function (err, updatedProject_user) {
255
194
  if (err) {
256
195
  winston.error("Error gettting project_user for update", err);
257
196
  return res.status(500).send({ success: false, msg: 'Error updating object.' });
258
197
  }
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
198
 
267
-
199
+ updatedProject_user.populate({ path:'id_user', select: { 'firstname': 1, 'lastname': 1 }}, function (err, updatedProject_userPopulated) {
200
+ var pu = updatedProject_userPopulated.toJSON();
201
+ pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat);
202
+ authEvent.emit('project_user.update', {updatedProject_userPopulated:pu, req: req});
203
+ });
204
+
268
205
  res.json(updatedProject_user);
269
206
  });
270
207
  });
271
208
 
272
-
273
209
  router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['subscription'])], function (req, res) {
274
210
 
275
211
  winston.debug("project_userid update", req.body);
@@ -300,8 +236,9 @@ router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
300
236
  update.attributes = req.body.attributes;
301
237
  }
302
238
 
303
- if (req.body.status!=undefined) {
304
- update.status = req.body.status;
239
+ const allowedStatuses = ['active', 'disabled'];
240
+ if (req.body.status !== undefined && allowedStatuses.includes(req.body.status)) {
241
+ update.status = req.body.status;
305
242
  }
306
243
 
307
244
  if (req.body["settings.email.notification.conversation.assigned.toyou"]!=undefined) {
@@ -338,28 +275,78 @@ router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
338
275
  });
339
276
  });
340
277
 
341
-
342
-
343
278
  // TODO fai servizio di patch degli attributi come request
344
279
  // TODO blocca cancellazione owner?
345
280
  router.delete('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) {
346
281
 
282
+ const { hard, soft } = req.query;
283
+ const pu_id = req.params.project_userid;
284
+
347
285
  winston.debug(req.body);
348
286
 
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
- }
287
+ if (soft === "true") {
288
+ // Soft Delete
289
+ Project_user.findByIdAndUpdate(pu_id, { trashed: true }, { new: true }, (err, project_user) => {
290
+ if (err) {
291
+ winston.error("Error gettting project_user for soft delete", err);
292
+ return res.status(500).send({ success: false, msg: 'Error deleting Project User with id ' + pu_id });
293
+ }
294
+
295
+ winston.debug("Soft deleted project_user", project_user);
296
+ if (!project_user) {
297
+ winston.warn("Project user not found for soft delete with id " + pu_id);
298
+ return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id });
299
+ }
300
+
301
+ // Event 'project_user.delete' not working - Check it and improve it to manage soft/hard delete
302
+ return res.status(200).send(project_user);
303
+
304
+ })
305
+ }
306
+ else if (hard === "true") {
307
+ // Hard Delete
308
+ Project_user.findByIdAndRemove(pu_id, { new: false }, (err, project_user) => {
309
+ if (err) {
310
+ winston.error("Error gettting project_user for hard delete", err);
311
+ return res.status(500).send({ success: false, msg: 'Error deleting Project user with id ' + pu_id });
312
+ }
313
+
314
+ if (!project_user) {
315
+ winston.warn("Project user not found for soft delete with id " + pu_id);
316
+ return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id });
317
+ }
354
318
 
355
- winston.debug("Removed project_user", project_user);
319
+ winston.debug("Hard deleted project_user", project_user);
356
320
 
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});
321
+ if (project_user) {
322
+ project_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, project_userPopulated) {
323
+ authEvent.emit('project_user.delete', { req: req, project_userPopulated: project_userPopulated });
324
+ });
325
+ }
326
+
327
+ return res.status(200).send(project_user);
359
328
  });
360
-
361
- res.json(project_user);
362
- });
329
+ }
330
+ else {
331
+ // Disable
332
+ Project_user.findByIdAndUpdate(pu_id, { status: "disabled", user_available: false }, { new: true }, (err, project_user) => {
333
+ if (err) {
334
+ winston.error("Error gettting project_user for disable user", err);
335
+ return res.status(500).send({ success: false, msg: 'Error disabling Project User with id ' + pu_id });
336
+ }
337
+
338
+ if (!project_user) {
339
+ winston.warn("Project user not found for soft delete with id " + pu_id);
340
+ return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id });
341
+ }
342
+
343
+ winston.debug("Disabled project_user", project_user);
344
+
345
+ // Event 'project_user.delete' not working - Check it and improve it to manage disable project user
346
+ return res.status(200).send(project_user);
347
+ }
348
+ );
349
+ }
363
350
  });
364
351
 
365
352
  router.get('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res) {
@@ -383,7 +370,6 @@ router.get('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
383
370
 
384
371
  });
385
372
 
386
-
387
373
  router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('user', ['subscription'])], async (req, res, next) => { //changed for smtp
388
374
  // router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], async (req, res, next) => {
389
375
  winston.debug("--> users search ");
@@ -420,8 +406,6 @@ router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session:
420
406
  /**
421
407
  * GET PROJECT-USER BY PROJECT ID AND CURRENT USER ID
422
408
  // */
423
-
424
-
425
409
  router.get('/users/:user_id', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res, next) {
426
410
  winston.debug("--> users USER ID ", req.params.user_id);
427
411
 
@@ -498,7 +482,7 @@ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
498
482
  }
499
483
  winston.debug("role", role);
500
484
 
501
- var query = {id_project: req.projectid, role: { $in : role } };
485
+ var query = { id_project: req.projectid, role: { $in : role }, trashed: { $ne: true } };
502
486
 
503
487
  if (req.query.presencestatus) {
504
488
  query["presence.status"] = req.query.presencestatus;
@@ -506,6 +490,10 @@ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
506
490
 
507
491
  winston.debug("query", query);
508
492
 
493
+ if (req.query.status) {
494
+ query["status"] = req.query.status;
495
+ }
496
+
509
497
  Project_user.find(query).
510
498
  populate('id_user').
511
499
  // lean().
package/routes/widget.js CHANGED
@@ -188,7 +188,7 @@ router.get('/', async (req, res, next) => {
188
188
 
189
189
  //@DISABLED_CACHE .cache(cacheUtil.queryTTL, "projects:query:id:status:100:"+req.projectid+":select:-settings")
190
190
 
191
- Project.findOne({_id: req.projectid, status: 100}).select('-settings -ipFilter -ipFilterEnabled').exec(function(err, project) {
191
+ Project.findOne({_id: req.projectid, status: 100}).select('-ipFilter -ipFilterEnabled').exec(function(err, project) {
192
192
  // not use .lean I need project.trialExpired
193
193
 
194
194
  if (err) {
@@ -198,6 +198,19 @@ router.get('/', async (req, res, next) => {
198
198
 
199
199
  winston.debug("project", project);
200
200
 
201
+ // This code filters the project settings to only include the properties
202
+ // 'allowed_urls', 'allowed_urls_list', and 'allowed_send_emoji', removing all others.
203
+ // Removed the "-settings" command from the query that excluded the entire "settings" field from the selection
204
+ if (project && project.settings) {
205
+ const { allowed_urls, allowed_urls_list, allow_send_emoji } = project.settings;
206
+ project.settings = {};
207
+ Object.assign(project.settings,
208
+ allowed_urls !== undefined ? { allowed_urls } : {},
209
+ allowed_urls_list !== undefined ? { allowed_urls_list } : {},
210
+ allow_send_emoji !== undefined ? { allow_send_emoji } : {}
211
+ );
212
+ }
213
+
201
214
  // ProjectSetter project not found with id: 62d8cf8b2b10b30013bb9b99
202
215
  // Informazioni
203
216
  // 2022-07-27 14:32:14.772 CESTerror: Error getting widget. {"err":"Project Not Found"}
@@ -200,7 +200,7 @@ class AiService {
200
200
 
201
201
  askNamespace(data) {
202
202
  let base_url = kb_endpoint_qa;
203
- if (data.hybrid) {
203
+ if (data.hybrid || data.search_type === 'hybrid') {
204
204
  base_url = kb_endpoint_qa_gpu;
205
205
  }
206
206
  winston.debug("[OPENAI SERVICE] kb endpoint: " + base_url);
@@ -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
  }
@@ -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) {
package/test/kbRoute.js CHANGED
@@ -3,9 +3,9 @@ process.env.NODE_ENV = 'test';
3
3
  process.env.GPTKEY = "fakegptkey";
4
4
  process.env.LOG_LEVEL = 'critical'
5
5
  process.env.KB_WEBHOOK_TOKEN = "testtoken"
6
- process.env.PINECONE_INDEX = "test_index";
6
+ process.env.PINECONE_INDEX = "test-index";
7
7
  process.env.PINECONE_TYPE = "pod";
8
- process.env.PINECONE_INDEX_HYBRID = "test_index_hybrid";
8
+ process.env.PINECONE_INDEX_HYBRID = "test-index-hybrid";
9
9
  process.env.PINECONE_TYPE_HYBRID = "serverless";
10
10
  process.env.ADMIN_EMAIL = "admin@tiledesk.com";
11
11
 
@@ -69,7 +69,7 @@ describe('KbRoute', () => {
69
69
 
70
70
  res.should.have.status(200);
71
71
  expect(res.body.length).to.equal(1);
72
- expect(res.body[0].engine.index_name).to.equal('test_index')
72
+ expect(res.body[0].engine.index_name).to.equal('test-index')
73
73
 
74
74
  let namespace_id = res.body[0].id;
75
75
 
@@ -1149,7 +1149,7 @@ describe('KbRoute', () => {
1149
1149
  expect(res.body.name).to.equal('MyCustomNamespace');
1150
1150
  should.exist(res.body.engine)
1151
1151
  expect(res.body.engine.name).to.equal('pinecone');
1152
- expect(res.body.engine.type).to.equal('pod');
1152
+ expect(res.body.engine.type).to.equal('serverless');
1153
1153
 
1154
1154
  // Get again all namespace. A new default namespace should not be created.
1155
1155
  chai.request(server)