@tiledesk/tiledesk-server 2.11.8 → 2.11.9
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 +4 -0
- package/middleware/recaptcha.js +11 -5
- package/models/project_user.js +23 -1
- package/package.json +1 -1
- package/routes/auth.js +54 -60
- package/routes/kb.js +3 -1
- package/routes/project_user.js +119 -155
- package/test/kbRoute.js +4 -4
package/CHANGELOG.md
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
7
7
|
|
8
|
+
# 2.11.9
|
9
|
+
- Changed: oauth2 endpoints in auth route
|
10
|
+
- Updated: improved project users management (soft delete)
|
11
|
+
|
8
12
|
# 2.11.8
|
9
13
|
- Added: migration file to migrate namespace engine
|
10
14
|
|
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
|
+
}
|
package/models/project_user.js
CHANGED
@@ -74,6 +74,11 @@ var TagSchema = require("../models/tag");
|
|
74
74
|
index: true,
|
75
75
|
required: true
|
76
76
|
},
|
77
|
+
trashed: {
|
78
|
+
type: Boolean,
|
79
|
+
default: false,
|
80
|
+
required: false
|
81
|
+
}
|
77
82
|
}, {
|
78
83
|
timestamps: true,
|
79
84
|
toJSON: { virtuals: true } //used to polulate messages in toJSON// https://mongoosejs.com/docs/populate.html
|
@@ -116,7 +121,24 @@ Project_userSchema.virtual('isAuthenticated').get(function () {
|
|
116
121
|
Project_userSchema.index({ id_project: 1, role: 1, status: 1, createdAt: 1 });
|
117
122
|
|
118
123
|
|
119
|
-
|
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
|
+
});
|
120
142
|
|
121
143
|
|
122
144
|
module.exports = mongoose.model('project_user', Project_userSchema);;
|
package/package.json
CHANGED
package/routes/auth.js
CHANGED
@@ -773,78 +773,72 @@ 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
|
-
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();
|
802
|
-
|
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);
|
844
|
-
|
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);
|
845
795
|
|
846
|
-
|
847
|
-
|
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 = "/#/";
|
825
|
+
|
826
|
+
if (req.session.redirect_url) {
|
827
|
+
homeurl = req.session.redirect_url;
|
828
|
+
}
|
829
|
+
|
830
|
+
const separator = homeurl.includes('?') ? '&' : '?';
|
831
|
+
var url = dashboard_base_url + homeurl + separator + "token=JWT " + token;
|
832
|
+
|
833
|
+
if (req.session.forced_redirect_url) {
|
834
|
+
const separator = req.session.forced_redirect_url.includes('?') ? '&' : '?';
|
835
|
+
url = req.session.forced_redirect_url + separator + "jwt=JWT " + token; //attention we use jwt= (ionic) instead token=(dashboard) for ionic
|
836
|
+
}
|
837
|
+
|
838
|
+
winston.debug("(/oauth2/callback) Google Redirect: " + url);
|
839
|
+
|
840
|
+
res.redirect(url);
|
841
|
+
});
|
848
842
|
|
849
843
|
router.get(
|
850
844
|
"/keycloak",
|
package/routes/kb.js
CHANGED
@@ -1538,10 +1538,12 @@ router.post('/sitemap', async (req, res) => {
|
|
1538
1538
|
|
1539
1539
|
const sitemap = new Sitemapper({
|
1540
1540
|
url: sitemap_url,
|
1541
|
-
timeout: 15000
|
1541
|
+
timeout: 15000,
|
1542
|
+
debug: true
|
1542
1543
|
});
|
1543
1544
|
|
1544
1545
|
sitemap.fetch().then((data) => {
|
1546
|
+
// TODO - check on data.errors to catch error
|
1545
1547
|
winston.debug("data: ", data);
|
1546
1548
|
res.status(200).send(data);
|
1547
1549
|
}).catch((err) => {
|
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)
|
151
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
|
+
});
|
152
94
|
|
153
|
-
|
154
|
-
|
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);
|
95
|
+
return res.status(200).send(updatedPuser);
|
96
|
+
})
|
160
97
|
|
98
|
+
} else {
|
161
99
|
|
162
|
-
|
163
|
-
|
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
|
+
})
|
164
108
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
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);
|
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
|
+
}
|
181
114
|
|
182
|
-
|
183
|
-
|
115
|
+
emailService.sendYouHaveBeenInvited(email, req.user.firstname, req.user.lastname, req.project.name, id_project, user.firstname, user.lastname, req.body.role)
|
116
|
+
|
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
|
}
|
@@ -264,7 +206,6 @@ router.put('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
|
|
264
206
|
});
|
265
207
|
});
|
266
208
|
|
267
|
-
|
268
209
|
router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['subscription'])], function (req, res) {
|
269
210
|
|
270
211
|
winston.debug("project_userid update", req.body);
|
@@ -334,23 +275,48 @@ router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
|
|
334
275
|
});
|
335
276
|
});
|
336
277
|
|
337
|
-
|
338
|
-
|
339
278
|
// TODO fai servizio di patch degli attributi come request
|
340
279
|
// TODO blocca cancellazione owner?
|
341
280
|
router.delete('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) {
|
342
281
|
|
282
|
+
const { hard, soft } = req.query;
|
283
|
+
const pu_id = req.params.project_userid;
|
284
|
+
|
343
285
|
winston.debug(req.body);
|
344
|
-
|
345
|
-
if (req.query.force === "true") {
|
346
286
|
|
347
|
-
|
287
|
+
if (soft === "true") {
|
288
|
+
// Soft Delete
|
289
|
+
Project_user.findByIdAndUpdate(pu_id, { trashed: true }, { new: true }, (err, project_user) => {
|
348
290
|
if (err) {
|
349
|
-
winston.error("Error gettting project_user for delete", err);
|
350
|
-
return res.status(500).send({ success: false, msg: 'Error deleting
|
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 });
|
351
293
|
}
|
352
294
|
|
353
|
-
winston.debug("
|
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
|
+
}
|
318
|
+
|
319
|
+
winston.debug("Hard deleted project_user", project_user);
|
354
320
|
|
355
321
|
if (project_user) {
|
356
322
|
project_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, project_userPopulated) {
|
@@ -358,25 +324,26 @@ router.delete('/:project_userid', [passport.authenticate(['basic', 'jwt'], { ses
|
|
358
324
|
});
|
359
325
|
}
|
360
326
|
|
361
|
-
res.
|
327
|
+
return res.status(200).send(project_user);
|
362
328
|
});
|
363
|
-
}
|
364
|
-
|
365
|
-
|
329
|
+
}
|
330
|
+
else {
|
331
|
+
// Disable
|
332
|
+
Project_user.findByIdAndUpdate(pu_id, { status: "disabled", user_available: false }, { new: true }, (err, project_user) => {
|
366
333
|
if (err) {
|
367
|
-
winston.error("Error gettting project_user for
|
368
|
-
return res.status(500).send({ success: false, msg: 'Error disabling
|
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 });
|
369
336
|
}
|
370
337
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
project_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, project_userPopulated) {
|
375
|
-
authEvent.emit('project_user.delete', { req: req, project_userPopulated: project_userPopulated });
|
376
|
-
});
|
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 });
|
377
341
|
}
|
378
342
|
|
379
|
-
|
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);
|
380
347
|
}
|
381
348
|
);
|
382
349
|
}
|
@@ -403,7 +370,6 @@ router.get('/:project_userid', [passport.authenticate(['basic', 'jwt'], { sessio
|
|
403
370
|
|
404
371
|
});
|
405
372
|
|
406
|
-
|
407
373
|
router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('user', ['subscription'])], async (req, res, next) => { //changed for smtp
|
408
374
|
// router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], async (req, res, next) => {
|
409
375
|
winston.debug("--> users search ");
|
@@ -440,8 +406,6 @@ router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session:
|
|
440
406
|
/**
|
441
407
|
* GET PROJECT-USER BY PROJECT ID AND CURRENT USER ID
|
442
408
|
// */
|
443
|
-
|
444
|
-
|
445
409
|
router.get('/users/:user_id', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res, next) {
|
446
410
|
winston.debug("--> users USER ID ", req.params.user_id);
|
447
411
|
|
@@ -518,7 +482,7 @@ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), va
|
|
518
482
|
}
|
519
483
|
winston.debug("role", role);
|
520
484
|
|
521
|
-
var query = { id_project: req.projectid, role: { $in : role }
|
485
|
+
var query = { id_project: req.projectid, role: { $in : role }, trashed: { $ne: true } };
|
522
486
|
|
523
487
|
if (req.query.presencestatus) {
|
524
488
|
query["presence.status"] = req.query.presencestatus;
|
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)
|