@tiledesk/tiledesk-server 2.12.0 → 2.13.0
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 +41 -1
- package/Dockerfile +1 -1
- package/Dockerfile-en +1 -1
- package/Dockerfile-jobs +1 -1
- package/Dockerfile-profiler +1 -1
- package/middleware/recaptcha.js +11 -5
- package/migrations/1752742733903-namespace-engine-migration.js +31 -0
- package/models/group.js +8 -0
- package/models/project_user.js +24 -1
- package/package.json +4 -4
- package/pubmodules/whatsapp/listener.js +8 -0
- package/routes/auth.js +53 -58
- package/routes/group.js +89 -12
- package/routes/kb.js +17 -5
- package/routes/project.js +17 -4
- package/routes/project_user.js +148 -160
- package/routes/widget.js +14 -1
- package/services/departmentService.js +16 -2
- package/services/requestService.js +1 -1
- package/test/kbRoute.js +4 -4
package/CHANGELOG.md
CHANGED
@@ -5,8 +5,48 @@
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
7
7
|
|
8
|
-
# 2.
|
8
|
+
# 2.12.0
|
9
|
+
- Updated: whatsapp module listener
|
10
|
+
- Updated: whatsapp-connector to 1.0.0
|
11
|
+
- Updated: tybot-connector to 2.0.26
|
12
|
+
- Updated: vxml-connector to 0.1.77
|
13
|
+
|
14
|
+
# 2.11.12 (deprecated)
|
15
|
+
- Updated: whatsapp-connector to 0.1.87
|
16
|
+
|
17
|
+
# 2.11.11 (deprecated)
|
18
|
+
- Updated: whatsapp module listener
|
19
|
+
- Updated: whatsapp-connector to 0.1.86
|
20
|
+
|
21
|
+
# 2.11.10 (deprecated)
|
22
|
+
- Updated: whatsapp module listener
|
23
|
+
- Updated: whatsapp-connector to 0.1.85
|
24
|
+
- Updated: tybot-connector to 2.0.26
|
25
|
+
- Updated: vxml-connector to 0.1.77
|
26
|
+
|
27
|
+
# 2.11.9
|
28
|
+
- Changed: oauth2 endpoints in auth route
|
29
|
+
- Updated: improved project users management (soft delete)
|
30
|
+
|
31
|
+
# 2.11.8
|
32
|
+
- Added: migration file to migrate namespace engine
|
33
|
+
|
34
|
+
# 2.11.7
|
35
|
+
- Hotfix: solved bug on findProjectUsersAllAndAvailableWithOperatingHours_group on searching group
|
36
|
+
|
37
|
+
# 2.11.6
|
38
|
+
- Added: possibility to enable/disable groups
|
39
|
+
- Updated: delete project user endpoint to logical delete
|
40
|
+
- Updated: tybot-connector to 2.0.23
|
41
|
+
- Updated: get all namespace adding counter
|
42
|
+
- Added: attributes field in groups model
|
43
|
+
|
44
|
+
# 2.11.5
|
45
|
+
- Added: log in requestService
|
46
|
+
|
47
|
+
# 2.11.4
|
9
48
|
- Added: authentication via Keycloak
|
49
|
+
- Added: project settings fields for allowed_urls, allowed_urls_list, allow_send_emoji
|
10
50
|
|
11
51
|
# 2.10.104
|
12
52
|
- Update: standard/hybrid namespace management
|
package/Dockerfile
CHANGED
package/Dockerfile-en
CHANGED
package/Dockerfile-jobs
CHANGED
package/Dockerfile-profiler
CHANGED
package/middleware/recaptcha.js
CHANGED
@@ -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
|
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
|
package/models/project_user.js
CHANGED
@@ -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.
|
4
|
+
"version": "2.13.0",
|
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.
|
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.
|
55
|
-
"@tiledesk/tiledesk-whatsapp-connector": "^0.
|
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
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
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
|
-
|
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',
|
129
|
+
router.delete('/:groupid', async (req, res) => {
|
83
130
|
|
84
|
-
|
131
|
+
let id_project = req.projectid;
|
132
|
+
let group_id = req.params.groupid;
|
85
133
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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 (
|
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
|
-
|
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
|
}
|
package/routes/project_user.js
CHANGED
@@ -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('
|
23
|
+
winston.debug('Invite ProjectUser body ', req.body);
|
27
24
|
|
28
|
-
|
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('
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
63
|
-
winston.debug('
|
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
|
-
|
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
|
89
|
-
return res.status(500).send(
|
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 (!
|
93
|
-
|
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 (
|
98
|
-
|
99
|
-
|
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
|
-
|
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(
|
148
|
-
return res.status(500).send({ success: false, msg:
|
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
|
-
|
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
|
-
|
163
|
-
|
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,
|
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
|
-
|
304
|
-
|
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
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
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
|
-
|
319
|
+
winston.debug("Hard deleted project_user", project_user);
|
356
320
|
|
357
|
-
|
358
|
-
|
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
|
-
|
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 =
|
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('-
|
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"}
|
@@ -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 = "
|
6
|
+
process.env.PINECONE_INDEX = "test-index";
|
7
7
|
process.env.PINECONE_TYPE = "pod";
|
8
|
-
process.env.PINECONE_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('
|
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('
|
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)
|